@smythos/sre 1.5.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 (188) hide show
  1. package/README.md +135 -0
  2. package/dist/index.js +7 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/types/Components/APICall/APICall.class.d.ts +34 -0
  5. package/dist/types/Components/APICall/AccessTokenManager.d.ts +17 -0
  6. package/dist/types/Components/APICall/ArrayBufferResponse.helper.d.ts +3 -0
  7. package/dist/types/Components/APICall/OAuth.helper.d.ts +10 -0
  8. package/dist/types/Components/APICall/mimeTypeCategories.d.ts +6 -0
  9. package/dist/types/Components/APICall/parseData.d.ts +5 -0
  10. package/dist/types/Components/APICall/parseHeaders.d.ts +3 -0
  11. package/dist/types/Components/APICall/parseProxy.d.ts +4 -0
  12. package/dist/types/Components/APICall/parseUrl.d.ts +7 -0
  13. package/dist/types/Components/APIEndpoint.class.d.ts +16 -0
  14. package/dist/types/Components/APIOutput.class.d.ts +15 -0
  15. package/dist/types/Components/AgentPlugin.class.d.ts +16 -0
  16. package/dist/types/Components/Async.class.d.ts +17 -0
  17. package/dist/types/Components/Await.class.d.ts +22 -0
  18. package/dist/types/Components/Classifier.class.d.ts +33 -0
  19. package/dist/types/Components/Component.class.d.ts +35 -0
  20. package/dist/types/Components/ComponentHost.class.d.ts +12 -0
  21. package/dist/types/Components/DataSourceCleaner.class.d.ts +19 -0
  22. package/dist/types/Components/DataSourceIndexer.class.d.ts +25 -0
  23. package/dist/types/Components/DataSourceLookup.class.d.ts +17 -0
  24. package/dist/types/Components/FEncDec.class.d.ts +17 -0
  25. package/dist/types/Components/FHash.class.d.ts +17 -0
  26. package/dist/types/Components/FSign.class.d.ts +18 -0
  27. package/dist/types/Components/FSleep.class.d.ts +19 -0
  28. package/dist/types/Components/FTimestamp.class.d.ts +19 -0
  29. package/dist/types/Components/FileStore.class.d.ts +11 -0
  30. package/dist/types/Components/ForEach.class.d.ts +16 -0
  31. package/dist/types/Components/GPTPlugin.class.d.ts +17 -0
  32. package/dist/types/Components/GenAILLM.class.d.ts +130 -0
  33. package/dist/types/Components/HuggingFace.class.d.ts +17 -0
  34. package/dist/types/Components/Image/imageSettings.config.d.ts +21 -0
  35. package/dist/types/Components/ImageGenerator.class.d.ts +17 -0
  36. package/dist/types/Components/JSONFilter.class.d.ts +13 -0
  37. package/dist/types/Components/LLMAssistant.class.d.ts +19 -0
  38. package/dist/types/Components/LogicAND.class.d.ts +7 -0
  39. package/dist/types/Components/LogicAtLeast.class.d.ts +9 -0
  40. package/dist/types/Components/LogicAtMost.class.d.ts +9 -0
  41. package/dist/types/Components/LogicOR.class.d.ts +7 -0
  42. package/dist/types/Components/LogicXOR.class.d.ts +7 -0
  43. package/dist/types/Components/MCPClient.class.d.ts +17 -0
  44. package/dist/types/Components/PromptGenerator.class.d.ts +19 -0
  45. package/dist/types/Components/ScrapflyWebScrape.class.d.ts +30 -0
  46. package/dist/types/Components/TavilyWebSearch.class.d.ts +31 -0
  47. package/dist/types/Components/index.d.ts +74 -0
  48. package/dist/types/Core/AgentProcess.helper.d.ts +36 -0
  49. package/dist/types/Core/Connector.class.d.ts +34 -0
  50. package/dist/types/Core/ConnectorsService.d.ts +64 -0
  51. package/dist/types/Core/DummyConnector.d.ts +4 -0
  52. package/dist/types/Core/HookService.d.ts +27 -0
  53. package/dist/types/Core/SmythRuntime.class.d.ts +28 -0
  54. package/dist/types/Core/SystemEvents.d.ts +12 -0
  55. package/dist/types/Core/boot.d.ts +1 -0
  56. package/dist/types/config.d.ts +11 -0
  57. package/dist/types/constants.d.ts +79 -0
  58. package/dist/types/helpers/BinaryInput.helper.d.ts +33 -0
  59. package/dist/types/helpers/Conversation.helper.d.ts +85 -0
  60. package/dist/types/helpers/JsonContent.helper.d.ts +16 -0
  61. package/dist/types/helpers/LocalCache.helper.d.ts +14 -0
  62. package/dist/types/helpers/Log.helper.d.ts +22 -0
  63. package/dist/types/helpers/OpenApiParser.helper.d.ts +10 -0
  64. package/dist/types/helpers/S3Cache.helper.d.ts +9 -0
  65. package/dist/types/helpers/SmythURI.helper.d.ts +3 -0
  66. package/dist/types/helpers/TemplateString.helper.d.ts +71 -0
  67. package/dist/types/helpers/TypeChecker.helper.d.ts +10 -0
  68. package/dist/types/index.d.ts +173 -0
  69. package/dist/types/subsystems/AgentManager/Agent.class.d.ts +78 -0
  70. package/dist/types/subsystems/AgentManager/Agent.helper.d.ts +1 -0
  71. package/dist/types/subsystems/AgentManager/AgentData.service/AgentDataConnector.d.ts +33 -0
  72. package/dist/types/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.d.ts +20 -0
  73. package/dist/types/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.d.ts +48 -0
  74. package/dist/types/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.d.ts +19 -0
  75. package/dist/types/subsystems/AgentManager/AgentData.service/index.d.ts +4 -0
  76. package/dist/types/subsystems/AgentManager/AgentLogger.class.d.ts +11 -0
  77. package/dist/types/subsystems/AgentManager/AgentRequest.class.d.ts +15 -0
  78. package/dist/types/subsystems/AgentManager/AgentRuntime.class.d.ts +91 -0
  79. package/dist/types/subsystems/AgentManager/AgentSSE.class.d.ts +40 -0
  80. package/dist/types/subsystems/AgentManager/AgentSettings.class.d.ts +12 -0
  81. package/dist/types/subsystems/AgentManager/Component.service/ComponentConnector.d.ts +17 -0
  82. package/dist/types/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.d.ts +14 -0
  83. package/dist/types/subsystems/AgentManager/Component.service/index.d.ts +4 -0
  84. package/dist/types/subsystems/AgentManager/EmbodimentSettings.class.d.ts +8 -0
  85. package/dist/types/subsystems/AgentManager/ForkedAgent.class.d.ts +15 -0
  86. package/dist/types/subsystems/AgentManager/OSResourceMonitor.d.ts +2 -0
  87. package/dist/types/subsystems/ComputeManager/Code.service/CodeConnector.d.ts +58 -0
  88. package/dist/types/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.d.ts +15 -0
  89. package/dist/types/subsystems/ComputeManager/Code.service/index.d.ts +4 -0
  90. package/dist/types/subsystems/IO/CLI.service/CLIConnector.d.ts +21 -0
  91. package/dist/types/subsystems/IO/CLI.service/index.d.ts +4 -0
  92. package/dist/types/subsystems/IO/Log.service/LogConnector.d.ts +17 -0
  93. package/dist/types/subsystems/IO/Log.service/connectors/ConsoleLog.class.d.ts +12 -0
  94. package/dist/types/subsystems/IO/Log.service/index.d.ts +4 -0
  95. package/dist/types/subsystems/IO/NKV.service/NKVConnector.d.ts +33 -0
  96. package/dist/types/subsystems/IO/NKV.service/connectors/NKVRAM.class.d.ts +43 -0
  97. package/dist/types/subsystems/IO/NKV.service/connectors/NKVRedis.class.d.ts +27 -0
  98. package/dist/types/subsystems/IO/NKV.service/index.d.ts +4 -0
  99. package/dist/types/subsystems/IO/Router.service/RouterConnector.d.ts +11 -0
  100. package/dist/types/subsystems/IO/Router.service/connectors/ExpressRouter.class.d.ts +21 -0
  101. package/dist/types/subsystems/IO/Router.service/connectors/NullRouter.class.d.ts +12 -0
  102. package/dist/types/subsystems/IO/Router.service/index.d.ts +4 -0
  103. package/dist/types/subsystems/IO/Storage.service/SmythFS.class.d.ts +49 -0
  104. package/dist/types/subsystems/IO/Storage.service/StorageConnector.d.ts +30 -0
  105. package/dist/types/subsystems/IO/Storage.service/connectors/LocalStorage.class.d.ts +58 -0
  106. package/dist/types/subsystems/IO/Storage.service/connectors/S3Storage.class.d.ts +53 -0
  107. package/dist/types/subsystems/IO/Storage.service/index.d.ts +4 -0
  108. package/dist/types/subsystems/IO/VectorDB.service/VectorDBConnector.d.ts +41 -0
  109. package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +49 -0
  110. package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +50 -0
  111. package/dist/types/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.d.ts +52 -0
  112. package/dist/types/subsystems/IO/VectorDB.service/embed/BaseEmbedding.d.ts +53 -0
  113. package/dist/types/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.d.ts +16 -0
  114. package/dist/types/subsystems/IO/VectorDB.service/embed/index.d.ts +16 -0
  115. package/dist/types/subsystems/IO/VectorDB.service/index.d.ts +4 -0
  116. package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +125 -0
  117. package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +36 -0
  118. package/dist/types/subsystems/LLMManager/LLM.service/LLMConnector.d.ts +62 -0
  119. package/dist/types/subsystems/LLMManager/LLM.service/LLMCredentials.helper.d.ts +3 -0
  120. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.d.ts +68 -0
  121. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.d.ts +46 -0
  122. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Echo.class.d.ts +18 -0
  123. package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +57 -0
  124. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Groq.class.d.ts +55 -0
  125. package/dist/types/subsystems/LLMManager/LLM.service/connectors/OpenAI.class.d.ts +92 -0
  126. package/dist/types/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.d.ts +86 -0
  127. package/dist/types/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.d.ts +38 -0
  128. package/dist/types/subsystems/LLMManager/LLM.service/index.d.ts +5 -0
  129. package/dist/types/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.d.ts +36 -0
  130. package/dist/types/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.d.ts +39 -0
  131. package/dist/types/subsystems/LLMManager/ModelsProvider.service/index.d.ts +4 -0
  132. package/dist/types/subsystems/LLMManager/custom-models.d.ts +785 -0
  133. package/dist/types/subsystems/LLMManager/models.d.ts +2629 -0
  134. package/dist/types/subsystems/LLMManager/paramMappings.d.ts +69 -0
  135. package/dist/types/subsystems/MemoryManager/Cache.service/CacheConnector.d.ts +41 -0
  136. package/dist/types/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.d.ts +33 -0
  137. package/dist/types/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.d.ts +31 -0
  138. package/dist/types/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.d.ts +33 -0
  139. package/dist/types/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.d.ts +38 -0
  140. package/dist/types/subsystems/MemoryManager/Cache.service/index.d.ts +4 -0
  141. package/dist/types/subsystems/MemoryManager/LLMCache.d.ts +27 -0
  142. package/dist/types/subsystems/MemoryManager/LLMContext.d.ts +25 -0
  143. package/dist/types/subsystems/MemoryManager/RuntimeContext.d.ts +50 -0
  144. package/dist/types/subsystems/Security/AccessControl/ACL.class.d.ts +29 -0
  145. package/dist/types/subsystems/Security/AccessControl/AccessCandidate.class.d.ts +21 -0
  146. package/dist/types/subsystems/Security/AccessControl/AccessRequest.class.d.ts +13 -0
  147. package/dist/types/subsystems/Security/Account.service/AccountConnector.d.ts +27 -0
  148. package/dist/types/subsystems/Security/Account.service/connectors/AWSAccount.class.d.ts +19 -0
  149. package/dist/types/subsystems/Security/Account.service/connectors/DummyAccount.class.d.ts +19 -0
  150. package/dist/types/subsystems/Security/Account.service/connectors/JSONFileAccount.class.d.ts +25 -0
  151. package/dist/types/subsystems/Security/Account.service/index.d.ts +4 -0
  152. package/dist/types/subsystems/Security/Credentials.helper.d.ts +16 -0
  153. package/dist/types/subsystems/Security/ManagedVault.service/ManagedVaultConnector.d.ts +23 -0
  154. package/dist/types/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.d.ts +14 -0
  155. package/dist/types/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.d.ts +22 -0
  156. package/dist/types/subsystems/Security/ManagedVault.service/index.d.ts +4 -0
  157. package/dist/types/subsystems/Security/SecureConnector.class.d.ts +13 -0
  158. package/dist/types/subsystems/Security/Vault.service/Vault.helper.d.ts +5 -0
  159. package/dist/types/subsystems/Security/Vault.service/VaultConnector.d.ts +17 -0
  160. package/dist/types/subsystems/Security/Vault.service/connectors/HashicorpVault.class.d.ts +13 -0
  161. package/dist/types/subsystems/Security/Vault.service/connectors/JSONFileVault.class.d.ts +23 -0
  162. package/dist/types/subsystems/Security/Vault.service/connectors/NullVault.class.d.ts +16 -0
  163. package/dist/types/subsystems/Security/Vault.service/connectors/SecretsManager.class.d.ts +20 -0
  164. package/dist/types/subsystems/Security/Vault.service/index.d.ts +4 -0
  165. package/dist/types/types/ACL.types.d.ts +83 -0
  166. package/dist/types/types/AWS.types.d.ts +7 -0
  167. package/dist/types/types/Agent.types.d.ts +52 -0
  168. package/dist/types/types/AgentLogger.types.d.ts +16 -0
  169. package/dist/types/types/Cache.types.d.ts +1 -0
  170. package/dist/types/types/Common.types.d.ts +3 -0
  171. package/dist/types/types/LLM.types.d.ts +365 -0
  172. package/dist/types/types/Redis.types.d.ts +6 -0
  173. package/dist/types/types/SRE.types.d.ts +60 -0
  174. package/dist/types/types/Security.types.d.ts +16 -0
  175. package/dist/types/types/Storage.types.d.ts +3 -0
  176. package/dist/types/types/VectorDB.types.d.ts +66 -0
  177. package/dist/types/utils/base64.utils.d.ts +86 -0
  178. package/dist/types/utils/cli.utils.d.ts +20 -0
  179. package/dist/types/utils/data.utils.d.ts +17 -0
  180. package/dist/types/utils/date-time.utils.d.ts +3 -0
  181. package/dist/types/utils/general.utils.d.ts +75 -0
  182. package/dist/types/utils/index.d.ts +9 -0
  183. package/dist/types/utils/numbers.utils.d.ts +2 -0
  184. package/dist/types/utils/oauth.utils.d.ts +7 -0
  185. package/dist/types/utils/string.utils.d.ts +28 -0
  186. package/dist/types/utils/url.utils.d.ts +1 -0
  187. package/dist/types/utils/validation.utils.d.ts +25 -0
  188. package/package.json +117 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/config.ts","../src/constants.ts","../src/types/SRE.types.ts","../src/utils/general.utils.ts","../src/utils/date-time.utils.ts","../src/utils/string.utils.ts","../src/utils/base64.utils.ts","../src/utils/data.utils.ts","../src/utils/cli.utils.ts","../src/utils/numbers.utils.ts","../src/utils/validation.utils.ts","../src/helpers/Log.helper.ts","../src/Core/DummyConnector.ts","../src/helpers/LocalCache.helper.ts","../src/types/ACL.types.ts","../src/subsystems/Security/AccessControl/AccessRequest.class.ts","../src/subsystems/Security/AccessControl/AccessCandidate.class.ts","../src/Core/Connector.class.ts","../src/Core/SystemEvents.ts","../src/Core/ConnectorsService.ts","../src/subsystems/Security/Vault.service/Vault.helper.ts","../src/helpers/TemplateString.helper.ts","../src/subsystems/AgentManager/AgentLogger.class.ts","../src/subsystems/MemoryManager/RuntimeContext.ts","../src/subsystems/MemoryManager/LLMCache.ts","../src/subsystems/AgentManager/AgentRuntime.class.ts","../src/subsystems/AgentManager/OSResourceMonitor.ts","../src/subsystems/AgentManager/AgentSSE.class.ts","../src/subsystems/AgentManager/Agent.class.ts","../src/subsystems/AgentManager/AgentRequest.class.ts","../src/subsystems/AgentManager/EmbodimentSettings.class.ts","../src/subsystems/AgentManager/AgentSettings.class.ts","../src/Core/AgentProcess.helper.ts","../src/subsystems/Security/AccessControl/ACL.class.ts","../src/subsystems/Security/SecureConnector.class.ts","../src/subsystems/IO/Storage.service/StorageConnector.ts","../src/subsystems/MemoryManager/Cache.service/CacheConnector.ts","../src/helpers/JsonContent.helper.ts","../src/subsystems/IO/Storage.service/SmythFS.class.ts","../src/helpers/BinaryInput.helper.ts","../src/types/LLM.types.ts","../src/subsystems/AgentManager/Agent.helper.ts","../src/subsystems/LLMManager/LLM.inference.ts","../src/subsystems/MemoryManager/LLMContext.ts","../src/helpers/OpenApiParser.helper.ts","../src/Core/HookService.ts","../src/helpers/Conversation.helper.ts","../src/helpers/TypeChecker.helper.ts","../src/Components/Component.class.ts","../src/Components/AgentPlugin.class.ts","../src/Components/APIEndpoint.class.ts","../src/Components/APIOutput.class.ts","../src/subsystems/AgentManager/ForkedAgent.class.ts","../src/Components/Async.class.ts","../src/Components/Await.class.ts","../src/Components/Classifier.class.ts","../src/Components/ComponentHost.class.ts","../src/Components/DataSourceIndexer.class.ts","../src/Components/DataSourceCleaner.class.ts","../src/Components/DataSourceLookup.class.ts","../src/Components/FEncDec.class.ts","../src/Components/FHash.class.ts","../src/Components/FileStore.class.ts","../src/Components/ForEach.class.ts","../src/Components/FSign.class.ts","../src/Components/FSleep.class.ts","../src/Components/FTimestamp.class.ts","../src/Components/GenAILLM.class.ts","../src/Components/GPTPlugin.class.ts","../src/Components/HuggingFace.class.ts","../src/Components/Image/imageSettings.config.ts","../src/subsystems/Security/Credentials.helper.ts","../src/Components/ImageGenerator.class.ts","../src/Components/PromptGenerator.class.ts","../src/Components/APICall/parseHeaders.ts","../src/Components/APICall/parseUrl.ts","../src/Components/APICall/parseData.ts","../src/Components/APICall/parseProxy.ts","../src/Components/APICall/mimeTypeCategories.ts","../src/Components/APICall/ArrayBufferResponse.helper.ts","../src/Components/APICall/AccessTokenManager.ts","../src/Components/APICall/OAuth.helper.ts","../src/Components/APICall/APICall.class.ts","../src/Components/JSONFilter.class.ts","../src/Components/LogicAND.class.ts","../src/Components/LogicOR.class.ts","../src/Components/LogicXOR.class.ts","../src/Components/LogicAtLeast.class.ts","../src/Components/LogicAtMost.class.ts","../src/Components/LLMAssistant.class.ts","../src/Components/ScrapflyWebScrape.class.ts","../src/Components/TavilyWebSearch.class.ts","../src/Components/MCPClient.class.ts","../src/Components/index.ts","../src/helpers/S3Cache.helper.ts","../src/subsystems/IO/Storage.service/connectors/S3Storage.class.ts","../src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts","../src/subsystems/IO/Storage.service/index.ts","../src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts","../src/subsystems/LLMManager/LLM.service/LLMConnector.ts","../src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts","../src/subsystems/LLMManager/LLM.helper.ts","../src/subsystems/LLMManager/LLM.service/connectors/OpenAI.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts","../src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts","../src/subsystems/LLMManager/LLM.service/index.ts","../src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts","../src/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.ts","../src/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.ts","../src/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.ts","../src/subsystems/MemoryManager/Cache.service/index.ts","../src/subsystems/Security/Vault.service/VaultConnector.ts","../src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts","../src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts","../src/subsystems/Security/Vault.service/connectors/NullVault.class.ts","../src/subsystems/Security/Vault.service/index.ts","../src/subsystems/Security/Account.service/AccountConnector.ts","../src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts","../src/subsystems/Security/Account.service/connectors/AWSAccount.class.ts","../src/subsystems/Security/Account.service/connectors/JSONFileAccount.class.ts","../src/subsystems/Security/Account.service/index.ts","../src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts","../src/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.ts","../src/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.ts","../src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts","../src/subsystems/AgentManager/AgentData.service/index.ts","../src/subsystems/IO/VectorDB.service/VectorDBConnector.ts","../src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts","../src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts","../src/subsystems/IO/VectorDB.service/embed/index.ts","../src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts","../src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts","../src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts","../src/subsystems/IO/VectorDB.service/index.ts","../src/subsystems/IO/CLI.service/CLIConnector.ts","../src/subsystems/IO/CLI.service/index.ts","../src/subsystems/IO/NKV.service/NKVConnector.ts","../src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts","../src/subsystems/IO/NKV.service/connectors/NKVRAM.class.ts","../src/subsystems/IO/NKV.service/index.ts","../src/subsystems/IO/Router.service/RouterConnector.ts","../src/subsystems/IO/Router.service/connectors/ExpressRouter.class.ts","../src/subsystems/IO/Router.service/connectors/NullRouter.class.ts","../src/subsystems/IO/Router.service/index.ts","../src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts","../src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts","../src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts","../src/subsystems/Security/ManagedVault.service/index.ts","../src/subsystems/IO/Log.service/LogConnector.ts","../src/subsystems/IO/Log.service/connectors/ConsoleLog.class.ts","../src/subsystems/IO/Log.service/index.ts","../src/subsystems/AgentManager/Component.service/ComponentConnector.ts","../src/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.ts","../src/subsystems/AgentManager/Component.service/index.ts","../src/subsystems/LLMManager/models.ts","../src/subsystems/LLMManager/custom-models.ts","../src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts","../src/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.ts","../src/subsystems/LLMManager/ModelsProvider.service/index.ts","../src/subsystems/ComputeManager/Code.service/CodeConnector.ts","../src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts","../src/subsystems/ComputeManager/Code.service/index.ts","../src/Core/boot.ts","../src/Core/SmythRuntime.class.ts","../src/helpers/SmythURI.helper.ts","../src/subsystems/Security/Vault.service/connectors/HashicorpVault.class.ts"],"sourcesContent":["import dotenv from 'dotenv';\r\ndotenv.config();\r\n//FIXME : this is a legacy structure from Smyth SaaS we need to convert it to a Service/Connector structure\r\nconst config = {\r\n env: {\r\n LOG_LEVEL: process.env.LOG_LEVEL || 'none',\r\n LOG_FILTER: process.env.LOG_FILTER || '',\r\n NODE_ENV: process.env?.NODE_ENV,\r\n },\r\n agent: {\r\n ENDPOINT_PREFIX: '/api',\r\n },\r\n};\r\n\r\nexport default config;\r\n","// supported request methods\r\nexport const REQUEST_METHODS = ['GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS'];\r\n\r\nexport const REQUEST_CONTENT_TYPES = {\r\n none: 'none',\r\n urlEncodedFormData: 'application/x-www-form-urlencoded',\r\n multipartFormData: 'multipart/form-data',\r\n json: 'application/json',\r\n text: 'text/plain',\r\n xml: 'application/xml',\r\n binary: 'binary',\r\n};\r\n\r\nexport enum EMBODIMENT_TYPES {\r\n ChatBot = 'chatBot',\r\n ChatGPT = 'chatGPT',\r\n}\r\n\r\nexport const ERR_MSG_INVALID_IMAGE_SOURCE =\r\n 'Please provide a valid Image Source. Supported image sources are: HTTP(S) URL, Base64 string, Data URL, Output Image from other component(s).';\r\nexport const ERR_MSG_INVALID_BINARY =\r\n 'Please provide a valid data that is either a Blob, SmythFileObject (Binary Output from any Component), ArrayBuffer, Buffer, Base64 string, Data URL, or HTTP(s) URL';\r\nexport const ERR_MSG_MAX_DEPTH = 'The maximum depth has been exceeded for the provided array or object.';\r\nexport const ERR_MSG_MAX_ARRAY_SIZE = 'The maximum array size has been exceeded for the provided array.';\r\nexport const ERR_MSG_MAX_OBJECT_SIZE = 'The maximum object size has been exceeded for the provided object.';\r\n\r\nexport const MAX_DEPTH = 10;\r\nexport const MAX_OBJECT_SIZE = 1000;\r\nexport const MAX_ARRAY_SIZE = 1000;\r\n\r\nexport const MAX_FILE_SIZE = 10 * 1024 * 1024; // 10MB\r\n\r\nexport const MAX_FILE_COUNT = 10;\r\n\r\n// Default maximum number of tokens allowed for LLM\r\nexport const DEFAULT_MAX_TOKENS_FOR_LLM = 2048;\r\n\r\n// life cycle tag for daily purge of s3 objects\r\nexport const S3_DAILY_PURGE_LIFECYCLE_TAG = 'ExpirationPolicy=DeleteDaily';\r\nexport const S3_WEEKLY_PURGE_LIFECYCLE_TAG = 'ExpirationPolicy=DeleteWeekly';\r\nexport const S3_MONTHLY_PURGE_LIFECYCLE_TAG = 'ExpirationPolicy=DeleteMonthly';\r\n\r\nexport const TOOL_USE_DEFAULT_MODEL = 'gpt-4o-mini';\r\n\r\nexport const COMP_NAMES = {\r\n apiCall: 'APICall',\r\n code: 'Code',\r\n llmPrompt: 'PromptGenerator',\r\n visionLLM: 'VisionLLM',\r\n};\r\n\r\nexport const JSON_RESPONSE_INSTRUCTION = `\r\nRespond ONLY with a valid, parsable JSON object. Follow these strict guidelines:\r\n1. The response must begin with '{' and end with '}'.\r\n2. Use double quotes for all keys and string values.\r\n3. Do not include any explanations, markdown, or text outside the JSON object.\r\n4. Do not use newlines or indentation within the JSON structure.\r\n5. For single-key responses, use the format: {\"result\": \"your content here\"}\r\n6. For multiple keys, use: {\"key1\": \"value1\", \"key2\": \"value2\", ...}\r\n\r\nExample of a valid response:\r\n{\"result\": \"This is a valid JSON response without any extra text.\"}\r\n`;\r\n\r\nexport const SUPPORTED_MIME_TYPES_MAP = {\r\n OpenAI: {\r\n image: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/gif'],\r\n imageGen: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp'],\r\n document: ['application/pdf'],\r\n },\r\n TogetherAI: {\r\n image: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/gif'], // Same as OpenAI\r\n },\r\n Anthropic: {\r\n image: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/gif'],\r\n },\r\n GoogleAI: {\r\n image: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/heic', 'image/heif'],\r\n video: [\r\n 'video/mp4',\r\n 'video/mpeg',\r\n 'video/mov',\r\n 'video/avi',\r\n 'video/x-msvideo', // mimetype for .avi files\r\n 'video/x-flv',\r\n 'video/mpg',\r\n 'video/webm',\r\n 'video/wmv',\r\n 'video/3gpp',\r\n ],\r\n audio: ['audio/wav', 'audio/mp3', 'audio/mpeg', 'audio/aiff', 'audio/aac', 'audio/ogg', 'audio/flac'],\r\n document: [\r\n 'application/pdf',\r\n 'application/x-javascript',\r\n 'application/x-typescript',\r\n 'application/x-python-code',\r\n 'application/json',\r\n 'application/rtf',\r\n 'text/plain',\r\n 'text/html',\r\n 'text/css',\r\n 'text/javascript',\r\n 'text/x-typescript',\r\n 'text/csv',\r\n 'text/markdown',\r\n 'text/x-python',\r\n 'text/xml',\r\n 'text/rtf',\r\n ],\r\n },\r\n Groq: {\r\n image: ['image/png', 'image/jpeg', 'image/jpg', 'image/webp', 'image/gif'],\r\n },\r\n};\r\n\r\nexport const DEFAULT_SMYTHOS_LLM_PROVIDERS_SETTINGS = {\r\n openai: { enabled: true },\r\n anthropic: { enabled: true },\r\n googleai: { enabled: true },\r\n togetherai: { enabled: true },\r\n groq: { enabled: true },\r\n xai: { enabled: true },\r\n};\r\n\r\nexport const BUILT_IN_MODEL_PREFIX = 'smythos/';\r\n","import { AgentDataService } from '@sre/AgentManager/AgentData.service';\r\nimport { CLIService } from '@sre/IO/CLI.service';\r\nimport { NKVService } from '@sre/IO/NKV.service';\r\nimport { StorageService } from '@sre/IO/Storage.service';\r\nimport { VectorDBService } from '@sre/IO/VectorDB.service';\r\nimport { LLMService } from '@sre/LLMManager/LLM.service';\r\nimport { CacheService } from '@sre/MemoryManager/Cache.service';\r\nimport { AccountService } from '@sre/Security/Account.service';\r\nimport { VaultService } from '@sre/Security/Vault.service';\r\nimport { RouterService } from '@sre/IO/Router.service';\r\nimport { ManagedVaultService } from '@sre/Security/ManagedVault.service';\r\nimport { LogService } from '@sre/IO/Log.service';\r\nimport { ComponentService } from '@sre/AgentManager/Component.service';\r\nimport { ModelsProviderService } from '@sre/LLMManager/ModelsProvider.service';\r\nimport { CodeService } from '@sre/ComputeManager/Code.service';\r\n\r\nexport type TServiceRegistry = {\r\n Storage?: StorageService;\r\n VectorDB?: VectorDBService;\r\n Cache?: CacheService;\r\n LLM?: LLMService;\r\n Vault?: VaultService;\r\n Account?: AccountService;\r\n AgentData?: AgentDataService;\r\n CLI?: CLIService;\r\n NKV?: NKVService;\r\n Router?: RouterService;\r\n ManagedVault?: ManagedVaultService;\r\n Log?: LogService;\r\n Component?: ComponentService;\r\n ModelsProvider?: ModelsProviderService;\r\n Code?: CodeService;\r\n};\r\n\r\nexport enum TConnectorService {\r\n Storage = 'Storage',\r\n VectorDB = 'VectorDB',\r\n Cache = 'Cache',\r\n LLM = 'LLM',\r\n Vault = 'Vault',\r\n Account = 'Account',\r\n AgentData = 'AgentData',\r\n CLI = 'CLI',\r\n NKV = 'NKV',\r\n Router = 'Router',\r\n ManagedVault = 'ManagedVault',\r\n Log = 'Log',\r\n Component = 'Component',\r\n ModelsProvider = 'ModelsProvider',\r\n Code = 'Code',\r\n}\r\n\r\nexport type SREConnectorConfig = {\r\n Connector: string;\r\n Id?: string;\r\n Default?: boolean;\r\n Settings?: {\r\n [hashedOwnerKey: string]: any;\r\n };\r\n};\r\n\r\nexport type SREConfig = {\r\n [key in TConnectorService]?: SREConnectorConfig[] | SREConnectorConfig | {};\r\n};\r\n","import { LogHelper } from '@sre/helpers/Log.helper';\r\nimport pLimit from 'p-limit';\r\nexport function uid() {\r\n return (Date.now() + Math.random()).toString(36).replace('.', '').toUpperCase();\r\n}\r\n\r\n/**\r\n * this function is used to check if a class is a subclass of another class\r\n * @param subClass\r\n * @param superClass\r\n * @returns\r\n */\r\nexport function isSubclassOf(subClass: any, superClass: any): boolean {\r\n if (typeof subClass !== 'function' || typeof superClass !== 'function') {\r\n return false;\r\n }\r\n\r\n let prototype = Object.getPrototypeOf(subClass.prototype);\r\n let depth = 10;\r\n\r\n while (prototype && depth >= 0) {\r\n if (prototype === superClass.prototype) {\r\n return true;\r\n }\r\n prototype = Object.getPrototypeOf(prototype);\r\n depth++;\r\n }\r\n\r\n return false;\r\n}\r\n\r\n/**\r\n * Processes an array of tasks concurrently with a specified concurrency limit.\r\n *\r\n * @template T - The type of the result returned by each task.\r\n *\r\n * @param {(() => Promise<T>)[]} tasks - An array of functions that return promises.\r\n * Each function represents a task to be processed.\r\n * @param {number} [maxConcurrentTasks=10] - The maximum number of concurrent tasks.\r\n *\r\n * @returns {Promise<T[]>} - A promise that resolves to an array of results.\r\n * Only successfully fulfilled promises are included in the result array.\r\n *\r\n * @throws {TypeError} - Throws an error if the tasks parameter is not an array of functions.\r\n *\r\n * @example\r\n * const tasks = [\r\n * () => await processFile('file1.txt'),\r\n * () => await processFile('file2.txt'),\r\n * () => await processFile('file3.txt'),\r\n * ];\r\n *\r\n * const maxConcurrentTasks = 2;\r\n *\r\n * processWithConcurrencyLimit(tasks, maxConcurrentTasks)\r\n * .then(results => console.log(results)) // Array of results from the fulfilled promises\r\n * .catch(error => console.error(error));\r\n *\r\n * @note Currently, this function ignores tasks that fail to process.\r\n * Only successfully fulfilled promises are included in the result array.\r\n * To improve this behavior, we could add an option to control whether to exit the function if a task fails.\r\n */\r\nexport async function processWithConcurrencyLimit<T>(tasks: (() => Promise<T>)[], maxConcurrentTasks: number = 10): Promise<T[]> {\r\n const limit = pLimit(maxConcurrentTasks);\r\n\r\n const limitedTasks = tasks.map((task) => limit(task));\r\n\r\n const results = await Promise.allSettled(limitedTasks);\r\n\r\n // Filter for successfully fulfilled promises and extract their values\r\n const validResults = results.flatMap((result) => (result.status === 'fulfilled' ? [result.value] : [])).filter(Boolean);\r\n\r\n return validResults;\r\n}\r\n\r\nexport const detectURLSourceType = (url: string) => {\r\n const urlObj = new URL(url);\r\n const ext = urlObj.pathname.split('.').pop();\r\n\r\n switch (ext) {\r\n case 'pdf':\r\n return 'PDF';\r\n case 'xml':\r\n return 'SITEMAP';\r\n case 'html':\r\n case 'htm':\r\n case 'txt':\r\n return 'WEBPAGE';\r\n case 'doc':\r\n case 'docx':\r\n return 'WORD';\r\n default:\r\n return 'WEBPAGE';\r\n }\r\n};\r\n\r\n/**\r\n * This function checks if a string is a valid JSON string.\r\n * @param str\r\n * @returns\r\n */\r\nexport const isJSONString = (str: string): boolean => {\r\n try {\r\n return typeof str === 'string' && !!JSON.parse(str);\r\n } catch {\r\n return false;\r\n }\r\n};\r\n\r\nexport class ControlledPromise<T> extends Promise<T> {\r\n private _isSettled = false;\r\n public readonly isSettled: () => boolean;\r\n public resolve!: (value: T) => void;\r\n public reject!: (reason?: any) => void;\r\n\r\n constructor(executor: (resolve: (value: T) => void, reject: (reason?: any) => void, isSettled: () => boolean) => void) {\r\n let internalResolve!: (value: T) => void;\r\n let internalReject!: (reason?: any) => void;\r\n let _isSettled = false;\r\n\r\n super((resolve, reject) => {\r\n internalResolve = (value: T) => {\r\n if (!_isSettled) {\r\n _isSettled = true;\r\n resolve(value);\r\n }\r\n };\r\n\r\n internalReject = (reason?: any) => {\r\n if (!_isSettled) {\r\n _isSettled = true;\r\n reject(reason);\r\n }\r\n };\r\n });\r\n\r\n this.resolve = internalResolve;\r\n this.reject = internalReject;\r\n this.isSettled = () => _isSettled;\r\n\r\n // run user executor with the third isSettled arg\r\n executor(this.resolve, this.reject, this.isSettled);\r\n }\r\n}\r\n\r\n/**\r\n * This function ensures that a function is called at most once per wait time.\r\n * @param func - The function to debounce\r\n * @param wait - The wait time in milliseconds\r\n * @param options - The options object : leading means the function will be called immediately if it's called within the wait time,\r\n * trailing means the function will be called after the wait time has passed. maxWait is the maximum time to wait before calling the function.\r\n * if maxWait is provided, the function will be called after the maxWait time has passed.\r\n *\r\n * @returns\r\n */\r\nexport function debounce(func: Function, wait: number, options: { leading: boolean; trailing: boolean; maxWait?: number }) {\r\n let timeout: NodeJS.Timeout | null = null;\r\n let lastCall = 0;\r\n\r\n return function (this: any, ...args: any[]) {\r\n const now = Date.now();\r\n const later = () => {\r\n timeout = null;\r\n lastCall = now;\r\n func.apply(this, args);\r\n };\r\n\r\n if (timeout) {\r\n clearTimeout(timeout);\r\n }\r\n\r\n if (options.leading && !timeout) {\r\n func.apply(this, args);\r\n lastCall = now;\r\n }\r\n\r\n if (options.maxWait && now - lastCall >= options.maxWait) {\r\n func.apply(this, args);\r\n lastCall = now;\r\n }\r\n\r\n timeout = setTimeout(later, wait);\r\n };\r\n}\r\n\r\n/**\r\n * Extracts and formats the last N calls from the stack trace in a user-friendly way\r\n */\r\nexport function getFormattedStackTrace(limit: number = 3, skip: number = 0): string[] {\r\n const stack = new Error().stack;\r\n if (!stack) return [];\r\n\r\n const stackLines = stack.split('\\n');\r\n // Skip the first few lines (Error message, this function, and the caller)\r\n const relevantLines = stackLines.slice(3 + skip);\r\n\r\n const formattedCalls: string[] = [];\r\n\r\n const length = Math.min(limit, relevantLines.length);\r\n for (let i = 0; i < length; i++) {\r\n const line = relevantLines[i].trim();\r\n if (!line) continue;\r\n\r\n // Parse different stack trace formats\r\n let match = line.match(/at\\s+(.+?)\\s+\\((.+?):(\\d+):(\\d+)\\)/); // at functionName (file:line:col)\r\n if (!match) {\r\n match = line.match(/at\\s+(.+?):(\\d+):(\\d+)/); // at file:line:col\r\n if (match) {\r\n const [, filePath, lineNum] = match;\r\n const fileName = filePath.split(/[/\\\\]/).pop() || filePath;\r\n formattedCalls.push(` ${fileName}:${lineNum}`);\r\n }\r\n } else {\r\n const [, functionName, filePath, lineNum] = match;\r\n const fileName = filePath.split(/[/\\\\]/).pop() || filePath;\r\n const cleanFunctionName = functionName.includes('.') ? functionName.split('.').pop() : functionName;\r\n formattedCalls.push(`${i < length - 1 ? '├' : '└'} ${cleanFunctionName}() in ${fileName} (${filePath}:${lineNum})`);\r\n }\r\n\r\n // Fallback for other formats\r\n if (!match && line.includes('at ')) {\r\n const cleanLine = line.replace('at ', '').trim();\r\n formattedCalls.push(` ${cleanLine}`);\r\n }\r\n }\r\n\r\n return formattedCalls;\r\n}\r\n\r\nexport function printStackTrace(logger: LogHelper | Console, limit: number = 3, skip: number = 0) {\r\n const stackTrace = getFormattedStackTrace(limit, skip);\r\n if (stackTrace.length > 0) {\r\n logger.debug('Call trace:');\r\n stackTrace.forEach((call, index) => {\r\n logger.debug(` ${call}`);\r\n });\r\n }\r\n}\r\n","export function getCurrentFormattedDate() {\r\n const date = new Date();\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-based\r\n const day = String(date.getDate()).padStart(2, '0');\r\n const hours = String(date.getHours()).padStart(2, '0');\r\n const minutes = String(date.getMinutes()).padStart(2, '0');\r\n const seconds = String(date.getSeconds()).padStart(2, '0');\r\n return `${year}-${month}-${day}-${hours}-${minutes}-${seconds}`;\r\n}\r\n\r\nexport function getDayFormattedDate() {\r\n const date = new Date();\r\n const year = date.getFullYear();\r\n const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are 0-based\r\n const day = String(date.getDate()).padStart(2, '0');\r\n return `${year}-${month}-${day}`;\r\n}\r\n\r\nexport function delay(ms) {\r\n return new Promise((r) => setTimeout(r, ms));\r\n}\r\n","/**\r\n * perform a replace operation on a string asynchronously\r\n * @param str\r\n * @param regex\r\n * @param asyncFn\r\n * @returns\r\n */\r\nexport async function asyncReplace(str, regex, asyncFn) {\r\n const matches = [];\r\n let match;\r\n\r\n // Find all matches and store them in an array\r\n while ((match = regex.exec(str)) !== null) {\r\n matches.push(match);\r\n }\r\n\r\n // Process each match asynchronously\r\n const replacements = await Promise.all(\r\n matches.map(async (match) => {\r\n // Call the async function with all match groups\r\n return asyncFn(...match);\r\n }),\r\n );\r\n\r\n // Reassemble the string with replacements\r\n let result = '';\r\n let lastIndex = 0;\r\n\r\n matches.forEach((match, index) => {\r\n result += str.slice(lastIndex, match.index) + replacements[index];\r\n lastIndex = match.index + match[0].length;\r\n });\r\n\r\n // Append the remaining part of the string\r\n result += str.slice(lastIndex);\r\n\r\n return result;\r\n}\r\n\r\nexport function isValidString(str: string): boolean {\r\n return str && typeof str === 'string';\r\n}\r\n\r\nconst isValidNumber = (str: string): boolean => {\r\n const num = parseFloat(str);\r\n return !isNaN(num) && num <= Number.MAX_SAFE_INTEGER && num >= Number.MIN_SAFE_INTEGER && num.toString() === str.trim();\r\n};\r\n\r\n/**\r\n * The function parseJson() won't parse the data for property values.\r\n * For instance, if you have '{\"a\": \"1\",\"b\": \"true\"}', it will be parsed as {a: '1', b: 'true'}. That's why we parse the appropriate data type for property values\r\n * so that the data will be parsed as {a: 1, b: true}\r\n * @param data\r\n * @returns\r\n */\r\nexport function convertStringToRespectiveType(data: any): any {\r\n if (data === null || data === undefined) return data;\r\n\r\n if (typeof data !== 'object') {\r\n // If it's a string, perform conversions\r\n if (typeof data === 'string') {\r\n if (data.toLowerCase() === 'true') {\r\n return true;\r\n } else if (data.toLowerCase() === 'false') {\r\n return false;\r\n } else if (isValidNumber(data)) {\r\n return Number(data);\r\n } else if (data.toLowerCase() === 'null') {\r\n return null;\r\n } else if (data.toLowerCase() === 'undefined') {\r\n return undefined;\r\n }\r\n }\r\n\r\n return data;\r\n }\r\n\r\n // If it's an array, map over it and parse each item\r\n if (Array.isArray(data)) {\r\n return data.map((item) => convertStringToRespectiveType(item));\r\n }\r\n\r\n // If it's an object, map over its properties and parse each one\r\n return Object.fromEntries(Object.entries(data).map(([key, value]) => [key, convertStringToRespectiveType(value)]));\r\n}\r\n\r\nexport const kebabToCamel = (input) => {\r\n if (!input || typeof input !== 'string') return input;\r\n\r\n return input.replace(/-([a-z])/g, function (match, group) {\r\n return group.toUpperCase();\r\n });\r\n};\r\n\r\nexport const kebabToCapitalize = (input) => {\r\n if (!input || typeof input !== 'string') return input;\r\n\r\n return input\r\n .split('-')\r\n .map((word) => word.charAt(0).toUpperCase() + word.slice(1))\r\n .join(' ');\r\n};\r\n\r\n/**\r\n * This function reads a string and tries to identify the mimetype (e.g. text/plain, application/json, application/xml ...)\r\n * @param input\r\n */\r\nexport const identifyMimetypeFromString = (input: string) => {\r\n // Return null if input is not a string\r\n if (typeof input !== 'string') {\r\n return '';\r\n }\r\n\r\n // Return null for empty strings\r\n if (!input.trim()) {\r\n return '';\r\n }\r\n\r\n const trimmedInput = input.trim();\r\n\r\n // Check for JSON\r\n if ((trimmedInput.startsWith('{') && trimmedInput.endsWith('}')) || (trimmedInput.startsWith('[') && trimmedInput.endsWith(']'))) {\r\n try {\r\n JSON.parse(trimmedInput);\r\n return 'application/json';\r\n } catch {\r\n // Not valid JSON, continue checking\r\n }\r\n }\r\n\r\n // Check for XML\r\n if (trimmedInput.startsWith('<') && trimmedInput.endsWith('>')) {\r\n // More specific XML patterns\r\n if (trimmedInput.match(/^<\\?xml\\s/i) || trimmedInput.match(/^<[a-zA-Z][^>]*>.*<\\/[a-zA-Z][^>]*>$/s)) {\r\n return 'application/xml';\r\n }\r\n\r\n // Check for HTML\r\n if (\r\n trimmedInput.match(/^<!DOCTYPE\\s+html/i) ||\r\n trimmedInput.match(/<html[^>]*>/i) ||\r\n trimmedInput.match(/<head[^>]*>/i) ||\r\n trimmedInput.match(/<body[^>]*>/i) ||\r\n trimmedInput.match(/<div[^>]*>/i) ||\r\n trimmedInput.match(/<p[^>]*>/i)\r\n ) {\r\n return 'text/html';\r\n }\r\n\r\n // Check for SVG\r\n if (trimmedInput.match(/<svg[^>]*>/i)) {\r\n return 'image/svg+xml';\r\n }\r\n\r\n // Generic XML if it has XML structure\r\n return 'application/xml';\r\n }\r\n\r\n // Check for CSS\r\n if (trimmedInput.match(/^[^{]*\\{[^}]*\\}/s) || trimmedInput.match(/@(import|media|charset|keyframes|font-face)/i)) {\r\n return 'text/css';\r\n }\r\n\r\n // Check for JavaScript\r\n if (\r\n trimmedInput.match(/^(function\\s+\\w+|var\\s+\\w+|let\\s+\\w+|const\\s+\\w+|class\\s+\\w+)/i) ||\r\n trimmedInput.match(/(console\\.log|document\\.|window\\.|require\\(|import\\s+)/i) ||\r\n trimmedInput.match(/=>\\s*{|function\\s*\\(/)\r\n ) {\r\n return 'application/javascript';\r\n }\r\n\r\n // Check for YAML\r\n if (trimmedInput.match(/^---\\s*$/m) || trimmedInput.match(/^[a-zA-Z_][a-zA-Z0-9_]*:\\s*[^\\n]+$/m) || trimmedInput.match(/^\\s*-\\s+[^\\n]+$/m)) {\r\n return 'application/yaml';\r\n }\r\n\r\n // Check for CSV\r\n const lines = trimmedInput.split('\\n');\r\n if (lines.length > 1) {\r\n const firstLine = lines[0];\r\n const hasCommas = firstLine.includes(',');\r\n const hasSemicolons = firstLine.includes(';');\r\n const hasTabs = firstLine.includes('\\t');\r\n\r\n if (hasCommas || hasSemicolons || hasTabs) {\r\n // Check if multiple lines have similar delimiter patterns\r\n const delimiter = hasCommas ? ',' : hasSemicolons ? ';' : '\\t';\r\n const firstLineFields = firstLine.split(delimiter).length;\r\n\r\n let csvLikeLines = 0;\r\n for (let i = 0; i < Math.min(lines.length, 5); i++) {\r\n const fieldsCount = lines[i].split(delimiter).length;\r\n if (fieldsCount === firstLineFields && fieldsCount > 1) {\r\n csvLikeLines++;\r\n }\r\n }\r\n\r\n if (csvLikeLines >= Math.min(lines.length, 3)) {\r\n return 'text/csv';\r\n }\r\n }\r\n }\r\n\r\n // Check for Markdown\r\n if (\r\n trimmedInput.match(/^#+\\s+/m) ||\r\n trimmedInput.match(/^\\*\\s+/m) ||\r\n trimmedInput.match(/^-\\s+/m) ||\r\n trimmedInput.match(/\\*\\*[^*]+\\*\\*/g) ||\r\n trimmedInput.match(/\\[[^\\]]+\\]\\([^)]+\\)/g)\r\n ) {\r\n return 'text/markdown';\r\n }\r\n\r\n // Check for SQL\r\n if (trimmedInput.match(/^\\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|DROP|ALTER|GRANT|REVOKE)\\s+/i)) {\r\n return 'application/sql';\r\n }\r\n\r\n // Default to plain text\r\n return 'text/plain';\r\n};\r\n\r\nexport function chunkText(\r\n text: string,\r\n {\r\n chunkSize = 4000,\r\n chunkOverlap = 500,\r\n }: {\r\n chunkSize?: number;\r\n chunkOverlap?: number;\r\n } = {},\r\n): string[] {\r\n const textSplitter = new RecursiveTextSplitter({\r\n chunkSize,\r\n chunkOverlap,\r\n });\r\n let output = textSplitter.splitText(text);\r\n\r\n return output;\r\n}\r\nclass TextSplitter {\r\n private chunkSize: number;\r\n private chunkOverlap: number;\r\n private separators: string[] = ['\\n\\n', '\\n', ' ', ''];\r\n private keepSeparator: boolean = true;\r\n\r\n constructor({\r\n chunkSize = 1000,\r\n chunkOverlap = 200,\r\n separators,\r\n keepSeparator,\r\n }: {\r\n chunkSize?: number;\r\n chunkOverlap?: number;\r\n separators?: string[];\r\n keepSeparator?: boolean;\r\n } = {}) {\r\n this.chunkSize = chunkSize;\r\n this.chunkOverlap = chunkOverlap;\r\n\r\n if (separators) {\r\n this.separators = separators;\r\n }\r\n\r\n if (keepSeparator !== undefined) {\r\n this.keepSeparator = keepSeparator;\r\n }\r\n\r\n if (this.chunkOverlap >= this.chunkSize) {\r\n throw new Error('Cannot have chunkOverlap >= chunkSize');\r\n }\r\n }\r\n\r\n public splitText(text: string): string[] {\r\n return this._splitText(text, this.separators);\r\n }\r\n\r\n private _splitText(text: string, separators: string[]): string[] {\r\n const finalChunks: string[] = [];\r\n\r\n // Get appropriate separator to use\r\n let separator: string = separators[separators.length - 1];\r\n let newSeparators: string[] | undefined;\r\n\r\n for (let i = 0; i < separators.length; i += 1) {\r\n const s = separators[i];\r\n if (s === '') {\r\n separator = s;\r\n break;\r\n }\r\n if (text.includes(s)) {\r\n separator = s;\r\n newSeparators = separators.slice(i + 1);\r\n break;\r\n }\r\n }\r\n\r\n // Split the text using the identified separator\r\n const splits = this.splitOnSeparator(text, separator);\r\n\r\n // Process splits, recursively splitting longer texts\r\n let goodSplits: string[] = [];\r\n const _separator = this.keepSeparator ? '' : separator;\r\n\r\n for (const s of splits) {\r\n if (this.lengthFunction(s) < this.chunkSize) {\r\n goodSplits.push(s);\r\n } else {\r\n if (goodSplits.length) {\r\n const mergedText = this.mergeSplits(goodSplits, _separator);\r\n finalChunks.push(...mergedText);\r\n goodSplits = [];\r\n }\r\n\r\n if (!newSeparators) {\r\n finalChunks.push(s);\r\n } else {\r\n const otherInfo = this._splitText(s, newSeparators);\r\n finalChunks.push(...otherInfo);\r\n }\r\n }\r\n }\r\n\r\n if (goodSplits.length) {\r\n const mergedText = this.mergeSplits(goodSplits, _separator);\r\n finalChunks.push(...mergedText);\r\n }\r\n\r\n return finalChunks;\r\n }\r\n\r\n private splitOnSeparator(text: string, separator: string): string[] {\r\n let splits: string[];\r\n\r\n if (separator) {\r\n if (this.keepSeparator) {\r\n const regexEscapedSeparator = separator.replace(/[/\\-\\\\^$*+?.()|[\\]{}]/g, '\\\\$&');\r\n splits = text.split(new RegExp(`(?=${regexEscapedSeparator})`));\r\n } else {\r\n splits = text.split(separator);\r\n }\r\n } else {\r\n splits = text.split('');\r\n }\r\n\r\n return splits.filter((s) => s !== '');\r\n }\r\n\r\n private lengthFunction(text: string): number {\r\n return text.length;\r\n }\r\n\r\n private joinDocs(docs: string[], separator: string): string | null {\r\n const text = docs.join(separator).trim();\r\n return text === '' ? null : text;\r\n }\r\n\r\n private mergeSplits(splits: string[], separator: string): string[] {\r\n const docs: string[] = [];\r\n const currentDoc: string[] = [];\r\n let total = 0;\r\n\r\n for (const d of splits) {\r\n const _len = this.lengthFunction(d);\r\n\r\n if (total + _len + currentDoc.length * separator.length > this.chunkSize) {\r\n if (total > this.chunkSize) {\r\n console.warn(`Created a chunk of size ${total}, which is longer than the specified ${this.chunkSize}`);\r\n }\r\n\r\n if (currentDoc.length > 0) {\r\n const doc = this.joinDocs(currentDoc, separator);\r\n if (doc !== null) {\r\n docs.push(doc);\r\n }\r\n\r\n // Keep popping if conditions are met\r\n while (total > this.chunkOverlap || (total + _len + currentDoc.length * separator.length > this.chunkSize && total > 0)) {\r\n total -= this.lengthFunction(currentDoc[0]);\r\n currentDoc.shift();\r\n }\r\n }\r\n }\r\n\r\n currentDoc.push(d);\r\n total += _len;\r\n }\r\n\r\n const doc = this.joinDocs(currentDoc, separator);\r\n if (doc !== null) {\r\n docs.push(doc);\r\n }\r\n\r\n return docs;\r\n }\r\n}\r\n\r\nclass RecursiveTextSplitter extends TextSplitter {\r\n constructor({\r\n chunkSize = 1000,\r\n chunkOverlap = 200,\r\n separators = ['\\n\\n', '\\n', ' ', ''],\r\n keepSeparator = true,\r\n }: {\r\n chunkSize?: number;\r\n chunkOverlap?: number;\r\n separators?: string[];\r\n keepSeparator?: boolean;\r\n } = {}) {\r\n super({ chunkSize, chunkOverlap, separators, keepSeparator });\r\n }\r\n}\r\n","import { fileTypeFromBuffer } from 'file-type';\r\nimport { isValidString } from './string.utils';\r\nimport { MAX_FILE_SIZE } from '@sre/constants';\r\n\r\n/**\r\n * This function converts a text string to a base64 URL.\r\n * @param text\r\n * @returns\r\n */\r\nexport function textToBase64Url(text) {\r\n // Create a Buffer from the string\r\n const buffer = Buffer.from(text, 'utf-8');\r\n\r\n // Convert the Buffer to a base64 string\r\n const base64String = buffer.toString('base64');\r\n\r\n // Construct the data URL\r\n const base64Url = `data:text/plain;base64,${base64String}`;\r\n\r\n return base64Url;\r\n}\r\n\r\nexport const isBase64FileUrl = (url: string): boolean => {\r\n if (typeof url !== 'string') return false;\r\n\r\n const regex = /^data:([\\w+\\-\\.]+\\/[\\w+\\-\\.]+);base64,(.*)$/;\r\n const match = url.match(regex);\r\n if (!match) return false;\r\n const [, , base64Data] = match;\r\n\r\n return isBase64(base64Data);\r\n};\r\n\r\nexport const getMimetypeFromBase64Data = async (data: string) => {\r\n try {\r\n data = _cleanUpBase64Data(data);\r\n\r\n // Convert the base64 string back to a Buffer\r\n const imageBuffer = Buffer.from(data, 'base64');\r\n\r\n const type = await fileTypeFromBuffer(imageBuffer);\r\n return type?.mime || '';\r\n } catch (error) {\r\n console.error('Error getting mimetype from base64 data: ', error);\r\n return '';\r\n }\r\n};\r\n\r\nexport async function getBase64FileInfo(data: string): Promise<{ data: string; mimetype: string; size: number } | null> {\r\n if (isBase64FileUrl(data)) {\r\n const regex = /^data:([^;]+);base64,(.*)$/;\r\n const match = data.match(regex);\r\n if (!match) return { data: '', mimetype: '', size: 0 };\r\n const [, mimetype, base64Data] = match;\r\n\r\n const cleanData = _cleanUpBase64Data(base64Data);\r\n const buffer = Buffer.from(cleanData, 'base64');\r\n\r\n return { data: cleanData, mimetype, size: buffer.byteLength };\r\n } else if (isBase64(data)) {\r\n const cleanData = _cleanUpBase64Data(data);\r\n const buffer = Buffer.from(cleanData, 'base64');\r\n\r\n return {\r\n data: cleanData,\r\n mimetype: await getMimetypeFromBase64Data(cleanData),\r\n size: buffer.byteLength,\r\n };\r\n }\r\n\r\n return null;\r\n}\r\n\r\n//=== Legacy code below ===\r\n//@Forhad the functions below need to be reviewed and refactored\r\n\r\n/**\r\n * Remove all whitespace characters and literal \\n and \\s sequences\r\n *\r\n * @note It's common practice to split base64 data into multiple lines for better readability and to avoid issues with systems that can't handle very long lines. So we need to clean up newline characters from the base64 data before processing it.\r\n * @param {string} str - The input string.\r\n * @returns {string} The input string with all newline characters and escaped newline strings removed.\r\n */\r\nfunction cleanBase64(str: string): string {\r\n return str.replace(/\\s|\\\\n|\\\\s/g, '');\r\n}\r\n\r\n/**\r\n * Checks if the input is a data URL.\r\n *\r\n * @param {string} input - The input string.\r\n * @returns {boolean} True if the input is a data URL, false otherwise.\r\n */\r\nexport function isBase64DataUrl(input: string): boolean {\r\n // Data URL pattern: data:[<mediatype>][;base64],<data>\r\n const pattern = /^data:([\\w+\\-\\.]+\\/[\\w+\\-\\.]+);base64,(.*)$/;\r\n\r\n return pattern.test(input);\r\n}\r\n\r\n/**\r\n * Checks if the given string is a valid Base64-encoded string.\r\n *\r\n * @param {string} str - The string to check.\r\n * @returns {boolean} True if the string is a valid Base64-encoded string, false otherwise.\r\n */\r\nexport function isBase64(str: string): boolean {\r\n if (!isValidString(str)) return false;\r\n\r\n const cleanedBase64Data = cleanBase64(str);\r\n\r\n // Sometimes words like 'male' and hashes like md5, sha1, sha256, sha512 are detected as base64\r\n if (cleanedBase64Data.length < 128) return false;\r\n\r\n try {\r\n const buffer = Buffer.from(cleanedBase64Data, 'base64');\r\n\r\n // ignoring trailing padding ensures that the comparison is based on the actual content, not the padding\r\n return buffer.toString('base64').replace(/=+$/, '') === cleanedBase64Data.replace(/=+$/, '');\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Parses a Base64-encoded data URL and extracts the MIME type and cleaned data.\r\n *\r\n * @param {string} input - The Base64-encoded data URL.\r\n * @returns {{ mimetype: string; data: string }} An object containing the MIME type and the cleaned Base64 data.\r\n * @throws {Error} If the input is invalid.\r\n */\r\nfunction parseBase64DataUrl(input: string): { mimetype: string; data: string } {\r\n const pattern = /^data:([\\w+\\-\\.]+\\/[\\w+\\-\\.]+);base64,(.*)$/;\r\n const matches = input.match(pattern);\r\n\r\n if (!matches) {\r\n throw new Error('Invalid data URL!');\r\n }\r\n\r\n const [, mimetype, data] = matches;\r\n\r\n if (!isBase64(data)) {\r\n throw new Error('Invalid base64 data!');\r\n }\r\n\r\n return { mimetype, data: cleanBase64(data) };\r\n}\r\n\r\n/**\r\n * Parses a Base64-encoded string and extracts the MIME type and cleaned data.\r\n *\r\n * @param {string} input - The Base64-encoded string.\r\n * @returns {Promise<{ mimetype: string; data: string }>} An object containing the MIME type and the cleaned Base64 data.\r\n */\r\nexport async function parseBase64(input: string): Promise<{ mimetype: string; data: string }> {\r\n const cleanedData = cleanBase64(input);\r\n const mimetype = await identifyMimetypeFromBase64(cleanedData);\r\n\r\n return { mimetype, data: cleanedData };\r\n}\r\n\r\n/**\r\n * Identifies the MIME type from a Base64-encoded string.\r\n *\r\n * This function cleans the input Base64 string, converts it to a buffer, and then identifies the MIME type\r\n * using the `fileTypeFromBuffer` function.\r\n *\r\n * @param {string} data - The Base64-encoded string from which to identify the MIME type.\r\n * @returns {Promise<string>} A promise that resolves to the MIME type of the data, or an empty string if the MIME type cannot be determined.\r\n *\r\n * @throws {Error} If an error occurs during the process, it logs the error and returns an empty string.\r\n */\r\nexport async function identifyMimetypeFromBase64(data: string): Promise<string> {\r\n try {\r\n const cleanedData = cleanBase64(data);\r\n\r\n // Convert the base64 string back to a Buffer\r\n const buffer = Buffer.from(cleanedData, 'base64');\r\n\r\n const type = await fileTypeFromBuffer(buffer);\r\n\r\n return type?.mime || '';\r\n } catch (error) {\r\n throw new Error(`Error identifying MIME type from base64 data: ${error?.message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Identifies the MIME type from a Base64-encoded string.\r\n *\r\n * This function cleans the input Base64 string, converts it to a buffer, and then identifies the MIME type\r\n * using the `fileTypeFromBuffer` function.\r\n *\r\n * @param {string} data - The Base64-encoded string from which to identify the MIME type.\r\n * @returns {Promise<string>} A promise that resolves to the MIME type of the data, or an empty string if the MIME type cannot be determined.\r\n *\r\n * @throws {Error} If an error occurs during the process, it logs the error and returns an empty string.\r\n */\r\nexport async function identifyMimeTypeFromBase64DataUrl(input: string): Promise<string> {\r\n try {\r\n const { data } = await parseBase64DataUrl(input);\r\n\r\n const buffer = Buffer.from(data, 'base64');\r\n\r\n const type = await fileTypeFromBuffer(buffer);\r\n\r\n return type?.mime || '';\r\n } catch (error) {\r\n throw new Error(`Error identifying MIME type from base64 data: ${error?.message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Calculates the size of a Base64-encoded string in bytes.\r\n *\r\n * This function validates the input string to ensure it is a valid Base64-encoded string,\r\n * converts it to a buffer, and then returns the byte length of the buffer.\r\n *\r\n * @param {string} str - The Base64-encoded string whose size is to be calculated.\r\n * @returns {number} The size of the Base64-encoded string in bytes.\r\n *\r\n * @throws {Error} If the input string is not a valid Base64-encoded string or if an error occurs during conversion.\r\n */\r\nexport function getSizeOfBase64(str: string): number {\r\n if (!isValidString(str)) {\r\n throw new Error('Invalid Base64 data!');\r\n }\r\n\r\n try {\r\n const buffer = Buffer.from(str, 'base64');\r\n return buffer.byteLength;\r\n } catch (error) {\r\n throw new Error(`Invalid Base64 data! ${error.message}`);\r\n }\r\n}\r\n\r\n/**\r\n * Generates a Base64 Data URL from a Base64-encoded string.\r\n *\r\n * This function validates the input Base64 string, removes any newline characters,\r\n * and constructs a Data URL with the specified MIME type.\r\n *\r\n * @param {string} data - The Base64-encoded string to be converted into a Data URL.\r\n * @param {string} [mimetype='application/octet-stream'] - The MIME type of the data. Defaults to 'application/octet-stream'.\r\n * @returns {string} The generated Base64 Data URL.\r\n *\r\n * @throws {Error} If the input string is not a valid Base64-encoded string.\r\n */\r\nexport function makeBase64Url(data: string, mimetype: string = 'application/octet-stream'): string {\r\n if (!isValidString(data)) {\r\n throw new Error('Invalid Base64 data!');\r\n }\r\n\r\n // Remove any newline characters from the Base64 string\r\n const cleanedData = data.replace(/\\n/g, '');\r\n\r\n // Construct and return the Data URL\r\n return `data:${mimetype};base64,${cleanedData}`;\r\n}\r\n\r\n/**\r\n ** It's common practice to split base64 data into multiple lines for better readability and to avoid issues with systems that can't handle very long lines.\r\n ** So we need to clean up newline characters from the base64 data before processing it.\r\n * @param {string} str - The input string.\r\n * @returns {string} The input string with all newline characters and escaped newline strings removed.\r\n */\r\nconst _cleanUpBase64Data = (str: string): string => {\r\n // Check if the input is a string and is not excessively large\r\n if (typeof str !== 'string' || str.length > MAX_FILE_SIZE) {\r\n throw new Error('Invalid input');\r\n }\r\n\r\n // Remove all whitespace characters and literal \\n and \\s sequences\r\n return str.replace(/\\s|\\\\n|\\\\s/g, '');\r\n};\r\n","import { Readable } from 'stream';\r\nimport axios from 'axios';\r\n\r\nimport { identifyMimeTypeFromBase64DataUrl, isBase64FileUrl, isBase64, identifyMimetypeFromBase64, isBase64DataUrl } from './base64.utils';\r\nimport { isBinaryFileSync } from 'isbinaryfile';\r\nimport { fileTypeFromBuffer } from 'file-type';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { identifyMimetypeFromString } from './string.utils';\r\n\r\n// Helper function to convert stream to buffer\r\nexport async function streamToBuffer(stream: Readable): Promise<Buffer> {\r\n const chunks: Buffer[] = [];\r\n for await (const chunk of stream) {\r\n chunks.push(typeof chunk === 'string' ? Buffer.from(chunk) : chunk);\r\n }\r\n return Buffer.concat(chunks);\r\n}\r\n\r\n/////////////////////////////////////////////////////////////////////////////////////////////\r\n// == Helpers from Legacy Smyth implementation ==============================================\r\n// FIXME : below functions should probably be converted to a validator\r\n\r\n//export declare function isBinaryFile(file: string | Buffer, size?: number): Promise<boolean>;\r\n//export declare function isBinaryFileSync(file: string | Buffer, size?: number): boolean;\r\nconst binaryMimeTypes = ['image/', 'audio/', 'video/', 'application/pdf', 'application/zip', 'application/octet-stream'];\r\n\r\nexport function dataToBuffer(data: any): Buffer | null {\r\n let bufferData;\r\n switch (true) {\r\n case data instanceof ArrayBuffer:\r\n bufferData = Buffer.from(new Uint8Array(data));\r\n break;\r\n case ArrayBuffer.isView(data) && !(data instanceof DataView):\r\n bufferData = Buffer.from(new Uint8Array(data.buffer));\r\n break;\r\n case data instanceof DataView:\r\n bufferData = Buffer.from(new Uint8Array(data.buffer, data.byteOffset, data.byteLength));\r\n break;\r\n case Buffer.isBuffer(data):\r\n bufferData = data;\r\n break;\r\n case typeof data === 'string':\r\n bufferData = Buffer.from(data, 'utf-8');\r\n break;\r\n default:\r\n return null;\r\n }\r\n\r\n return bufferData;\r\n}\r\n\r\nexport const getSizeFromBinary = (data: any) => {\r\n const buffer = dataToBuffer(data);\r\n if (!buffer) return 0;\r\n return buffer.byteLength;\r\n};\r\n\r\n/**\r\n * Calculates the size in bytes of a base64-encoded string after decoding\r\n *\r\n * @param base64String - The base64 string to calculate the size for. Can be a raw base64 string or a data URL.\r\n * @returns The size in bytes of the decoded data\r\n */\r\nfunction getBase64FileSize(base64String: string): number {\r\n // Remove data URL prefix if present\r\n const base64Data = base64String.includes(';base64,') ? base64String.split(';base64,')[1] : base64String;\r\n\r\n // Formula: (n * 3) / 4 - padding\r\n const padding = base64Data.endsWith('==') ? 2 : base64Data.endsWith('=') ? 1 : 0;\r\n return Math.floor((base64Data.length * 3) / 4) - padding;\r\n}\r\n\r\nexport const isPlainObject = (data: any): boolean => {\r\n return (\r\n typeof data === 'object' &&\r\n data !== null &&\r\n !Array.isArray(data) &&\r\n Object.prototype.toString.call(data) === '[object Object]' &&\r\n data.constructor === Object\r\n );\r\n};\r\n\r\n// isBuffer checks if the provided data is a Buffer object in Node.js.\r\nexport const isBuffer = (data: any): boolean => {\r\n try {\r\n return Buffer.isBuffer(data);\r\n } catch {\r\n // Buffer.isBuffer throws error when non-array Object is passed\r\n return false;\r\n }\r\n};\r\n\r\n// isBinaryMimeType checks if the provided mimetype indicates binary data.\r\nexport const isBinaryMimeType = (mimetype): boolean => {\r\n if (mimetype) {\r\n return binaryMimeTypes.some((type) => mimetype.startsWith(type));\r\n }\r\n return false;\r\n};\r\n\r\n// isBinaryData checks if the provided data is binary.\r\n// If the data is a Buffer, ArrayBuffer, TypedArray, or DataView, it checks if it contains binary data.\r\nexport const isBinaryData = (data): boolean => {\r\n // To prevent returning true when we have emojis in the string like \"Hello 😀\"\r\n if (typeof data === 'string') return false;\r\n\r\n try {\r\n const buffer = dataToBuffer(data);\r\n if (!buffer) return false;\r\n return isBinaryFileSync(buffer, buffer.byteLength);\r\n } catch (error) {\r\n return false;\r\n }\r\n};\r\n\r\n// TODO: Need to check if this is intentional, I think we're checking for http/https urls only\r\nexport function isUrl(str: string): boolean {\r\n if (typeof str !== 'string') return false;\r\n // This regex checks for protocol, hostname, domain, port (optional), path (optional), and query string (optional)\r\n //const regex = /^(https?:\\/\\/)([^\\s.]+\\.[^\\s]{2,})(:[0-9]{1,5})?(\\/[^\\s]*)?(\\?[^\\s]*)?$/i;\r\n const regex = /^([a-zA-Z0-9]+:\\/\\/)([^\\s.]+\\.[^\\s]{2,})(:[0-9]{1,5})?(\\/[^\\s]*)?(\\?[^\\s]*)?$/i;\r\n\r\n return regex.test(str);\r\n}\r\n\r\nexport function isSmythFsUrl(str: string): boolean {\r\n if (typeof str !== 'string') return false;\r\n const regex = /^smythfs:\\/\\/([^\\s.]+\\.[^\\s]{2,})(:[0-9]{1,5})?(\\/[^\\s]*)?(\\?[^\\s]*)?$/i;\r\n return regex.test(str);\r\n}\r\n\r\nexport const isSmythFileObject = (data: any): boolean => {\r\n return !!(typeof data === 'object' && data !== null && data?.url && isUrl(data?.url) && 'size' in data && 'mimetype' in data);\r\n};\r\n\r\nexport const isBufferObject = (data: Record<string, any>): boolean => {\r\n if (!data) return false;\r\n\r\n return typeof data === 'object' && data !== null && data?.buffer && isBuffer(data.buffer) && 'size' in data && 'mimetype' in data;\r\n};\r\n\r\nexport const isBase64Object = (data: Record<string, any>): boolean => {\r\n if (!data) return false;\r\n\r\n return typeof data === 'object' && data !== null && data?.base64 && isBase64(data.base64) && 'size' in data && 'mimetype' in data;\r\n};\r\n\r\nexport async function getMimeType(data: any): Promise<string> {\r\n const mimeTypeGetters = {\r\n blob: () => data.type,\r\n buffer: async () => {\r\n try {\r\n // TODO: debug why this is not returning a file type for images when used through BinaryInput.helper.ts\r\n const fileType = await fileTypeFromBuffer(data);\r\n return fileType?.mime ?? '';\r\n } catch {\r\n console.warn('Failed to get mime type from buffer');\r\n return '';\r\n }\r\n },\r\n url: async () => {\r\n try {\r\n const response = await axios.get(data); // head() method does not work for all URLs\r\n const contentType = response.headers['content-type'];\r\n return contentType;\r\n } catch {\r\n console.warn('Failed to get mime type from URL');\r\n return '';\r\n }\r\n },\r\n smythFile: () => data.mimetype,\r\n base64DataUrl: () => identifyMimeTypeFromBase64DataUrl(data),\r\n base64: () => identifyMimetypeFromBase64(data),\r\n string: () => identifyMimetypeFromString(data),\r\n };\r\n\r\n const typeChecks = {\r\n blob: data instanceof Blob,\r\n buffer: isBuffer(data),\r\n url: isUrl(data),\r\n smythFile: isSmythFileObject(data),\r\n base64DataUrl: isBase64FileUrl(data),\r\n base64: isBase64(data),\r\n string: typeof data === 'string',\r\n };\r\n\r\n const [matchedType = ''] = Object.entries(typeChecks).find(([, value]) => value) || [];\r\n if (!matchedType) return '';\r\n\r\n return await mimeTypeGetters?.[matchedType]?.();\r\n}\r\n\r\n// Mask data like Buffer, FormData, etc. in debug output\r\n// TODO [Forhad]: Need to get the size of FormData\r\nexport async function formatDataForDebug(data: any) {\r\n let dataForDebug;\r\n\r\n if (!data) {\r\n return data;\r\n }\r\n\r\n try {\r\n if (data.constructor?.name === 'BinaryInput') {\r\n const jsonData = await data.getJsonData();\r\n dataForDebug = `[BinaryInput size=${jsonData?.size}]`;\r\n } else if (isBuffer(data)) {\r\n dataForDebug = `[Buffer size=${data.byteLength}]`;\r\n } else if (data.constructor?.name === 'FormData') {\r\n dataForDebug = `[FormData]`;\r\n } else if (isBase64(data) || isBase64DataUrl(data)) {\r\n dataForDebug = `[Base64 size=${getBase64FileSize(data)}]`;\r\n } else {\r\n dataForDebug = data;\r\n }\r\n } catch (error) {\r\n // Fallback to a safe representation if any error occurs\r\n dataForDebug = '[Binary]';\r\n }\r\n\r\n return dataForDebug;\r\n}\r\n\r\n// TODO: Maybe we need move this function to any helper file, as it depends on BinaryInput class\r\nexport async function normalizeImageInput(inputImage: string | BinaryInput): Promise<string> {\r\n if (!inputImage) {\r\n return '';\r\n }\r\n\r\n // Handle string inputs\r\n if (typeof inputImage === 'string') {\r\n if (isBase64(inputImage)) {\r\n // Convert raw base64 to data URL with proper MIME type\r\n const mimeType = (await getMimeType(inputImage)) || 'image/png';\r\n return `data:${mimeType};base64,${inputImage}`;\r\n }\r\n\r\n if (isBase64DataUrl(inputImage)) {\r\n return inputImage; // Already in correct format\r\n }\r\n\r\n if (isUrl(inputImage)) {\r\n return inputImage; // Valid URL, return as-is\r\n }\r\n\r\n throw new Error('Invalid string input: must be base64, data URL, or HTTP(S) URL');\r\n }\r\n\r\n // Handle BinaryInput\r\n // * There is a bug (server crash) when we check like this: inputImage instanceof BinaryInput\r\n // TODO [Forhad]: Need find out the root cause and fix it\r\n if (inputImage.constructor?.name === 'BinaryInput') {\r\n try {\r\n const buffer = await inputImage.getBuffer();\r\n const mimeType = (await getMimeType(buffer)) || 'image/png';\r\n const base64Data = buffer.toString('base64');\r\n return `data:${mimeType};base64,${base64Data}`;\r\n } catch (error) {\r\n throw new Error(`Failed to process BinaryInput: ${error.message}`);\r\n }\r\n }\r\n\r\n throw new Error('Unsupported input type');\r\n}\r\n","/**\r\n * This function parses the command line arguments and returns an object with the parsed values.\r\n * The expected format is --file ./path/to/file.txt or --settings key1=value1 key2=value2\r\n * Examples:\r\n * --file ./path/to/file.txt : calling parseCLIArgs('file', process.argv) will return {file: './path/to/file.txt'}\r\n * --settings key1=value1 key2=value2 : calling parseCLIArgs('settings', process.argv) will return {settings: {key1: 'value1', key2: 'value2'}}\r\n * it can also parse multiple arguments at once, for example:\r\n * parseCLIArgs(['file', 'settings'], process.argv) will return {file: './path/to/file.txt', settings: {key1: 'value1', key2: 'value2'}}\r\n *\r\n * @param argList the argument to parse\r\n * @param argv the command line arguments, usually process.argv\r\n * @returns parsed arguments object\r\n */\r\n\r\nexport function parseCLIArgs(argList: string | Array<string>, argv?: Array<string>): Record<string, any> {\r\n if (!argv) argv = process.argv;\r\n const args = argv;\r\n const result = {};\r\n const mainArgs = Array.isArray(argList) ? argList : [argList];\r\n mainArgs.forEach((mainArg) => {\r\n const mainArgIndex = args.indexOf(`--${mainArg}`);\r\n if (mainArgIndex !== -1) {\r\n const values: any = [];\r\n for (let i = mainArgIndex + 1; i < args.length; i++) {\r\n if (args[i].startsWith('--')) break;\r\n values.push(args[i]);\r\n }\r\n\r\n if (values.length === 1 && values[0].includes('=')) {\r\n const keyValuePairs = {};\r\n const [key, ...valParts] = values[0].split('=');\r\n const val = valParts.join('=').replace(/^\"|\"$/g, '');\r\n keyValuePairs[key] = val;\r\n result[mainArg] = keyValuePairs;\r\n } else if (values.length === 1) {\r\n result[mainArg] = values[0];\r\n } else if (values.length > 1) {\r\n const keyValuePairs = {};\r\n values.forEach((value) => {\r\n const [key, ...valParts] = value.split('=');\r\n const val = valParts.join('=').replace(/^\"|\"$/g, '');\r\n keyValuePairs[key] = val;\r\n });\r\n result[mainArg] = keyValuePairs;\r\n }\r\n }\r\n });\r\n\r\n return result;\r\n}\r\n\r\n/**\r\n * List all cli main arguments\r\n * example : node index.js --file ./path/to/file.txt --settings key1=value1 key2=value2\r\n * calling getMainArgs(process.argv) will return ['file', 'settings']\r\n */\r\nexport function getMainArgs(argv?: Array<string>): Array<string> {\r\n if (!argv) argv = process.argv;\r\n const args = argv;\r\n const result = [];\r\n for (let i = 2; i < args.length; i++) {\r\n if (args[i].startsWith('--')) {\r\n result.push(args[i].replace(/^--/, ''));\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n","export function isDigits(str: string): boolean {\r\n if (typeof str === 'number') return true;\r\n\r\n if (typeof str !== 'string') return false;\r\n\r\n const numRegex = /^-?\\d+(\\.\\d+)?$/;\r\n return numRegex.test(str.trim());\r\n}\r\n\r\nexport function isSafeNumber(str: string): boolean {\r\n const num = parseFloat(str);\r\n return !isNaN(num) && num <= Number.MAX_SAFE_INTEGER && num >= Number.MIN_SAFE_INTEGER && num.toString() === str.trim();\r\n}\r\n","interface RangeValidationArgs {\r\n min?: number;\r\n max?: number;\r\n}\r\n\r\n/**\r\n * Custom validation function to check if a string contains only specified characters.\r\n * @param {string} value - The string to validate.\r\n * @returns {string} - The validated string.\r\n */\r\nexport function validateCharacterSet(value: string): boolean {\r\n if (value === '') return true;\r\n // Check for {{sometext}} structures and split the string\r\n const parts = value.split(/(\\{\\{[^}]+\\}\\})/).filter(Boolean);\r\n\r\n for (const part of parts) {\r\n if (part.startsWith('{{') && part.endsWith('}}')) {\r\n // Check if the content inside {{...}} is not empty\r\n const innerContent = part.slice(2, -2).trim();\r\n if (innerContent === '') {\r\n return false; // Empty content inside {{...}}\r\n }\r\n } else {\r\n // Check for valid characters outside of {{...}}\r\n if (!/^[a-zA-Z0-9\\-_.]+$/.test(part)) {\r\n return false; // Invalid characters found\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n}\r\n\r\n/**\r\n * Validates whether a given string value can be converted to an integer that falls within a specified range.\r\n * This function is designed to be used as a custom validator in Joi schemas.\r\n *\r\n * @param {RangeValidationArgs} args - An object containing optional 'min' and 'max' properties to define the range.\r\n * @returns {Function} A function that takes a string value and a Joi helper object, and performs the validation.\r\n *\r\n * The validation function first converts the string value to a number. It then checks if the number is within the\r\n * specified range (if provided). If the value is not a number or falls outside the range, it throws an error with a\r\n * descriptive message.\r\n *\r\n * The error message includes the field name for clarity, using the label from the Joi schema if available.\r\n */\r\nexport const validateInteger = (args: RangeValidationArgs) => {\r\n return (value: string, helpers: any) => {\r\n const numValue = Number(value);\r\n const fieldName = helpers.schema._flags.label || helpers.state.path[helpers.state.path.length - 1];\r\n\r\n // Check if the value is a number\r\n if (isNaN(numValue)) {\r\n throw new Error(`The value for '${fieldName}' must be a number`);\r\n }\r\n\r\n // Range validations\r\n if (args.min !== undefined && args.max !== undefined) {\r\n if (numValue < args.min || numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be from ${args.min} to ${args.max}`);\r\n }\r\n } else if (args.min !== undefined) {\r\n if (numValue < args.min) {\r\n throw new Error(`The value for '${fieldName}' must be greater or equal to ${args.min}`);\r\n }\r\n } else if (args.max !== undefined) {\r\n if (numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be less or equal to ${args.max}`);\r\n }\r\n }\r\n\r\n return value; // Value is valid\r\n };\r\n};\r\n","import 'dotenv/config';\r\nimport winston from 'winston';\r\nimport Transport from 'winston-transport';\r\nimport { getFormattedStackTrace, parseCLIArgs } from '../utils';\r\nimport config from '@sre/config';\r\nimport { EventEmitter } from 'events';\r\nwinston.addColors({\r\n error: 'red',\r\n warn: 'yellow',\r\n info: 'green',\r\n debug: 'blue',\r\n});\r\n\r\nconst logLevelMap = {\r\n min: 'info',\r\n full: 'debug',\r\n};\r\n\r\nlet logLevel = () => {\r\n let val = parseCLIArgs('debug')?.debug || config?.env?.LOG_LEVEL || 'none';\r\n if (logLevelMap[val]) val = logLevelMap[val];\r\n return !['none', 'error', 'warn', 'info', 'debug'].includes(val) ? 'none' : val;\r\n};\r\n\r\n// Retrieve the DEBUG environment variable and split it into an array of namespaces\r\nconst namespaces = (config.env.LOG_FILTER || '').split(',');\r\n\r\n// Create a Winston format that filters messages based on namespaces\r\nconst namespaceFilter = winston.format((info: any) => {\r\n // If DEBUG is not set, log everything\r\n if (!config.env.LOG_FILTER || namespaces.some((ns) => info.module?.includes(ns))) {\r\n return info;\r\n }\r\n return false; // Filter out messages that do not match the namespace\r\n})();\r\n\r\n// Custom stream for your transport\r\nclass ArrayTransport extends Transport {\r\n private logs: any[];\r\n constructor(opts) {\r\n super(opts);\r\n // Configure your storage array\r\n this.logs = opts.logs;\r\n }\r\n\r\n log(info, callback) {\r\n setImmediate(() => {\r\n this.emit('logged', info);\r\n });\r\n\r\n // Perform the writing to the array storage\r\n this.logs.push(`${info.level}: ${info.message}`);\r\n\r\n // Perform the writing to the remote service\r\n callback();\r\n }\r\n}\r\n\r\nexport class LogHelper extends EventEmitter {\r\n public startTime = Date.now();\r\n public get output() {\r\n return Array.isArray(this.data) ? this.data.join('\\n') : undefined;\r\n }\r\n public get elapsedTime() {\r\n return Date.now() - this.startTime;\r\n }\r\n constructor(\r\n private _logger: winston.Logger,\r\n public data,\r\n private labels: { [key: string]: any },\r\n ) {\r\n super();\r\n }\r\n\r\n public log(...args) {\r\n this._logger.log('info', formatLogMessage(...args), this.labels);\r\n this.emit('logged', { level: 'info', message: formatLogMessage(...args) });\r\n }\r\n public warn(...args) {\r\n this._logger.log('warn', formatLogMessage(...args), this.labels);\r\n this.emit('logged', { level: 'warn', message: formatLogMessage(...args) });\r\n }\r\n public debug(...args) {\r\n this._logger.log('debug', formatLogMessage(...args), this.labels);\r\n this.emit('logged', { level: 'debug', message: formatLogMessage(...args) });\r\n }\r\n public info(...args) {\r\n this._logger.log('info', formatLogMessage(...args), this.labels);\r\n this.emit('logged', { level: 'info', message: formatLogMessage(...args) });\r\n }\r\n public verbose(...args) {\r\n this._logger.log('verbose', formatLogMessage(...args), this.labels);\r\n this.emit('logged', { level: 'verbose', message: formatLogMessage(...args) });\r\n }\r\n\r\n public error(...args) {\r\n const stack = '\\nCall Stack:\\n' + getFormattedStackTrace(10).join('\\n');\r\n\r\n this._logger.log('error', formatLogMessage(...args), { ...this.labels, stack });\r\n\r\n this.emit('logged', { level: 'error', message: formatLogMessage(...args) });\r\n }\r\n\r\n public close() {\r\n this._logger.clear();\r\n this._logger.close();\r\n }\r\n}\r\n\r\nconst colorizedFormat = winston.format.printf((info) => {\r\n return `${info.timestamp} ${winston.format.colorize().colorize(info.level, `${info.level}: ${info.message}`)}`;\r\n});\r\n\r\nconst MAX_LOG_MESSAGE_LENGTH = 500;\r\n\r\nfunction redactLogMessage(logMessage: string) {\r\n if (config.env.NODE_ENV !== 'PROD') return logMessage; //only redact logs in PROD\r\n if (logMessage.length > 500) {\r\n return logMessage;\r\n }\r\n\r\n const sensitiveWords = ['password', 'eyJ', 'token', 'email', 'secret', 'key', 'apikey', 'api_key', 'auth', 'credential'];\r\n const obfuscatedString = ' [!! SmythOS::REDACTED_DATA !!] ';\r\n\r\n // Iterate through the sensitive words list and replace sensitive data in the log message\r\n\r\n for (const sensitiveWord of sensitiveWords) {\r\n // Create a regular expression to find the sensitive word followed by any character (non-greedy) until a space, newline, or separator is found.\r\n const regex = new RegExp(`(${sensitiveWord})((?:[^\\\\n]{0,29}(?=\\\\n))|(?:[^\\\\n]{30}\\\\S*))`, 'gmi');\r\n\r\n // Replace sensitive data with the obfuscated string\r\n logMessage = logMessage.replace(regex, `$1${obfuscatedString}`);\r\n }\r\n\r\n return logMessage;\r\n}\r\n\r\nfunction createBaseLogger(memoryStore?: any[]) {\r\n const logger = winston.createLogger({\r\n //level: 'info', // log level\r\n\r\n format: winston.format.combine(\r\n winston.format((info: any) => {\r\n if (config.env.LOG_LEVEL == 'none' || logLevel() == 'none' || logLevel() == '') return false; // skip logging if log level is none\r\n\r\n // Apply redaction to the log message\r\n //info.message = redactSecrets(info.message, sensitiveOptions);\r\n\r\n info.message = redactLogMessage(info.message);\r\n return info;\r\n })(),\r\n winston.format.timestamp(),\r\n winston.format.errors({\r\n stack: true,\r\n }),\r\n winston.format.splat(),\r\n winston.format.json(),\r\n ),\r\n\r\n transports: [\r\n new winston.transports.Console({\r\n level: 'error',\r\n //handleExceptions: true,\r\n format: winston.format.combine(\r\n winston.format.printf((info: any) => {\r\n let message = info.message;\r\n message = message?.length > MAX_LOG_MESSAGE_LENGTH ? message.substring(0, MAX_LOG_MESSAGE_LENGTH) + '...' : message;\r\n return `${info.level}:${info.module || ''} ${message} ${info.stack || ''}`;\r\n }),\r\n ),\r\n stderrLevels: ['error'], // Define levels that should be logged to stderr\r\n }),\r\n new winston.transports.Console({\r\n level: logLevel(),\r\n format: winston.format.combine(\r\n namespaceFilter,\r\n winston.format.printf((info: any) => {\r\n const module = info.module ? winston.format.colorize().colorize(info.level, ` [${info.module}]`) : '';\r\n const ns = winston.format.colorize().colorize(info.level, `${info.level}${module}`);\r\n\r\n let message = info.message;\r\n message = message?.length > MAX_LOG_MESSAGE_LENGTH ? message.substring(0, MAX_LOG_MESSAGE_LENGTH) + '...' : message;\r\n\r\n return `${ns} - ${message}`;\r\n }),\r\n ),\r\n\r\n //handleExceptions: true,\r\n }),\r\n ],\r\n });\r\n\r\n if (Array.isArray(memoryStore)) {\r\n logger.add(\r\n new ArrayTransport({\r\n level: 'debug',\r\n logs: memoryStore,\r\n }),\r\n );\r\n }\r\n\r\n return logger;\r\n}\r\n\r\nfunction formatLogMessage(...args) {\r\n return args\r\n .map((arg) => {\r\n // If the argument is an object (and not null), serialize it to JSON\r\n if (typeof arg === 'object' && arg !== null && !(arg instanceof Error)) {\r\n try {\r\n return JSON.stringify(arg, null, 2); // set the space to 2 for better readability\r\n } catch (error) {\r\n return String(arg);\r\n }\r\n }\r\n // Otherwise, just convert it to a string in case it's not\r\n return String(arg);\r\n })\r\n .join(' '); // Concatenate all arguments with a space\r\n}\r\n\r\nfunction createLabeledLogger(labels: { [key: string]: any }, memoryStore?: any[]) {\r\n const _logger = createBaseLogger(memoryStore);\r\n\r\n _logger.defaultMeta = labels;\r\n\r\n const logger = new LogHelper(_logger, memoryStore, labels);\r\n\r\n return logger;\r\n}\r\n\r\nexport function Logger(module: string, withMemoryStore = false) {\r\n return createLabeledLogger({ module }, withMemoryStore ? [] : undefined);\r\n}\r\n","import { Logger } from '../helpers/Log.helper';\r\nimport { getFormattedStackTrace, printStackTrace } from '../utils';\r\n\r\n/**\r\n * DummyConnector is a placeholder for unimplemented connectors, it logs a warning when a method is called in order to help developers identify missing connectors\r\n */\r\nexport const DummyConnector: any = (name: string) => {\r\n const logger = Logger(`DummyConnector<${name}>`);\r\n return new Proxy(\r\n {},\r\n {\r\n get: function (target, prop, receiver) {\r\n //check if we are accessing the valid property\r\n if (prop === 'valid') {\r\n return false; //when DummyConnector is used it means that the main connector failed to load\r\n }\r\n\r\n // Check if the property being accessed is a function\r\n if (typeof target[prop] === 'function') {\r\n return target[prop];\r\n } else {\r\n // Return a function that logs \"unavailable\"\r\n return function (...args: any[]) {\r\n const argsString =\r\n args.length > 0\r\n ? args\r\n .map((arg) => {\r\n if (typeof arg === 'object') return JSON.stringify(arg, null, 0).slice(0, 50) + '...';\r\n if (typeof arg === 'string') return `\"${arg.slice(0, 50)}...\"`;\r\n if (typeof arg === 'number') return arg.toString();\r\n if (typeof arg === 'boolean') return arg.toString();\r\n if (typeof arg === 'function') return arg.toString();\r\n if (typeof arg === 'symbol') return arg.toString();\r\n if (typeof arg === 'undefined') return 'undefined';\r\n\r\n return String(arg);\r\n })\r\n .join(', ')\r\n : '(no arguments)';\r\n\r\n logger.warn(`[!!] Unimplemented Connector tried to call: ${name}.${prop.toString()}(${argsString})`);\r\n\r\n printStackTrace(logger, 3, 1); //the argument 1 means that we skip one more strack element because we are calling printStackTrace from an anonymous function\r\n };\r\n }\r\n },\r\n },\r\n );\r\n};\r\n","interface CacheItem<T> {\r\n value: T;\r\n expiry: number;\r\n}\r\n\r\nexport class LocalCache<K, V> {\r\n private cache: Map<K, V>;\r\n private expiryMap: Map<K, number>;\r\n private timeouts: Map<K, NodeJS.Timeout>;\r\n private defaultTTL: number = 60 * 60 * 1000;\r\n\r\n constructor(defaultTTL: number = 60 * 60 * 1000) {\r\n this.defaultTTL = defaultTTL;\r\n this.cache = new Map<K, V>();\r\n this.expiryMap = new Map<K, number>();\r\n this.timeouts = new Map<K, NodeJS.Timeout>();\r\n }\r\n\r\n set(key: K, value: V, ttlMs: number = this.defaultTTL): void {\r\n this.cache.set(key, value);\r\n const expiry = Date.now() + ttlMs;\r\n this.expiryMap.set(key, expiry);\r\n\r\n // Clear any existing timeout for this key\r\n this.clearTimeout(key);\r\n\r\n // Set a new timeout to remove the item when it expires\r\n const timeout = setTimeout(() => {\r\n this.delete(key);\r\n }, ttlMs);\r\n this.timeouts.set(key, timeout);\r\n timeout.unref(); //unblock the event loop\r\n }\r\n\r\n updateTTL(key: K, ttlMs: number = this.defaultTTL): void {\r\n if (!this.has(key)) {\r\n return;\r\n }\r\n const expiry = Date.now() + ttlMs;\r\n this.expiryMap.set(key, expiry);\r\n\r\n // Clear existing timeout and set a new one\r\n this.clearTimeout(key);\r\n const timeout = setTimeout(() => {\r\n this.delete(key);\r\n }, ttlMs);\r\n this.timeouts.set(key, timeout);\r\n timeout.unref(); //unblock the event loop\r\n }\r\n\r\n get(key: K, ttlMs?: number): V | undefined {\r\n if (!this.has(key)) {\r\n return undefined;\r\n }\r\n const value = this.cache.get(key);\r\n if (value === undefined) {\r\n return undefined;\r\n }\r\n this.updateTTL(key, ttlMs);\r\n return value;\r\n }\r\n\r\n has(key: K): boolean {\r\n if (!this.cache.has(key)) {\r\n return false;\r\n }\r\n const expiry = this.expiryMap.get(key);\r\n if (expiry && Date.now() > expiry) {\r\n this.delete(key);\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n delete(key: K): boolean {\r\n this.clearTimeout(key);\r\n this.expiryMap.delete(key);\r\n return this.cache.delete(key);\r\n }\r\n\r\n clear(): void {\r\n for (const key of this.cache.keys()) {\r\n this.clearTimeout(key);\r\n }\r\n this.cache.clear();\r\n this.expiryMap.clear();\r\n this.timeouts.clear();\r\n }\r\n\r\n private clearTimeout(key: K): void {\r\n const timeout = this.timeouts.get(key);\r\n if (timeout) {\r\n clearTimeout(timeout);\r\n this.timeouts.delete(key);\r\n }\r\n }\r\n}\r\n","//==[ SRE: ACL Types ]======================\r\nexport const DEFAULT_TEAM_ID = 'default';\r\n\r\nexport enum TAccessLevel {\r\n None = 'none',\r\n Owner = 'owner',\r\n Read = 'read',\r\n Write = 'write',\r\n}\r\n\r\nexport enum TAccessRole {\r\n Agent = 'agent',\r\n User = 'user',\r\n Team = 'team',\r\n Public = 'public',\r\n}\r\n\r\n// role and level mappings are used for ACL serialization / deserialization\r\nexport const RoleMap = {\r\n user: 'u',\r\n agent: 'a',\r\n team: 't',\r\n public: 'p',\r\n};\r\n\r\nexport const LevelMap = {\r\n none: 'n',\r\n owner: 'o',\r\n read: 'r',\r\n write: 'w',\r\n};\r\n\r\n// Reverse mappings\r\nexport const ReverseRoleMap = Object.fromEntries(Object.entries(RoleMap).map(([k, v]) => [v, k]));\r\nexport const ReverseLevelMap = Object.fromEntries(Object.entries(LevelMap).map(([k, v]) => [v, k]));\r\n\r\n/**\r\n * an ACLEntry is a list of access levels for a given owner.\r\n * an owner can be an agent, a user, a team or the public.\r\n */\r\nexport type TACLEntry = {\r\n [hashedOwnerKey: string]: TAccessLevel[] | undefined;\r\n};\r\n/**\r\n * The Access Control List (ACL) is a list of access rights for a given resource.\r\n * Each entry in this ACL represents a role\r\n * Role entries define a list of owners of the resource and the access levels they have.\r\n * e.g.\r\n * The following ACL defines that agentA and teamA has read and write access, while agentB and teamC has read access.\r\n * {\r\n * agent: {\r\n * 'agentA': ['read', 'write'],\r\n * 'agentB': ['read'],\r\n * },\r\n * team: {\r\n * 'teamA': ['read', 'write'],\r\n * 'teamC': ['read'],\r\n * }\r\n * }\r\n */\r\n// prettier-ignore\r\nexport interface IACL { \r\n hashAlgorithm?: string | undefined;\r\n entries?: {\r\n [key in TAccessRole]?: TACLEntry | undefined;\r\n };\r\n migrated?: boolean | undefined;\r\n}\r\n\r\n// export type TACLMetadata = {\r\n// acl?: TACL | undefined;\r\n// };\r\n\r\nexport interface IAccessCandidate {\r\n role: TAccessRole;\r\n id: string;\r\n}\r\n\r\nexport interface IAccessRequest {\r\n id: string;\r\n resourceId: string;\r\n candidate: IAccessCandidate;\r\n level: TAccessLevel | TAccessLevel[];\r\n}\r\n\r\nexport enum TAccessResult {\r\n Granted = 'granted',\r\n Denied = 'denied',\r\n}\r\n\r\nexport type TAccessTicket = {\r\n request: IAccessRequest;\r\n access: TAccessResult;\r\n};\r\n\r\n//custom errors\r\n\r\n//access denied error\r\nexport class ACLAccessDeniedError extends Error {\r\n constructor(message?: string) {\r\n super(message);\r\n this.name = 'ACLAccessDeniedError';\r\n }\r\n}\r\n","import { IAccessCandidate, IAccessRequest, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { uid } from '@sre/utils/index';\r\n\r\nexport class AccessRequest implements IAccessRequest {\r\n public id: string;\r\n public resourceId: string;\r\n\r\n public level: TAccessLevel[] = [];\r\n public candidate: IAccessCandidate;\r\n\r\n constructor(object?: IAccessRequest | IAccessCandidate) {\r\n if (!object) {\r\n this.id = 'aclR:' + uid();\r\n }\r\n if (['role', 'id'].every((k) => k in object)) {\r\n //this is a candidate\r\n this.id = 'aclR:' + uid();\r\n this.candidate = object as IAccessCandidate;\r\n } else {\r\n const acReq: AccessRequest = object as AccessRequest;\r\n this.id = acReq.id;\r\n //this.resourceId = acReq.resourceId;\r\n this.level = acReq.level;\r\n this.candidate = acReq.candidate;\r\n }\r\n\r\n this.resourceId = undefined;\r\n }\r\n\r\n public static clone(request: IAccessRequest): AccessRequest {\r\n return new AccessRequest(request);\r\n }\r\n\r\n public setLevel(level: TAccessLevel | TAccessLevel[]): AccessRequest {\r\n this.level = Array.isArray(level) ? level : [level];\r\n return this;\r\n }\r\n public addLevel(level: TAccessLevel | TAccessLevel[]): AccessRequest {\r\n this.level = [...this.level, ...(Array.isArray(level) ? level : [level])];\r\n return this;\r\n }\r\n public resource(resourceId: string): AccessRequest {\r\n this.resourceId = resourceId;\r\n\r\n return this;\r\n }\r\n public setCandidate(candidate: IAccessCandidate): AccessRequest {\r\n this.candidate = candidate;\r\n\r\n return this;\r\n }\r\n}\r\n","import { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AccessRequest } from './AccessRequest.class';\r\n\r\nexport class AccessCandidate implements IAccessCandidate {\r\n public role: TAccessRole;\r\n public id: string;\r\n //public _candidate: TAccessCandidate;\r\n constructor(candidate?: IAccessCandidate) {\r\n //this._candidate = candidate || { role: TAccessRole.Public, id: '' };\r\n\r\n this.role = candidate ? candidate.role : TAccessRole.Public;\r\n this.id = candidate ? candidate.id : '';\r\n }\r\n\r\n public toString(): string {\r\n return `AC:R[${this.role}]:ID[${this.id}]`;\r\n }\r\n\r\n public get request(): AccessRequest {\r\n return new AccessRequest(this);\r\n }\r\n\r\n public get readRequest(): AccessRequest {\r\n return new AccessRequest(this).setLevel(TAccessLevel.Read);\r\n }\r\n public get writeRequest(): AccessRequest {\r\n return new AccessRequest(this).setLevel(TAccessLevel.Write);\r\n }\r\n public get ownerRequest(): AccessRequest {\r\n return new AccessRequest(this).setLevel(TAccessLevel.Owner);\r\n }\r\n\r\n public static clone(candidate: IAccessCandidate): AccessCandidate {\r\n return new AccessCandidate(candidate);\r\n }\r\n\r\n public team(teamId: string): AccessCandidate {\r\n this.role = TAccessRole.Team;\r\n this.id = teamId;\r\n\r\n return this;\r\n }\r\n static team(teamId: string): AccessCandidate {\r\n return new AccessCandidate({ role: TAccessRole.Team, id: teamId });\r\n }\r\n\r\n public agent(agentId: string): AccessCandidate {\r\n this.role = TAccessRole.Agent;\r\n this.id = agentId;\r\n return this;\r\n }\r\n static agent(agentId: string): AccessCandidate {\r\n return new AccessCandidate({ role: TAccessRole.Agent, id: agentId });\r\n }\r\n\r\n public user(userId: string): AccessCandidate {\r\n this.role = TAccessRole.User;\r\n this.id = userId;\r\n return this;\r\n }\r\n static user(userId: string): AccessCandidate {\r\n return new AccessCandidate({ role: TAccessRole.User, id: userId });\r\n }\r\n\r\n public public(): AccessCandidate {\r\n this.role = TAccessRole.Public;\r\n\r\n //public is a special case we use the role as the owner id because public access does not have specific candidate IDs\r\n this.id = TAccessRole.Public;\r\n\r\n return this;\r\n }\r\n static public(): AccessCandidate {\r\n return new AccessCandidate({ role: TAccessRole.Public, id: '' });\r\n }\r\n}\r\n","import { LocalCache } from '@sre/helpers/LocalCache.helper';\r\nimport { Logger } from '../helpers/Log.helper';\r\nimport { createHash } from 'crypto';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nconst console = Logger('Connector');\r\n//const lCache = new LocalCache();\r\n\r\nexport class Connector<TRequest = any> {\r\n public name: string;\r\n public started = false;\r\n private _interactionHandler: () => void;\r\n private _readyPromise: Promise<boolean>;\r\n private static lCache = new LocalCache();\r\n\r\n public get settings() {\r\n return this._settings;\r\n }\r\n\r\n public get interactionHandler() {\r\n return this._interactionHandler;\r\n }\r\n\r\n //this flag is used to check if the connector is valid\r\n //when a connector fails to load, it is replaced by a DummyConnector instance which returns false for this flag\r\n public get valid() {\r\n return true;\r\n }\r\n\r\n constructor(protected _settings?: any) {\r\n //TODO : check if smyth runtime is initialized and throw an error if it is not\r\n }\r\n\r\n /**\r\n * If the connector is interactive, The connector initializer will wait for start() method to complete before loading the next connector\r\n */\r\n protected setInteraction(handler: () => void) {\r\n this._interactionHandler = handler;\r\n }\r\n /**\r\n * Creates a new instance of the current class using the provided settings.\r\n * This method can be called on both Connector instances and its subclasses.\r\n * This is used when we need to create a connector instance with a specific configuration (for example with user provided keys)\r\n *\r\n * @param settings - Configuration settings for the new instance.\r\n * @returns A new instance of the current class.\r\n */\r\n public instance(settings: any): this {\r\n const configHash = createHash('sha256')\r\n .update(JSON.stringify(settings || {}))\r\n .digest('hex');\r\n const key = `${this.name}-${configHash}`;\r\n\r\n if (Connector.lCache.has(key)) {\r\n return Connector.lCache.get(key) as this;\r\n }\r\n\r\n // if not in cache, create a new instance from the concrete class\r\n const constructor = this.constructor as { new (config: any): any };\r\n const instance = new constructor(settings);\r\n Connector.lCache.set(key, instance, 60 * 60 * 1000); // cache for 1 hour\r\n\r\n return instance;\r\n }\r\n\r\n static isValid(connector: Connector): boolean {\r\n return connector.name !== undefined && connector.name !== null && connector.name !== '';\r\n }\r\n\r\n public async start() {\r\n console.info(`Starting ${this.name} connector ...`);\r\n this.started = true;\r\n }\r\n\r\n public async stop() {\r\n console.info(`Stopping ${this.name} connector ...`);\r\n }\r\n\r\n public ready() {\r\n if (!this._readyPromise) {\r\n this._readyPromise = new Promise((resolve) => {\r\n let maxWait = 60000;\r\n const tick = 100;\r\n if (this.started) {\r\n resolve(true);\r\n } else {\r\n const interval = setInterval(() => {\r\n if (this.started) {\r\n clearInterval(interval);\r\n resolve(true);\r\n }\r\n\r\n maxWait -= tick;\r\n if (maxWait <= 0) {\r\n clearInterval(interval);\r\n resolve(false);\r\n }\r\n }, tick);\r\n }\r\n });\r\n }\r\n return this._readyPromise;\r\n }\r\n\r\n public requester(candidate: AccessCandidate): TRequest {\r\n return null as TRequest;\r\n }\r\n\r\n public user(candidate: AccessCandidate | string): TRequest {\r\n if (typeof candidate === 'string') {\r\n return this.requester(AccessCandidate.user(candidate));\r\n }\r\n return this.requester(candidate);\r\n }\r\n\r\n public team(teamId: string): TRequest {\r\n return this.requester(AccessCandidate.team(teamId));\r\n }\r\n\r\n public agent(agentId: string): TRequest {\r\n return this.requester(AccessCandidate.agent(agentId));\r\n }\r\n}\r\n","import { SmythLLMUsage, SmythTaskUsage } from '@sre/types/LLM.types';\r\nimport { TServiceRegistry } from '@sre/types/SRE.types';\r\nimport { EventEmitter } from 'events';\r\n\r\nexport type SystemEventMap = {\r\n 'SRE:Booted': [TServiceRegistry];\r\n 'SRE:Initialized': [];\r\n 'USAGE:LLM': [SmythLLMUsage];\r\n 'USAGE:API': any;\r\n 'USAGE:TASK': [SmythTaskUsage];\r\n};\r\n\r\nconst SystemEvents = new EventEmitter<SystemEventMap>();\r\n\r\nexport { SystemEvents };\r\n","import { SREConnectorConfig, TConnectorService, TServiceRegistry } from '@sre/types/SRE.types';\r\nimport { DummyConnector } from './DummyConnector';\r\nimport { Logger } from '../helpers/Log.helper';\r\nimport { Connector } from './Connector.class';\r\nimport { getFormattedStackTrace, isSubclassOf, printStackTrace } from '@sre/utils';\r\nimport { SystemEvents } from './SystemEvents';\r\nimport { StorageConnector } from '@sre/IO/Storage.service/StorageConnector';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport { LLMConnector } from '@sre/LLMManager/LLM.service/LLMConnector';\r\nimport { VaultConnector } from '@sre/Security/Vault.service/VaultConnector';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { AgentDataConnector } from '@sre/AgentManager/AgentData.service/AgentDataConnector';\r\nimport { VectorDBConnector } from '@sre/IO/VectorDB.service/VectorDBConnector';\r\nimport { CLIConnector } from '@sre/IO/CLI.service/CLIConnector';\r\nimport { NKVConnector } from '@sre/IO/NKV.service/NKVConnector';\r\nimport { RouterConnector } from '@sre/IO/Router.service/RouterConnector';\r\nimport { ManagedVaultConnector } from '@sre/Security/ManagedVault.service/ManagedVaultConnector';\r\nimport { LogConnector } from '@sre/IO/Log.service/LogConnector';\r\nimport { ComponentConnector } from '@sre/AgentManager/Component.service/ComponentConnector';\r\nimport { ModelsProviderConnector } from '@sre/LLMManager/ModelsProvider.service/ModelsProviderConnector';\r\nconst console = Logger('ConnectorService');\r\n\r\nlet ServiceRegistry: TServiceRegistry = {};\r\nlet _ready = false;\r\nSystemEvents.on('SRE:Booted', (services) => {\r\n ServiceRegistry = services;\r\n _ready = true;\r\n});\r\nexport class ConnectorService {\r\n public static Connectors = {};\r\n\r\n public static ConnectorInstances: any = {};\r\n public static get ready() {\r\n return _ready;\r\n }\r\n\r\n public static get service(): TServiceRegistry {\r\n return ServiceRegistry;\r\n }\r\n /**\r\n * Allows SRE services to register their connectors, a registered conector can then be initialized and used by SRE or its services\r\n * @param connectorType\r\n * @param connectorName\r\n * @param connectorConstructor\r\n * @returns\r\n */\r\n static register(connectorType: TConnectorService, connectorName: string, connectorConstructor: any) {\r\n if (typeof connectorConstructor !== 'function' || !isSubclassOf(connectorConstructor, Connector)) {\r\n console.error(`Invalid Connector ${connectorType}:${connectorName}`);\r\n return;\r\n }\r\n if (!ConnectorService.Connectors[connectorType]) {\r\n ConnectorService.Connectors[connectorType] = {};\r\n }\r\n ConnectorService.Connectors[connectorType][connectorName] = connectorConstructor;\r\n }\r\n\r\n /**\r\n * The init method instantiates a connector and starts it, a connector cannot be used before it is initialized\r\n * Usually the initialization phase happens during the SRE startup, but some connectors can be initialized later if they are not mandatory for the SRE to start\r\n *\r\n *\r\n * @param connectorType\r\n * @param connectorName\r\n * @param settings\r\n * @param isDefault\r\n * @returns\r\n */\r\n static init(connectorType: TConnectorService, connectorName: string, connectorId?: string, settings: any = {}, isDefault = false) {\r\n if (ConnectorService.ConnectorInstances[connectorType]?.[connectorName]) {\r\n throw new Error(`Connector ${connectorType}:${connectorName} already initialized`);\r\n }\r\n\r\n const entry = ConnectorService.Connectors[connectorType];\r\n if (!entry) return;\r\n const connectorConstructor = entry[connectorName];\r\n\r\n if (connectorConstructor) {\r\n const connector: Connector = new connectorConstructor(settings);\r\n if (connector.interactionHandler) {\r\n connector.interactionHandler();\r\n }\r\n\r\n connector.start();\r\n if (!ConnectorService.ConnectorInstances[connectorType]) ConnectorService.ConnectorInstances[connectorType] = {};\r\n const id = connectorId || connectorName;\r\n ConnectorService.ConnectorInstances[connectorType][id] = connector;\r\n\r\n if (!ConnectorService.ConnectorInstances[connectorType].default && isDefault) {\r\n ConnectorService.ConnectorInstances[connectorType].default = connector;\r\n }\r\n\r\n return connector;\r\n }\r\n }\r\n static async _stop() {\r\n for (let connectorName in ConnectorService.ConnectorInstances) {\r\n let allConnectors: Connector[] = Object.values(ConnectorService.ConnectorInstances[connectorName]);\r\n //deduplicate\r\n allConnectors = allConnectors.filter((value, index, self) => self.indexOf(value) === index);\r\n for (let connector of allConnectors) {\r\n connector.stop();\r\n }\r\n }\r\n }\r\n static getInstance<T>(connectorType: TConnectorService, connectorName: string = 'default'): T {\r\n const instance = ConnectorService.ConnectorInstances[connectorType]?.[connectorName || 'default'] as T;\r\n if (!instance) {\r\n //TODO only apply the fallback below if resilient mode is enabled\r\n // if (ConnectorService.ConnectorInstances[connectorType] && Object.keys(ConnectorService.ConnectorInstances[connectorType]).length > 0) {\r\n // //return the first instance\r\n // return ConnectorService.ConnectorInstances[connectorType][Object.keys(ConnectorService.ConnectorInstances[connectorType])[0]] as T;\r\n // }\r\n console.warn(`Connector ${connectorType} not initialized returning DummyConnector`);\r\n //print stack trace\r\n\r\n printStackTrace(console, 5);\r\n\r\n return DummyConnector(connectorType) as T;\r\n }\r\n return instance;\r\n }\r\n\r\n static getStorageConnector(name?: string): StorageConnector {\r\n return ConnectorService.getInstance<StorageConnector>(TConnectorService.Storage, name);\r\n }\r\n\r\n static getCacheConnector(name?: string): CacheConnector {\r\n return ConnectorService.getInstance<any>(TConnectorService.Cache, name);\r\n }\r\n\r\n static getVectorDBConnector(name?: string): VectorDBConnector {\r\n return ConnectorService.getInstance<VectorDBConnector>(TConnectorService.VectorDB, name);\r\n }\r\n\r\n static getNKVConnector(name?: string): NKVConnector {\r\n return ConnectorService.getInstance<NKVConnector>(TConnectorService.NKV, name);\r\n }\r\n\r\n static getLLMConnector(name?: string): LLMConnector {\r\n return ConnectorService.getInstance<LLMConnector>(TConnectorService.LLM, name);\r\n }\r\n\r\n static getVaultConnector(name?: string): VaultConnector {\r\n return ConnectorService.getInstance<VaultConnector>(TConnectorService.Vault, name);\r\n }\r\n\r\n static getManagedVaultConnector(name?: string): ManagedVaultConnector {\r\n return ConnectorService.getInstance<ManagedVaultConnector>(TConnectorService.ManagedVault, name);\r\n }\r\n\r\n static getAccountConnector(name?: string): AccountConnector {\r\n return ConnectorService.getInstance<AccountConnector>(TConnectorService.Account, name);\r\n }\r\n\r\n static getAgentDataConnector(name?: string): AgentDataConnector {\r\n return ConnectorService.getInstance<AgentDataConnector>(TConnectorService.AgentData, name);\r\n }\r\n\r\n static getCLIConnector(name?: string): CLIConnector {\r\n return ConnectorService.getInstance<CLIConnector>(TConnectorService.CLI, name);\r\n }\r\n\r\n static getLogConnector(name?: string): LogConnector {\r\n return ConnectorService.getInstance<LogConnector>(TConnectorService.Log, name);\r\n }\r\n\r\n static getComponentConnector(name?: string): ComponentConnector {\r\n return ConnectorService.getInstance<ComponentConnector>(TConnectorService.Component, name);\r\n }\r\n\r\n static getModelsProviderConnector(name?: string): ModelsProviderConnector {\r\n return ConnectorService.getInstance<ModelsProviderConnector>(TConnectorService.ModelsProvider, name);\r\n }\r\n\r\n static hasInstance(connectorType: TConnectorService, connectorName: string = 'default') {\r\n const instance = ConnectorService.ConnectorInstances[connectorType]?.[connectorName];\r\n return instance && instance.valid;\r\n }\r\n\r\n static getRouterConnector(name?: string): RouterConnector {\r\n return ConnectorService.getInstance<RouterConnector>(TConnectorService.Router, name);\r\n }\r\n}\r\n\r\nexport abstract class ConnectorServiceProvider {\r\n public abstract register();\r\n public init() {}\r\n public constructor() {\r\n this.register();\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '../AccessControl/AccessCandidate.class';\r\nimport axios from 'axios';\r\nimport config from '@sre/config';\r\nimport qs from 'qs';\r\n\r\nexport class VaultHelper {\r\n static async getTeamKey(key: string, teamId: string): Promise<string> {\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n return await vaultConnector.requester(AccessCandidate.team(teamId)).get(key);\r\n }\r\n\r\n static async getUserKey(key: string, userId: string): Promise<string> {\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n\r\n const teamId = await accountConnector.getCandidateTeam(AccessCandidate.user(userId));\r\n\r\n return await vaultConnector.requester(AccessCandidate.team(teamId)).get(key);\r\n }\r\n\r\n static async getAgentKey(key: string, agentId: string): Promise<string> {\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n\r\n const teamId = await accountConnector.getCandidateTeam(AccessCandidate.agent(agentId));\r\n\r\n return await vaultConnector.requester(AccessCandidate.team(teamId)).get(key);\r\n }\r\n}\r\n","import { VaultHelper } from '@sre/Security/Vault.service/Vault.helper';\r\n\r\nexport type TemplateStringMatch = RegExp;\r\n\r\nexport const Match = {\r\n default: /{{(.*?)}}/g,\r\n //matches all placeholders\r\n doubleCurly: /{{(.*?)}}/g,\r\n singleCurly: /{(.*?)}/g,\r\n doubleCurlyForSingleMatch: /{{(.*?)}}/,\r\n\r\n //matches component template variables\r\n //example of matching strings\r\n // {{VAULTINPUT:Input label:[APIKEY]}}\r\n // {{VARINPUT:Variable label:{ \"key\":\"value\" }}}\r\n templateVariables: /{{([A-Z]+):([\\w\\s]+):[\\[{](.*?)[\\]}]}}/gm,\r\n\r\n //matches only the placeholders that have a specific prefix\r\n prefix(prefix: string) {\r\n return new RegExp(`{{${prefix}(.*?)}}`, 'g');\r\n },\r\n\r\n //matches only the placeholders that have a specific suffix\r\n suffix(suffix: string) {\r\n return new RegExp(`{{(.*?)${suffix}}}`, 'g');\r\n },\r\n //matches only the placeholders that have a specific prefix and suffix\r\n prefSuf(prefix: string, suffix: string) {\r\n return new RegExp(`{{${prefix}(.*?)${suffix}}}`, 'g');\r\n },\r\n\r\n //matches a function annotation with a given name, just like prefix but with wrapping parenthesis\r\n fn(name: string) {\r\n return new RegExp(`{{${name}\\\\((.*?)\\\\)}}`, 'g');\r\n },\r\n};\r\n\r\nexport const TPLProcessor = {\r\n vaultTeam(teamId: string): (token) => Promise<string> {\r\n //the token here represents the vault key name\r\n return async (token) => {\r\n try {\r\n return await VaultHelper.getTeamKey(token, teamId);\r\n } catch (error) {\r\n return token;\r\n }\r\n };\r\n },\r\n componentTemplateVar(templateSettings: Record<string, any>): (token, matches) => Promise<string> {\r\n return async (token, matches) => {\r\n try {\r\n const label = matches[2]; //template variables are identified by their label inside the component config\r\n if (!label) return token;\r\n\r\n const entry: any = Object.values(templateSettings).find((o: any) => o.label == label);\r\n if (!entry) return token;\r\n return `{{${entry.id}}}`;\r\n } catch (error) {\r\n return token;\r\n }\r\n };\r\n },\r\n};\r\n\r\n/**\r\n * Provides a chainable to manipulate template strings\r\n *\r\n * Template strings are strings that can contain placeholders, which are expressions that get evaluated to produce a resulting string.\r\n * The placeholders are defined by double curly braces `{{` and `}}`.\r\n */\r\n\r\n//FIXME: async parsing breaks the chainability of the TemplateStringHelper\r\nexport class TemplateStringHelper {\r\n private _current: string;\r\n\r\n //this queue is used to wait for asyncronous results when async processors are used\r\n //if all processors are synchronous, this queue will be empty and .result getter can be used\r\n //if any processor is async, the .result getter will throw an error and you should use .asyncResult instead\r\n private _promiseQueue: Promise<any>[] = [];\r\n\r\n public get result(): string {\r\n if (this._promiseQueue.length <= 0) return this._current;\r\n throw new Error('This template object has async results, you should use .asyncResult with await instead of .result');\r\n }\r\n\r\n public get asyncResult(): Promise<string> {\r\n return new Promise(async (resolve, reject) => {\r\n await Promise.all(this._promiseQueue);\r\n resolve(this._current);\r\n });\r\n }\r\n\r\n private constructor(private templateString: string) {\r\n this._current = templateString;\r\n }\r\n\r\n public static create(templateString: string) {\r\n return new TemplateStringHelper(templateString);\r\n }\r\n\r\n /**\r\n * Parses a template string by replacing the placeholders with the values from the provided data object\r\n * unmatched placeholders will be left as is\r\n */\r\n public parse(data: Record<string, string>, regex: TemplateStringMatch = Match.default) {\r\n if (typeof this._current !== 'string' || typeof data !== 'object') return this;\r\n this._current = this._current.replace(regex, (match, token) => {\r\n const val = data?.[token] ?? match; // Use nullish coalescing to preserve falsy values (0, '', false)\r\n\r\n return typeof val === 'object' ? JSON.stringify(val) : escapeJsonField(val);\r\n });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Parses a template string by replacing placeholders with values from the provided data object, keeping the original raw values intact. This is particularly important for BinaryInput instances, as they include buffer data.\r\n * unmatched placeholders will be left as is\r\n */\r\n // Note: right now this method only match the first occurrence of the regex\r\n public parseRaw(data: Record<string, string>, regex: TemplateStringMatch = Match.doubleCurlyForSingleMatch) {\r\n if (typeof this._current !== 'string' || typeof data !== 'object') return this;\r\n\r\n const match = this._current.match(regex);\r\n const key = match ? match[1] : '';\r\n\r\n if (key) {\r\n const value = data?.[key];\r\n this._current = value;\r\n }\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * This is a shortcut function that parses vault key values and replace them with corresponding values from team vault\r\n * @param teamId\r\n * @returns\r\n */\r\n public parseTeamKeysAsync(teamId: string) {\r\n return this.process(TPLProcessor.vaultTeam(teamId), Match.fn('KEY'));\r\n }\r\n\r\n /**\r\n * This is a shortcut function that parses component template variables and replace them with their corresponding values\r\n * @param templateSettings the component template settings to be used for parsing\r\n * @returns\r\n */\r\n public parseComponentTemplateVarsAsync(templateSettings: Record<string, any>) {\r\n return this.process(TPLProcessor.componentTemplateVar(templateSettings), Match.templateVariables);\r\n }\r\n\r\n /**\r\n * Processes a template string by replacing the placeholders with the result of the provided processor function\r\n * The processor function receives the token as an argument and should return the value to replace the token with\r\n * If the processor function returns undefined, the token will be left as is\r\n */\r\n public process(processor: (token, matches?) => Promise<string> | string, regex: TemplateStringMatch = Match.default) {\r\n if (typeof this._current !== 'string') return this;\r\n //first build a json object with all matching tokens\r\n let tokens = {};\r\n let match;\r\n\r\n const prosessorPromises = [];\r\n while ((match = regex.exec(this._current)) !== null) {\r\n const token = match[1];\r\n tokens[token] = match[0];\r\n\r\n const _processor = processor(token, match);\r\n\r\n //if an async processor is used, the TemplateStringHelper switches to async mode\r\n if (_processor instanceof Promise) {\r\n _processor.then((result) => {\r\n if (result === undefined) {\r\n return match?.[0];\r\n }\r\n tokens[token] = result;\r\n });\r\n prosessorPromises.push(_processor);\r\n } else {\r\n tokens[token] = _processor;\r\n }\r\n }\r\n\r\n if (prosessorPromises.length > 0) {\r\n const promise = new Promise(async (resolve, reject) => {\r\n await Promise.all(prosessorPromises);\r\n this.parse(tokens, regex);\r\n resolve(true);\r\n });\r\n this._promiseQueue.push(Promise.all(prosessorPromises));\r\n } else {\r\n this.parse(tokens, regex);\r\n }\r\n\r\n // this._current = await asyncReplace(this._current, regex, async (match, token) => {\r\n // let result = await processor(token);\r\n // if (result === undefined) {\r\n // return match;\r\n // }\r\n // return result;\r\n // });\r\n\r\n return this;\r\n }\r\n\r\n /**\r\n * Removes all placeholders from the template string, leaving only the plain text\r\n * This is useful when you want to clean up a template string that has placeholders that were not parsed\r\n */\r\n public clean(regex: TemplateStringMatch = Match.default, replaceWith: string = '') {\r\n if (typeof this._current !== 'string') return this;\r\n this._current = this._current.replace(regex, replaceWith);\r\n return this;\r\n }\r\n\r\n // public toString() {\r\n // if (this._promiseQueue.length <= 0) return this._current;\r\n // return new Promise(async (resolve, reject) => {\r\n // await Promise.all(this._promiseQueue);\r\n // resolve(this._current);\r\n // });\r\n // }\r\n}\r\n\r\n/**\r\n * a helper function that takes a string and escape it\r\n * This is useful when you have a stringified json and want to replace one of its values while making sure it won't break the json structure (e.g new lines, double quotes ...etc)\r\n */\r\nexport function escapeString(str?: string) {\r\n if (!str) return str;\r\n return str.replace(/\\\\/g, '\\\\\\\\').replace(/\"/g, '\\\\\"').replace(/\\n/g, '\\\\n').replace(/\\r/g, '\\\\r').replace(/\\t/g, '\\\\t');\r\n}\r\n\r\n// This is used escape JSON values characters like double quotes '\"' to parse it properly\r\nexport function escapeJsonField(str?: string) {\r\n if (typeof str !== 'string') return str;\r\n return str.replace(/\\\\\"/g, '\"').replace(/\"/g, '\\\\\"');\r\n}\r\n\r\nexport function TemplateString(templateString: string) {\r\n return TemplateStringHelper.create(templateString);\r\n}\r\n","import { Agent } from './Agent.class';\r\n\r\nimport { encode } from 'gpt-tokenizer';\r\nimport { AgentCallLog } from '@sre/types/AgentLogger.types';\r\nimport { debounce, delay, getDayFormattedDate, uid } from '@sre/utils';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { StorageConnector } from '@sre/IO/Storage.service/StorageConnector';\r\nimport path from 'path';\r\n\r\nconst console = Logger('AgentLogger.class');\r\n\r\n//TODO : for performance optimization we should handle a non blocking logs queue\r\n// in the current implementation, the initial log line write is blocking, log update is non blocking\r\n\r\nclass LogTransaction {\r\n private _callId: string = '';\r\n private queue: any[] = [];\r\n private _isProcessing: boolean = false;\r\n private _lastPush: number = 0;\r\n private storage: StorageConnector;\r\n\r\n constructor(private agent: Agent, private trId: string) {\r\n this.storage = ConnectorService.getStorageConnector();\r\n }\r\n\r\n public async getCallId() {\r\n return this._callId;\r\n }\r\n\r\n public push(logData: AgentCallLog) {\r\n const logConnector = ConnectorService.getLogConnector();\r\n\r\n if (!logConnector.valid) return;\r\n\r\n this.queue.push(logData);\r\n this._lastPush = Date.now();\r\n this.processQueue();\r\n }\r\n\r\n private formatData(data: any, maxLength = 1000) {\r\n if (!data) return undefined;\r\n let result = typeof data == 'string' ? data : JSON.stringify(data);\r\n if (result.length > maxLength) {\r\n result = result.substr(0, maxLength) + '...';\r\n }\r\n return result;\r\n }\r\n\r\n private getDataFilePath(data: any, maxLength = 1000) {\r\n if (!data) return undefined;\r\n let str = typeof data == 'string' ? data : JSON.stringify(data);\r\n if (str.length > maxLength) {\r\n const dayFolder = getDayFormattedDate();\r\n const trId = 'L' + uid().toUpperCase();\r\n return `${dayFolder}/${trId}`;\r\n }\r\n return null;\r\n }\r\n\r\n private prepareData(firstData: AgentCallLog) {\r\n let sourceId = firstData.sourceId;\r\n let componentId = firstData.componentId;\r\n\r\n let input = firstData.input\r\n ? {\r\n preview: this.formatData(firstData.input),\r\n full: this.getDataFilePath(firstData.input),\r\n action: firstData.input.__action,\r\n status: firstData.input.__status,\r\n }\r\n : undefined;\r\n let output = firstData.output ? { preview: this.formatData(firstData.output), full: this.getDataFilePath(firstData.output) } : undefined;\r\n\r\n let domain = firstData.domain;\r\n let inputTimestamp = firstData.inputTimestamp;\r\n let outputTimestamp = firstData.outputTimestamp;\r\n let result = firstData.result\r\n ? JSON.stringify({ preview: this.formatData(firstData.result), full: this.getDataFilePath(firstData.result) })\r\n : undefined;\r\n let sessionID = firstData.sessionID;\r\n\r\n const sourceData = this.agent.components[sourceId];\r\n const componentData = this.agent.components[componentId];\r\n const sourceCptName = sourceData?.name;\r\n const componentCptName = componentData?.name;\r\n const sourceName = sourceData?.displayName || sourceData?.name || sourceId;\r\n const componentName = componentData?.displayName || componentData?.name || componentId;\r\n\r\n const curStepOrder = firstData.step || this.agent?.agentRuntime?.curStep || '';\r\n const nextStepOrder = curStepOrder + 1;\r\n if (sourceCptName) sourceId += `@${sourceCptName}@${curStepOrder}`;\r\n if (componentCptName) componentId += `@${componentCptName}@${nextStepOrder}`;\r\n\r\n const inputTokensObj = encode(typeof firstData.input == 'string' ? firstData.input : JSON.stringify(firstData.input) || '');\r\n const outputTokensObj = encode(typeof firstData.output == 'string' ? firstData.output : JSON.stringify(firstData.output) || '');\r\n const inputTokens = inputTokensObj.length || undefined;\r\n const outputTokens = outputTokensObj.length || undefined;\r\n\r\n const tags = firstData.tags || '';\r\n let raw_error =\r\n firstData.error ||\r\n firstData?.output?.error ||\r\n firstData?.output?._error ||\r\n firstData?.result?.error ||\r\n firstData?.result?.result?.error ||\r\n firstData?.result?._error ||\r\n firstData?.result?.result?._error;\r\n\r\n const error = raw_error ? JSON.stringify({ preview: this.formatData(raw_error), full: this.getDataFilePath(raw_error) }) : undefined;\r\n\r\n return {\r\n sourceId,\r\n componentId,\r\n domain,\r\n input,\r\n output,\r\n inputTimestamp,\r\n outputTimestamp,\r\n result,\r\n error,\r\n sourceName,\r\n componentName,\r\n sessionID,\r\n inputTokens,\r\n outputTokens,\r\n tags,\r\n workflowID: firstData.workflowID,\r\n processID: firstData.processID,\r\n raw_input: firstData.input,\r\n raw_output: firstData.output,\r\n raw_result: firstData.result,\r\n raw_error,\r\n };\r\n }\r\n\r\n private async storeLogData(filePath: string, content: any) {\r\n const logConnector = ConnectorService.getLogConnector();\r\n if (!logConnector.valid) return;\r\n\r\n if (!filePath) return;\r\n try {\r\n const body = typeof content == 'string' ? content : JSON.stringify(content);\r\n // setTeamPath(this.agent.teamId, `logs/${this.agent.id}`);\r\n // path.posix.join('teams', teamId, category ? category : '');\r\n const storagePath = path.posix.join('teams', this.agent.teamId, `logs/${this.agent.id}/${filePath}`);\r\n const metadata = { teamid: this.agent.teamId, agentid: this.agent.id, ContentType: 'text/plain' };\r\n await this.storage.requester(AccessCandidate.agent(this.agent.id)).write(storagePath, body, undefined, metadata);\r\n } catch (error) {\r\n console.error('Error storing Log File : ', filePath, error);\r\n }\r\n }\r\n\r\n public async processQueue() {\r\n const logConnector = ConnectorService.getLogConnector();\r\n if (!logConnector.valid || this.queue.length <= 0 || this._isProcessing) return;\r\n this._isProcessing = true;\r\n\r\n try {\r\n if (!this._callId) {\r\n const firstData = this.queue.shift();\r\n const data = this.prepareData(firstData);\r\n const raw_input = data.raw_input;\r\n const raw_output = data.raw_output;\r\n const raw_result = data.raw_result;\r\n const raw_error = data.raw_error;\r\n\r\n delete data.raw_input;\r\n delete data.raw_output;\r\n delete data.raw_result;\r\n delete data.raw_error;\r\n\r\n const resultObj = data.result ? JSON.parse(data.result) : undefined;\r\n const errorObj = data.error ? JSON.parse(data.error) : undefined;\r\n await this.storeLogData(data?.input?.full, raw_input);\r\n await this.storeLogData(data?.output?.full, raw_output);\r\n await this.storeLogData(resultObj?.full, raw_result);\r\n await this.storeLogData(errorObj?.full, raw_error);\r\n\r\n const logResult = await logConnector.requester(AccessCandidate.agent(this.agent.id)).log(data);\r\n\r\n this._callId = logResult?.data?.log?.id;\r\n } else {\r\n while (this.queue.length > 0) {\r\n const logData = this.queue.shift();\r\n const data = this.prepareData(logData);\r\n\r\n Object.keys(data).forEach((key) => {\r\n if (!data[key]) delete data[key];\r\n });\r\n\r\n const raw_input = data.raw_input;\r\n const raw_output = data.raw_output;\r\n const raw_result = data.raw_result;\r\n const raw_error = data.raw_error;\r\n\r\n delete data.raw_input;\r\n delete data.raw_output;\r\n delete data.raw_result;\r\n delete data.raw_error;\r\n\r\n const resultObj = data.result ? JSON.parse(data.result) : undefined;\r\n const errorObj = data.error ? JSON.parse(data.error) : undefined;\r\n await this.storeLogData(data?.input?.full, raw_input);\r\n await this.storeLogData(data?.output?.full, raw_output);\r\n await this.storeLogData(resultObj?.full, raw_result);\r\n await this.storeLogData(errorObj?.full, raw_error);\r\n\r\n await logConnector.requester(AccessCandidate.agent(this.agent.id)).log(data, this._callId);\r\n }\r\n }\r\n } catch (error) {\r\n console.error('Error processing log queue:', error?.response?.data?.message || error);\r\n }\r\n\r\n this._isProcessing = false;\r\n debounce(this.processQueue.bind(this), 1000, { leading: true, trailing: true, maxWait: 10000 });\r\n\r\n await delay(1000);\r\n this.processQueue();\r\n }\r\n\r\n public canDelete() {\r\n if (this.queue.length > 0) {\r\n this.processQueue();\r\n return false;\r\n }\r\n return this._lastPush != 0 && this._lastPush + 1000 * 60 * 60 * 1 < Date.now();\r\n }\r\n}\r\nexport class AgentLogger {\r\n private static transactions: any = {};\r\n private static cleanupInterval: NodeJS.Timeout;\r\n constructor(private agent: Agent) {}\r\n\r\n // private static setupCleanupInterval() {\r\n // if (this.cleanupInterval) return;\r\n // this.cleanupInterval = setInterval(\r\n // () => {\r\n // this.cleanup();\r\n // },\r\n // 1000 * 60 * 1,\r\n // ); //every 1 minute\r\n // }\r\n public static async cleanup() {\r\n const logConnector = ConnectorService.getLogConnector();\r\n if (!logConnector.valid) return;\r\n const trIds = Object.keys(AgentLogger.transactions);\r\n for (const trId of trIds) {\r\n const transaction = AgentLogger.transactions[trId];\r\n if (transaction.canDelete()) {\r\n delete AgentLogger.transactions[trId];\r\n }\r\n }\r\n }\r\n public static log(agent, trId, logData: AgentCallLog) {\r\n const logConnector = ConnectorService.getLogConnector();\r\n if (!logConnector.valid) return;\r\n if (agent.agentRuntime.debug) logData.tags = 'DEBUG ';\r\n if (!trId) trId = 'log-' + uid();\r\n if (!this.transactions[trId]) {\r\n this.transactions[trId] = new LogTransaction(agent, trId);\r\n }\r\n this.transactions[trId].push(logData);\r\n\r\n //ensure that a cleanup interval is running\r\n //this.setupCleanupInterval();\r\n debounce(this.cleanup.bind(this), 1000, { leading: true, trailing: true, maxWait: 10000 * 1 });\r\n return trId;\r\n }\r\n public static async logTask(agent: Agent, tasks) {\r\n // const token = (await getM2MToken('https://api.smyth.ai')) as string;\r\n // const day = new Date().toISOString().split('T')[0] + 'T00:00:00.000Z';\r\n // const logData = {\r\n // number: tasks,\r\n // day,\r\n // };\r\n // if (!agent.usingTestDomain) {\r\n // //only log tasks if debug session is not enabled\r\n // mwSysAPI.put(`/quota/agent/${agent.id}/tasks`, logData, includeAuth(token)).catch((error) => {\r\n // console.error('Error in AgentLogger.logTask() function: ', error?.response?.data?.message);\r\n // });\r\n // }\r\n const logConnector = ConnectorService.getLogConnector();\r\n if (!logConnector.valid) return;\r\n\r\n if (!agent.usingTestDomain) {\r\n // only report if on a non test domain\r\n await logConnector.requester(AccessCandidate.agent(agent.id)).logTask(tasks, agent.usingTestDomain);\r\n }\r\n\r\n //ensure that a cleanup interval is running\r\n //this.setupCleanupInterval();\r\n debounce(this.cleanup.bind(this), 1000, { leading: true, trailing: true, maxWait: 10000 * 1 });\r\n }\r\n}\r\n","import EventEmitter from 'events';\r\nimport { delay, uid } from '@sre/utils';\r\nimport { AgentRuntime } from '@sre/AgentManager/AgentRuntime.class';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { CacheConnector } from './Cache.service/CacheConnector';\r\n\r\nconst console = Logger('RuntimeContext');\r\n\r\ntype TRuntimeData = {\r\n input?: { [key: string]: any };\r\n _LoopData?: any;\r\n _ChildLoopData?: any;\r\n};\r\ntype TComponentContext = {\r\n active: boolean;\r\n name: string;\r\n runtimeData?: TRuntimeData;\r\n step: number;\r\n input?: { [key: string]: any };\r\n output?: { [key: string]: any };\r\n};\r\nexport class RuntimeContext extends EventEmitter {\r\n public circularLimitReached: string | boolean = false;\r\n public step: number = 0;\r\n public sessionResult: boolean = false;\r\n public sessionResults: any;\r\n public components: { [id: string]: { ctx: TComponentContext } } = {};\r\n\r\n public checkRuntimeContext: any = null;\r\n\r\n private ctxFile: string = '';\r\n private _runtimeFileReady: any;\r\n private _cacheConnector: CacheConnector;\r\n\r\n private _readyPromise: Promise<boolean>;\r\n\r\n constructor(private runtime: AgentRuntime) {\r\n super();\r\n const agent = runtime.agent;\r\n\r\n this._cacheConnector = ConnectorService.getCacheConnector();\r\n\r\n const processRootID = runtime.processID?.split(':')[0] || '';\r\n const reqId = processRootID == runtime.xDebugId ? '' : '.' + uid() + runtime.reqTag;\r\n\r\n this.ctxFile = `${runtime.xDebugId}${reqId}${agent.jobID ? `-job-${agent.jobID}` : ''}`;\r\n\r\n this._readyPromise = new Promise((resolve, reject) => {\r\n let resolved = false;\r\n this.on('ready', () => {\r\n resolved = true;\r\n resolve(true);\r\n });\r\n const timer = setTimeout(() => {\r\n if (!resolved) {\r\n reject(new Error('Agent Runtime context initialization timeout'));\r\n }\r\n }, 5 * 60 * 1000);\r\n timer.unref(); //unblock the event loop\r\n });\r\n\r\n this.initRuntimeContext();\r\n }\r\n\r\n private serialize() {\r\n const data = {\r\n step: this.step,\r\n sessionResult: this.sessionResult,\r\n sessionResults: this.sessionResults,\r\n components: this.components,\r\n };\r\n\r\n return data;\r\n }\r\n private deserialize(data: any) {\r\n this.step = data.step;\r\n this.sessionResult = data.sessionResult;\r\n this.sessionResults = data.sessionResults;\r\n this.components = data.components;\r\n }\r\n private reset() {\r\n this.step = 0;\r\n this.sessionResult = false;\r\n this.sessionResults = null;\r\n this.components = {};\r\n }\r\n\r\n private initRuntimeContext() {\r\n if (this._runtimeFileReady) return;\r\n\r\n const endpointDBGCall = this.runtime.xDebugId?.startsWith('dbg-'); //weak check for debug session, we need to improve this\r\n console.debug('Init ctxFile', this.ctxFile);\r\n const agent = this.runtime.agent;\r\n let method = (agent.agentRequest.method || 'POST').toUpperCase();\r\n const endpoint = agent.endpoints?.[agent.agentRequest.path]?.[method];\r\n\r\n let ctxData: any = {};\r\n\r\n this._cacheConnector\r\n .requester(AccessCandidate.agent(this.runtime.agent.id))\r\n .get(this.ctxFile)\r\n .then(async (data) => {\r\n if (!data) {\r\n ctxData = JSON.parse(JSON.stringify({ components: agent.components, connections: agent.connections, timestamp: Date.now() }));\r\n if (!ctxData.step) ctxData.step = 0;\r\n for (let cptId in ctxData.components) {\r\n ctxData.components[cptId] = {\r\n id: cptId,\r\n name: ctxData.components[cptId].name,\r\n //dbg: { active: false, name: ctxData.components[cptId].name },\r\n ctx: { active: false, name: ctxData.components[cptId].name },\r\n };\r\n\r\n const cpt = ctxData.components[cptId];\r\n //if this debug session was initiated from an endpoint, we mark the endpoint component as active\r\n if (endpoint && endpoint.id != undefined && cpt.id == endpoint.id && endpointDBGCall) {\r\n //cpt.dbg.active = true;\r\n cpt.ctx.active = true;\r\n }\r\n }\r\n //fs.writeFileSync(this.ctxFile, JSON.stringify(ctxData, null, 2));\r\n await this._cacheConnector\r\n .requester(AccessCandidate.agent(this.runtime.agent.id))\r\n .set(this.ctxFile, JSON.stringify(ctxData, null, 2), null, null, 6 * 60 * 60); //expires in 6 hours max\r\n } else {\r\n ctxData = JSON.parse(data);\r\n if (!ctxData.step) ctxData.step = 0;\r\n }\r\n\r\n this.deserialize(ctxData);\r\n this._runtimeFileReady = true;\r\n this.emit('ready');\r\n });\r\n\r\n // if (!fs.existsSync(this.ctxFile)) {\r\n // ctxData = JSON.parse(JSON.stringify({ components: agent.components, connections: agent.connections, timestamp: Date.now() }));\r\n // if (!ctxData.step) ctxData.step = 0;\r\n // for (let cptId in ctxData.components) {\r\n // ctxData.components[cptId] = {\r\n // id: cptId,\r\n // name: ctxData.components[cptId].name,\r\n // //dbg: { active: false, name: ctxData.components[cptId].name },\r\n // ctx: { active: false, name: ctxData.components[cptId].name },\r\n // };\r\n\r\n // const cpt = ctxData.components[cptId];\r\n // //if this debug session was initiated from an endpoint, we mark the endpoint component as active\r\n // if (endpoint && endpoint.id != undefined && cpt.id == endpoint.id && endpointDBGCall) {\r\n // //cpt.dbg.active = true;\r\n // cpt.ctx.active = true;\r\n // }\r\n // }\r\n // fs.writeFileSync(this.ctxFile, JSON.stringify(ctxData, null, 2));\r\n // } else {\r\n // ctxData = JSON.parse(fs.readFileSync(this.ctxFile, 'utf8'));\r\n // if (!ctxData.step) ctxData.step = 0;\r\n // }\r\n\r\n // this.deserialize(ctxData);\r\n // this._runtimeFileReady = true;\r\n // this.emit('ready');\r\n }\r\n\r\n public async ready() {\r\n if (this._runtimeFileReady) return true;\r\n return this._readyPromise;\r\n }\r\n public async sync() {\r\n if (!this.ctxFile) return;\r\n this.emit('syncing');\r\n\r\n const deleteSession = this.runtime.sessionClosed;\r\n\r\n if (deleteSession) {\r\n const exists = await this._cacheConnector.requester(AccessCandidate.agent(this.runtime.agent.id)).exists(this.ctxFile);\r\n\r\n if (exists) {\r\n if (this.runtime.debug)\r\n this._cacheConnector\r\n .requester(AccessCandidate.agent(this.runtime.agent.id))\r\n .updateTTL(this.ctxFile, 5 * 60); //expires in 5 minute\r\n else this._cacheConnector.requester(AccessCandidate.agent(this.runtime.agent.id)).delete(this.ctxFile);\r\n //if (this.runtime.debug && fs.existsSync(this.ctxFile)) await delay(1000 * 60); //if we're in debug mode, we keep the file for a while to allow final state read\r\n //if (fs.existsSync(this.ctxFile)) fs.unlinkSync(this.ctxFile);\r\n }\r\n } else {\r\n const data = this.serialize();\r\n //if (data) fs.writeFileSync(this.ctxFile, JSON.stringify(data, null, 2));\r\n if (data)\r\n await this._cacheConnector\r\n .requester(AccessCandidate.agent(this.runtime.agent.id))\r\n .set(this.ctxFile, JSON.stringify(data, null, 2), null, null, 6 * 60 * 60); //expires in 6 hours max\r\n }\r\n }\r\n\r\n public incStep() {\r\n this.step++;\r\n this.sync();\r\n }\r\n\r\n public updateComponent(componentId: string, data: any) {\r\n const ctxData = this;\r\n if (!ctxData) return;\r\n const component = ctxData.components[componentId];\r\n\r\n if (!component) {\r\n console.log('>>>>>>> updateComponent Component debug data not found', componentId, component);\r\n console.log('>>> ctxFile', this.ctxFile);\r\n console.log('>>> ctxData', ctxData);\r\n }\r\n component.ctx = { ...component.ctx, ...data, step: this.step };\r\n\r\n //if (this.debug) component.dbg = { ...component.dbg, ...data };\r\n\r\n this.sync();\r\n }\r\n public resetComponent(componentId: string) {\r\n const ctxData = this;\r\n const component = ctxData.components[componentId];\r\n if (!component) {\r\n console.log('>>>>>>> resetComponent Component debug data not found', componentId, component);\r\n console.log('>>> ctxFile', this.ctxFile);\r\n console.log('>>> ctxData', ctxData);\r\n }\r\n //component.dbg.active = false;\r\n //component.dbg.runtimeData = {};\r\n component.ctx.runtimeData = {};\r\n component.ctx.active = false;\r\n\r\n this.sync();\r\n }\r\n\r\n public getComponentData(componentId: string) {\r\n const ctxData = this;\r\n if (!ctxData) return null;\r\n const component = ctxData.components[componentId];\r\n if (!component) {\r\n console.log('>>>>>>> getComponentData Component debug data not found', componentId, component);\r\n console.log('>>> ctxFile', this.ctxFile);\r\n console.log('>>> ctxData', ctxData);\r\n }\r\n //const data = this.debug ? component.dbg : component.ctx;\r\n const data = component.ctx;\r\n\r\n return data;\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { CacheConnector } from './Cache.service/CacheConnector';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { uid } from '@sre/utils/index';\r\n\r\nexport type LLMCacheObject = {\r\n ttl: number;\r\n data: any;\r\n};\r\n\r\nexport class LLMCache {\r\n private _cacheConnector: CacheConnector;\r\n private _cacheId: string;\r\n private _ttl: number;\r\n private _candidate: AccessCandidate;\r\n\r\n public get id() {\r\n return this._cacheId;\r\n }\r\n\r\n /**\r\n * Creates a new LLMCache instace for a smythOS actor, the actor can be an agent, a user or a team\r\n * This is mainly use with agent to maintain a cache of the current LLM context\r\n *\r\n * This class can be used to share llm contexts data accross multiple instances of an agent, or between a ConversationHelper and a remote agent\r\n *\r\n * @param candidate\r\n * @param cacheId\r\n * @param ttl\r\n */\r\n constructor(candidate: AccessCandidate, cacheId?: string, ttl: number = 1 * 60 * 60) {\r\n this._cacheConnector = ConnectorService.getCacheConnector();\r\n this._cacheId = cacheId || 'llm_cache_' + uid();\r\n this._ttl = ttl;\r\n this._candidate = candidate;\r\n }\r\n\r\n async set(key: string, data: any) {\r\n if (!this._cacheConnector.valid) return;\r\n\r\n await this._cacheConnector\r\n .requester(this._candidate)\r\n .set(`${this._cacheId}:${key}`, typeof data === 'object' ? JSON.stringify(data) : data, null, null, this._ttl);\r\n }\r\n async get(key: string, format: 'json' | 'text' = 'json') {\r\n if (!this._cacheConnector.valid) return;\r\n\r\n const obj = await this._cacheConnector.requester(this._candidate).get(`${this._cacheId}:${key}`);\r\n let result;\r\n if (format === 'json') {\r\n try {\r\n result = JSON.parse(obj);\r\n } catch (e) {\r\n console.warn(`Invalid JSON data for key ${key}`);\r\n result = null;\r\n }\r\n } else {\r\n result = obj;\r\n }\r\n return result;\r\n }\r\n async delete(key: string) {\r\n if (!this._cacheConnector.valid) return;\r\n\r\n await this._cacheConnector.requester(this._candidate).delete(`${this._cacheId}:${key}`);\r\n }\r\n async clear() {\r\n if (!this._cacheConnector.valid) return;\r\n\r\n await this._cacheConnector.requester(this._candidate).delete(this._cacheId);\r\n }\r\n}\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { Agent } from './Agent.class';\r\nimport { Component } from '@sre/Components/Component.class';\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { uid } from '@sre/utils';\r\nimport { RuntimeContext } from '@sre/MemoryManager/RuntimeContext';\r\nimport { LLMCache } from '@sre/MemoryManager/LLMCache';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nconst console = Logger('AgentRuntime');\r\nconst AgentRuntimeUnavailable = new Proxy(\r\n {},\r\n {\r\n get: function (target, prop, receiver) {\r\n // Check if the property being accessed is a function\r\n if (typeof target[prop] === 'function') {\r\n return target[prop];\r\n } else {\r\n // Return a function that logs \"unavailable\"\r\n return function () {\r\n console.warn(`AgentRuntime Unavailable tried to call : ${prop.toString()}`);\r\n };\r\n }\r\n },\r\n },\r\n);\r\nexport class AgentRuntime {\r\n private static processResults: any = {};\r\n private static tagsData = {};\r\n public static dummy = AgentRuntimeUnavailable;\r\n\r\n private agentContext: RuntimeContext;\r\n public llmCache: LLMCache;\r\n //private ctxFile: string = '';\r\n private xDebugRun: string | undefined = '';\r\n private xDebugInject: string | undefined = '';\r\n private xDebugRead: string | undefined = '';\r\n private xDebugStop: string | undefined = '';\r\n private xDebugPendingInject: any = null;\r\n private xMockDataInject: any = null;\r\n public xDebugId: string | undefined = '';\r\n\r\n private xDebugCmd: string | undefined = '';\r\n private _debugActive = false;\r\n private _runtimeFileReady = false;\r\n public sessionClosed = false;\r\n\r\n private reqTagOwner = false;\r\n\r\n //reqTag is used to identify the current running workflow including nested calls, it allows us to identify circular calls\r\n public reqTag: any;\r\n public processID: any; //this identifies the current processID, a process ID is the full set of runCycles that is executed by the agent.\r\n public workflowReqId: any; //this identifies the current running workflow. a workflow starts when and agent endpoint is called, or a debug session is initiated, and ends when no more steps can be executed.\r\n\r\n public alwaysActiveComponents: any = {};\r\n public exclusiveComponents: any = {};\r\n\r\n private checkRuntimeContext: any = null;\r\n\r\n public get circularLimitReached() {\r\n return this.agentContext?.circularLimitReached || false;\r\n }\r\n public set circularLimitReached(value) {\r\n if (this.agentContext) this.agentContext.circularLimitReached = value;\r\n }\r\n\r\n public get debug() {\r\n return this._debugActive;\r\n }\r\n public get curStep() {\r\n return this.agentContext?.step || 0;\r\n }\r\n\r\n constructor(public agent: Agent) {\r\n this.reqTag = agent.agentRequest.header('X-REQUEST-TAG');\r\n const isNestedProcess: boolean = !!this.reqTag;\r\n\r\n if (!this.reqTag) {\r\n //tagged request should not be run in debug mode, this comes from a parent agent\r\n this.xDebugStop = agent.agentRequest.header('X-DEBUG-STOP');\r\n this.xDebugRun = agent.agentRequest.header('X-DEBUG-RUN'); //send this as header to create a session and attach it\r\n this.xDebugInject = agent.agentRequest.header('X-DEBUG-INJ');\r\n this.xDebugRead = agent.agentRequest.header('X-DEBUG-READ');\r\n this.reqTag = 'xTAG-' + uid(); //if request tag is not set, set a new value, this will be used to tag nested agent calls\r\n this.reqTagOwner = true;\r\n } else {\r\n this.xDebugStop = undefined;\r\n this.xDebugRun = undefined;\r\n this.xDebugInject = undefined;\r\n this.xDebugRead = undefined;\r\n }\r\n\r\n this.xDebugId = this.xDebugStop || this.xDebugRun || this.xDebugRead;\r\n\r\n //if (req.body) {\r\n if (!this.xDebugId && agent.agentRequest.body) {\r\n if (this.xDebugInject != undefined && this.xDebugInject != null) {\r\n this.xDebugPendingInject = agent.agentRequest.body;\r\n this.xDebugRun = this.xDebugInject || 'inj-' + uid();\r\n } else {\r\n if (this.xDebugRun == '') {\r\n this.xDebugRun = 'dbg-' + uid(); //generate a random debug id\r\n }\r\n }\r\n this.xDebugId = this.xDebugRun;\r\n }\r\n\r\n if (agent.agentRequest.header('X-MOCK-DATA-INJ') !== undefined) {\r\n this.xMockDataInject = agent.agentRequest.body;\r\n }\r\n\r\n this.processID = this.xDebugId;\r\n\r\n if (!this.xDebugId) {\r\n //if it's not a debug session, processID is unique per request\r\n this.xDebugId = agent.sessionId;\r\n this.processID = this.reqTag;\r\n }\r\n if (isNestedProcess) {\r\n // Need to make processID unique to run same sub-agents multiple times in parallel\r\n this.processID += `:${Math.floor(1000 + Math.random() * 9000)}`;\r\n }\r\n\r\n //we need a way to identify current running workflow in a unique way\r\n //=> In debug mode, xDebugRun holds the debug sessionID which is unique per workflow run\r\n // if the debug session is stopped, xDebugStop holds the sessionID\r\n // Note : We can't use reqTag in debug mode because it changes every time a new debug step is executed\r\n //\r\n //=> In normal mode, reqTag is unique per workflow run\r\n this.workflowReqId = this.xDebugRun || this.xDebugStop || this.reqTag;\r\n\r\n //tagsData can be updated from external integrations (eg. Chatbot, API Endpoint, etc.)\r\n if (!AgentRuntime.tagsData[this.reqTag]) AgentRuntime.tagsData[this.reqTag] = {};\r\n if (!AgentRuntime.processResults[this.processID])\r\n AgentRuntime.processResults[this.processID] = {\r\n timestamp: Date.now(),\r\n errorResults: [],\r\n sessionResults: [],\r\n };\r\n\r\n this.agentContext = new RuntimeContext(this);\r\n this.agentContext.on('ready', () => {\r\n this.alwaysActiveComponents = {};\r\n this.exclusiveComponents = {};\r\n for (let component of this.agent.data.components) {\r\n const cpt: Component = this.agent.ComponentInstances[component.name];\r\n if (!cpt) {\r\n console.warn(`Component ${component.name} Exists in agent but has no implementation`);\r\n continue;\r\n }\r\n\r\n if (cpt.alwaysActive) {\r\n this.alwaysActiveComponents[component.id] = cpt;\r\n this.updateComponent(component.id, { active: true, alwaysActive: true });\r\n const runtimeData = { ...this.getRuntimeData(component.id) };\r\n this.saveRuntimeComponentData(component.id, runtimeData);\r\n }\r\n if (cpt.exclusive) {\r\n this.exclusiveComponents[component.id] = cpt;\r\n this.updateComponent(component.id, { exclusive: true });\r\n const runtimeData = { ...this.getRuntimeData(component.id) };\r\n this.saveRuntimeComponentData(component.id, runtimeData);\r\n }\r\n }\r\n });\r\n\r\n //if xDebugId is equal to agent session, it means that the debugging features are not active\r\n this._debugActive = this.xDebugId != agent.sessionId;\r\n\r\n const xCacheId = agent.agentRequest.header('X-CACHE-ID') || '';\r\n this.llmCache = new LLMCache(AccessCandidate.agent(this.agent.id), xCacheId);\r\n //this.xCacheId =\r\n }\r\n\r\n public async ready() {\r\n return this.agentContext.ready();\r\n }\r\n\r\n public destroy() {\r\n this.sessionClosed = true;\r\n this.sync();\r\n }\r\n\r\n public incTag(componentId) {\r\n if (!AgentRuntime.tagsData[this.reqTag][componentId]) AgentRuntime.tagsData[this.reqTag][componentId] = 0;\r\n AgentRuntime.tagsData[this.reqTag][componentId]++;\r\n\r\n // console.log(\r\n // `incTag agentId=${this.agent.id} componentId=${componentId} tag=${this.reqTag} ==> ${AgentRuntime.tagsData[this.reqTag][componentId]}`,\r\n // );\r\n //console.log('incTag tagsData', tagsData);\r\n }\r\n\r\n public async sync() {\r\n //if (!this.ctxFile) return;\r\n\r\n const deleteTag = (this.reqTagOwner && this.sessionClosed) || this.circularLimitReached;\r\n if (deleteTag) {\r\n console.log('>>>>>>>>>>>> deleting tagsData', this.reqTag);\r\n delete AgentRuntime.tagsData[this.reqTag];\r\n }\r\n\r\n this.agentContext.sync();\r\n }\r\n public getWaitingComponents() {\r\n const ctxData = this.agentContext;\r\n const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);\r\n const waitingComponents: any = dbgComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);\r\n return waitingComponents;\r\n }\r\n public getExclusiveActiveComponents() {\r\n const ctxData = this.agentContext;\r\n const dbgComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);\r\n const exclusiveActiveComponents: any = dbgComponents.filter((c: any) => c?.ctx?.exclusive == true);\r\n return exclusiveActiveComponents;\r\n }\r\n public readState(stateId: string, deltaOnly = false) {\r\n //if (!this._debugActive || !this.xDebugRead) return null;\r\n if (!this._debugActive || !stateId) return null;\r\n\r\n //this.checkRuntimeContext();\r\n const runtime = this;\r\n const agent = this.agent;\r\n\r\n const ctxData = runtime.agentContext;\r\n const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);\r\n\r\n //first try to find exclusive active components\r\n let dbgActiveComponents: any;\r\n dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);\r\n //if no exclusive active components, find all active components\r\n if (!dbgActiveComponents || dbgActiveComponents.length == 0)\r\n dbgActiveComponents = dbgAllComponents.filter(\r\n (c: any) =>\r\n c?.ctx?.active == true ||\r\n (!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0),\r\n );\r\n //find waiting components that was not previously run\r\n const dbgActiveWaitingComponents: any = dbgAllComponents.filter(\r\n (c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined,\r\n );\r\n\r\n const dbgActiveReadyComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);\r\n\r\n let state = {};\r\n for (let dbgComponent of dbgAllComponents) {\r\n state[dbgComponent.id] = dbgComponent.ctx;\r\n }\r\n\r\n //let dbgSession: any = runtime.xDebugRead;\r\n let dbgSession: any = stateId;\r\n\r\n // let alwaysActiveComponents = 0;\r\n // for (let activeCpt of dbgActiveComponents) {\r\n // if (this.agent.alwaysActiveComponents[activeCpt.id]) alwaysActiveComponents++;\r\n // }\r\n\r\n if (!dbgActiveComponents || dbgActiveComponents.length == 0 /*|| dbgActiveComponents.length == alwaysActiveComponents*/) {\r\n dbgSession = null;\r\n runtime.sessionClosed = true;\r\n }\r\n\r\n const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter(\r\n (c: any) => c?.ctx?.active == true && !c?.ctx?.alwaysActive,\r\n );\r\n const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(\r\n (c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0,\r\n );\r\n\r\n if (remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/) {\r\n runtime.sessionClosed = true;\r\n }\r\n\r\n if (runtime.circularLimitReached) {\r\n const circularLimitData = runtime.checkCircularLimit();\r\n const error = `Circular Calls Limit Reached on ${circularLimitData}. Current agent circular limit is ${agent.circularLimit}`;\r\n runtime.sessionClosed = true;\r\n return { state, dbgSession, sessionClosed: runtime.sessionClosed, error };\r\n }\r\n\r\n const step = this.curStep >= 1 ? this.curStep - 1 : 0; //current state was executed in previous step\r\n\r\n if (deltaOnly) {\r\n const delta = {};\r\n for (let cptId in state) {\r\n const cpt = state[cptId];\r\n\r\n //workaround, here we are supposed to test component steps that are equalt to current step\r\n //but due to an inconsistency, the Async component has sometimes a step greater than the current step\r\n if (cpt.step >= step) delta[cptId] = cpt;\r\n //FIXME : identify the root cause of this issue and replace >= with ==\r\n }\r\n //return { state: delta, dbgSession, sessionClosed: runtime.sessionClosed, step };\r\n state = delta;\r\n }\r\n\r\n return { state, dbgSession, sessionClosed: runtime.sessionClosed, step };\r\n }\r\n\r\n /**\r\n * This method is called by the agent to run a process cycle, it will run all active components and return the results\r\n * The function is called multiple times until all components are executed and no more active components are available\r\n * @returns\r\n */\r\n public async runCycle() {\r\n console.debug(\r\n `runCycle agentId=${this.agent.id} wfReqId=${this.workflowReqId} reqTag=${this.reqTag} session=${this.xDebugRun} cycleId=${this.processID}`,\r\n );\r\n //this.checkRuntimeContext();\r\n\r\n const runtime = this;\r\n const agent = this.agent;\r\n const ctxData = runtime.agentContext;\r\n const dbgAllComponents: any = runtime.xDebugPendingInject || Object.values(ctxData?.components || []);\r\n\r\n //first try to find exclusive active components\r\n let dbgActiveComponents: any;\r\n dbgActiveComponents = dbgAllComponents.filter((c: any) => c?.ctx?.active == true && c?.ctx?.exclusive == true);\r\n //if no exclusive active components, find all active components\r\n if (!dbgActiveComponents || dbgActiveComponents.length == 0)\r\n dbgActiveComponents = dbgAllComponents.filter(\r\n (c: any) =>\r\n c?.ctx?.active == true ||\r\n (!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0),\r\n );\r\n //find waiting components that was not previously run\r\n const dbgActiveWaitingComponents: any = dbgAllComponents.filter(\r\n (c: any) => c?.ctx?.active == true && c?.ctx?.status && typeof c?.ctx?.output !== undefined,\r\n );\r\n const dbgActiveReadyComponents: any = dbgAllComponents.filter(\r\n (c: any) =>\r\n (c?.ctx?.active == true && !c?.ctx?.status) ||\r\n (!c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0),\r\n );\r\n //const dbgActiveReadyComponents: any = dbgActiveComponents.filter((c: any) => c?.ctx?.active == true && !c?.ctx?.status);\r\n\r\n let step: any;\r\n\r\n if (!dbgActiveComponents || dbgActiveComponents.length == 0) {\r\n runtime.sessionClosed = true;\r\n step = {\r\n state: { sessionClosed: true },\r\n dbgSession: null,\r\n //expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,\r\n expiredDbgSession: runtime.xDebugId,\r\n sessionClosed: true,\r\n };\r\n }\r\n\r\n if (!step && dbgActiveComponents.length == dbgActiveWaitingComponents.length && ctxData.sessionResult) {\r\n runtime.sessionClosed = true;\r\n step = {\r\n state: { sessionClosed: true },\r\n dbgSession: null,\r\n //expiredDbgSession: runtime.xDebugRun,\r\n expiredDbgSession: runtime.xDebugId,\r\n sessionClosed: true,\r\n };\r\n }\r\n if (!step && dbgActiveReadyComponents.length > 0) {\r\n const promises: any = [];\r\n\r\n for (let dbgComponent of dbgActiveReadyComponents) {\r\n const injectInput = runtime.xDebugPendingInject ? dbgComponent.ctx.input : undefined;\r\n\r\n promises.push(agent.callComponent(dbgComponent.ctx.sourceId, dbgComponent.id, injectInput));\r\n }\r\n const dbgResults = await Promise.all(promises);\r\n const state = dbgResults.length == 1 ? dbgResults[0] : dbgResults;\r\n\r\n runtime.xDebugPendingInject = null;\r\n\r\n const remainingActiveComponents: any = Object.values(ctxData?.components || []).filter((c: any) => c?.ctx?.active == true);\r\n const activeAsyncComponents: any = Object.values(ctxData?.components || []).filter(\r\n (c: any) => !c?.ctx?.output?._error && Array.isArray(c?.ctx?._job_components) && c?.ctx?._job_components.length > 0,\r\n );\r\n const dbgActiveWaitingComponents: any = dbgAllComponents.filter((c: any) => c?.ctx?.status && typeof c?.ctx?.output !== undefined);\r\n\r\n if (dbgActiveWaitingComponents.length == remainingActiveComponents.length) {\r\n ctxData.sessionResult = true;\r\n }\r\n\r\n //capture results\r\n let sessionResults = dbgResults.flat().filter(\r\n (e) =>\r\n e.id &&\r\n e.result &&\r\n !e.result._missing_inputs &&\r\n //check if this is the last component in the chain\r\n !agent.connections.find((c) => c.sourceId == e.id),\r\n );\r\n\r\n let errorResults = dbgResults.flat().filter((e) => e.id && (e.error || e.result?._error));\r\n\r\n //also filter out erroneous components that are children of a loop\r\n //otherwise, errors inside a loop will be reported as session results and can lead to wrong results or generated noise in the final agent output\r\n errorResults = errorResults.filter((e) => {\r\n return !ctxData?.components?.[e.id]?.ctx?.runtimeData?._ChildLoopData;\r\n });\r\n\r\n if (ctxData.sessionResult && sessionResults.length == 0 && runtime.sessionClosed) {\r\n //no result ? check if we have errors\r\n sessionResults = errorResults;\r\n }\r\n\r\n ctxData.sessionResults = sessionResults;\r\n step = {\r\n state,\r\n dbgSession: runtime.xDebugRun,\r\n sessionResult: runtime.agentContext.sessionResult,\r\n sessionResults: runtime.agentContext.sessionResults,\r\n errorResults,\r\n sessionClosed: remainingActiveComponents.length == 0 && activeAsyncComponents.length == 0 /*&& awaitingInputs.length == 0*/,\r\n };\r\n } else {\r\n runtime.sessionClosed = true;\r\n //return { sessionClosed: true };\r\n step = {\r\n state: { sessionClosed: true },\r\n dbgSession: null,\r\n //expiredDbgSession: runtime.xDebugRun || runtime.xDebugStop,\r\n expiredDbgSession: runtime.xDebugId,\r\n sessionClosed: true,\r\n };\r\n }\r\n\r\n this.checkCircularLimit();\r\n if (step.sessionResults) {\r\n AgentRuntime.processResults[this.processID].sessionResults.push(step.sessionResults);\r\n }\r\n if (step.errorResults) {\r\n AgentRuntime.processResults[this.processID].errorResults.push(step.errorResults);\r\n }\r\n\r\n if (step?.sessionClosed || this.circularLimitReached) {\r\n const finalResult = this.processResults();\r\n step.finalResult = finalResult;\r\n runtime.sessionClosed = true;\r\n }\r\n\r\n this.incStep();\r\n this.sync();\r\n return step;\r\n }\r\n\r\n private processResults() {\r\n //this.checkCircularLimit();\r\n let result: any = { error: 'Error processing results' };\r\n const sessionResults = AgentRuntime.processResults[this.processID].sessionResults;\r\n const errorResults = AgentRuntime.processResults[this.processID].errorResults;\r\n if (this.circularLimitReached) {\r\n const circularLimitData = this.circularLimitReached;\r\n result = { error: `Circular Calls Limit Reached on ${circularLimitData}. Current circular limit is ${this.agent.circularLimit}` };\r\n } else {\r\n let state = [sessionResults, errorResults].flat(Infinity);\r\n if (!state || state.length == 0) state = errorResults.flat(Infinity);\r\n\r\n //post process run cycle results\r\n //deduplicating redundant entries\r\n\r\n const data = state\r\n .reduce(\r\n (acc, current) => {\r\n if (!acc.seen[current.id]) {\r\n acc.result.push(current);\r\n acc.seen[current.id] = true;\r\n }\r\n return acc;\r\n },\r\n { seen: {}, result: [] },\r\n )\r\n .result.filter((e) => !e.result?._exclude);\r\n\r\n //data.forEach((d: any) => delete d?.result?._debug);\r\n\r\n result = data;\r\n /////////////\r\n }\r\n\r\n //cleanup\r\n delete AgentRuntime.processResults[this.processID];\r\n\r\n this.sync();\r\n return result;\r\n }\r\n\r\n public checkCircularLimit() {\r\n if (this.circularLimitReached) return this.agentContext.circularLimitReached;\r\n for (let componentId in AgentRuntime.tagsData[this.reqTag]) {\r\n if (AgentRuntime.tagsData[this.reqTag][componentId] > this.agent.circularLimit) {\r\n this.sessionClosed = true;\r\n this.agentContext.circularLimitReached = componentId;\r\n return componentId;\r\n }\r\n }\r\n return false;\r\n }\r\n\r\n public async injectDebugOutput(componentId: string) {\r\n let component: {\r\n ctx?: Record<string, any>;\r\n } = {};\r\n\r\n if (this.xDebugPendingInject) {\r\n component = this.xDebugPendingInject?.find((c: any) => c.id == componentId);\r\n } else if (this.xMockDataInject) {\r\n component = this.xMockDataInject?.find((c: any) => c.id == componentId);\r\n }\r\n\r\n if (component?.ctx?.output) {\r\n //if all outputs values are empty, we don't inject\r\n let allEmpty = true;\r\n for (let key in component.ctx.output) {\r\n if (component.ctx.output[key] != '') {\r\n allEmpty = false;\r\n break;\r\n }\r\n }\r\n if (allEmpty) return null;\r\n\r\n return component.ctx.output;\r\n }\r\n }\r\n public getRuntimeData(componentId) {\r\n const componentData = this.getComponentData(componentId);\r\n if (!componentData) return {};\r\n const rData = componentData.runtimeData || {};\r\n\r\n return rData;\r\n }\r\n public updateRuntimeData(componentId, data) {\r\n const componentData = this.getComponentData(componentId);\r\n if (!componentData) return;\r\n componentData.runtimeData = { ...componentData.runtimeData, ...data };\r\n\r\n this.sync();\r\n }\r\n\r\n public saveRuntimeComponentData(componentId, data) {\r\n this.updateComponent(componentId, { runtimeData: data });\r\n }\r\n\r\n public incStep() {\r\n this.agentContext.incStep();\r\n }\r\n public updateComponent(componentId: string, data: any) {\r\n this.agentContext.updateComponent(componentId, data);\r\n }\r\n\r\n public resetComponent(componentId: string) {\r\n this.agentContext.resetComponent(componentId);\r\n }\r\n\r\n public getComponentData(componentId: string) {\r\n return this.agentContext.getComponentData(componentId);\r\n }\r\n}\r\n","import os from 'os';\r\nimport process from 'process';\r\n\r\nconst OSResourceMonitor: any = {\r\n mem: getMemoryUsage(),\r\n //processMemory: getProcessMemoryUsage(),\r\n cpu: getCpuUsage(),\r\n //processCpu: getProcessCpuUsage(),\r\n};\r\nexport { OSResourceMonitor };\r\n\r\nfunction getCpuUsage() {\r\n const cpus = os.cpus();\r\n let user = 0;\r\n let nice = 0;\r\n let sys = 0;\r\n let idle = 0;\r\n let irq = 0;\r\n let total = 0;\r\n\r\n for (let cpu of cpus) {\r\n user += cpu.times.user;\r\n nice += cpu.times.nice;\r\n sys += cpu.times.sys;\r\n idle += cpu.times.idle;\r\n irq += cpu.times.irq;\r\n }\r\n\r\n total = user + nice + sys + idle + irq;\r\n\r\n return {\r\n user: (user / total) * 100,\r\n sys: (sys / total) * 100,\r\n idle: (idle / total) * 100,\r\n load: 100 - (idle / total) * 100,\r\n };\r\n}\r\n\r\nfunction getMemoryUsage() {\r\n const totalMemory = os.totalmem();\r\n const freeMemory = os.freemem();\r\n const usedMemory = totalMemory - freeMemory;\r\n\r\n return {\r\n totalMemory: (totalMemory / 1024 ** 3).toFixed(2) + ' GB',\r\n freeMemory: (freeMemory / 1024 ** 3).toFixed(2) + ' GB',\r\n usedMemory: (usedMemory / 1024 ** 3).toFixed(2) + ' GB',\r\n memoryUsagePercentage: ((usedMemory / totalMemory) * 100).toFixed(2),\r\n };\r\n}\r\n\r\nfunction getProcessMemoryUsage() {\r\n const memoryUsage = process.memoryUsage();\r\n return {\r\n total: memoryUsage.rss,\r\n heapTotal: (memoryUsage.heapTotal / 1024 ** 2).toFixed(2) + ' MB',\r\n heapUsed: (memoryUsage.heapUsed / 1024 ** 2).toFixed(2) + ' MB',\r\n external: (memoryUsage.external / 1024 ** 2).toFixed(2) + ' MB',\r\n };\r\n}\r\n\r\nfunction getProcessCpuUsage() {\r\n const cpuUsage = process.cpuUsage();\r\n return {\r\n user: cpuUsage.user,\r\n system: cpuUsage.system,\r\n };\r\n}\r\n\r\nfunction logSystemUsage() {\r\n OSResourceMonitor.mem = getMemoryUsage();\r\n OSResourceMonitor.cpu = getCpuUsage();\r\n //OSResourceMonitor.processMemory = getProcessMemoryUsage();\r\n //OSResourceMonitor.processCpu = getProcessCpuUsage();\r\n}\r\n\r\n//setInterval(logSystemUsage, 5000); // update every 5 seconds\r\n","import { Agent } from './Agent.class';\r\n\r\nexport class AgentSSE {\r\n private connections: Map<string, any> = new Map();\r\n\r\n /**\r\n * Creates a new AgentSSE instance\r\n * @param agent - The agent instance this SSE belongs to\r\n */\r\n constructor(private agent: Agent) {}\r\n\r\n /**\r\n * Updates or adds a response object with the given monitor ID\r\n * Maintains backward compatibility by also setting the res property\r\n * @param res - The response object to add or update\r\n * @param monitorId - The monitor ID associated with this connection\r\n * @returns The connection ID that was created or updated\r\n */\r\n public add(res: any, monitorId: string) {\r\n // Store the connection\r\n this.connections.set(monitorId, res);\r\n }\r\n\r\n public [Symbol.iterator](): IterableIterator<[string, any]> {\r\n return this.connections.entries();\r\n }\r\n\r\n /**\r\n * Sends an event to all connected clients\r\n * @param _type - The event type\r\n * @param _data - The event data\r\n */\r\n public async send(_type: string, _data: any): Promise<void> {\r\n if (!_type || !_data) return;\r\n\r\n // Format the data once\r\n const data = typeof _data === 'string' ? _data : JSON.stringify(_data);\r\n const message = `event: ${_type}\\ndata: ${data}\\n\\n`;\r\n\r\n // Send to all connections\r\n for (const [id, connection] of this.connections.entries()) {\r\n try {\r\n if (connection && !connection.finished) {\r\n connection.write(message);\r\n } else {\r\n // Remove closed connections\r\n this.connections.delete(id);\r\n }\r\n } catch (error) {\r\n // Handle errors (connection might be closed)\r\n console.error(`Error sending SSE to connection ${id}:`, error);\r\n this.connections.delete(id);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * Removes a specific connection\r\n * @param connectionId - The ID of the connection to remove\r\n * @returns True if the connection was found and removed, false otherwise\r\n */\r\n public remove(connectionId: string): boolean {\r\n const connection = this.connections.get(connectionId);\r\n if (connection) {\r\n try {\r\n if (connection && !connection.finished) {\r\n connection.end();\r\n }\r\n } catch (error) {\r\n console.error(`Error closing connection ${connectionId}:`, error);\r\n }\r\n return this.connections.delete(connectionId);\r\n }\r\n return false;\r\n }\r\n\r\n /**\r\n * Closes all connections\r\n */\r\n public async close(): Promise<void> {\r\n for (const [id, connection] of this.connections.entries()) {\r\n try {\r\n if (connection && !connection.finished) {\r\n connection.end();\r\n console.log('Delibertly shutting down sse connection with id: ', id);\r\n }\r\n } catch (error) {\r\n console.error(`Error closing connection ${id}:`, error);\r\n }\r\n }\r\n this.connections.clear();\r\n }\r\n\r\n /**\r\n * Gets the number of active connections\r\n * @returns The number of active connections\r\n */\r\n public getConnectionCount(): number {\r\n return this.connections.size;\r\n }\r\n}\r\n","import { Component } from '@sre/Components/Component.class';\r\nimport { AgentLogger } from './AgentLogger.class';\r\nimport { AgentRequest } from './AgentRequest.class';\r\nimport { AgentRuntime } from './AgentRuntime.class';\r\nimport { AgentSettings } from './AgentSettings.class';\r\nimport { OSResourceMonitor } from './OSResourceMonitor';\r\nimport config from '@sre/config';\r\nimport { ControlledPromise, delay, getCurrentFormattedDate, uid } from '@sre/utils/index';\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { AgentSSE } from './AgentSSE.class';\r\nimport { IAgent } from '@sre/types/Agent.types';\r\nimport { IModelsProviderRequest, ModelsProviderConnector } from '@sre/LLMManager/ModelsProvider.service/ModelsProviderConnector';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nconst console = Logger('Agent');\r\nconst idPromise = (id) => id;\r\n\r\nexport class Agent implements IAgent {\r\n public name: any;\r\n public data: any;\r\n public teamId: any;\r\n public components: any;\r\n public connections: any;\r\n public endpoints: any = {};\r\n public sessionId;\r\n public sessionTag = '';\r\n public callerSessionId;\r\n public apiBasePath = '/api';\r\n public agentRuntime: AgentRuntime | any;\r\n\r\n public usingTestDomain = false;\r\n public domain = '';\r\n public debugSessionEnabled = false;\r\n public circularLimit = 100; //TODO : make it configurable from agent settings\r\n public version = '';\r\n\r\n //public baseUrl = '';\r\n public agentVariables: any = {};\r\n private _kill = false;\r\n //public agentRequest: Request | AgentRequest | any;\r\n public async = false;\r\n public jobID = '';\r\n public planInfo: any = {};\r\n public callback: (data: any) => void;\r\n\r\n public agentRequest: AgentRequest;\r\n public sse: AgentSSE;\r\n public modelsProvider: IModelsProviderRequest;\r\n\r\n private _componentInstance = {};\r\n\r\n public get ComponentInstances() {\r\n return this._componentInstance;\r\n }\r\n\r\n private _componentInstancesLoader = new ControlledPromise(() => {});\r\n\r\n constructor(\r\n public id,\r\n agentData,\r\n public agentSettings: AgentSettings,\r\n agentRequest?: AgentRequest | any //private req: express.Request,\r\n ) {\r\n //this.agentRequest = new AgentRequest(req);\r\n const json = typeof agentData === 'string' ? JSON.parse(agentData) : agentData;\r\n this.data = json.connections && json.components ? json : json.data;\r\n if (!this.data) this.data = { name: '', connections: [], components: [] };\r\n //this.agentVariables = json.data.variables || {};\r\n\r\n this.name = this.data.name;\r\n this.version = this.data.agentVersion || ''; //when version is not set we load the latest dev version\r\n this.teamId = this.data.teamId;\r\n this.connections = this.data.connections;\r\n this.debugSessionEnabled = this.data.debugSessionEnabled;\r\n this.usingTestDomain = this.data.usingTestDomain;\r\n\r\n this.agentVariables = this.data.variables || {};\r\n\r\n const endpoints = this.data.components.filter((c) => c.name == 'APIEndpoint');\r\n for (let endpoint of endpoints) {\r\n let method = endpoint.data.method || 'POST';\r\n method = method.toUpperCase();\r\n if (!this.endpoints[`${this.apiBasePath}/${endpoint.data.endpoint}`])\r\n this.endpoints[`${this.apiBasePath}/${endpoint.data.endpoint}`] = {};\r\n this.endpoints[`${this.apiBasePath}/${endpoint.data.endpoint}`][method] = endpoint;\r\n }\r\n\r\n this.components = {};\r\n for (let component of this.data.components) {\r\n //FIXME : this does not persist in debug mode, it breaks key value mem logic\r\n\r\n this.components[component.id] = component;\r\n }\r\n\r\n for (let connection of this.data.connections) {\r\n const sourceComponent = this.components[connection.sourceId];\r\n const targetComponent = this.components[connection.targetId];\r\n\r\n //if connections ids passed as names, we convert them to indexes\r\n //TODO : harmonize connections formats\r\n const sourceIndex =\r\n typeof connection.sourceIndex === 'number'\r\n ? connection.sourceIndex\r\n : sourceComponent.outputs.findIndex((o) => o.name == connection.sourceIndex);\r\n const targetIndex =\r\n typeof connection.targetIndex === 'number'\r\n ? connection.targetIndex\r\n : targetComponent.inputs.findIndex((i) => i.name == connection.targetIndex);\r\n\r\n connection.sourceIndex = sourceIndex;\r\n connection.targetIndex = targetIndex;\r\n\r\n const output = sourceComponent.outputs[sourceIndex];\r\n output.index = sourceIndex; // legacy ids (numbers)\r\n\r\n const input = targetComponent.inputs[targetIndex];\r\n input.index = targetIndex;\r\n\r\n if (!output.next) output.next = [];\r\n output.next.push(targetComponent.id);\r\n\r\n if (!input.prev) input.prev = [];\r\n input.prev.push(sourceComponent.id);\r\n }\r\n\r\n this.tagAsyncComponents();\r\n\r\n if (agentRequest) {\r\n this.setRequest(agentRequest);\r\n }\r\n\r\n this.sse = new AgentSSE(this);\r\n //this.settings = new AgentSettings(this.id);\r\n\r\n try {\r\n //add hosted components to the available instances\r\n //hosted components are custom components that are specific to some SRE instances implementations : e.g Shell component is only available to local SRE\r\n const componentConnector = ConnectorService.getComponentConnector();\r\n componentConnector\r\n .requester(AccessCandidate.agent(id))\r\n .getAll()\r\n .then((customComponents) => {\r\n this._componentInstance = { ...this._componentInstance, ...customComponents };\r\n this._componentInstancesLoader.resolve(true);\r\n });\r\n } catch (error) {\r\n console.warn('Could not load custom components');\r\n this._componentInstancesLoader.reject('Could not load custom components');\r\n }\r\n\r\n const modelsProvider: ModelsProviderConnector = ConnectorService.getModelsProviderConnector();\r\n if (modelsProvider.valid) {\r\n this.modelsProvider = modelsProvider.agent(id);\r\n }\r\n }\r\n\r\n /**\r\n * Add a SSE connection to the agent\r\n * @param sseSource - The SSE source to add\r\n * @param monitorId - The monitor ID to add\r\n */\r\n public addSSE(sseSource: Response | AgentSSE, monitorId?: string) {\r\n if (sseSource instanceof AgentSSE) {\r\n for (const [monitorId, res] of sseSource) {\r\n this.sse.add(res, monitorId); // add each connection to the new sse\r\n }\r\n } else {\r\n const id = monitorId || Math.random().toString(36).substring(2, 15);\r\n this.sse.add(sseSource, id);\r\n }\r\n }\r\n public setRequest(agentRequest: AgentRequest | any) {\r\n if (this.agentRequest) return;\r\n this.agentRequest = agentRequest;\r\n this.agentRequest = agentRequest;\r\n const dateTime = getCurrentFormattedDate();\r\n this.sessionId = 'rt-' + (this.agentRequest.sessionID || dateTime + '.' + uid());\r\n\r\n const sessionTags = this?.agentRequest?.headers['x-session-tag'];\r\n if (sessionTags) this.sessionTag += this.sessionTag ? `,${sessionTags}` : sessionTags;\r\n\r\n var regex = new RegExp(`^\\/v[0-9]+(\\.[0-9]+)?${this.apiBasePath}\\/(.*)`);\r\n if (this.agentRequest?.path?.startsWith(`${this.apiBasePath}/`) || this.agentRequest?.path?.match(regex)) {\r\n //we only need runtime context for API calls\r\n this.agentRuntime = new AgentRuntime(this);\r\n this.callerSessionId =\r\n this?.agentRequest?.headers['x-caller-session-id']?.substring(0, 256) || this.agentRuntime.workflowReqId || this.sessionId;\r\n } else {\r\n this.agentRuntime = AgentRuntime.dummy;\r\n }\r\n }\r\n public setCallback(callback: (data: any) => void) {\r\n this.callback = callback;\r\n }\r\n\r\n public kill() {\r\n this._kill = true;\r\n }\r\n public isKilled() {\r\n return this._kill;\r\n }\r\n private async parseVariables() {\r\n //parse vault agent variables\r\n if (typeof this.agentVariables === 'object') {\r\n for (let key in this.agentVariables) {\r\n const value = this.agentVariables[key];\r\n if (value.startsWith('{{') && value.endsWith('}}')) {\r\n //this.agentVariables[key] = (await parseKey(value, this.teamId)) || '';\r\n this.agentVariables[key] = await TemplateString(value).parseTeamKeysAsync(this.teamId).asyncResult;\r\n }\r\n }\r\n }\r\n }\r\n\r\n async process(endpointPath, input) {\r\n await this.agentRuntime.ready();\r\n\r\n //TODO: replace endpointPath + input params with a single agentRequest object. (This will require intensive regression testing)\r\n let result: any;\r\n let dbgSession: any = null;\r\n let sessionClosed = false;\r\n\r\n const eventId = 'e-' + uid();\r\n const startTime = Date.now();\r\n\r\n this.sse.send('agent', {\r\n eventId,\r\n action: 'callStart',\r\n endpointPath,\r\n id: this.id,\r\n name: this.name,\r\n startTime,\r\n input,\r\n });\r\n //this.agentRuntime.checkRuntimeContext();\r\n //insert log\r\n const logId = AgentLogger.log(this, null, {\r\n sourceId: endpointPath,\r\n componentId: `AGENT`,\r\n domain: this.domain,\r\n input,\r\n workflowID: this.agentRuntime.workflowReqId,\r\n processID: this.agentRuntime.processID,\r\n inputTimestamp: new Date().toISOString(),\r\n sessionID: this.callerSessionId,\r\n tags: this.sessionTag,\r\n });\r\n\r\n const method = this.agentRequest.method.toUpperCase();\r\n const endpoint = this.endpoints[endpointPath]?.[method];\r\n\r\n //first check if this is a debug session, and return debug result if it's the case\r\n if (this.agentRuntime.debug) {\r\n if (!endpoint && this.agentRequest.path != '/api/') {\r\n if (logId) AgentLogger.log(this, logId, { error: `Endpoint ${method} ${endpointPath} Not Found` });\r\n\r\n throw new Error(`Endpoint ${method} ${endpointPath} Not Found`);\r\n }\r\n let dbgResult: any;\r\n //let dbgResult: any = await this.agentRuntime.readState(true); //is this a debug read reqeust ?\r\n\r\n if (!dbgResult) dbgResult = await this.agentRuntime.runCycle(); //no, is this a step over request ?\r\n\r\n // result = dbgResult?.state;\r\n // dbgSession = dbgResult?.dbgSession;\r\n // sessionClosed = dbgResult?.sessionClosed;\r\n if (dbgResult && typeof dbgResult?.state !== 'undefined') {\r\n this.agentRuntime.sync();\r\n if (dbgResult?.finalResult) {\r\n dbgResult.finalResult = await this.postProcess(dbgResult.finalResult).catch((error) => ({ error }));\r\n }\r\n return dbgResult;\r\n }\r\n }\r\n\r\n if (!endpoint) {\r\n if (logId) AgentLogger.log(this, logId, { error: `Endpoint ${method} ${endpointPath} Not Found` });\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('agent', {\r\n eventId,\r\n action: 'callStop',\r\n endpointPath,\r\n id: this.id,\r\n name: this.name,\r\n startTime,\r\n endTime,\r\n duration,\r\n input,\r\n error: `Endpoint ${method} ${endpointPath} Not Found`,\r\n });\r\n throw new Error(`Endpoint ${method} ${endpointPath} Not Found`);\r\n }\r\n\r\n this.agentRuntime.updateComponent(endpoint.id, { active: true, input, sourceId: null });\r\n\r\n let step;\r\n do {\r\n step = await this.agentRuntime.runCycle();\r\n\r\n //adjust latency based on cpu load\r\n const qosLatency = Math.floor(OSResourceMonitor.cpu.load * this.planInfo?.maxLatency || 0);\r\n\r\n await delay(30 + qosLatency);\r\n } while (!step?.finalResult && !this._kill);\r\n\r\n if (this._kill) {\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('agent', {\r\n eventId,\r\n action: 'callStop',\r\n endpointPath,\r\n id: this.id,\r\n name: this.name,\r\n startTime,\r\n endTime,\r\n duration,\r\n input,\r\n error: 'Agent killed',\r\n });\r\n console.warn(`Agent ${this.id} was killed`);\r\n return { error: 'Agent killed' };\r\n }\r\n result = await this.postProcess(step?.finalResult).catch((error) => ({ error }));\r\n\r\n //post process all results\r\n if (this.agentRuntime.circularLimitReached) {\r\n const circularLimitData = this.agentRuntime.circularLimitReached;\r\n result = { error: `Circular Calls Limit Reached on ${circularLimitData}. Current circular limit is ${this.circularLimit}` };\r\n\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('agent', {\r\n eventId,\r\n action: 'callStop',\r\n endpointPath,\r\n id: this.id,\r\n name: this.name,\r\n startTime,\r\n endTime,\r\n duration,\r\n input,\r\n error: result.error,\r\n });\r\n\r\n throw new Error(`Circular Calls Limit Reached on ${circularLimitData}. Current circular limit is ${this.circularLimit}`);\r\n }\r\n\r\n if (logId) AgentLogger.log(this, logId, { outputTimestamp: '' + Date.now(), result });\r\n\r\n this.updateTasksCount(); //Important, don't use await here, we need the call to be non blocking\r\n\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('agent', {\r\n eventId,\r\n action: 'callStop',\r\n endpointPath,\r\n id: this.id,\r\n name: this.name,\r\n startTime,\r\n endTime,\r\n duration,\r\n input,\r\n result,\r\n });\r\n\r\n //FIXME: does debug call ever reach this point ?\r\n return this.agentRuntime.debug ? { state: result, dbgSession, sessionClosed } : result;\r\n }\r\n\r\n private async updateTasksCount() {\r\n //tasks count update logic\r\n }\r\n\r\n public async postProcess(result) {\r\n if (Array.isArray(result)) result = result.flat(Infinity);\r\n if (!Array.isArray(result)) result = [result];\r\n\r\n //filter out handled errors\r\n result = result.filter((r) => !(r?.result?._error && r?.result?._error_handled));\r\n\r\n for (let i = 0; i < result.length; i++) {\r\n const _result = result[i];\r\n if (!_result) continue;\r\n if (_result._debug) delete _result._debug;\r\n if (_result._debug_time) delete _result._debug_time;\r\n const _componentData = this.components[_result.id];\r\n if (!_componentData) continue;\r\n const _component: Component = this._componentInstance[_componentData.name];\r\n if (!_component) continue;\r\n //if (_component.hasPostProcess) {\r\n const postProcessResult = await _component.postProcess(_result, _componentData, this).catch((error) => ({ error }));\r\n\r\n result[i] = postProcessResult;\r\n //}\r\n }\r\n\r\n if (result.length == 1) result = result[0];\r\n return result;\r\n }\r\n\r\n // public saveRuntimeComponentData(componentId, data) {\r\n // //let runtimeData = { ...this.agentRuntime.getRuntimeData(componentId), ...data };\r\n // //this.agentRuntime.updateComponent(componentId, { runtimeData: data });\r\n\r\n // this.agentRuntime.saveRuntimeComponentData(componentId, data);\r\n // }\r\n // private getRuntimeData(componentId) {\r\n // // const componentData = this.agentRuntime.getComponentData(componentId);\r\n // // if (!componentData) return {};\r\n // // const rData = componentData.runtimeData || {};\r\n\r\n // return this.agentRuntime.getRuntimeData(componentId);\r\n // }\r\n\r\n // private clearRuntimeComponentData(componentId) {\r\n // this.agentRuntime.resetComponent(componentId);\r\n // }\r\n\r\n private hasLoopAncestor(inputEntry) {\r\n if (!inputEntry.prev) return false;\r\n for (let prevId of inputEntry.prev) {\r\n const prevComponentData = this.components[prevId];\r\n if (prevComponentData.name == 'ForEach') return true;\r\n\r\n for (let inputEntry of prevComponentData.inputs) {\r\n if (this.hasLoopAncestor(inputEntry)) return true;\r\n }\r\n }\r\n }\r\n\r\n private clearChildLoopRuntimeComponentData(componentId) {\r\n const componentData = this.components[componentId];\r\n const runtimeData = this.agentRuntime.getRuntimeData(componentId);\r\n if (runtimeData._ChildLoopData) {\r\n for (let inputEntry of componentData.inputs) {\r\n if (this.hasLoopAncestor(inputEntry)) {\r\n delete runtimeData.input[inputEntry.name];\r\n }\r\n }\r\n }\r\n }\r\n private getComponentMissingInputs(componentId, _input) {\r\n let missingInputs: any = [];\r\n const componentData = this.components[componentId];\r\n const component: Component = this._componentInstance[componentData.name];\r\n if (component.alwaysActive) return missingInputs;\r\n\r\n const readablePredecessors = this.findReadablePredecessors(componentId);\r\n const readableInputNames = {};\r\n for (let pred of readablePredecessors) {\r\n if (pred) {\r\n readableInputNames[pred.input.name] = pred;\r\n }\r\n }\r\n //readablePredecessors.map((e) => e.input.name);\r\n\r\n const allInputIndexes = this.connections.filter((c) => c.targetId == componentId).map((e) => e.targetIndex);\r\n const allInputs = componentData.inputs.filter((r) => allInputIndexes.includes(r.index));\r\n\r\n if (Array.isArray(allInputs) && allInputs.length > 0) {\r\n //if the next component has named inputs\r\n for (let input of allInputs) {\r\n if (input.optional) continue;\r\n if (readableInputNames[input.name]) {\r\n const pred = readableInputNames[input.name];\r\n const component: Component = pred.component;\r\n const predComponentData = this.components[pred.id];\r\n const foundOutput = component.hasOutput(pred.output.name, predComponentData, this);\r\n if (foundOutput) continue; //if the input is readable, skip it, because we can read it's value when needed. Readable inputs are non blocking\r\n }\r\n if (typeof _input[input.name] == 'undefined' /* || _input[input.name] == null*/) {\r\n missingInputs.push(input.name);\r\n }\r\n }\r\n }\r\n\r\n return missingInputs;\r\n }\r\n\r\n public findReadablePredecessors(componentId) {\r\n const componentData = this.components[componentId];\r\n const component: Component = this._componentInstance[componentData.name];\r\n\r\n const connections = this.connections.filter((c) => c.targetId == componentId);\r\n const readablePredecessors = connections.map((c) => {\r\n //this.components[c.sourceId])\r\n const sourceComponentData = this.components[c.sourceId];\r\n const sourceComponent: Component = this._componentInstance[sourceComponentData.name];\r\n const output = sourceComponentData.outputs[c.sourceIndex];\r\n const input = componentData.inputs[c.targetIndex];\r\n if (sourceComponent.hasReadOutput) {\r\n return { output, input, component: sourceComponent, id: c.sourceId };\r\n }\r\n return null;\r\n });\r\n\r\n return readablePredecessors.filter((e) => e != null);\r\n }\r\n\r\n /**\r\n *\r\n * @param sourceId\r\n * @param componentId\r\n */\r\n private updateStep(sourceId, componentId) {\r\n const agentRuntime = this.agentRuntime;\r\n const step = agentRuntime.curStep;\r\n const componentData = agentRuntime.getComponentData(componentId);\r\n\r\n // if (!componentData.steps) componentData.steps = {};\r\n // if (!componentData.steps[step]) componentData.steps[step] = { sources: [] };\r\n // componentData.steps[step].sources.push(sourceId);\r\n\r\n // if (!componentData.stepSources) componentData.stepSources = {};\r\n // if (!componentData.stepSources[sourceId]) componentData.stepSources[sourceId] = [];\r\n // componentData.stepSources[sourceId].push(step);\r\n\r\n agentRuntime.updateComponent(componentId, { step });\r\n }\r\n\r\n async callComponent(sourceId, componentId, input?) {\r\n const startTime = Date.now();\r\n const agentRuntime = this.agentRuntime;\r\n const componentData = this.components[componentId];\r\n const component: Component = this._componentInstance[componentData.name];\r\n\r\n const eventId = 'e-' + uid();\r\n\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStart',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n input,\r\n });\r\n\r\n if (this._kill) {\r\n console.warn(`Agent ${this.id} was killed, skipping component ${componentData.name}`);\r\n\r\n const output = { id: componentData.id, name: componentData.displayName, result: null, error: 'Agent killed' };\r\n\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStop',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n endTime,\r\n duration,\r\n output,\r\n });\r\n\r\n return output;\r\n }\r\n\r\n if (!component) {\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStop',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n endTime,\r\n duration,\r\n output: { error: 'Component not found' },\r\n });\r\n throw new Error(`Component ${componentData.name} not found`);\r\n }\r\n\r\n this.agentRuntime.incTag(componentId);\r\n this.agentRuntime.checkCircularLimit();\r\n if (this.agentRuntime.circularLimitReached) {\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStop',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n endTime,\r\n duration,\r\n output: { error: 'Circular Calls Reached' },\r\n });\r\n\r\n return { error: `Circular Calls Reached` };\r\n }\r\n\r\n const data = agentRuntime.getComponentData(componentId);\r\n if (data?.output?._missing_inputs) {\r\n agentRuntime.updateComponent(componentId, { output: {} });\r\n }\r\n\r\n const _input = this.prepareComponentInput(componentId, input);\r\n\r\n //insert log\r\n const logId = AgentLogger.log(this, null, {\r\n sourceId: sourceId || 'AGENT',\r\n componentId,\r\n domain: this.domain,\r\n workflowID: this.agentRuntime.workflowReqId,\r\n processID: this.agentRuntime.processID,\r\n input:\r\n componentData.name == 'APIEndpoint' ? (this.agentRequest.method == 'GET' ? this.agentRequest.query : this.agentRequest.body) : _input,\r\n inputTimestamp: new Date().toISOString(),\r\n sessionID: this.callerSessionId,\r\n tags: this.sessionTag,\r\n });\r\n\r\n let output: any = null;\r\n let missingInputs: any = [];\r\n\r\n //agentRuntime.updateComponent(componentId, { step: agentRuntime.curStep });\r\n this.updateStep(sourceId, componentId);\r\n\r\n //first we check if the debugger is injecting an output, if yes we skip the inputs check\r\n if (agentRuntime.debug) {\r\n output = await agentRuntime.injectDebugOutput(componentId);\r\n }\r\n\r\n if (!output) {\r\n missingInputs = this.getComponentMissingInputs(componentId, _input);\r\n\r\n if (missingInputs.length > 0) {\r\n agentRuntime.updateComponent(componentId, { active: true, status: 'waiting' });\r\n //check if _error output is connected to a component\r\n const connections = this.connections.filter((c) => c.sourceId == componentId) || [];\r\n let hasErrorHandler = false;\r\n for (let connection of connections) {\r\n const outputEndpoint = componentData.outputs[connection.sourceIndex];\r\n if (outputEndpoint.name == '_error') {\r\n hasErrorHandler = true;\r\n break;\r\n }\r\n }\r\n //if (hasErrorHandler) return { id: componentData.id, name: componentData.name, result: null };\r\n\r\n output = { _error: 'Missing inputs : ' + JSON.stringify(missingInputs), _missing_inputs: missingInputs };\r\n }\r\n\r\n if (!output) {\r\n //the following case happens when no debugger injection was performed\r\n const validationResult = await component.validateConfig(componentData);\r\n if (validationResult._error) {\r\n output = validationResult;\r\n } else {\r\n try {\r\n await this.parseVariables(); //make sure that any vault variable is loaded before processing the component\r\n //TODO: apply type inference here instead of in the component .process method\r\n output = await component.process({ ...this.agentVariables, ..._input }, { ...componentData, eventId }, this);\r\n console.log(output);\r\n } catch (error: any) {\r\n //this are fatal errors requiring to cancel the execution of this component.\r\n console.error('Error on component process: ', { componentId, name: componentData.name, input: _input }, error);\r\n if (error?.message) output = { Response: undefined, _error: error.message, _debug: error.message };\r\n else output = { Response: undefined, _error: error.toString(), _debug: error.toString() };\r\n }\r\n }\r\n }\r\n }\r\n const runtimeData = this.agentRuntime.getRuntimeData(componentId);\r\n agentRuntime.updateComponent(componentId, { output });\r\n\r\n if (output._in_progress) {\r\n agentRuntime.updateComponent(componentId, { active: true, status: 'in_progress' });\r\n }\r\n\r\n if (output.error || output._error) {\r\n //TODO : check if we need to keep loop data while clearing runtime data here\r\n //in fact, output._error might be connected to a next component, in which case we need to keep the loop data\r\n if (!runtimeData?._ChildLoopData?._in_progress) {\r\n //don't reset if we are inside a loop, otherwise ._error branches will break the loop\r\n\r\n this.agentRuntime.resetComponent(componentId);\r\n }\r\n\r\n if (logId) {\r\n //update log\r\n AgentLogger.log(this, logId, { error: output.error || output._error });\r\n }\r\n if (output.error) {\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStop',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n endTime,\r\n duration,\r\n output: { error: output.error || output._error },\r\n });\r\n\r\n return [\r\n {\r\n id: componentData.id,\r\n name: componentData.displayName,\r\n result: null,\r\n error: output.error || output._error,\r\n _debug: output.error || output._error,\r\n },\r\n ];\r\n }\r\n }\r\n\r\n let results: any = [];\r\n if (output /*&& !component.hasReadOutput*/ && !output._missing_inputs) {\r\n AgentLogger.logTask(this, 1); //log successful task (non blocking call)\r\n\r\n //proceed with the next component(s)\r\n results = await this.callNextComponents(componentId, output).catch((error) => ({\r\n error,\r\n id: componentData.id,\r\n name: componentData.displayName,\r\n }));\r\n\r\n //TODO : maybe handle the number of branches inside ForEach component\r\n if (runtimeData._LoopData && output._in_progress && runtimeData._LoopData.branches == undefined) {\r\n //handle loop branching\r\n const branches = Array.isArray(results) ? results.length : 1;\r\n if (output._in_progress) {\r\n runtimeData._LoopData.branches = branches;\r\n agentRuntime.updateRuntimeData(componentId, { _LoopData: runtimeData._LoopData });\r\n }\r\n }\r\n\r\n if (results._is_leaf) {\r\n //we reached the end of the execution tree, we need to check if this branch is a loop\r\n delete results._is_leaf;\r\n const _ChildLoopData = runtimeData._ChildLoopData;\r\n if (_ChildLoopData && _ChildLoopData.parentId) {\r\n const parentId = _ChildLoopData.parentId;\r\n const _LoopData = this.agentRuntime.getRuntimeData(parentId)._LoopData;\r\n if (_LoopData) {\r\n if (!_LoopData.result) _LoopData.result = [];\r\n //we are in a loop, we need to update loop parent status in order to signal that we can run the next loop cycle\r\n\r\n let resultsCopy = JSON.parse(JSON.stringify(results));\r\n if (results.result) results.result._exclude = true;\r\n\r\n resultsCopy = await component.postProcess(resultsCopy, componentData, this);\r\n\r\n _LoopData.result.push(resultsCopy);\r\n _LoopData.branches--;\r\n\r\n if (_LoopData.branches <= 0) {\r\n agentRuntime.updateComponent(parentId, { active: true, status: '' }); //remove _in_progress status after processing all branches\r\n }\r\n //save the last result so that the loop parent can read it\r\n agentRuntime.updateRuntimeData(parentId, { _LoopData });\r\n }\r\n } else {\r\n //leaf but no childLoopData, is this a loop component with no children ?\r\n const _LoopData = this.agentRuntime.getRuntimeData(componentId)._LoopData;\r\n if (_LoopData && _LoopData.loopIndex == 1) {\r\n _LoopData._in_progress = false;\r\n output._in_progress = false;\r\n agentRuntime.updateComponent(componentId, { active: true, status: '' });\r\n agentRuntime.updateRuntimeData(componentId, { _LoopData });\r\n }\r\n }\r\n }\r\n }\r\n\r\n //check if the component context is potentially needed in next cycles\r\n if (!output._missing_inputs && !output._in_progress) {\r\n //we processed the current component, we can now reset the runtime data and active status\r\n const inLoop =\r\n runtimeData?._ChildLoopData?._in_progress && runtimeData._ChildLoopData?.loopIndex < runtimeData._ChildLoopData?.loopLength;\r\n if (inLoop) {\r\n // loop children require to keep external runtime data, we only clear the data that was set inside the loop\r\n this.clearChildLoopRuntimeComponentData(componentId);\r\n agentRuntime.updateComponent(componentId, { active: true, status: 'waiting' });\r\n } else {\r\n this.agentRuntime.resetComponent(componentId); //also sets active to false\r\n }\r\n } //if inputs were missing, the output contains error information, not actual component processing output, in this case we keep the runtime data\r\n\r\n //filter out null results\r\n if (Array.isArray(results)) results = results.flat(Infinity).filter((r) => r.result != null);\r\n\r\n if (logId) {\r\n //update log\r\n AgentLogger.log(this, logId, { output, outputTimestamp: '' + Date.now() });\r\n }\r\n\r\n //return this.agentRuntime.debug ? [results, { id: componentData.id, name: componentData.name, result: output }] : results;\r\n\r\n const endTime = Date.now();\r\n const duration = endTime - startTime;\r\n this.sse.send('component', {\r\n eventId,\r\n action: 'callStop',\r\n sourceId,\r\n id: componentId,\r\n name: componentData.displayName,\r\n title: componentData.title,\r\n startTime,\r\n endTime,\r\n duration,\r\n output,\r\n });\r\n\r\n return [results, { id: componentData.id, name: componentData.displayName, result: output }];\r\n }\r\n JSONExpression(obj, propertyString) {\r\n const properties = propertyString.split(/\\.|\\[|\\]\\.|\\]\\[|\\]/).filter(Boolean);\r\n let currentProperty = obj;\r\n\r\n for (let property of properties) {\r\n if (currentProperty === undefined || currentProperty === null) {\r\n return undefined;\r\n }\r\n\r\n currentProperty = currentProperty[property];\r\n }\r\n\r\n return currentProperty;\r\n }\r\n\r\n //\r\n async callNextComponents(componentId, output) {\r\n const agentRuntime = this.agentRuntime;\r\n //agentRuntime.incStep();\r\n\r\n const componentData = this.components[componentId];\r\n const component: Component = this._componentInstance[componentData.name];\r\n\r\n //if (component.hasReadOutput) return [];\r\n\r\n //get the list of connections for the current component in order to determine the next component(s) to call\r\n let connections = this.connections\r\n .filter((c) => c.sourceId == componentId /*|| this.alwaysActiveComponents[c.sourceId]*/)\r\n .map((c) => ({ ...c, output, componentData }));\r\n\r\n //also find connections from always active components to components with status 'waiting'\r\n\r\n const waitingComponents = agentRuntime.getWaitingComponents();\r\n const waitingComponentIds = waitingComponents.map((e) => e.id);\r\n const alwaysActiveIds = Object.keys(this.agentRuntime.alwaysActiveComponents);\r\n const alwaysActiveConnections = this.connections\r\n .filter((c) => alwaysActiveIds.includes(c.sourceId) && waitingComponentIds.includes(c.targetId))\r\n .map((c) => {\r\n const output = {};\r\n const waitingComponent = waitingComponents.find((e) => e.id == c.targetId);\r\n const prevComponentData = this.components[c.sourceId];\r\n const prevComponent: Component = this._componentInstance[prevComponentData.name];\r\n const outputEndpoint = prevComponentData.outputs[c.sourceIndex];\r\n output[outputEndpoint.name] = prevComponent.readOutput(outputEndpoint.name, prevComponentData, this);\r\n\r\n return { ...c, output, componentData: this.components[c.sourceId] };\r\n });\r\n connections = [...connections, ...alwaysActiveConnections];\r\n\r\n //no more components to call, return the output\r\n if (!Array.isArray(connections) || connections.length == 0) {\r\n return { id: componentData.id, name: componentData.name, result: output, _is_leaf: true };\r\n }\r\n\r\n const targetComponents = //classify connections by objects\r\n connections.reduce((acc, obj) => {\r\n let key = obj.targetId;\r\n if (!acc[key]) {\r\n acc[key] = [];\r\n }\r\n acc[key].push(obj);\r\n return acc;\r\n }, {});\r\n\r\n const promises: any = [];\r\n for (let targetId in targetComponents) {\r\n const targetComponentData = this.components[targetId];\r\n\r\n //if we are not inside an async component, we skip async branches\r\n //Note : we exclude Async component from this rule because it's the one that initiates the async job\r\n if (!this.async && targetComponentData.async && targetComponentData.name !== 'Async') continue;\r\n\r\n const targetComponent: Component = this._componentInstance[targetComponentData.name];\r\n const connections = targetComponents[targetId];\r\n\r\n let _isErrorHandler = false;\r\n if (Array.isArray(connections) && connections.length > 0) {\r\n const nextInput = {};\r\n for (let connection of connections) {\r\n const output = connection.output;\r\n const componentData = connection.componentData;\r\n const outputEndpoint = componentData.outputs[connection.sourceIndex]; //source\r\n const inputEndpoint = targetComponentData.inputs[connection.targetIndex]; //target\r\n\r\n //outputs can be named (e.g \"user:email\" or \"Req:body:data\") in which case they refer to a path in the output object\r\n const outputExpression = outputEndpoint.expression || outputEndpoint.name;\r\n const outputParts = outputExpression.split('.');\r\n\r\n const defaultOutputs = componentData.outputs.find((c) => c.default);\r\n let value: any = undefined;\r\n\r\n if (outputEndpoint.name == '_error') _isErrorHandler = true;\r\n\r\n if (outputEndpoint.default) value = output[outputEndpoint.name] /* || null*/;\r\n else {\r\n if (defaultOutputs /* && output[defaultOutputs.name]?.[outputEndpoint.name]*/) {\r\n value = output[defaultOutputs.name]?.[outputEndpoint.name];\r\n }\r\n }\r\n if (/*value === null || */ value === undefined && outputParts.length >= 1) {\r\n let val = this.JSONExpression(output, outputExpression);\r\n if (val !== undefined) value = val;\r\n }\r\n\r\n // if (/*value !== null && */ value !== undefined) {\r\n // nextInput[inputEndpoint.name] = [...new Set([[nextInput[inputEndpoint.name], value]].flat(Infinity))].filter(\r\n // (e) => e !== undefined /*&& e !== null*/,\r\n // );\r\n\r\n // if (nextInput[inputEndpoint.name].length == 1) nextInput[inputEndpoint.name] = nextInput[inputEndpoint.name][0];\r\n // }\r\n\r\n //Fix suggested by Sentinel Agent\r\n if (/*value !== null && */ value !== undefined) {\r\n // let combinedInput = [...[nextInput[inputEndpoint.name]].flat(), ...[value].flat()].filter(\r\n // (e) => e !== undefined /*&& e !== null*/,\r\n // ); // ! Deprecated\r\n\r\n let combinedInput = _mergeInputs(nextInput[inputEndpoint.name], value).filter((e) => e !== undefined /*&& e !== null*/);\r\n\r\n nextInput[inputEndpoint.name] = combinedInput.length === 1 ? combinedInput[0] : combinedInput;\r\n }\r\n }\r\n if (!nextInput || JSON.stringify(nextInput) == '{}') continue;\r\n\r\n const input = this.prepareComponentInput(targetId, nextInput);\r\n\r\n const targetComponent = this.components[targetId];\r\n\r\n if (_isErrorHandler && targetComponent) {\r\n output._error_handled = true;\r\n }\r\n\r\n const missingInputs = this.getComponentMissingInputs(targetId, input);\r\n const status = missingInputs.length > 0 ? 'waiting' : undefined;\r\n\r\n const sourceRuntimeData = this.agentRuntime.getRuntimeData(componentId); //We read the previous component runtime data\r\n\r\n let _ChildLoopData = sourceRuntimeData._LoopData; //is the source a loop component ?\r\n\r\n if (!_ChildLoopData || !_ChildLoopData._in_progress) {\r\n //if it's a loop component we need to check if the loop is still in progress\r\n\r\n _ChildLoopData = sourceRuntimeData._ChildLoopData; // if the loop is completed, check if the loop component is a nested loop, in which case we pass the parent context to the following component\r\n }\r\n\r\n agentRuntime.updateComponent(targetId, { active: true, input: nextInput, sourceId: componentId, status });\r\n agentRuntime.updateRuntimeData(targetId, { _ChildLoopData, _LoopData: null });\r\n promises.push(idPromise({ id: targetId, name: targetComponent.name, inputs: nextInput }));\r\n\r\n if (status) {\r\n //if status is set, track the component status update\r\n //if not set, it means that the component is active and will be logged upon execution\r\n //this can be considered as a fake log step that help us keep track of the execution tree\r\n const logId = AgentLogger.log(this, null, {\r\n sourceId: componentId,\r\n componentId: targetId,\r\n step: this.agentRuntime.curStep + 1, //we force to next step because the current step order is updated in the next runCycle()\r\n domain: this.domain,\r\n workflowID: this.agentRuntime.workflowReqId,\r\n processID: this.agentRuntime.processID,\r\n input: { __action: 'status_update', __status: status, data: nextInput },\r\n inputTimestamp: new Date().toISOString(),\r\n sessionID: this.callerSessionId,\r\n tags: this.sessionTag,\r\n });\r\n }\r\n }\r\n }\r\n\r\n if (promises.length == 0) {\r\n return { id: componentData.id, name: componentData.name, result: output, _is_leaf: true };\r\n }\r\n const results = await Promise.all(promises);\r\n\r\n //TODO : exclusive components handling\r\n //in order to run exclusive components first, we need to run them in current cycle\r\n //then we signal to the caller component that one more run cycle is needed\r\n return results.length == 1 ? results[0] : results;\r\n }\r\n private prepareComponentInput(targetId, inputs) {\r\n const rData: any = this.agentRuntime.getRuntimeData(targetId);\r\n const componentData = this.components[targetId];\r\n const rDataInput = rData?.input || {};\r\n\r\n let _input = { ...rDataInput };\r\n if (inputs) {\r\n // for (let key in inputs) {\r\n // let value = inputs[key];\r\n // //_input[key] = mergeJsonData(_input[key], value);\r\n\r\n // _input[key] = [...new Set([[rDataInput[key]], [value]].flat(Infinity))].filter((e) => e !== undefined /* && e !== null*/);\r\n // if (_input[key].length == 1) _input[key] = _input[key][0];\r\n // }\r\n\r\n //Fix suggested by Sentinel Agent\r\n for (let key in inputs) {\r\n let value = inputs[key];\r\n // Concatenate the existing value with the new input, without using Set to preserve duplicates\r\n // _input[key] = [rDataInput[key], value].flat(Infinity).filter((e) => e !== undefined); // ! Deprecated\r\n _input[key] = _mergeInputs(rDataInput[key], value).filter((e) => e !== undefined);\r\n\r\n // Simplify the array to a single value if there is only one element after flattening\r\n if (_input[key].length == 1) _input[key] = _input[key][0];\r\n }\r\n }\r\n\r\n const readablePredecessors = this.findReadablePredecessors(targetId);\r\n for (let c of readablePredecessors) {\r\n if (c) {\r\n const predComponentData = this.components[c.id];\r\n const value = c.component.readOutput(c.output.name, predComponentData, this);\r\n if (value && c.input?.name) {\r\n if (!_input) _input = {};\r\n _input[c.input.name] = value;\r\n }\r\n }\r\n }\r\n\r\n //this.saveRuntimeComponentData(targetId, { input: _input }); //TODO : check if we can use this.agentRuntime.updateRuntimeData instead (need to be carefully tested)\r\n this.agentRuntime.updateRuntimeData(targetId, { input: _input });\r\n\r\n for (let input of componentData.inputs) {\r\n if (input.defaultVal && _input[input.name] === undefined) {\r\n _input[input.name] = TemplateString(input.defaultVal).parse(this.agentVariables).result;\r\n //parseTemplate(input.defaultVal, this.agentVariables, { escapeString: false, processUnmatched: false });\r\n }\r\n }\r\n return _input;\r\n }\r\n\r\n public getConnectionSource(connection) {\r\n return this.components[connection.sourceId].inputs.find((e) => e.index === connection.sourceIndex);\r\n }\r\n\r\n public getConnectionTarget(connection) {\r\n return this.components[connection.targetId].inputs.find((e) => e.index === connection.targetIndex);\r\n }\r\n\r\n private recursiveTagAsyncComponents(component) {\r\n const agent = this;\r\n for (let output of component.outputs) {\r\n if (component.name == 'Async' && output.name === 'JobID') continue; //'JobID' is a special output\r\n const connected = agent.connections.filter((c) => c.sourceId === component.id && c.sourceIndex === output.index);\r\n if (!connected) continue;\r\n for (let con of connected) {\r\n const targetComponent = agent.components[con.targetId];\r\n if (!targetComponent) continue;\r\n targetComponent.async = true;\r\n this.recursiveTagAsyncComponents(targetComponent);\r\n }\r\n }\r\n }\r\n private tagAsyncComponents() {\r\n const agent = this;\r\n const componentsList: any[] = Object.values(agent.components);\r\n const AsyncComponents: any[] = componentsList.filter((c) => c.name === 'Async');\r\n if (!AsyncComponents || AsyncComponents.length == 0) return;\r\n for (let AsyncComponent of AsyncComponents) {\r\n AsyncComponent.async = true;\r\n this.recursiveTagAsyncComponents(AsyncComponent);\r\n }\r\n\r\n //AsyncComponents.async = true;\r\n\r\n //this.recursiveTagAsyncComponents(AsyncComponent, agent);\r\n }\r\n}\r\n\r\nfunction _mergeInputs(existing, newValue) {\r\n if (existing === undefined) {\r\n return [newValue];\r\n }\r\n\r\n if (!Array.isArray(existing)) {\r\n existing = [existing];\r\n }\r\n\r\n return [...existing, newValue];\r\n}\r\n","export class AgentRequest {\r\n public headers: any;\r\n public body: any;\r\n public query: any;\r\n public params: any;\r\n public method: string = 'GET';\r\n public path: string = '';\r\n public sessionID: string = '';\r\n public res: Response | null = null;\r\n public req: Request | null = null;\r\n public files: any[] = [];\r\n public _agent_authinfo: any;\r\n constructor(req?: AgentRequest | string[] | any) {\r\n if (!req) return;\r\n this.headers = JSON.parse(JSON.stringify(req.headers || {}));\r\n this.body = JSON.parse(JSON.stringify(req.body || req.data || {}));\r\n this.query = JSON.parse(JSON.stringify(req.query || {}));\r\n this.params = JSON.parse(JSON.stringify(req.params || {}));\r\n\r\n //make a copy of headers in lower case\r\n const lowerCaseHeaders = Object.fromEntries(Object.entries(this.headers).map(([key, value]) => [key.toLowerCase(), value]));\r\n\r\n this.headers = { ...lowerCaseHeaders, ...this.headers };\r\n\r\n if (req?.url) {\r\n try {\r\n const url = new URL(req.url);\r\n this.path = url.pathname;\r\n this.query = { ...this.query, ...Object.fromEntries(url.searchParams) };\r\n } catch {\r\n // Ignore invalid or relative paths\r\n }\r\n }\r\n\r\n if (req?.path) {\r\n this.path = req.path;\r\n }\r\n\r\n this.method = req.method;\r\n\r\n this.sessionID = req.sessionID;\r\n this.files = req.files || [];\r\n this._agent_authinfo = req._agent_authinfo;\r\n\r\n this.req = req instanceof AgentRequest ? req?.req : req;\r\n this.res = req?.res || null;\r\n }\r\n header(name: string) {\r\n return this.headers[name.toLowerCase()];\r\n }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nconst console = Logger('EmbodimentSettings');\r\n\r\nexport class EmbodimentSettings {\r\n private _embodiments: any;\r\n private _ready = false;\r\n\r\n constructor(agentId) {\r\n this.init(agentId);\r\n }\r\n\r\n async init(agentId) {\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n this._embodiments = await agentDataConnector.getAgentEmbodiments(agentId).catch((error) => []);\r\n this._ready = true;\r\n }\r\n public ready(maxWait = 10000) {\r\n return new Promise((resolve, reject) => {\r\n const interval = setInterval(() => {\r\n if (this._ready) {\r\n clearInterval(interval);\r\n resolve(true);\r\n }\r\n maxWait -= 100;\r\n }, 100);\r\n\r\n setTimeout(() => {\r\n clearInterval(interval);\r\n reject(false);\r\n }, maxWait);\r\n });\r\n }\r\n\r\n public get(embodimentType: string, key?: string) {\r\n if (!this._embodiments) return undefined;\r\n const _embodiment = this._embodiments.find((embodiment: any) => embodiment.type?.toLowerCase() === embodimentType.toLowerCase());\r\n\r\n if (!_embodiment) {\r\n //console.error(`Error: No ${embodimentType} embodiment found for agent`);\r\n }\r\n if (key) {\r\n return _embodiment?.properties?.[key];\r\n }\r\n return _embodiment?.properties;\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { EmbodimentSettings } from './EmbodimentSettings.class';\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nconst console = Logger('AgentSettings');\r\n\r\nexport class AgentSettings {\r\n private _settings: any;\r\n public embodiments?: EmbodimentSettings;\r\n private _ready = false;\r\n\r\n constructor(agentId?) {\r\n if (agentId) {\r\n this.init(agentId);\r\n }\r\n }\r\n\r\n async init(agentId) {\r\n // Set embodiments before _settings allow us to use it immediately; otherwise, we need to wait both AgentSettings instance and EmbodimentSettings instance to be ready\r\n this.embodiments = new EmbodimentSettings(agentId);\r\n\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n this._settings = (await agentDataConnector.getAgentSettings(agentId).catch((e) => {})) || {};\r\n this._ready = true;\r\n }\r\n\r\n public ready(maxWait = 10000) {\r\n return new Promise((resolve, reject) => {\r\n const interval = setInterval(() => {\r\n if (this._ready) {\r\n clearInterval(interval);\r\n resolve(true);\r\n }\r\n maxWait -= 100;\r\n }, 100);\r\n\r\n setTimeout(() => {\r\n clearInterval(interval);\r\n reject(false);\r\n }, maxWait);\r\n });\r\n }\r\n public get(key: string) {\r\n return this._settings?.[key] || '';\r\n }\r\n public set(key: string, value: any) {\r\n this._settings[key] = value;\r\n }\r\n public has(key: string) {\r\n return this._settings[key];\r\n }\r\n}\r\n","//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { AgentRequest } from '@sre/AgentManager/AgentRequest.class';\r\nimport { AgentSettings } from '@sre/AgentManager/AgentSettings.class';\r\nimport { TAgentProcessParams } from '@sre/types/Agent.types';\r\nimport { uid } from '../utils';\r\n\r\nimport { CLIConnector } from '@sre/IO/CLI.service/CLIConnector';\r\nimport * as FileType from 'file-type';\r\nimport fs from 'fs';\r\nimport mime from 'mime';\r\nimport path from 'path';\r\nimport { ConnectorService } from './ConnectorsService';\r\n\r\nexport class AgentProcess {\r\n public agent: Agent;\r\n\r\n private _loadPromise: Promise<any>;\r\n\r\n private constructor(\r\n private agentData: any,\r\n private agentVersion?: string,\r\n ) {\r\n this.initAgent(agentData, agentVersion);\r\n }\r\n private async initAgent(agentData: any, agentVersion?: string) {\r\n //await SmythRuntime.Instance.ready();\r\n let data;\r\n let agentId;\r\n\r\n if (typeof agentData === 'object') {\r\n data = agentData;\r\n if (data.components && data.connections) {\r\n data = { data, version: '1.0' };\r\n }\r\n\r\n agentId = data.data.id || 'tmp-' + uid();\r\n } else {\r\n const jsonRegex = /^{.*}$/g;\r\n const jsonData = agentData.match(jsonRegex)?.[0];\r\n\r\n const idRegex = /^[a-zA-Z0-9\\-]+$/g;\r\n agentId = agentData.match(idRegex)?.[0];\r\n\r\n //We are loading from an agentId\r\n if (agentId) {\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n\r\n data = await agentDataConnector.getAgentData(agentId, agentVersion);\r\n }\r\n\r\n //we are loading an agent from provided data\r\n if (!data && jsonData) {\r\n data = JSON.parse(jsonData);\r\n //generate an agentId if not provided\r\n agentId = data.id || 'tmp-' + uid();\r\n\r\n if (data.components && data.connections) {\r\n data = { data, version: '1.0' };\r\n }\r\n }\r\n }\r\n\r\n const agentSettings = new AgentSettings(agentId);\r\n this.agent = new Agent(agentId, data, agentSettings);\r\n }\r\n\r\n public async ready() {\r\n if (this._loadPromise) {\r\n return this._loadPromise;\r\n }\r\n\r\n return (this._loadPromise = new Promise((resolve) => {\r\n let maxWait = 10000;\r\n //wait for agent to be set\r\n const itv = setInterval(() => {\r\n if (this.agent) {\r\n clearInterval(itv);\r\n resolve(true);\r\n }\r\n maxWait -= 100;\r\n if (maxWait <= 0) {\r\n clearInterval(itv);\r\n resolve(false);\r\n }\r\n }, 100);\r\n }));\r\n }\r\n\r\n public static load(agentData: any, agentVersion?: string) {\r\n const agentProcess = new AgentProcess(agentData, agentVersion);\r\n return agentProcess;\r\n }\r\n\r\n /**\r\n * Run the agent process\r\n * @param reqConfig - The request configuration\r\n * @param callback - The callback function is used if we want to send status data, meta information, or stream response progressively.\r\n * Note: even if the response is streamed through the callback, the response is still returned as a single object in the response.data field.\r\n * @returns The result of the agent process\r\n */\r\n public async run(\r\n reqConfig: TAgentProcessParams | Array<string> | AgentRequest,\r\n callback?: (data: any) => void,\r\n ): Promise<{\r\n status?: number;\r\n data: any;\r\n }> {\r\n await this.ready();\r\n if (!this.agent) throw new Error('Failed to load agent');\r\n let request: AgentRequest = this.parseReqConfig(reqConfig);\r\n\r\n this.agent.setRequest(request);\r\n\r\n if (typeof callback === 'function') {\r\n this.agent.setCallback(callback);\r\n }\r\n\r\n const pathMatches = request.path.match(/(^\\/v[0-9]+\\.[0-9]+?)?(\\/api\\/(.+)?)/);\r\n if (!pathMatches || !pathMatches[2]) {\r\n return { status: 404, data: { error: 'Endpoint not found' } };\r\n }\r\n const endpointPath = pathMatches[2];\r\n const input = request.method == 'GET' ? request.query : request.body;\r\n const result: any = await this.agent.process(endpointPath, input).catch((error) => ({ error: error.message }));\r\n\r\n return { data: result };\r\n }\r\n\r\n public reset() {\r\n //the current version of agent cannot be used to run multiple requests\r\n //as a workaround we provide this function to reset AgentProcess state by generating a new Agent\r\n //TODO: refactor Agent.class in order to allow multiple consecutive requests running\r\n this.initAgent(this.agentData);\r\n }\r\n\r\n private parseReqConfig(reqConfig: TAgentProcessParams | Array<string> | AgentRequest): AgentRequest {\r\n if (reqConfig instanceof AgentRequest) return reqConfig;\r\n if (Array.isArray(reqConfig)) return this.parseCLI(reqConfig);\r\n return new AgentRequest(reqConfig);\r\n }\r\n\r\n private parseCLI(argList: Array<string>): AgentRequest {\r\n const cliConnector: CLIConnector = ConnectorService.getCLIConnector();\r\n const methods = ['get', 'post', 'put', 'delete', 'patch', 'head', 'options'];\r\n const cli: any = cliConnector.parse(argList, ['endpoint', 'post', 'get', 'put', 'delete', 'patch', 'head', 'options', 'headers', 'session']);\r\n\r\n const usedMethod = methods.find((method) => cli[method]);\r\n\r\n const req: AgentRequest = new AgentRequest();\r\n\r\n req.method = usedMethod?.toUpperCase() || 'GET';\r\n req.body = {};\r\n req.query = {};\r\n\r\n switch (usedMethod) {\r\n case 'get':\r\n case 'delete':\r\n case 'head':\r\n case 'options':\r\n req.query = cli[usedMethod];\r\n break;\r\n case 'post':\r\n case 'put':\r\n case 'patch':\r\n req.body = cli[usedMethod];\r\n break;\r\n }\r\n\r\n req.path = `/api/${cli.endpoint}`;\r\n req.params = cli.endpoint?.split('/');\r\n\r\n req.headers = cli.headers || {};\r\n //convert all keys to lowercase\r\n for (let key in req.headers) {\r\n req.headers[key.toLowerCase()] = req.headers[key];\r\n delete req.headers[key];\r\n }\r\n\r\n req.sessionID = cli.session || uid();\r\n\r\n req.files = [];\r\n if (req.body) {\r\n for (let entry in req.body) {\r\n let value = req.body[entry];\r\n const filePath = path.join(process.cwd(), value);\r\n const fileName = path.basename(filePath);\r\n if (!fs.existsSync(filePath)) continue;\r\n\r\n //read the file and create a file object\r\n\r\n try {\r\n // Read the file content\r\n const fileBuffer = fs.readFileSync(filePath);\r\n const ext: any = fileName.split('.').pop();\r\n\r\n const fileObj = {\r\n fieldname: entry,\r\n originalname: fileName,\r\n buffer: fileBuffer,\r\n mimetype: mime.getType(ext) || 'application/octet-stream',\r\n };\r\n\r\n delete req.body[entry];\r\n req.files.push(fileObj);\r\n\r\n // Try to determine the MIME type from the file content\r\n FileType.fileTypeFromBuffer(fileBuffer).then((fileType) => {\r\n if (fileType) {\r\n fileObj.mimetype = fileType.mime;\r\n }\r\n });\r\n } catch (error) {\r\n console.warn('Coud not read file', filePath, error.message);\r\n }\r\n }\r\n }\r\n\r\n return req;\r\n }\r\n\r\n public async post(path: string, input?: any, headers?: any) {\r\n return this.run({ method: 'POST', path, body: input || {}, headers });\r\n }\r\n\r\n public async get(path: string, query?: any, headers?: any) {\r\n return this.run({ method: 'GET', path, query, headers });\r\n }\r\n\r\n public async readDebugState(stateId: string, reqConfig: TAgentProcessParams | Array<string> | AgentRequest) {\r\n await this.ready();\r\n if (!this.agent) throw new Error('Failed to load agent');\r\n let request: AgentRequest = this.parseReqConfig(reqConfig);\r\n\r\n this.agent.setRequest(request);\r\n await this.agent.agentRuntime.ready();\r\n\r\n return this.agent.agentRuntime.readState(stateId, true);\r\n }\r\n}\r\n","//import { xxh3 } from '@node-rs/xxhash';\r\nimport xxhash from 'xxhashjs';\r\nimport { IACL, IAccessRequest, LevelMap, ReverseLevelMap, ReverseRoleMap, RoleMap, TACLEntry, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\n\r\nconst ACLHashAlgo = {\r\n none: (source) => source,\r\n //xxh3: (source) => xxh3.xxh64(source.toString()).toString(16),\r\n xxh3: (source) => {\r\n const h64 = xxhash.h64(); // Use xxhashjs's h64 function\r\n return source ? h64.update(source.toString()).digest().toString(16) : null;\r\n },\r\n};\r\n\r\nexport class ACL implements IACL {\r\n public hashAlgorithm?: string | undefined;\r\n public entries?: {\r\n [key in TAccessRole]?: TACLEntry | undefined;\r\n };\r\n public migrated?: boolean | undefined;\r\n //private acl: TACL;\r\n public get ACL(): IACL {\r\n return {\r\n hashAlgorithm: this.hashAlgorithm,\r\n entries: JSON.parse(JSON.stringify(this.entries)),\r\n migrated: this.migrated,\r\n };\r\n }\r\n public get serializedACL(): string {\r\n return this.serializeACL(this);\r\n }\r\n\r\n constructor(acl?: IACL | string) {\r\n if (typeof acl === 'string') {\r\n this.deserializeACL(acl);\r\n } else {\r\n this.hashAlgorithm = acl?.hashAlgorithm;\r\n this.entries = acl?.entries ? JSON.parse(JSON.stringify(acl?.entries)) : {};\r\n this.migrated = acl?.migrated;\r\n }\r\n if (!this.hashAlgorithm) this.hashAlgorithm = 'xxh3';\r\n if (!this.entries) this.entries = {};\r\n }\r\n\r\n static from(acl?: IACL | string): ACL {\r\n return new ACL(acl);\r\n }\r\n\r\n /**\r\n * This function checks if the candidate has access to the requested level\r\n * it only checks the exact access level, not the higher levels\r\n * Examples :\r\n * - if the candidate has read access, it will return true only if the requested level is read\r\n * - if the current ACL has team access but the candidate is an agent, it will not match the team access\r\n * @param acRequest\r\n * @returns\r\n */\r\n public checkExactAccess(acRequest: IAccessRequest): boolean {\r\n if (!this?.entries) return false; // cannot determine the access rights, prefer to deny access\r\n\r\n const role = this?.entries[acRequest.candidate.role];\r\n if (!role) return false;\r\n let entryId = acRequest.candidate.id;\r\n\r\n if (!ACLHashAlgo[this.hashAlgorithm]) {\r\n throw new Error(`Hash algorithm ${this.hashAlgorithm} not supported`);\r\n }\r\n\r\n entryId = ACLHashAlgo[this.hashAlgorithm](entryId);\r\n\r\n const access = role[entryId];\r\n if (!access) return false;\r\n\r\n const levels = Array.isArray(acRequest.level) ? acRequest.level : [acRequest.level];\r\n\r\n return levels.every((level) => access.includes(level));\r\n //return access.includes(req.level);\r\n }\r\n\r\n public addPublicAccess(level: TAccessLevel | TAccessLevel[]): ACL {\r\n if (!this?.entries[TAccessRole.Public]) this.entries[TAccessRole.Public] = {};\r\n if (!ACLHashAlgo[this.hashAlgorithm]) {\r\n throw new Error(`Hash algorithm ${this.hashAlgorithm} not supported`);\r\n }\r\n const ownerId = TAccessRole.Public; //public is a special case we use the role as the owner id because public access does not have specific candidate IDs\r\n const hashedOwner = ACLHashAlgo[this.hashAlgorithm](ownerId);\r\n\r\n if (!this?.entries[TAccessRole.Public]![hashedOwner]) this.entries[TAccessRole.Public]![hashedOwner] = [];\r\n //acl[TAccessRole.Public]![hashedOwner]!.push(level);\r\n //concatenate the levels\r\n const curLevel: any = this.entries[TAccessRole.Public]![hashedOwner]!;\r\n this.entries[TAccessRole.Public]![hashedOwner] = [...curLevel, ...level];\r\n\r\n return this;\r\n }\r\n public removePublicAccess(level: TAccessLevel | TAccessLevel[]): ACL {\r\n if (!this?.entries[TAccessRole.Public]) return this;\r\n const ownerId = TAccessRole.Public; //public is a special case we use the role as the owner id because public access does not have specific candidate IDs\r\n const hashedOwner = ACLHashAlgo[this.hashAlgorithm](ownerId);\r\n\r\n //remove the levels\r\n const curLevel = this[TAccessRole.Public]![hashedOwner]!;\r\n this[TAccessRole.Public]![hashedOwner] = curLevel.filter((l) => !level.includes(l));\r\n\r\n return this;\r\n }\r\n public addAccess(role: TAccessRole, ownerId: string, level: TAccessLevel | TAccessLevel[]): ACL {\r\n if (role === TAccessRole.Public) {\r\n throw new Error('Adding public access using addAccess method is not allowed. Use addPublicAccess method instead.');\r\n }\r\n const _level = Array.isArray(level) ? level : [level];\r\n if (!this?.entries[role]) this.entries[role] = {};\r\n if (!ACLHashAlgo[this.hashAlgorithm]) {\r\n throw new Error(`Hash algorithm ${this.hashAlgorithm} not supported`);\r\n }\r\n const hashedOwner = ACLHashAlgo[this.hashAlgorithm](ownerId);\r\n\r\n if (!hashedOwner) {\r\n throw new Error(`Invalid ownerId: ${role}:${ownerId}`);\r\n }\r\n\r\n if (!this?.entries[role]![hashedOwner]) this.entries[role]![hashedOwner] = [];\r\n //acl[role]![ownerId]!.push(level);\r\n //concatenate the levels\r\n const curLevel = this.entries[role]![hashedOwner]!;\r\n this.entries[role]![hashedOwner] = [...curLevel, ..._level];\r\n\r\n return this;\r\n }\r\n public static addAccess(role: TAccessRole, ownerId: string, level: TAccessLevel | TAccessLevel[]): ACL {\r\n return ACL.from().addAccess(role, ownerId, level);\r\n }\r\n\r\n public removeAccess(role: TAccessRole, ownerId: string, level: TAccessLevel | TAccessLevel[]): ACL {\r\n const _level = Array.isArray(level) ? level : [level];\r\n if (!this[role]) return this;\r\n if (!this[role]![ownerId]) return this;\r\n //acl[role]![ownerId] = acl[role]![ownerId]!.filter((l) => l !== level);\r\n //remove the levels\r\n const curLevel = this[role]![ownerId]!;\r\n this[role]![ownerId] = curLevel.filter((l) => !_level.includes(l));\r\n\r\n return this;\r\n }\r\n\r\n private serializeACL(tacl: IACL): string {\r\n let compressed = '';\r\n\r\n if (tacl.hashAlgorithm) {\r\n compressed += `h:${tacl.hashAlgorithm}|`;\r\n }\r\n\r\n if (tacl.entries) {\r\n for (const [role, entries] of Object.entries(tacl.entries)) {\r\n const roleShort = RoleMap[role]; // Use the mapping for role\r\n const entriesArray: any[] = [];\r\n\r\n for (const [hashedOwnerKey, accessLevels] of Object.entries(entries || {})) {\r\n if (accessLevels) {\r\n const accessLevelsShort = accessLevels.map((level) => LevelMap[level]).join('');\r\n entriesArray.push(`${hashedOwnerKey}/${accessLevelsShort}`);\r\n }\r\n }\r\n\r\n if (entriesArray.length > 0) {\r\n compressed += `${roleShort}:${entriesArray.join(',')}|`;\r\n }\r\n }\r\n }\r\n\r\n // Remove the trailing '|'\r\n if (compressed.endsWith('|')) {\r\n compressed = compressed.slice(0, -1);\r\n }\r\n\r\n return compressed;\r\n }\r\n\r\n private deserializeACL(compressed: string) {\r\n const parts = compressed.split('|');\r\n this.hashAlgorithm = '';\r\n this.entries = {};\r\n\r\n for (const part of parts) {\r\n if (part.startsWith('h:')) {\r\n this.hashAlgorithm = part.substring(2);\r\n } else {\r\n const [roleShort, entries] = part.split(':');\r\n const role = ReverseRoleMap[roleShort]; // Use the reverse mapping for role\r\n\r\n if (role) {\r\n const entriesObj = {};\r\n const entriesArray = entries.split(',');\r\n\r\n for (const entry of entriesArray) {\r\n const [hashedOwnerKey, accessLevelsShort] = entry.split('/');\r\n const accessLevels = accessLevelsShort.split('').map((short) => ReverseLevelMap[short]);\r\n\r\n entriesObj[hashedOwnerKey] = accessLevels;\r\n }\r\n\r\n this.entries[role] = entriesObj;\r\n }\r\n }\r\n }\r\n\r\n //return tacl;\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { ACLAccessDeniedError, IAccessCandidate, TAccessLevel, TAccessResult, TAccessTicket } from '@sre/types/ACL.types';\r\nimport { ACL } from './AccessControl/ACL.class';\r\nimport { AccessCandidate } from './AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from './AccessControl/AccessRequest.class';\r\n\r\nconst console = Logger('SecureConnector');\r\n\r\nexport abstract class SecureConnector<TRequest = any> extends Connector<TRequest> {\r\n public abstract name: string;\r\n\r\n //this determines the access rights for the requested resource\r\n //the connector should check if the resource exists or not\r\n //if the resource exists we read its ACL and return it\r\n //if the resource does not exist we return an write access ACL for the candidate\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n public async start() {\r\n console.info(`Starting ${this.name} connector ...`);\r\n }\r\n\r\n public async stop() {\r\n console.info(`Stopping ${this.name} connector ...`);\r\n }\r\n\r\n protected async hasAccess(acRequest: AccessRequest) {\r\n const aclHelper = await this.getResourceACL(acRequest.resourceId, acRequest.candidate).catch((error) => {\r\n console.error(`Error getting ACL for ${acRequest.resourceId}: ${error}`);\r\n return null;\r\n });\r\n\r\n if (!aclHelper) return false;\r\n\r\n //const aclHelper = ACLHelper.from(acl);\r\n\r\n const exactAccess = aclHelper.checkExactAccess(acRequest);\r\n if (exactAccess) return true;\r\n\r\n // if the exact access is denied, we check if the candidate has a higher access\r\n const ownerRequest = AccessRequest.clone(acRequest).setLevel(TAccessLevel.Owner);\r\n const ownerAccess = aclHelper.checkExactAccess(ownerRequest);\r\n if (ownerAccess) return true;\r\n\r\n // if the exact access is denied, we check if the requested resource has a public access\r\n const publicRequest = AccessRequest.clone(acRequest).setCandidate(AccessCandidate.public());\r\n const publicAccess = aclHelper.checkExactAccess(publicRequest);\r\n if (publicAccess) return true;\r\n\r\n // if the public access is denied, we check if the candidate's team has access\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);\r\n const teamRequest = AccessRequest.clone(acRequest).setCandidate(AccessCandidate.team(teamId));\r\n const teamAccess = aclHelper.checkExactAccess(teamRequest);\r\n if (teamAccess) return true;\r\n\r\n // if the team access is denied, we check if the team has a higher access\r\n const teamOwnerRequest = AccessRequest.clone(teamRequest).setLevel(TAccessLevel.Owner);\r\n const teamOwnerAccess = aclHelper.checkExactAccess(teamOwnerRequest);\r\n if (teamOwnerAccess) return true;\r\n\r\n return false;\r\n }\r\n public async getAccessTicket(resourceId: string, request: AccessRequest): Promise<TAccessTicket> {\r\n const sysAcRequest = AccessRequest.clone(request).resource(resourceId);\r\n const accessTicket = {\r\n request,\r\n access: (await this.hasAccess(sysAcRequest)) ? TAccessResult.Granted : TAccessResult.Denied,\r\n };\r\n\r\n return accessTicket as TAccessTicket;\r\n }\r\n\r\n //#region [ Decorators ]==========================\r\n\r\n //AccessControl decorator\r\n //This decorator will inject the access control logic into storage connector methods\r\n // in order to work properly, the connector expects the resourceId to be the first argument and the access request to be the second argument\r\n\r\n static AccessControl(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n // Store the original method in a variable\r\n const originalMethod = descriptor.value;\r\n\r\n // Modify the descriptor's value to wrap the original method\r\n descriptor.value = async function (...args: any[]) {\r\n // Extract the method arguments\r\n const [acRequest, resourceId] = args;\r\n\r\n if (resourceId !== undefined) {\r\n //: getAccessTicket requires a resourceId\r\n //FIXME: implement different access control for resources listing and methods that do not require a resourceId\r\n // Inject the access control logic\r\n const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n if (accessTicket.access !== TAccessResult.Granted) {\r\n console.error(`Access denied for ${acRequest.candidate.id} on ${resourceId}`);\r\n throw new ACLAccessDeniedError('Access Denied');\r\n }\r\n }\r\n\r\n // Call the original method with the original arguments\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n // Return the modified descriptor\r\n return descriptor;\r\n }\r\n\r\n //#endregion\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\n\r\nexport interface IStorageRequest {\r\n read(resourceId: string): Promise<StorageData>;\r\n write(resourceId: string, value: StorageData, acl?: IACL, metadata?: StorageMetadata): Promise<void>;\r\n delete(resourceId: string): Promise<void>;\r\n exists(resourceId: string): Promise<boolean>;\r\n getMetadata(resourceId: string): Promise<StorageMetadata | undefined>;\r\n setMetadata(resourceId: string, metadata: StorageMetadata): Promise<void>;\r\n getACL(resourceId: string): Promise<ACL | undefined>;\r\n setACL(resourceId: string, acl: IACL): Promise<void>;\r\n expire(resourceId: string, ttl: number): Promise<void>;\r\n}\r\n\r\nexport abstract class StorageConnector extends SecureConnector {\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n protected abstract read(acRequest: AccessRequest, resourceId: string): Promise<StorageData>;\r\n protected abstract write(acRequest: AccessRequest, resourceId: string, value: StorageData, acl?: IACL, metadata?: StorageMetadata): Promise<void>;\r\n protected abstract delete(acRequest: AccessRequest, resourceId: string): Promise<void>;\r\n protected abstract exists(acRequest: AccessRequest, resourceId: string): Promise<boolean>;\r\n\r\n protected abstract getMetadata(acRequest: AccessRequest, resourceId: string): Promise<StorageMetadata | undefined>;\r\n protected abstract setMetadata(acRequest: AccessRequest, resourceId: string, metadata: StorageMetadata): Promise<void>;\r\n\r\n protected abstract getACL(acRequest: AccessRequest, resourceId: string): Promise<ACL | undefined>;\r\n protected abstract setACL(acRequest: AccessRequest, resourceId: string, acl: IACL): Promise<void>;\r\n protected abstract expire(acRequest: AccessRequest, resourceId: string, ttl: number): Promise<void>;\r\n\r\n public requester(candidate: AccessCandidate): IStorageRequest {\r\n return {\r\n write: async (resourceId: string, value: StorageData, acl?: IACL, metadata?: StorageMetadata) => {\r\n return await this.write(candidate.writeRequest, resourceId, value, acl, metadata);\r\n },\r\n read: async (resourceId: string) => {\r\n return await this.read(candidate.readRequest, resourceId);\r\n },\r\n delete: async (resourceId: string) => {\r\n await this.delete(candidate.readRequest, resourceId);\r\n },\r\n exists: async (resourceId: string) => {\r\n return await this.exists(candidate.readRequest, resourceId);\r\n },\r\n getMetadata: async (resourceId: string) => {\r\n return await this.getMetadata(candidate.readRequest, resourceId);\r\n },\r\n setMetadata: async (resourceId: string, metadata: StorageMetadata) => {\r\n await this.setMetadata(candidate.writeRequest, resourceId, metadata);\r\n },\r\n getACL: async (resourceId: string) => {\r\n return await this.getACL(candidate.readRequest, resourceId);\r\n },\r\n setACL: async (resourceId: string, acl: IACL) => {\r\n return await this.setACL(candidate.writeRequest, resourceId, acl);\r\n },\r\n expire: async (resourceId: string, ttl: number) => {\r\n return await this.expire(candidate.writeRequest, resourceId, ttl);\r\n },\r\n } as IStorageRequest;\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IACL, IAccessCandidate, IAccessRequest } from '@sre/types/ACL.types';\r\nimport { CacheMetadata } from '@sre/types/Cache.types';\r\n\r\nexport interface ICacheRequest {\r\n get: (key: string) => Promise<any>;\r\n\r\n /**\r\n * Set a value in the cache\r\n * @param key\r\n * @param data\r\n * @param acl\r\n * @param metadata\r\n * @param ttl Cache time to live in seconds\r\n * @returns\r\n */\r\n set: (key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number) => Promise<boolean>;\r\n delete: (key: string) => Promise<void>;\r\n exists: (key: string) => Promise<boolean>;\r\n\r\n getMetadata: (key: string) => Promise<CacheMetadata | undefined>;\r\n setMetadata: (key: string, metadata: CacheMetadata) => Promise<void>;\r\n\r\n updateTTL: (key: string, ttl?: number) => Promise<void>;\r\n getTTL: (key: string) => Promise<number>;\r\n\r\n getACL: (key: string) => Promise<IACL | undefined>;\r\n setACL: (key: string, acl: IACL) => Promise<void>;\r\n}\r\n\r\nexport abstract class CacheConnector extends SecureConnector {\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n public requester(candidate: AccessCandidate): ICacheRequest {\r\n return {\r\n get: async (key: string) => {\r\n return await this.get(candidate.readRequest, key);\r\n },\r\n set: async (key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number) => {\r\n return await this.set(candidate.writeRequest, key, data, acl, metadata, ttl);\r\n },\r\n delete: async (key: string) => {\r\n await this.delete(candidate.writeRequest, key);\r\n },\r\n exists: async (key: string) => {\r\n return await this.exists(candidate.readRequest, key);\r\n },\r\n\r\n getMetadata: async (key: string) => {\r\n return await this.getMetadata(candidate.readRequest, key);\r\n },\r\n setMetadata: async (key: string, metadata: CacheMetadata) => {\r\n await this.setMetadata(candidate.writeRequest, key, metadata);\r\n },\r\n updateTTL: async (key: string, ttl?: number) => {\r\n await this.updateTTL(candidate.writeRequest, key, ttl);\r\n },\r\n getTTL: async (key: string) => {\r\n return await this.getTTL(candidate.readRequest, key);\r\n },\r\n getACL: async (key: string) => {\r\n return await this.getACL(candidate.readRequest, key);\r\n },\r\n setACL: async (key: string, acl: IACL) => {\r\n await this.setACL(candidate.writeRequest, key, acl);\r\n },\r\n };\r\n }\r\n\r\n abstract get(acRequest: AccessRequest, key: string): Promise<any>;\r\n abstract set(acRequest: AccessRequest, key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number): Promise<boolean>;\r\n abstract delete(acRequest: AccessRequest, key: string): Promise<void>;\r\n abstract exists(acRequest: AccessRequest, key: string): Promise<boolean>;\r\n\r\n abstract getMetadata(acRequest: AccessRequest, key: string): Promise<CacheMetadata | undefined>;\r\n abstract setMetadata(acRequest: AccessRequest, key: string, metadata: CacheMetadata): Promise<void>;\r\n\r\n abstract updateTTL(acRequest: AccessRequest, key: string, ttl?: number): Promise<void>;\r\n abstract getTTL(acRequest: AccessRequest, key: string): Promise<number>;\r\n\r\n abstract getACL(acRequest: AccessRequest, key: string): Promise<IACL | undefined>;\r\n abstract setACL(acRequest: AccessRequest, key: string, acl: IACL): Promise<void>;\r\n}\r\n","import { jsonrepair } from 'jsonrepair';\r\nimport { isDigits, isSafeNumber, isValidString } from '@sre/utils';\r\n\r\nexport class JSONContentHelper {\r\n private _current: string;\r\n\r\n public get result() {\r\n return this._current;\r\n }\r\n private constructor(private dataString: string) {\r\n this._current = dataString;\r\n }\r\n\r\n public static create(dataString: string) {\r\n return new JSONContentHelper(dataString);\r\n }\r\n\r\n /**\r\n * This a permissive json parsing function : It tries to extract and parse a JSON object from a string. If it fails, it returns the original string.\r\n * if the string is not a JSON representation, but contains a JSON object, it will extract and parse it.\r\n * @returns\r\n */\r\n public tryParse() {\r\n const strInput = this._current;\r\n\r\n // is it an object ? a digit ? a safe number ?\r\n if (!isValidString(strInput) || isDigits(strInput) || isSafeNumber(strInput)) return strInput;\r\n\r\n let str = strInput.trim();\r\n\r\n // the string seems to be a json object\r\n if ((str.startsWith('{') && str.endsWith('}')) || (str.startsWith('[') && str.endsWith(']'))) {\r\n try {\r\n return JSON.parse(str);\r\n } catch (e) {\r\n try {\r\n const repairedJson = jsonrepair(str);\r\n return JSON.parse(repairedJson);\r\n } catch (e: any) {}\r\n }\r\n }\r\n\r\n // the string does not seem to be a json object, so we try to extract a json object from it\r\n str = (this.extractJsonFromString(strInput) || strInput).trim();\r\n\r\n if ((isDigits(str) && !isSafeNumber(str)) || (!str.startsWith('{') && !str.startsWith('['))) return str;\r\n\r\n try {\r\n return JSON.parse(str);\r\n } catch (e) {\r\n try {\r\n const repairedJson = jsonrepair(str);\r\n return JSON.parse(repairedJson);\r\n } catch (e: any) {\r\n //console.warn('Error on parseJson: ', e.toString());\r\n //console.warn(' Tried to parse: ', str);\r\n return strInput;\r\n }\r\n }\r\n }\r\n\r\n // Same as tryParse but it does not extract JSON from string\r\n public tryFullParse() {\r\n const str = this._current;\r\n if (!str) return str;\r\n\r\n if ((isDigits(str) && !isSafeNumber(str)) || (!str.startsWith('{') && !str.startsWith('['))) return str;\r\n\r\n try {\r\n return JSON.parse(str);\r\n } catch (e) {\r\n try {\r\n return JSON.parse(jsonrepair(str));\r\n } catch (e: any) {\r\n console.warn('Error on parseJson: ', e.toString());\r\n console.warn(' Tried to parse: ', str);\r\n return { result: str, error: e.toString() };\r\n }\r\n }\r\n }\r\n\r\n private extractJsonFromString(str) {\r\n try {\r\n const regex = /(\\{.*\\})/s; // LLMs in smythOS are expected to generate json between curly brackets only\r\n\r\n const match = str.match(regex);\r\n\r\n return match?.[1];\r\n } catch {\r\n return null;\r\n }\r\n }\r\n}\r\n\r\nexport function JSONContent(dataString: string) {\r\n return JSONContentHelper.create(dataString);\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { DEFAULT_TEAM_ID, IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\nimport { getMimeType } from '@sre/utils';\r\nimport mime from 'mime';\r\nimport { Readable } from 'stream';\r\nimport { StorageConnector } from './StorageConnector';\r\nimport { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport crypto from 'crypto';\r\nimport { JSONContentHelper } from '@sre/helpers/JsonContent.helper';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\nexport type TSmythFSURI = {\r\n hash: string;\r\n team: string;\r\n path: string;\r\n};\r\n\r\n// SystemEvents.on('SRE:Booted', () => {\r\n// const router = ConnectorService.getRouterConnector();\r\n// if (router && router?.get instanceof Function) {\r\n// router.get('/_temp/:uid', SmythFS.Instance.serveTempContent.bind(SmythFS.Instance));\r\n// router.get('/storage/:file_id', SmythFS.Instance.serveResource.bind(SmythFS.Instance));\r\n// }\r\n// });\r\n\r\nexport class SmythFS {\r\n private hash: string; // Store the instance hash for URL generation\r\n\r\n static instances: any = {};\r\n\r\n // Centralized hash generation to ensure consistency\r\n private static generateInstanceHash(storageName: string, cacheName: string): string {\r\n const instanceProps = `${storageName}:${cacheName}`;\r\n return crypto.createHash('sha256').update(instanceProps).digest('hex').substring(0, 6);\r\n }\r\n\r\n // Default singleton instance (most common use case)\r\n public static get Instance(): SmythFS {\r\n return SmythFS.getInstance(); // Uses default empty string providers\r\n }\r\n\r\n // Multiton pattern - get instance based on storage and cache provider combination\r\n public static getInstance(storageProvider: string | StorageConnector = '', cacheProvider: string | CacheConnector = ''): SmythFS {\r\n // First get the actual connector names to calculate the correct hash\r\n const storage = storageProvider instanceof StorageConnector ? storageProvider : ConnectorService.getStorageConnector(storageProvider);\r\n const cache = cacheProvider instanceof CacheConnector ? cacheProvider : ConnectorService.getCacheConnector(cacheProvider);\r\n const hash = SmythFS.generateInstanceHash(storage.name, cache.name);\r\n\r\n if (SmythFS.instances[hash]) {\r\n return SmythFS.instances[hash];\r\n }\r\n\r\n const instance = new SmythFS(storage, cache);\r\n\r\n //register routes\r\n const router = ConnectorService.getRouterConnector();\r\n if (router && router?.get instanceof Function) {\r\n router.get(`/_temp/${hash}/:uid`, instance.serveTempContent.bind(instance));\r\n router.get(`/storage/${hash}/:file_id`, instance.serveResource.bind(instance));\r\n }\r\n\r\n SmythFS.instances[hash] = instance;\r\n return instance;\r\n }\r\n\r\n private constructor(private storage: StorageConnector, private cache: CacheConnector) {\r\n //SmythFS cannot be used without SRE\r\n if (!ConnectorService.ready) {\r\n throw new Error('SRE not available');\r\n }\r\n\r\n // Use centralized hash generation method\r\n this.hash = SmythFS.generateInstanceHash(this.storage.name, this.cache.name);\r\n }\r\n\r\n // public getStoragePath(uri: string) {\r\n // const smythURI = this.URIParser(uri);\r\n // if (!smythURI) throw new Error('Invalid Resource URI');\r\n // return `teams/${smythURI.team}${smythURI.path}`;\r\n // }\r\n\r\n public getBaseUri(candidate: IAccessCandidate) {\r\n const uri = `smythfs://${candidate.id}.${candidate.role}`;\r\n\r\n return uri;\r\n }\r\n\r\n /**\r\n * Reads a resource from smyth file system\r\n * @param uri smythfs:// uri\r\n * @param candidate\r\n * @returns\r\n */\r\n public async read(uri: string, candidate?: IAccessCandidate): Promise<Buffer> {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n\r\n const data = await this.storage.requester(_candidate).read(resourceId);\r\n\r\n return data ? this.toBuffer(data) : null;\r\n }\r\n\r\n public async write(uri: string, data: any, candidate?: IAccessCandidate, metadata?: StorageMetadata, ttl?: number) {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n //when we write a file, it does not exist we need to explicitly provide a resource team in order to have access rights set properly\r\n\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n\r\n let acl: ACL;\r\n\r\n //give team read access if this is a team resource and not the default team\r\n //because the default team is a fallback used when no team is specified or account connector is not available\r\n //in that case we need to only allow the creator to access the resource\r\n if (smythURI.team && smythURI.team !== DEFAULT_TEAM_ID) {\r\n acl = new ACL()\r\n //.addAccess(candidate.role, candidate.id, TAccessLevel.Owner) // creator is owner\r\n .addAccess(TAccessRole.Team, smythURI.team, TAccessLevel.Read).ACL as ACL; // team has read access\r\n }\r\n\r\n if (!metadata) metadata = {};\r\n if (!metadata?.ContentType) {\r\n metadata.ContentType = await getMimeType(data);\r\n if (!metadata.ContentType) {\r\n const ext: any = uri.split('.').pop();\r\n if (ext) {\r\n metadata.ContentType = mime.getType(ext) || 'application/octet-stream';\r\n }\r\n }\r\n }\r\n await this.storage.requester(_candidate).write(resourceId, data, acl, metadata);\r\n\r\n if (ttl) {\r\n await this.storage.requester(_candidate).expire(resourceId, ttl);\r\n }\r\n }\r\n\r\n public async delete(uri: string, candidate?: IAccessCandidate) {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n\r\n await this.storage.requester(_candidate).delete(resourceId);\r\n }\r\n\r\n //TODO: should we require access token here ?\r\n public async exists(uri: string, candidate?: IAccessCandidate) {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n\r\n //in order to get a consistent access check in case of inexisting resource, we need to explicitly set a default resource team\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n\r\n return await this.storage.requester(_candidate).exists(resourceId);\r\n }\r\n\r\n //#region Temp URL (mainly used for returning agent output to user for temporary access)\r\n public async genTempUrl(uri: string, candidate?: IAccessCandidate, ttlSeconds: number = 3600) {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const exists = await this.exists(uri, candidate);\r\n if (!exists) throw new Error('Resource does not exist');\r\n\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n const resourceMetadata = await this.storage.requester(_candidate).getMetadata(resourceId);\r\n\r\n const uid = crypto.randomUUID();\r\n const tempUserCandidate = AccessCandidate.user(`system:${uid}`);\r\n\r\n await this.cache.requester(tempUserCandidate).set(\r\n `pub_url:${uid}`,\r\n JSON.stringify({\r\n accessCandidate: _candidate,\r\n uri,\r\n contentType: resourceMetadata?.ContentType,\r\n }),\r\n undefined,\r\n undefined,\r\n ttlSeconds\r\n ); // 1 hour\r\n\r\n const baseUrl = ConnectorService.getRouterConnector().baseUrl;\r\n return `${baseUrl}/_temp/${this.hash}/${uid}`;\r\n }\r\n\r\n public async destroyTempUrl(url: string, { delResource }: { delResource: boolean } = { delResource: false }) {\r\n // Parse URL with new format: /_temp/{hash}/{uid}\r\n const tempPath = url.split('/_temp/')[1];\r\n if (!tempPath) throw new Error('Invalid Temp URL format');\r\n\r\n const uid = tempPath.split('/')[1]?.split('?')[0]; // get uid and remove query params\r\n if (!uid) throw new Error('Invalid Temp URL format');\r\n\r\n let cacheVal = await this.cache.requester(AccessCandidate.user(`system:${uid}`)).get(`pub_url:${uid}`);\r\n if (!cacheVal) throw new Error('Invalid Temp URL');\r\n cacheVal = JSONContentHelper.create(cacheVal).tryParse();\r\n await this.cache.requester(AccessCandidate.user(`system:${uid}`)).delete(`pub_url:${uid}`);\r\n if (delResource) {\r\n await this.delete(cacheVal.uri, AccessCandidate.clone(cacheVal.accessCandidate));\r\n }\r\n }\r\n\r\n public async serveTempContent(req: any, res: any) {\r\n try {\r\n const { uid } = req.params;\r\n let cacheVal = await this.cache.requester(AccessCandidate.user(`system:${uid}`)).get(`pub_url:${uid}`);\r\n if (!cacheVal) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Invalid Temp URL');\r\n return;\r\n }\r\n cacheVal = JSONContentHelper.create(cacheVal).tryParse();\r\n const content = await this.read(cacheVal.uri, AccessCandidate.clone(cacheVal.accessCandidate));\r\n\r\n const contentBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'binary');\r\n\r\n const contentType = cacheVal.contentType || 'application/octet-stream';\r\n\r\n res.writeHead(200, {\r\n 'Content-Type': contentType,\r\n 'Content-Disposition': 'inline',\r\n 'Content-Length': contentBuffer.length,\r\n });\r\n\r\n res.end(contentBuffer);\r\n } catch (error) {\r\n console.error('Error serving temp content:', error);\r\n res.writeHead(500, { 'Content-Type': 'text/plain' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n //#endregion\r\n\r\n //#region Resource Serving\r\n\r\n /**\r\n * Generates a public url for the resource\r\n * @param uri\r\n * @param candidate\r\n * @returns\r\n */\r\n public async genResourceUrl(uri: string, candidate?: IAccessCandidate) {\r\n const smythURI = await this.URIParser(uri);\r\n if (!smythURI) throw new Error('Invalid Resource URI');\r\n candidate = candidate || smythURI.defaultCandidate; //fallback to default candidate if not provided\r\n\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const isMember = await accountConnector.isTeamMember(smythURI.team, candidate);\r\n if (!isMember) throw new Error('Access Denied');\r\n\r\n const exists = await this.exists(uri, candidate);\r\n if (!exists) throw new Error('Resource does not exist');\r\n\r\n const _candidate = candidate instanceof AccessCandidate ? candidate : new AccessCandidate(candidate);\r\n if (_candidate.role !== TAccessRole.Agent) {\r\n throw new Error('Only agents can generate resource urls');\r\n }\r\n const agentId = _candidate.id;\r\n\r\n const resourceId = `teams/${smythURI.team}${smythURI.path}`;\r\n const resourceMetadata = await this.storage.requester(_candidate).getMetadata(resourceId);\r\n\r\n const uid = crypto.randomUUID(); // maybe instead of a random uuid, u can use the resource\r\n const tempUserCandidate = AccessCandidate.user(`system:${uid}`);\r\n\r\n await this.cache.requester(tempUserCandidate).set(\r\n `storage_url:${uid}`,\r\n JSON.stringify({\r\n accessCandidate: _candidate,\r\n uri,\r\n contentType: resourceMetadata?.ContentType,\r\n }),\r\n undefined,\r\n undefined\r\n // 3600 // 1 hour\r\n );\r\n\r\n const contentType = resourceMetadata?.ContentType;\r\n const ext = contentType ? mime.getExtension(contentType) : undefined;\r\n\r\n // get the agent domain\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n const baseUrl = ConnectorService.getRouterConnector().baseUrl;\r\n const domain = agentDataConnector.getAgentConfig(agentId)?.agentStageDomain\r\n ? `https://${agentDataConnector.getAgentConfig(agentId).agentStageDomain}`\r\n : baseUrl;\r\n\r\n return `${domain}/storage/${this.hash}/${uid}${ext ? `.${ext}` : ''}`;\r\n }\r\n public async destroyResourceUrl(url: string, { delResource }: { delResource: boolean } = { delResource: false }) {}\r\n public async serveResource(req: any, res: any) {\r\n try {\r\n const { file_id } = req.params;\r\n const [uid, extention] = file_id.split('.');\r\n let cacheVal = await this.cache.requester(AccessCandidate.user(`system:${uid}`)).get(`storage_url:${uid}`);\r\n if (!cacheVal) {\r\n res.writeHead(404, { 'Content-Type': 'text/plain' });\r\n res.end('Invalid Resource URL');\r\n return;\r\n }\r\n cacheVal = JSONContentHelper.create(cacheVal).tryParse();\r\n const content = await this.read(cacheVal.uri, AccessCandidate.clone(cacheVal.accessCandidate));\r\n\r\n const contentBuffer = Buffer.isBuffer(content) ? content : Buffer.from(content, 'binary');\r\n\r\n const contentType = cacheVal.contentType || 'application/octet-stream';\r\n\r\n res.writeHead(200, {\r\n 'Content-Type': contentType,\r\n 'Content-Disposition': 'inline',\r\n 'Content-Length': contentBuffer.length,\r\n });\r\n\r\n res.end(contentBuffer);\r\n } catch (error) {\r\n console.error('Error serving storage resource content:', error);\r\n res.writeHead(500, { 'Content-Type': 'text/plain' });\r\n res.end('Internal Server Error');\r\n }\r\n }\r\n //#endregion\r\n\r\n private async URIParser(uri: string) {\r\n const parts = uri.split('://');\r\n if (parts.length !== 2) return undefined;\r\n if (parts[0].toLowerCase() !== 'smythfs') return undefined;\r\n const parsed = this.CaseSensitiveURL(`http://${parts[1]}`);\r\n const tld = parsed.hostname.split('.').pop();\r\n if (tld !== 'team' && tld !== 'user' && tld !== 'agent' && tld !== 'smyth') throw new Error('Invalid Resource URI');\r\n let team = tld === 'team' ? parsed.hostname.replace(`.${tld}`, '') : undefined;\r\n const user = tld === 'user' ? parsed.hostname.replace(`.${tld}`, '') : undefined;\r\n const agent = tld === 'agent' ? parsed.hostname.replace(`.${tld}`, '') : undefined;\r\n const smyth = tld === 'smyth' ? parsed.hostname.replace(`.${tld}`, '') : undefined;\r\n\r\n let basePath = '';\r\n if (!team) {\r\n let candidate: IAccessCandidate;\r\n if (user) {\r\n candidate = AccessCandidate.user(user);\r\n basePath = '/' + user;\r\n } else if (agent) {\r\n candidate = AccessCandidate.agent(agent);\r\n basePath = '/' + agent;\r\n }\r\n\r\n if (candidate) {\r\n team = await ConnectorService.getAccountConnector().getCandidateTeam(candidate);\r\n }\r\n }\r\n\r\n // create a default candidate based on the uri\r\n let defaultCandidate: IAccessCandidate;\r\n\r\n if (team) {\r\n defaultCandidate = AccessCandidate.team(team);\r\n } else if (user) {\r\n defaultCandidate = AccessCandidate.user(user);\r\n } else if (agent) {\r\n defaultCandidate = AccessCandidate.agent(agent);\r\n }\r\n\r\n return {\r\n hash: parsed.hash,\r\n team,\r\n user,\r\n agent,\r\n smyth,\r\n defaultCandidate,\r\n path: basePath + parsed.pathname,\r\n };\r\n }\r\n\r\n private CaseSensitiveURL(urlString: string) {\r\n // First, extract the original hostname for case preservation\r\n const parts = urlString.split('://');\r\n if (parts.length !== 2) return null;\r\n\r\n const afterProtocol = parts[1];\r\n const hostnameEnd = Math.min(\r\n ...[afterProtocol.indexOf('/'), afterProtocol.indexOf('?'), afterProtocol.indexOf('#'), afterProtocol.length].filter((i) => i >= 0)\r\n );\r\n\r\n const originalHostnamePart = afterProtocol.substring(0, hostnameEnd);\r\n const [originalHostname, originalPort] = originalHostnamePart.split(':');\r\n\r\n // Use URL constructor for robust parsing of everything else\r\n const parsed = new URL(urlString);\r\n\r\n // Explicitly copy URL properties since they're not enumerable\r\n return {\r\n protocol: parsed.protocol,\r\n hostname: originalHostname, // Case-sensitive hostname\r\n port: parsed.port,\r\n pathname: parsed.pathname,\r\n search: parsed.search,\r\n searchParams: parsed.searchParams,\r\n hash: parsed.hash,\r\n href: parsed.href,\r\n origin: parsed.origin,\r\n host: originalHostname + (parsed.port ? `:${parsed.port}` : ''),\r\n originalPort: originalPort || null,\r\n };\r\n }\r\n\r\n private async toBuffer(data: StorageData): Promise<Buffer> {\r\n if (Buffer.isBuffer(data)) {\r\n return data;\r\n } else if (typeof data === 'string') {\r\n return Buffer.from(data, 'utf-8');\r\n } else if (data instanceof Uint8Array) {\r\n return Buffer.from(data);\r\n } else if (data instanceof Readable) {\r\n return new Promise<Buffer>((resolve, reject) => {\r\n const chunks: Buffer[] = [];\r\n data.on('data', (chunk) => {\r\n chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));\r\n });\r\n data.on('end', () => {\r\n resolve(Buffer.concat(chunks));\r\n });\r\n data.on('error', (err) => {\r\n reject(err);\r\n });\r\n });\r\n } else {\r\n throw new Error('Unsupported data type');\r\n }\r\n }\r\n}\r\n","import axios from 'axios';\r\nimport mime from 'mime';\r\nimport { fileTypeFromBuffer } from 'file-type';\r\nimport { Readable } from 'stream';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport os from 'os';\r\n\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { SmythFS } from '@sre/IO/Storage.service/SmythFS.class';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport { getSizeFromBinary, isUrl, uid, getBase64FileInfo, getMimeType } from '@sre/utils';\r\nimport config from '@sre/config';\r\nexport class BinaryInput {\r\n private size: number;\r\n private url: string;\r\n private _ready;\r\n private _readyPromise;\r\n private _source: Buffer;\r\n private _uploading: boolean = false;\r\n\r\n constructor(\r\n data: BinaryInput | Buffer | ArrayBuffer | Blob | string | Record<string, any>,\r\n private _name?: string,\r\n public mimetype?: string,\r\n private candidate?: IAccessCandidate,\r\n ) {\r\n if (!_name) _name = uid();\r\n this._name = _name;\r\n //this._source = data;\r\n\r\n this.load(data, _name, mimetype, candidate);\r\n }\r\n\r\n public async ready() {\r\n if (this._ready) return true;\r\n\r\n if (!this._readyPromise) {\r\n this._readyPromise = new Promise((resolve) => {\r\n const maxWait = 10000;\r\n const interval = setInterval(() => {\r\n if (this._ready) {\r\n clearInterval(interval);\r\n resolve(true);\r\n }\r\n if (maxWait <= 0) {\r\n clearInterval(interval);\r\n resolve(false);\r\n }\r\n }, 100);\r\n });\r\n }\r\n\r\n return this._readyPromise;\r\n }\r\n\r\n private async load(data, name: string, mimetype?: string, candidate?: IAccessCandidate) {\r\n //assume the mimetype from the provided name\r\n const ext: any = name.split('.')?.length > 1 ? name.split('.').pop() : '';\r\n // Need to set mimetype empty string if no extension is found, setting default mimetype to 'application/octet-stream' lead wrong direction when try to get the mimetype from base64 or buffer data (as it's not accurate all the time)\r\n this.mimetype = mimetype || mime.getType(ext) || '';\r\n this.url = ``;\r\n\r\n if (typeof data === 'object' && data.url && data.mimetype && data.size) {\r\n this.mimetype = data.mimetype;\r\n this.size = data.size;\r\n this.url = data.url;\r\n\r\n const ext = mime.getExtension(this.mimetype);\r\n if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;\r\n\r\n if (candidate) {\r\n this._source = await SmythFS.Instance.read(this.url, candidate).finally(() => {\r\n this._ready = true;\r\n });\r\n } else {\r\n this._ready = true;\r\n }\r\n return;\r\n }\r\n\r\n if (typeof data === 'string' && data.startsWith('smythfs://')) {\r\n this.url = data;\r\n if (candidate) {\r\n try {\r\n this._source = await SmythFS.Instance.read(this.url, candidate);\r\n this.mimetype = await getMimeType(this._source);\r\n this.size = this._source.byteLength;\r\n\r\n if (!this.mimetype) {\r\n this.mimetype = mime.getType(this.url) || mime.getType(this._name) || '';\r\n }\r\n\r\n const ext = mime.getExtension(this.mimetype);\r\n if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;\r\n } finally {\r\n this._ready = true;\r\n }\r\n } else {\r\n this._ready = true;\r\n }\r\n return;\r\n }\r\n\r\n if (isUrl(data)) {\r\n try {\r\n const response = await axios({\r\n method: 'get',\r\n url: data,\r\n responseType: 'arraybuffer', // Important for handling binary data\r\n });\r\n\r\n this.size = response.data.byteLength;\r\n this._source = Buffer.from(response.data, 'binary');\r\n\r\n let mimetype = response.headers?.['content-type'] || '';\r\n\r\n // Try to get the file extension from the URL\r\n const urlPath = new URL(data).pathname;\r\n let extension = urlPath.split('.')?.length > 1 ? urlPath.split('.').pop() : '';\r\n\r\n // When content-type header is missing or invalid, try to determine mime type from file extension\r\n if (!mimetype || mimetype.startsWith('binary/octet-stream')) {\r\n mimetype = extension ? mime.getType(extension) : '';\r\n }\r\n\r\n // If we couldn't determine the mime type from headers or file extension, try detecting it from the actual file content\r\n if (!mimetype) {\r\n const type = await fileTypeFromBuffer(this._source);\r\n mimetype = type?.mime || '';\r\n }\r\n\r\n this.mimetype = mimetype;\r\n\r\n extension = extension || mime.getExtension(this.mimetype);\r\n if (!this._name.endsWith(`.${extension}`)) this._name += `.${extension}`;\r\n } catch (error) {\r\n console.error('Error loading binary data from url:', data.url);\r\n }\r\n\r\n //this._source = data.url;\r\n\r\n this._ready = true;\r\n return;\r\n }\r\n\r\n // console.log('>>>>>>>>>>>>>>>>>>> is base64 file ?', isBase64DataUrl(data));\r\n const base64FileInfo = await getBase64FileInfo(data);\r\n if (base64FileInfo) {\r\n // If the MIME type is already set, it's safe to use it,\r\n // as determining the MIME type from the base64 string is not always accurate, specially when it's not a base64 URL\r\n if (!this.mimetype) {\r\n this.mimetype = base64FileInfo.mimetype;\r\n }\r\n this.size = base64FileInfo.size;\r\n this._source = Buffer.from(base64FileInfo.data, 'base64');\r\n\r\n const ext = mime.getExtension(this.mimetype);\r\n if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;\r\n\r\n this._ready = true;\r\n return;\r\n }\r\n\r\n if (typeof data === 'string') {\r\n this._source = Buffer.from(data);\r\n this.size = data.length;\r\n this.mimetype = 'text/plain';\r\n if (!this._name.endsWith(`.txt`)) this._name += `.txt`;\r\n\r\n this._ready = true;\r\n return;\r\n }\r\n\r\n //this.size = getSizeFromBinary(data);\r\n // //try to enforce the mimetype from the provided data\r\n // if (Buffer.isBuffer(data)) {\r\n // const fileType = await FileType.fileTypeFromBuffer(data);\r\n // this.mimetype = fileType.mime;\r\n // const ext = mime.getExtension(this.mimetype);\r\n // if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;\r\n\r\n // this._ready = true;\r\n // return;\r\n // }\r\n //try to enforce the mimetype from the provided data\r\n if (Buffer.isBuffer(data)) {\r\n this._source = data;\r\n this.size = getSizeFromBinary(data);\r\n // If the MIME type is already set, it's safe to use it,\r\n // as determining the MIME type from the buffer is not always accurate.\r\n if (!this.mimetype) {\r\n this.mimetype = await getMimeType(data);\r\n }\r\n const ext = mime.getExtension(this.mimetype);\r\n if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;\r\n }\r\n\r\n if (data instanceof Blob) {\r\n this._source = Buffer.from(await data.arrayBuffer());\r\n this.size = data.size;\r\n this.mimetype = data.type;\r\n }\r\n\r\n this._ready = true;\r\n }\r\n\r\n private async getUrlInfo(url) {\r\n try {\r\n // Before we had axios.head(), head method does not work for all URLs\r\n const response = await axios.get(url);\r\n const contentType = response.headers['content-type'];\r\n const contentLength = response.headers['content-length'];\r\n return { contentType, contentLength };\r\n } catch (error) {\r\n return { contentType: '', contentLength: 0 };\r\n }\r\n }\r\n\r\n public static from(data, name?: string, mimetype?: string, candidate?: IAccessCandidate) {\r\n if (data instanceof BinaryInput) return data;\r\n return new BinaryInput(data, name, mimetype, candidate);\r\n }\r\n\r\n public async upload(candidate: IAccessCandidate, ttl?: number) {\r\n await this.ready();\r\n if (this._uploading) return;\r\n\r\n try {\r\n this._uploading = true;\r\n if (!this.url) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n this.url = `smythfs://${teamId}.team/${candidate.id}/_temp/${this._name}`;\r\n await SmythFS.Instance.write(this.url, this._source, candidate, undefined, ttl);\r\n this._uploading = false;\r\n }\r\n } catch (error) {\r\n console.error('Error uploading binary data:', error);\r\n this._uploading = false;\r\n }\r\n }\r\n\r\n public async getJsonData(candidate: IAccessCandidate, ttl?: number) {\r\n await this.upload(candidate, ttl);\r\n return {\r\n mimetype: this.mimetype,\r\n size: this.size,\r\n url: this.url,\r\n name: this._name,\r\n };\r\n }\r\n\r\n public async readData(candidate: IAccessCandidate) {\r\n await this.ready();\r\n if (!this.url) {\r\n throw new Error('Binary data not ready');\r\n }\r\n const data = await SmythFS.Instance.read(this.url, candidate);\r\n return data;\r\n }\r\n\r\n public async getName() {\r\n await this.ready();\r\n return this._name;\r\n }\r\n\r\n public async getBuffer() {\r\n await this.ready();\r\n\r\n return this._source;\r\n }\r\n\r\n /**\r\n * Creates a read stream from the binary data.\r\n * Uses temporary files to reduce memory usage for large files.\r\n */\r\n public async getReadStream(): Promise<Readable> {\r\n await this.ready();\r\n\r\n // * Direct in-memory stream; faster but uses memory for the entire file.\r\n return Readable.from(this._source);\r\n\r\n // * Uses temp files (slower but memory-efficient). Disabled in favor of simpler in-memory approach.\r\n // let tempDir: string;\r\n\r\n // try {\r\n // tempDir = path.join(config.env.DATA_PATH, 'tmp');\r\n // // Test if we can access/write to this directory\r\n // if (!fs.existsSync(tempDir)) {\r\n // fs.mkdirSync(tempDir, { recursive: true });\r\n // }\r\n // } catch (error) {\r\n // // Last resort: try to use an in-memory stream instead of a temp file\r\n // console.warn('Failed to access temporary directories:', error, error);\r\n // return Readable.from(this._source);\r\n // }\r\n\r\n // // Generate a unique temp file name\r\n // const tempFilePath = path.join(tempDir, `${Date.now()}-${this._name || uid()}`);\r\n\r\n // try {\r\n // // Write the buffer to a temp file\r\n // fs.writeFileSync(tempFilePath, this._source);\r\n\r\n // // Create cleanup handler to remove temp file when stream ends\r\n // const stream = fs.createReadStream(tempFilePath);\r\n // stream.on('close', () => {\r\n // try {\r\n // fs.unlinkSync(tempFilePath);\r\n // } catch (e) {\r\n // console.warn('Failed to clean up temporary file:', tempFilePath, e);\r\n // }\r\n // });\r\n\r\n // return stream;\r\n // } catch (writeError) {\r\n // // If we can't write to the temp file, fall back to an in-memory stream\r\n // console.warn('Failed to write temporary file:', writeError);\r\n // return Readable.from(this._source);\r\n // }\r\n }\r\n}\r\n","import OpenAI from 'openai';\r\nimport Anthropic from '@anthropic-ai/sdk';\r\nimport { FunctionCallingMode, ModelParams, GenerateContentRequest } from '@google/generative-ai';\r\n\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { type models } from '@sre/LLMManager/models';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ConverseCommandInput } from '@aws-sdk/client-bedrock-runtime';\r\n\r\nexport type LLMProvider = Extract<(typeof models)[keyof typeof models], { llm: string }>['llm'] | 'VertexAI' | 'Bedrock';\r\nexport type LLMModel = keyof typeof models;\r\nexport type LLMModelInfo = (typeof models)[LLMModel];\r\n\r\n// Google Service Account Credentials Interface\r\nexport interface VertexAICredentials {\r\n type: 'service_account';\r\n project_id: string;\r\n private_key_id: string;\r\n private_key: string;\r\n client_email: string;\r\n client_id: string;\r\n auth_uri: string;\r\n token_uri: string;\r\n auth_provider_x509_cert_url: string;\r\n client_x509_cert_url: string;\r\n universe_domain?: string; // Optional, defaults to \"googleapis.com\"\r\n}\r\n\r\n// Basic LLM Credentials Interface\r\nexport interface BasicCredentials {\r\n apiKey: string;\r\n isUserKey: boolean;\r\n}\r\n\r\n// AWS Bedrock Credentials Interface\r\nexport interface BedrockCredentials {\r\n accessKeyId: string;\r\n secretAccessKey: string;\r\n sessionToken?: string;\r\n}\r\n\r\n// Union type for all credential types\r\nexport type ILLMConnectorCredentials = BasicCredentials | BedrockCredentials | VertexAICredentials;\r\n\r\nexport type TOpenAIResponseToolChoice = OpenAI.Responses.ToolChoiceOptions | OpenAI.Responses.ToolChoiceTypes | OpenAI.Responses.ToolChoiceFunction;\r\nexport type TLLMToolChoice = OpenAI.ChatCompletionToolChoiceOption;\r\n\r\nexport type TLLMParams = {\r\n model: TLLMModel | string;\r\n modelEntryName?: string; // for usage reporting\r\n credentials?: ILLMConnectorCredentials;\r\n\r\n prompt?: string;\r\n messages?: any[]; // TODO [Forhad]: apply proper typing\r\n temperature?: number;\r\n maxTokens?: number;\r\n stopSequences?: string[];\r\n topP?: number;\r\n topK?: number;\r\n frequencyPenalty?: number;\r\n presencePenalty?: number;\r\n responseFormat?: any; // TODO [Forhad]: apply proper typing\r\n modelInfo?: TCustomLLMModel;\r\n files?: BinaryInput[];\r\n toolsConfig?: {\r\n tools?: OpenAI.ChatCompletionTool[] | OpenAI.Responses.Tool[] | OpenAI.Responses.WebSearchTool[];\r\n tool_choice?: TLLMToolChoice;\r\n };\r\n baseURL?: string;\r\n\r\n size?: OpenAI.Images.ImageGenerateParams['size'] | OpenAI.Images.ImageEditParams['size']; // for image generation and image editing\r\n quality?: 'standard' | 'hd'; // for image generation\r\n n?: number; // for image generation\r\n style?: 'vivid' | 'natural'; // for image generation\r\n\r\n cache?: boolean;\r\n agentId?: string;\r\n teamId?: string;\r\n thinking?: {\r\n // for Anthropic\r\n type: 'enabled' | 'disabled';\r\n budget_tokens: number;\r\n };\r\n maxThinkingTokens?: number;\r\n\r\n // #region Search\r\n useWebSearch?: boolean;\r\n webSearchContextSize?: 'high' | 'medium' | 'low';\r\n webSearchCity?: string;\r\n webSearchCountry?: string;\r\n webSearchRegion?: string;\r\n webSearchTimezone?: string;\r\n // #endregion\r\n\r\n useReasoning?: boolean;\r\n\r\n isUserKey?: boolean;\r\n capabilities?: {\r\n search?: boolean;\r\n reasoning?: boolean;\r\n imageGeneration?: boolean;\r\n imageEditing?: boolean;\r\n };\r\n max_output_tokens?: number;\r\n\r\n abortSignal?: AbortSignal;\r\n};\r\n\r\nexport type TLLMParamsV2 = {\r\n model: string;\r\n modelEntryName: string;\r\n messages: any[];\r\n toolsConfig?: {\r\n tools?: OpenAI.Responses.Tool[];\r\n tool_choice?: OpenAI.Responses.ToolChoiceOptions | OpenAI.Responses.ToolChoiceTypes | OpenAI.Responses.ToolChoiceFunction;\r\n };\r\n baseURL?: string;\r\n stream?: boolean;\r\n responseFormat?: any;\r\n credentials?: {\r\n apiKey?: string;\r\n isUserKey?: boolean;\r\n };\r\n max_output_tokens?: number;\r\n temperature?: number;\r\n top_p?: number;\r\n top_k?: number;\r\n frequency_penalty?: number;\r\n presence_penalty?: number;\r\n teamId?: string;\r\n files?: BinaryInput[];\r\n\r\n // #region Search\r\n useWebSearch?: boolean;\r\n webSearchContextSize?: 'high' | 'medium' | 'low';\r\n webSearchCity?: string;\r\n webSearchCountry?: string;\r\n webSearchRegion?: string;\r\n webSearchTimezone?: string;\r\n // #endregion\r\n};\r\n\r\nexport type TLLMConnectorParams = Omit<TLLMParams, 'model'> & {\r\n //the LLMConnector accepts a model object that we extract the model info from instead of relying on the internal models list\r\n model: string | TLLMModel | TCustomLLMModel;\r\n};\r\n\r\nexport type TLLMModelEntry = {\r\n llm: string;\r\n tokens?: number;\r\n completionTokens?: number;\r\n enabled?: boolean;\r\n components?: string[];\r\n alias?: string;\r\n tags?: string[];\r\n keyOptions?: {\r\n tokens: number;\r\n completionTokens: number;\r\n };\r\n};\r\n\r\nexport enum TLLMCredentials {\r\n Vault = 'vault',\r\n Internal = 'internal',\r\n BedrockVault = 'bedrock_vault',\r\n VertexAIVault = 'vertexai_vault',\r\n None = 'none',\r\n}\r\nexport type TLLMModel = {\r\n llm?: string;\r\n isCustomLLM?: boolean;\r\n modelId?: string;\r\n tokens?: number;\r\n completionTokens?: number;\r\n components?: string[];\r\n tags?: string[];\r\n label?: string;\r\n provider?: LLMProvider;\r\n features?: string[];\r\n enabled?: boolean;\r\n alias?: string;\r\n baseURL?: string;\r\n keyOptions?: {\r\n tokens: number;\r\n completionTokens: number;\r\n };\r\n credentials?: TLLMCredentials;\r\n\r\n //models can come with predefined params\r\n //this can also be used to pass a preconfigured model object\r\n params?: TLLMParams;\r\n};\r\n\r\n// #region [ Handle extendable LLM Providers ] ================================================\r\nexport const BuiltinLLMProviders = {\r\n Echo: 'Echo',\r\n OpenAI: 'OpenAI',\r\n DeepSeek: 'DeepSeek',\r\n GoogleAI: 'GoogleAI',\r\n Anthropic: 'Anthropic',\r\n Groq: 'Groq',\r\n TogetherAI: 'TogetherAI',\r\n Bedrock: 'Bedrock',\r\n VertexAI: 'VertexAI',\r\n xAI: 'xAI',\r\n Perplexity: 'Perplexity',\r\n} as const;\r\n// Base provider type\r\nexport type TBuiltinLLMProvider = (typeof BuiltinLLMProviders)[keyof typeof BuiltinLLMProviders];\r\n\r\n// Extensible interface for custom providers\r\nexport interface ILLMProviders {}\r\n// Combined provider type that can be extended\r\nexport type TLLMProvider = TBuiltinLLMProvider | keyof ILLMProviders;\r\n\r\n// For backward compatibility, export the built-in providers as enum-like object\r\nexport const TLLMProvider = BuiltinLLMProviders;\r\n\r\n// #endregion\r\n\r\nexport type TBedrockSettings = {\r\n keyIDName: string;\r\n secretKeyName: string;\r\n sessionKeyName: string;\r\n};\r\nexport type TVertexAISettings = {\r\n projectId: string;\r\n credentialsName: string;\r\n jsonCredentialsName: string;\r\n};\r\n\r\nexport type TCustomLLMModel = TLLMModel & {\r\n name: string;\r\n settings: {\r\n foundationModel: string;\r\n customModel: string;\r\n region: string;\r\n } & (TBedrockSettings | TVertexAISettings);\r\n};\r\n\r\n//#region === LLM Tools ===========================\r\nexport type ToolData = {\r\n index: number;\r\n id: string;\r\n type: string;\r\n name: string;\r\n arguments: string | Record<string, any>;\r\n role: 'user' | 'tool' | 'assistant';\r\n result?: string; // result string from the used tool\r\n function?: any;\r\n error?: string; // for Bedrock\r\n};\r\n\r\nexport interface AnthropicToolDefinition {\r\n name: string;\r\n description: string;\r\n input_schema: {\r\n type: 'object';\r\n properties: Record<string, unknown>;\r\n required: string[];\r\n };\r\n}\r\nexport type ToolDefinition = OpenAI.ChatCompletionTool | AnthropicToolDefinition;\r\nexport type ToolChoice = OpenAI.ChatCompletionToolChoiceOption | FunctionCallingMode;\r\n\r\nexport interface ToolsConfig {\r\n tools?: ToolDefinition[];\r\n tool_choice?: ToolChoice;\r\n}\r\n\r\n//#endregion\r\n\r\nexport enum TLLMMessageRole {\r\n User = 'user',\r\n Assistant = 'assistant',\r\n System = 'system',\r\n Model = 'model',\r\n Tool = 'tool',\r\n Function = 'function',\r\n}\r\n\r\nexport type TLLMMessageBlock = {\r\n role: TLLMMessageRole;\r\n content?:\r\n | string\r\n | { text: string }[]\r\n | Array<Anthropic.TextBlockParam | Anthropic.ImageBlockParam | Anthropic.ToolUseBlockParam | Anthropic.ToolResultBlockParam>;\r\n parts?: {\r\n text?: string;\r\n functionCall?: { name: string; args: string };\r\n functionResponse?: { name: string; response: { name: string; content: string } };\r\n }[]; // for Google Vertex AI\r\n tool_calls?: ToolData[];\r\n};\r\n\r\nexport type TLLMToolResultMessageBlock = TLLMMessageBlock & {\r\n tool_call_id?: string; // for tool result message block of OpenAI\r\n name?: string; // for tool result message block of OpenAI\r\n};\r\n\r\nexport type GenerateImageConfig = {\r\n size?: '256x256' | '512x512' | '1024x1024' | '1792x1024' | '1024x1792';\r\n quality?: 'standard' | 'hd';\r\n model: string;\r\n style?: 'vivid' | 'natural';\r\n n?: number;\r\n response_format?: 'url' | 'b64_json';\r\n prompt?: string;\r\n};\r\n\r\n// ! Deprecated\r\nexport type TLLMInputMessage = {\r\n role: string;\r\n content?: string | { text: string }[];\r\n parts?: { text: string }[]; // * 'part' is for Google Vertex AI\r\n};\r\n\r\nexport interface ILLMContextStore {\r\n save(messages: any[]): Promise<void>;\r\n load(count?: number): Promise<any[]>;\r\n getMessage(message_id: string): Promise<any[]>;\r\n}\r\n\r\nexport enum APIKeySource {\r\n Smyth = 'smyth-managed',\r\n User = 'user-managed',\r\n Custom = 'custom',\r\n}\r\n\r\nexport interface SmythLLMUsage {\r\n sourceId: string;\r\n input_tokens: number;\r\n input_tokens_cache_write: number;\r\n input_tokens_cache_read: number;\r\n output_tokens: number;\r\n keySource?: APIKeySource;\r\n agentId: string;\r\n teamId: string;\r\n tier?: string; // for Google AI\r\n}\r\n\r\nexport interface SmythTaskUsage {\r\n sourceId: string;\r\n number: number;\r\n agentId: string;\r\n teamId: string;\r\n}\r\n\r\nexport type TLLMModelsList = {\r\n [key: string]: TLLMModel | TCustomLLMModel;\r\n};\r\n\r\nexport enum TLLMEvent {\r\n /** Generated response chunks */\r\n Content = 'content',\r\n /** Thinking blocks/chunks */\r\n Thinking = 'thinking',\r\n /** End of the response */\r\n End = 'end',\r\n /** Error */\r\n Error = 'error',\r\n /** Tool information : emitted by the LLM determines the next tool call */\r\n ToolInfo = 'toolInfo',\r\n /** Tool call : emitted before the tool call */\r\n ToolCall = 'toolCall',\r\n /** Tool result : emitted after the tool call */\r\n ToolResult = 'toolResult',\r\n /** Tokens usage information */\r\n Usage = 'usage',\r\n /** Interrupted : emitted when the response is interrupted before completion */\r\n Interrupted = 'interrupted',\r\n}\r\n\r\nexport interface ILLMRequestContext {\r\n modelEntryName: string;\r\n agentId: string;\r\n teamId: string;\r\n isUserKey: boolean;\r\n hasFiles?: boolean;\r\n modelInfo: TCustomLLMModel | TLLMModel;\r\n credentials: ILLMConnectorCredentials;\r\n}\r\n\r\n// Generic interface that can be extended by specific providers\r\nexport interface ILLMRequestFuncParams<TBody = any> {\r\n acRequest: AccessRequest;\r\n body: TBody;\r\n context: ILLMRequestContext;\r\n}\r\n\r\n// For future providers, you can add similar types:\r\n// export type TAnthropicRequestBody = Anthropic.MessageCreateParams | Anthropic.MessageStreamParams;\r\n// export type IAnthropicRequestFuncParams = ILLMRequestFuncParams<TAnthropicRequestBody>;\r\n\r\nexport type TLLMChatResponse = {\r\n content: string;\r\n finishReason: string;\r\n thinkingContent?: string;\r\n usage?: any;\r\n useTool?: boolean;\r\n toolsData?: ToolData[];\r\n message?: OpenAI.ChatCompletionMessageParam | Anthropic.MessageParam;\r\n};\r\n\r\nexport type TOpenAIRequestBody =\r\n | OpenAI.ChatCompletionCreateParamsNonStreaming\r\n | OpenAI.ChatCompletionCreateParamsStreaming\r\n | OpenAI.ChatCompletionCreateParams\r\n | OpenAI.Responses.ResponseCreateParams\r\n | OpenAI.Responses.ResponseCreateParamsNonStreaming\r\n | OpenAI.Responses.ResponseCreateParamsStreaming\r\n | OpenAI.Images.ImageGenerateParams\r\n | OpenAI.Images.ImageEditParams;\r\n\r\nexport type TAnthropicRequestBody = Anthropic.MessageCreateParamsNonStreaming;\r\n\r\nexport type TGoogleAIRequestBody = ModelParams & { messages: string | TLLMMessageBlock[] | GenerateContentRequest };\r\n\r\nexport type TLLMRequestBody = TOpenAIRequestBody | TAnthropicRequestBody | TGoogleAIRequestBody | ConverseCommandInput;\r\n","export function isAgent(agent: any): boolean {\r\n return typeof agent === 'object' && agent.id && typeof agent.callComponent === 'function';\r\n}\r\n","import _ from 'lodash';\r\nimport { type OpenAI } from 'openai';\r\nimport { encodeChat } from 'gpt-tokenizer';\r\nimport { ChatMessage } from 'gpt-tokenizer/esm/GptEncoding';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { LLMConnector } from './LLM.service/LLMConnector';\r\nimport { EventEmitter } from 'events';\r\nimport { GenerateImageConfig, TLLMMessageRole, TLLMModel, TLLMChatResponse } from '@sre/types/LLM.types';\r\nimport { IModelsProviderRequest, ModelsProviderConnector } from './ModelsProvider.service/ModelsProviderConnector';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { IAgent } from '@sre/types/Agent.types';\r\nimport { isAgent } from '@sre/AgentManager/Agent.helper';\r\nimport { TLLMParams } from '@sre/types/LLM.types';\r\n\r\nconst console = Logger('LLMInference');\r\n\r\ntype TPromptParams = { query?: string; contextWindow?: any[]; files?: any[]; params: TLLMParams };\r\n\r\nexport class LLMInference {\r\n private model: string | TLLMModel;\r\n private llmConnector: LLMConnector;\r\n private modelProviderReq: IModelsProviderRequest;\r\n public teamId?: string;\r\n\r\n public static async getInstance(model: string | TLLMModel, candidate: AccessCandidate) {\r\n const modelsProvider: ModelsProviderConnector = ConnectorService.getModelsProviderConnector();\r\n if (!modelsProvider.valid) {\r\n throw new Error(`Model provider Not available, cannot create LLM instance`);\r\n }\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.requester(candidate).getTeam();\r\n\r\n const llmInference = new LLMInference();\r\n llmInference.teamId = teamId;\r\n\r\n llmInference.modelProviderReq = modelsProvider.requester(candidate);\r\n\r\n const llmProvider = await llmInference.modelProviderReq.getProvider(model);\r\n if (llmProvider) {\r\n llmInference.llmConnector = ConnectorService.getLLMConnector(llmProvider);\r\n }\r\n\r\n if (!llmInference.llmConnector) {\r\n console.error(`Model ${model} unavailable for team ${teamId}`);\r\n }\r\n\r\n llmInference.model = model;\r\n\r\n return llmInference;\r\n }\r\n\r\n public static user(candidate: AccessCandidate): any {}\r\n\r\n public get connector(): LLMConnector {\r\n return this.llmConnector;\r\n }\r\n\r\n public async prompt({ query, contextWindow, files, params }: TPromptParams) {\r\n let messages = contextWindow || [];\r\n\r\n if (query) {\r\n const content = this.llmConnector.enhancePrompt(query, params);\r\n messages.push({ role: TLLMMessageRole.User, content });\r\n }\r\n\r\n if (!params.model) params.model = this.model;\r\n params.messages = messages;\r\n params.files = files;\r\n\r\n try {\r\n let response: TLLMChatResponse = await this.llmConnector.requester(AccessCandidate.agent(params.agentId)).request(params);\r\n\r\n const result = this.llmConnector.postProcess(response?.content);\r\n if (result.error) {\r\n // If the model stopped before completing the response, this is usually due to output token limit reached.\r\n if (response.finishReason !== 'stop') {\r\n throw new Error('The model stopped before completing the response, this is usually due to output token limit reached.');\r\n }\r\n\r\n // If the model stopped due to other reasons, throw the error\r\n throw new Error(result.error);\r\n }\r\n return result;\r\n } catch (error: any) {\r\n console.error('Error in chatRequest: ', error);\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n public async promptStream({ query, contextWindow, files, params }: TPromptParams) {\r\n let messages = contextWindow || [];\r\n\r\n if (query) {\r\n const content = this.llmConnector.enhancePrompt(query, params);\r\n messages.push({ role: TLLMMessageRole.User, content });\r\n }\r\n\r\n if (!params.model) params.model = this.model;\r\n params.messages = messages;\r\n params.files = files;\r\n\r\n try {\r\n return await this.llmConnector.user(AccessCandidate.agent(params.agentId)).streamRequest(params);\r\n } catch (error) {\r\n console.error('Error in streamRequest:', error);\r\n\r\n const dummyEmitter = new EventEmitter();\r\n process.nextTick(() => {\r\n dummyEmitter.emit('error', error);\r\n dummyEmitter.emit('end');\r\n });\r\n return dummyEmitter;\r\n }\r\n }\r\n\r\n public async imageGenRequest({ query, files, params }: TPromptParams) {\r\n params.prompt = query;\r\n return this.llmConnector.user(AccessCandidate.agent(params.agentId)).imageGenRequest(params);\r\n }\r\n\r\n public async imageEditRequest({ query, files, params }: TPromptParams) {\r\n params.prompt = query;\r\n params.files = files;\r\n return this.llmConnector.user(AccessCandidate.agent(params.agentId)).imageEditRequest(params);\r\n }\r\n\r\n public async streamRequest(params: any, agent: string | IAgent) {\r\n const agentId = isAgent(agent) ? (agent as IAgent).id : agent;\r\n try {\r\n if (!params.messages || !params.messages?.length) {\r\n throw new Error('Input messages are required.');\r\n }\r\n\r\n const model = params.model || this.model;\r\n\r\n return await this.llmConnector.user(AccessCandidate.agent(agentId)).streamRequest({ ...params, model });\r\n } catch (error) {\r\n console.error('Error in streamRequest:', error);\r\n\r\n const dummyEmitter = new EventEmitter();\r\n process.nextTick(() => {\r\n dummyEmitter.emit('error', error);\r\n dummyEmitter.emit('end');\r\n });\r\n return dummyEmitter;\r\n }\r\n }\r\n\r\n public async multimodalStreamRequest(params: any, fileSources, agent: string | IAgent) {\r\n const agentId = isAgent(agent) ? (agent as IAgent).id : agent;\r\n\r\n const promises = [];\r\n const _fileSources = [];\r\n\r\n // TODO [Forhad]: For models from Google AI, we currently store files twice — once here and once in the GoogleAIConnector. We need to optimize this process.\r\n for (let file of fileSources) {\r\n const binaryInput = BinaryInput.from(file);\r\n _fileSources.push(binaryInput);\r\n promises.push(binaryInput.upload(AccessCandidate.agent(agentId)));\r\n }\r\n\r\n await Promise.all(promises);\r\n\r\n params.fileSources = _fileSources;\r\n\r\n try {\r\n //FIXME we need to update the connector multimediaStreamRequest in order to ignore prompt param if not provided\r\n const userMessage = Array.isArray(params.messages) ? params.messages.pop() : {};\r\n const prompt = userMessage?.content || '';\r\n const model = params.model || this.model;\r\n\r\n return await this.llmConnector.user(AccessCandidate.agent(agentId)).multimodalStreamRequest(prompt, { ...params, model });\r\n } catch (error: any) {\r\n console.error('Error in multimodalRequest: ', error);\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n public async multimodalStreamRequestLegacy(prompt, files: string[], config: any = {}, agent: string | IAgent) {\r\n const agentId = isAgent(agent) ? (agent as IAgent).id : agent;\r\n\r\n const promises = [];\r\n const _files = [];\r\n\r\n // TODO [Forhad]: For models from Google AI, we currently store files twice — once here and once in the GoogleAIConnector. We need to optimize this process.\r\n for (let file of files) {\r\n const binaryInput = BinaryInput.from(file);\r\n _files.push(binaryInput);\r\n promises.push(binaryInput.upload(AccessCandidate.agent(agentId)));\r\n }\r\n\r\n await Promise.all(promises);\r\n\r\n const params = config.data;\r\n\r\n params.files = _files;\r\n\r\n try {\r\n prompt = this.llmConnector.enhancePrompt(prompt, config);\r\n const model = params.model || this.model;\r\n\r\n return await this.llmConnector.user(AccessCandidate.agent(agentId)).multimodalStreamRequest(prompt, { ...params, model });\r\n } catch (error: any) {\r\n console.error('Error in multimodalRequest: ', error);\r\n\r\n throw error;\r\n }\r\n }\r\n\r\n //Not needed\r\n // public getConsistentMessages(messages: TLLMMessageBlock[]) {\r\n // if (!messages?.length) {\r\n // throw new Error('Input messages are required.');\r\n // }\r\n\r\n // try {\r\n // return this.llmConnector.getConsistentMessages(messages);\r\n // } catch (error) {\r\n // console.warn('Something went wrong in getConsistentMessages: ', error);\r\n\r\n // return messages; // if something went wrong then we return the original messages\r\n // }\r\n // }\r\n\r\n /**\r\n * Get the context window for the given messages\r\n * @param _messages - The messages to get the context window for (the messages are in smythos generic format)\r\n * @param maxTokens - The maximum number of tokens to use for the context window\r\n * @param maxOutputTokens - The maximum number of tokens to use for the output\r\n * @returns The context window for the given messages\r\n */\r\n public async getContextWindow(systemPrompt: string, _messages: any[], maxTokens: number, maxOutputTokens: number = 1024): Promise<any[]> {\r\n //TODO: handle non key accounts (limit tokens)\r\n // const maxModelContext = this._llmHelper?.modelInfo?.keyOptions?.tokens || this._llmHelper?.modelInfo?.tokens || 256;\r\n\r\n //#region get max model context\r\n\r\n const modelInfo = await this.modelProviderReq.getModelInfo(this.model, true);\r\n let maxModelContext = modelInfo?.tokens;\r\n let maxModelOutputTokens = modelInfo?.completionTokens || modelInfo?.tokens;\r\n // const isStandardLLM = LLMRegistry.isStandardLLM(this.model);\r\n\r\n // if (isStandardLLM) {\r\n // maxModelContext = LLMRegistry.getMaxContextTokens(this.model, true); // we just provide true for hasAPIKey to get the original max context\r\n // } else {\r\n // const team = AccessCandidate.team(this.teamId);\r\n // const customLLMRegistry = await CustomLLMRegistry.getInstance(team);\r\n // maxModelContext = customLLMRegistry.getMaxContextTokens(this.model);\r\n // maxModelOutputTokens = customLLMRegistry.getMaxCompletionTokens(this.model);\r\n // }\r\n //#endregion get max model context\r\n\r\n let maxInputContext = Math.min(maxTokens, maxModelContext);\r\n let maxOutputContext = Math.min(maxOutputTokens, maxModelOutputTokens || 0);\r\n\r\n if (maxInputContext + maxOutputContext > maxModelContext) {\r\n maxInputContext -= maxInputContext + maxOutputContext - maxModelContext;\r\n }\r\n\r\n const systemMessage = { role: 'system', content: systemPrompt };\r\n\r\n let smythContextWindow = [];\r\n\r\n //loop through messages from last to first and use encodeChat to calculate token lengths\r\n //we will use fake chatMessages to calculate the token lengths, these are not used by the LLM, but just for token counting\r\n let tokensCount = encodeChat([systemMessage as ChatMessage], 'gpt-4o').length;\r\n for (let i = _messages?.length - 1; i >= 0; i--) {\r\n const curMessage = _messages[i];\r\n if (curMessage.role === 'system') continue;\r\n\r\n tokensCount = 0;\r\n if (curMessage?.content) {\r\n // tokensCount += encodeChat([{ role: 'user', content: curMessage.content } as ChatMessage], 'gpt-4o').length;\r\n tokensCount += countTokens(curMessage.content);\r\n }\r\n\r\n if (curMessage?.messageBlock?.content) {\r\n // tokensCount += encodeChat([{ role: 'user', content: curMessage.messageBlock.content } as ChatMessage], 'gpt-4o').length;\r\n tokensCount += countTokens(curMessage.messageBlock.content);\r\n }\r\n if (curMessage.toolsData) {\r\n for (let tool of curMessage.toolsData) {\r\n // tokensCount += encodeChat([{ role: 'user', content: tool.result } as ChatMessage], 'gpt-4o').length;\r\n tokensCount += countTokens(tool.result);\r\n }\r\n }\r\n\r\n //did the last message exceed the context window ?\r\n if (tokensCount > maxInputContext) {\r\n break;\r\n }\r\n\r\n smythContextWindow.unshift(curMessage);\r\n }\r\n smythContextWindow.unshift(systemMessage);\r\n\r\n let modelContextWindow = [];\r\n //now transform the messages to the model format\r\n for (let message of smythContextWindow) {\r\n if (message.role && message.content) {\r\n modelContextWindow.push({ role: message.role, content: message.content });\r\n }\r\n\r\n if (message.messageBlock && message.toolsData) {\r\n const internal_message = this.connector.transformToolMessageBlocks({\r\n messageBlock: message?.messageBlock,\r\n toolsData: message?.toolsData,\r\n });\r\n\r\n modelContextWindow.push(...internal_message);\r\n }\r\n }\r\n\r\n modelContextWindow = this.connector.getConsistentMessages(modelContextWindow);\r\n\r\n return modelContextWindow;\r\n }\r\n}\r\n\r\nfunction countTokens(content: any, model: 'gpt-4o' | 'gpt-4o-mini' = 'gpt-4o') {\r\n try {\r\n // Content must be stringified since some providers like Anthropic use object content\r\n const _stringifiedContent = typeof content === 'string' ? content : JSON.stringify(content);\r\n\r\n const tokens = encodeChat([{ role: 'user', content: _stringifiedContent } as ChatMessage], model);\r\n return tokens.length;\r\n } catch (error) {\r\n console.warn('Error in countTokens: ', error);\r\n return 0;\r\n }\r\n}\r\n","import { encode, encodeChat } from 'gpt-tokenizer';\r\nimport { ChatMessage } from 'gpt-tokenizer/esm/GptEncoding';\r\nimport { ILLMContextStore } from '@sre/types/LLM.types';\r\nimport { LLMCache } from './LLMCache';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\n//content, name, role, tool_call_id, tool_calls, function_call\r\nexport class LLMContext {\r\n private _systemPrompt: string = '';\r\n private _llmContextStore: ILLMContextStore;\r\n private _llmCache: LLMCache;\r\n\r\n public get systemPrompt() {\r\n return this._systemPrompt;\r\n }\r\n public set systemPrompt(systemPrompt) {\r\n this._systemPrompt = systemPrompt;\r\n this._llmCache?.set('systemPrompt', this.systemPrompt);\r\n }\r\n\r\n public get llmCache() {\r\n return this._llmCache;\r\n }\r\n\r\n public contextLength: number;\r\n\r\n private _messages: any[] = [];\r\n public get messages() {\r\n //TODO : check if the store is ready\r\n return this._messages;\r\n }\r\n\r\n public get model() {\r\n return this.llmInference.model;\r\n }\r\n /**\r\n *\r\n * @param source a messages[] object, or smyth file system uri (smythfs://...)\r\n */\r\n constructor(\r\n private llmInference,\r\n _systemPrompt: string = '',\r\n /*private _messages: any[] = [],*/ llmContextStore?: ILLMContextStore,\r\n ) {\r\n this._llmCache = new LLMCache(AccessCandidate.team(this.llmInference.teamId));\r\n //this._systemPrompt = _systemPrompt;\r\n this.systemPrompt = _systemPrompt;\r\n\r\n //TODO:allow configuring a storage service\r\n if (llmContextStore) {\r\n this._llmContextStore = llmContextStore;\r\n this._llmContextStore.load().then((messages) => {\r\n this._messages = messages;\r\n this._llmCache.set('messages', this._messages);\r\n });\r\n }\r\n }\r\n\r\n private push(...message: any[]) {\r\n this._messages.push(...message);\r\n //TODO: persist to storage\r\n if (this._llmContextStore) {\r\n this._llmContextStore.save(this._messages);\r\n }\r\n this._llmCache.set('messages', this._messages);\r\n }\r\n public addUserMessage(content: string, message_id: string, metadata?: any) {\r\n //in the current implementation, we do not support forked conversations\r\n //we always attatch to the last message in the queue\r\n\r\n //TODO: implement forked conversations ==> might require updating the interfaces in order to support passing previous message_id explicitly\r\n const lastMessage = this._messages[this._messages.length - 1];\r\n\r\n if (lastMessage) {\r\n if (!lastMessage.__smyth_data__?.next) {\r\n lastMessage.__smyth_data__.next = [];\r\n }\r\n lastMessage.__smyth_data__.next.push(message_id);\r\n }\r\n\r\n const prev = lastMessage?.__smyth_data__?.message_id;\r\n const next = [];\r\n\r\n this.push({ role: 'user', content, __smyth_data__: { message_id, ...metadata, prev, next } });\r\n }\r\n public addAssistantMessage(content: string, message_id: string, metadata?: any) {\r\n const lastMessage = this._messages[this._messages.length - 1];\r\n\r\n if (lastMessage) {\r\n if (!lastMessage.__smyth_data__?.next) {\r\n lastMessage.__smyth_data__.next = [];\r\n }\r\n lastMessage.__smyth_data__.next.push(message_id);\r\n }\r\n\r\n const prev = lastMessage?.__smyth_data__?.message_id;\r\n const next = [];\r\n this.push({ role: 'assistant', content, __smyth_data__: { message_id, ...metadata, prev, next } });\r\n }\r\n public addToolMessage(messageBlock: any, toolsData: any, message_id: string, metadata?: any) {\r\n const lastMessage = this._messages[this._messages.length - 1];\r\n\r\n if (lastMessage) {\r\n if (!lastMessage.__smyth_data__?.next) {\r\n lastMessage.__smyth_data__.next = [];\r\n }\r\n lastMessage.__smyth_data__.next.push(message_id);\r\n }\r\n\r\n const prev = lastMessage?.__smyth_data__?.message_id;\r\n const next = [];\r\n this.push({ messageBlock, toolsData, __smyth_data__: { message_id, ...metadata, prev, next } });\r\n }\r\n\r\n public async getContextWindow(maxTokens: number, maxOutputTokens: number = 1024): Promise<any[]> {\r\n const messages = JSON.parse(JSON.stringify(this._messages));\r\n // if (messages[0]?.role === 'system') {\r\n // messages[0].content = this.systemPrompt;\r\n // } else {\r\n // messages.unshift({ role: 'system', content: this.systemPrompt });\r\n // }\r\n\r\n return this.llmInference.getContextWindow(this.systemPrompt, messages, maxTokens, maxOutputTokens);\r\n }\r\n}\r\n","import axios from 'axios';\r\nimport yaml from 'js-yaml';\r\n\r\nimport { REQUEST_METHODS } from '../constants';\r\n\r\n// * We need a couple of packages to resolve references in the OpenAPI specification\r\n//FIXME : YAML support temporarly disabled to allow executable packaging\r\n//import SwaggerParser from '@apidevtools/swagger-parser';\r\n//import $RefParser from '@apidevtools/json-schema-ref-parser';\r\n//import { JSONSchema } from '@apidevtools/json-schema-ref-parser/dist/lib/types';\r\n\r\n//const swaggerParser = new SwaggerParser();\r\n\r\ntype JSONSchema = Record<string, any>;\r\n\r\n/**\r\n * Utility function to resolve $ref values within a schema.\r\n * @param schema The schema containing potential $ref values.\r\n * @param root The root schema for reference resolution.\r\n * @returns The dereferenced schema.\r\n */\r\nconst dereferenceSchema = async (schema: any, root: any = schema): Promise<any> => {\r\n if (typeof schema !== 'object' || schema === null) {\r\n return schema;\r\n }\r\n\r\n if (schema.$ref) {\r\n const ref = schema.$ref;\r\n const path = ref.replace(/^#\\//, '').split('/'); // Remove the initial '#/' and split the path\r\n let resolved = root;\r\n for (const segment of path) {\r\n if (resolved[segment] === undefined) {\r\n throw new Error(`Could not resolve $ref: ${ref}`);\r\n }\r\n resolved = resolved[segment];\r\n }\r\n return dereferenceSchema(resolved, root); // Recursively dereference\r\n }\r\n\r\n // Recursively resolve all properties and items\r\n if (Array.isArray(schema)) {\r\n return Promise.all(schema.map((item) => dereferenceSchema(item, root)));\r\n }\r\n\r\n const result: any = {};\r\n for (const key of Object.keys(schema)) {\r\n result[key] = await dereferenceSchema(schema[key], root);\r\n }\r\n return result;\r\n};\r\n\r\nexport class OpenAPIParser {\r\n static mapReqMethods(paths: Array<Record<string, any>>): Map<string, any> {\r\n const methods = new Map();\r\n\r\n for (const path in paths) {\r\n const pathData = paths[path];\r\n\r\n for (const method in pathData) {\r\n const data = pathData[method];\r\n\r\n if (REQUEST_METHODS.includes(method.toUpperCase())) {\r\n methods.set(data?.operationId, method);\r\n }\r\n }\r\n }\r\n\r\n return methods;\r\n }\r\n static mapEndpoints(paths: Array<Record<string, any>>): Map<string, any> {\r\n const operationIds = new Map();\r\n\r\n for (const path in paths) {\r\n const pathData = paths[path];\r\n\r\n // it's possible we have multiple methods for a single path\r\n for (const method in pathData) {\r\n const data = pathData[method];\r\n\r\n if (REQUEST_METHODS.includes(method.toUpperCase())) {\r\n operationIds.set(data?.operationId, path);\r\n }\r\n }\r\n }\r\n\r\n return operationIds;\r\n }\r\n\r\n // static async yamlToJson(yamlData: string): Promise<JSONSchema> {\r\n // const data = yaml.load(yamlData);\r\n // //FIXME : YAML support temporarly disabled to allow executable packaging\r\n // const schema = await $RefParser.dereference(data);\r\n // //const schema: any = {};\r\n\r\n // return schema;\r\n // }\r\n\r\n static async yamlToJson(yamlData: string): Promise<JSONSchema> {\r\n const data = yaml.load(yamlData);\r\n const schema = await dereferenceSchema(data);\r\n return schema;\r\n }\r\n\r\n // static async getJson(data: string | Record<string, any>): Promise<Record<string, any>> {\r\n // try {\r\n // let _data = data;\r\n // if (typeof data === 'string') {\r\n // _data = JSON.parse(_data as string);\r\n // }\r\n // //FIXME : YAML support temporarly disabled to allow executable packaging\r\n // const result = swaggerParser.dereference(_data as any);\r\n // //const result: any = {};\r\n // return result;\r\n // } catch (error) {\r\n // try {\r\n // return OpenAPIParser.yamlToJson(data as string);\r\n // } catch (error) {\r\n // throw new Error('Invalid OpenAPI specification data format');\r\n // }\r\n // }\r\n // }\r\n\r\n static async getJson(data: string | Record<string, any>): Promise<Record<string, any>> {\r\n try {\r\n let parsedData = data;\r\n if (typeof data === 'string') {\r\n parsedData = JSON.parse(data);\r\n }\r\n\r\n return await dereferenceSchema(parsedData);\r\n } catch (error) {\r\n try {\r\n // Fallback to handle YAML data\r\n return await OpenAPIParser.yamlToJson(data as string);\r\n } catch (innerError) {\r\n throw new Error('Invalid OpenAPI specification or JSON data format');\r\n }\r\n }\r\n }\r\n static async getJsonFromUrl(url: string): Promise<Record<string, any>> {\r\n const response = await axios.get(url);\r\n const data = response.data;\r\n\r\n return OpenAPIParser.getJson(data);\r\n }\r\n\r\n static isValidOpenAPI(data: Record<string, any>): boolean {\r\n return data?.openapi && data?.paths && data?.servers;\r\n }\r\n}\r\n","// Type definition for hook callbacks\r\ntype HookCallback = (...args: any[]) => void;\r\n\r\n// Store hooks in a map where each hook name can have multiple callbacks\r\nconst hooks: { [key: string]: HookCallback[] } = {};\r\n\r\nexport class HookService {\r\n /**\r\n * Register a new hook callback for a given hook name\r\n * @param hookName The name of the hook to register\r\n * @param callback The callback function to execute when the hook is triggered\r\n */\r\n static register(hookName: string, callback: HookCallback): void {\r\n if (typeof callback !== 'function') {\r\n throw new Error('Hook callback must be a function');\r\n }\r\n\r\n if (!hooks[hookName]) {\r\n hooks[hookName] = [];\r\n }\r\n\r\n hooks[hookName].push(callback);\r\n }\r\n\r\n static trigger(hookName: string, ...args: any[]) {\r\n if (hooks[hookName]) {\r\n hooks[hookName].forEach((callback) => callback(...args));\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Decorator function that executes registered hooks before the decorated method\r\n * @param hookName The name of the hook to trigger\r\n */\r\nexport function hook(hookName: string) {\r\n return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n const originalMethod = descriptor.value;\r\n\r\n descriptor.value = function (...args: any[]) {\r\n // Execute all registered hooks for this hook name\r\n if (hooks[hookName]) {\r\n hooks[hookName].forEach((callback) => {\r\n callback.apply(this, args);\r\n });\r\n }\r\n\r\n // Call the original method\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Decorator function that executes registered hooks asynchronously before the decorated method\r\n * @param hookName The name of the hook to trigger\r\n */\r\nexport function hookAsync(hookName: string) {\r\n return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n const originalMethod = descriptor.value;\r\n\r\n descriptor.value = async function (...args: any[]) {\r\n // Execute all registered hooks for this hook name\r\n if (hooks[hookName]) {\r\n // Wait for all hooks to complete before proceeding\r\n await Promise.all(hooks[hookName].map((callback) => callback.apply(this, args)));\r\n }\r\n\r\n // Call the original method\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n return descriptor;\r\n };\r\n}\r\n\r\n/**\r\n * Decorator function that executes registered hooks asynchronously before the decorated method\r\n * @param hookName The name of the hook to trigger\r\n * @param contextFn Optional function to extract additional context from the class instance\r\n */\r\nexport function hookAsyncWithContext(hookName: string, contextFn?: (instance: any) => Record<string, any>) {\r\n return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n const originalMethod = descriptor.value;\r\n\r\n descriptor.value = async function (...args: any[]) {\r\n // Execute all registered hooks for this hook name\r\n if (hooks[hookName]) {\r\n // Get additional context if contextFn is provided\r\n const additionalContext = typeof contextFn === 'function' ? await contextFn(this) : {};\r\n\r\n // Wait for all hooks to complete before proceeding\r\n // We need to prepend the additional context before the args; otherwise, optional parameters may cause incorrect argument mapping.\r\n await Promise.all(hooks[hookName].map((callback) => callback.apply(this, [additionalContext, ...args])));\r\n }\r\n\r\n // Call the original method\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n return descriptor;\r\n };\r\n}\r\n","import { AgentProcess } from '@sre/Core/AgentProcess.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { LLMContext } from '@sre/MemoryManager/LLMContext';\r\nimport { TAgentProcessParams } from '@sre/types/Agent.types';\r\nimport { ILLMContextStore, TLLMEvent, TLLMModel, ToolData } from '@sre/types/LLM.types';\r\nimport { isUrl } from '@sre/utils/data.utils';\r\nimport { processWithConcurrencyLimit, uid } from '@sre/utils/general.utils';\r\nimport axios, { AxiosRequestConfig } from 'axios';\r\nimport EventEmitter from 'events';\r\nimport { JSONContent } from './JsonContent.helper';\r\nimport { OpenAPIParser } from './OpenApiParser.helper';\r\nimport { Match, TemplateString } from './TemplateString.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { delay } from '@sre/utils/date-time.utils';\r\nimport { EventSource, FetchLike } from 'eventsource';\r\nimport { hookAsyncWithContext } from '@sre/Core/HookService';\r\nimport { DEFAULT_TEAM_ID } from '@sre/types/ACL.types';\r\nimport { randomUUID } from 'crypto';\r\nimport * as acorn from 'acorn';\r\n\r\nconst console = Logger('ConversationHelper');\r\ntype FunctionDeclaration = {\r\n name: string;\r\n description: string;\r\n properties: Record<string, any>;\r\n requiredFields: string[];\r\n};\r\ntype ToolParams = {\r\n type: string;\r\n endpoint: string;\r\n args: Record<string, any>;\r\n method: string;\r\n baseUrl: string;\r\n headers?: Record<string, string>;\r\n agentCallback?: (data: any) => void;\r\n};\r\n\r\n//TODO: handle authentication\r\nexport class Conversation extends EventEmitter {\r\n private _agentId: string = '';\r\n private _systemPrompt;\r\n private userDefinedSystemPrompt: string = '';\r\n public toolChoice: string = 'auto';\r\n public get systemPrompt() {\r\n return this._systemPrompt;\r\n }\r\n public set systemPrompt(systemPrompt) {\r\n this._systemPrompt = systemPrompt;\r\n if (this._context) this._context.systemPrompt = systemPrompt;\r\n }\r\n public assistantName;\r\n\r\n private _reqMethods;\r\n private _toolsConfig;\r\n private _endpoints;\r\n private _baseUrl;\r\n\r\n private _status = '';\r\n private _currentWaitPromise;\r\n\r\n private _llmContextStore: ILLMContextStore;\r\n private _context: LLMContext;\r\n\r\n private _maxContextSize = 1024 * 128;\r\n private _maxOutputTokens = 1024 * 8;\r\n private _teamId: string = undefined;\r\n private _agentVersion: string = undefined;\r\n public agentData: any;\r\n\r\n public get context() {\r\n return this._context;\r\n }\r\n\r\n private _lastError;\r\n private _spec;\r\n private _customToolsDeclarations: FunctionDeclaration[] = [];\r\n private _customToolsHandlers: Record<string, (args: Record<string, any>) => Promise<any>> = {};\r\n public stop = false;\r\n public set spec(specSource) {\r\n this.ready.then(() => {\r\n this._status = '';\r\n this.loadSpecFromSource(specSource).then(async (spec) => {\r\n if (!spec) {\r\n this._status = 'error';\r\n this.emit('error', 'Invalid OpenAPI specification data format');\r\n throw new Error('Invalid OpenAPI specification data format');\r\n }\r\n this._spec = spec;\r\n\r\n // teamId is required to load custom LLMs, we must assign it before updateModel()\r\n await this.assignTeamIdFromAgentId(this._agentId);\r\n\r\n await this.updateModel(this._model);\r\n this._status = 'ready';\r\n });\r\n });\r\n }\r\n\r\n public set model(model: string | TLLMModel) {\r\n this.ready.then(async () => {\r\n this._status = '';\r\n await this.updateModel(model);\r\n this._status = 'ready';\r\n });\r\n }\r\n public get model() {\r\n return this._model;\r\n }\r\n\r\n constructor(\r\n private _model: string | TLLMModel,\r\n private _specSource?: string | Record<string, any>,\r\n private _settings?: {\r\n maxContextSize?: number;\r\n maxOutputTokens?: number;\r\n systemPrompt?: string;\r\n toolChoice?: string;\r\n store?: ILLMContextStore;\r\n experimentalCache?: boolean;\r\n toolsStrategy?: (toolsConfig) => any;\r\n agentId?: string;\r\n agentVersion?: string;\r\n }\r\n ) {\r\n //TODO: handle loading previous session (messages)\r\n super();\r\n\r\n //this event listener avoids unhandled errors that can cause crashes\r\n this.on('error', (error) => {\r\n this._lastError = error;\r\n console.warn('Conversation Error: ', error?.message);\r\n });\r\n if (_settings?.maxContextSize) this._maxContextSize = _settings.maxContextSize;\r\n if (_settings?.maxOutputTokens) this._maxOutputTokens = _settings.maxOutputTokens;\r\n if (_settings?.systemPrompt) {\r\n this.userDefinedSystemPrompt = _settings.systemPrompt;\r\n }\r\n if (_settings?.toolChoice) {\r\n this.toolChoice = _settings.toolChoice;\r\n }\r\n\r\n if (_settings?.store) {\r\n this._llmContextStore = _settings.store;\r\n }\r\n\r\n this._agentVersion = _settings?.agentVersion;\r\n\r\n (async () => {\r\n if (_specSource) {\r\n this.loadSpecFromSource(_specSource)\r\n .then(async (spec) => {\r\n if (!spec) {\r\n this._status = 'error';\r\n this.emit('error', 'Unable to parse OpenAPI specifications');\r\n throw new Error('Invalid OpenAPI specification data format');\r\n }\r\n this._spec = spec;\r\n\r\n if (!this._agentId && _settings?.agentId) this._agentId = _settings.agentId;\r\n if (!this._agentId) this._agentId = 'FAKE_AGENT_ID'; //We use a fake agent ID to avoid ACL check errors\r\n\r\n // teamId is required to load custom LLMs, we must assign it before updateModel()\r\n await this.assignTeamIdFromAgentId(this._agentId);\r\n\r\n await this.updateModel(this._model);\r\n\r\n this._status = 'ready';\r\n })\r\n .catch((error) => {\r\n this._status = 'error';\r\n this.emit('error', error);\r\n });\r\n } else {\r\n await this.updateModel(this._model);\r\n this._status = 'ready';\r\n }\r\n })();\r\n }\r\n\r\n public get ready() {\r\n if (this._currentWaitPromise) return this._currentWaitPromise;\r\n this._currentWaitPromise = new Promise((resolve, reject) => {\r\n if (this._status) {\r\n return resolve(this._status);\r\n }\r\n\r\n const maxWaitTime = 30000;\r\n let waitTime = 0;\r\n const interval = 100;\r\n\r\n const wait = setInterval(() => {\r\n if (this._status) {\r\n clearInterval(wait);\r\n return resolve(this._status);\r\n } else {\r\n waitTime += interval;\r\n if (waitTime >= maxWaitTime) {\r\n clearInterval(wait);\r\n return reject('Timeout: Failed to prepare data');\r\n }\r\n }\r\n }, interval);\r\n });\r\n\r\n return this._currentWaitPromise;\r\n }\r\n\r\n //TODO : handle attachments\r\n @hookAsyncWithContext('Conversation.prompt', async (instance: Conversation) => {\r\n await instance.ready;\r\n\r\n return {\r\n teamId: instance._teamId,\r\n agentId: instance._agentId,\r\n model: instance._model,\r\n };\r\n })\r\n public async prompt(message?: string, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {\r\n const result = await this.streamPrompt(message, toolHeaders, concurrentToolCalls, abortSignal);\r\n return result;\r\n }\r\n\r\n //TODO : handle attachments\r\n @hookAsyncWithContext('Conversation.streamPrompt', async (instance: Conversation) => {\r\n await instance.ready;\r\n\r\n return {\r\n teamId: instance._teamId,\r\n agentId: instance._agentId,\r\n model: instance._model,\r\n };\r\n })\r\n public async streamPrompt(message?: string, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {\r\n if (message) {\r\n //initial call, reset stop flag\r\n\r\n this.stop = false;\r\n }\r\n if (this.stop) {\r\n this.emit('interrupted', 'interrupted');\r\n this.emit('end');\r\n return;\r\n }\r\n await this.ready;\r\n\r\n // Add an abort handler\r\n if (abortSignal) {\r\n abortSignal.addEventListener('abort', () => {\r\n //this.emit('error', { name: 'AbortError', message: 'Request aborted by user!' });\r\n this.emit('aborted', 'Aborted by user!');\r\n //const error = new Error('Request aborted by user!');\r\n //error.name = 'AbortError';\r\n //throw error;\r\n });\r\n }\r\n\r\n const passThroughtContinueMessage = 'Continue with the next tool call if there are any, or just inform the user that you are done';\r\n //let promises = [];\r\n let _content = '';\r\n const reqMethods = this._reqMethods;\r\n const toolsConfig = this._toolsConfig;\r\n const endpoints = this._endpoints;\r\n const baseUrl = this._baseUrl;\r\n const message_id = 'msg_' + randomUUID();\r\n const isDebugSession = toolHeaders['X-DEBUG'];\r\n\r\n /* ==================== STEP ENTRY ==================== */\r\n // console.debug('Request to LLM with the given model, messages and functions properties.', {\r\n // model: this.model,\r\n // message,\r\n // toolsConfig,\r\n // });\r\n /* ==================== STEP ENTRY ==================== */\r\n const llmInference: LLMInference = await LLMInference.getInstance(this.model, AccessCandidate.team(this._teamId));\r\n\r\n if (message) this._context.addUserMessage(message, message_id);\r\n\r\n const contextWindow = await this._context.getContextWindow(this._maxContextSize, this._maxOutputTokens);\r\n\r\n let maxTokens = this._maxOutputTokens;\r\n if (typeof this.model === 'object' && this.model?.params?.maxTokens) {\r\n maxTokens = this.model.params.maxTokens;\r\n }\r\n\r\n const eventEmitter: any = await llmInference\r\n .promptStream({\r\n contextWindow,\r\n params: {\r\n model: this.model,\r\n toolsConfig: this._settings?.toolsStrategy ? this._settings.toolsStrategy(toolsConfig) : toolsConfig,\r\n maxTokens,\r\n cache: this._settings?.experimentalCache,\r\n agentId: this._agentId,\r\n abortSignal,\r\n },\r\n })\r\n .catch((error) => {\r\n console.error('Error on promptStream: ', error);\r\n this.emit(TLLMEvent.Error, error);\r\n });\r\n\r\n // remove listeners from llm event emitter to stop receiving stream data\r\n if (abortSignal) {\r\n abortSignal.addEventListener('abort', () => {\r\n eventEmitter.removeAllListeners();\r\n });\r\n }\r\n if (!eventEmitter || eventEmitter.error) {\r\n throw new Error('[LLM Request Error]');\r\n }\r\n\r\n if (message) this.emit('start');\r\n eventEmitter.on('data', (data) => {\r\n if (this.stop) return;\r\n this.emit('data', data);\r\n });\r\n\r\n eventEmitter.on(TLLMEvent.Thinking, (thinking) => {\r\n if (this.stop) return;\r\n this.emit(TLLMEvent.Thinking, thinking);\r\n });\r\n\r\n eventEmitter.on(TLLMEvent.Content, (content) => {\r\n if (this.stop) return;\r\n // if (toolHeaders['x-passthrough']) {\r\n // console.log('Passthrough skiped content ', content);\r\n // return;\r\n // }\r\n const lastMessage = this._context?.messages?.[this._context?.messages?.length - 1];\r\n const skip = lastMessage?.content?.includes(passThroughtContinueMessage) && lastMessage?.__smyth_data__?.internal;\r\n\r\n //skip if the content is the last generated message after a passthrough content\r\n if (skip) return;\r\n _content += content;\r\n this.emit(TLLMEvent.Content, content);\r\n });\r\n\r\n let finishReason = 'stop';\r\n\r\n let toolsPromise = new Promise((resolve, reject) => {\r\n let hasTools = false;\r\n let hasError = false;\r\n let passThroughContent = '';\r\n\r\n eventEmitter.on(TLLMEvent.Error, (error) => {\r\n hasError = true;\r\n reject(error);\r\n });\r\n\r\n eventEmitter.on(TLLMEvent.ToolInfo, async (toolsData, thinkingBlocks = []) => {\r\n if (this.stop) return;\r\n hasTools = true;\r\n let llmMessage: any = {\r\n role: 'assistant',\r\n content: _content,\r\n tool_calls: [],\r\n };\r\n\r\n if (thinkingBlocks?.length > 0) {\r\n this.emit(\r\n 'thoughtProcess',\r\n thinkingBlocks\r\n .filter((block) => block.type === 'thinking')\r\n .map((block) => block.thinking || '')\r\n .join('\\n')\r\n );\r\n\r\n llmMessage.thinkingBlocks = thinkingBlocks;\r\n }\r\n\r\n llmMessage.tool_calls = toolsData.map((tool) => {\r\n return {\r\n id: tool.id,\r\n type: tool.type,\r\n function: {\r\n name: tool.name,\r\n arguments: tool.arguments,\r\n },\r\n };\r\n });\r\n\r\n //if (llmMessage.tool_calls?.length <= 0) return;\r\n\r\n this.emit(TLLMEvent.ToolInfo, toolsData);\r\n\r\n //initialize the agent callback logic\r\n const _agentCallback = (data) => {\r\n if (this.stop) return;\r\n //if (typeof data !== 'string') return;\r\n let content = '';\r\n let thinking = '';\r\n if (typeof data === 'object') {\r\n if (data.content) {\r\n content = data.content;\r\n\r\n passThroughContent += content;\r\n eventEmitter.emit(TLLMEvent.Content, content);\r\n }\r\n if (data.thinking) {\r\n thinking = data.thinking;\r\n eventEmitter.emit(TLLMEvent.Thinking, thinking);\r\n }\r\n return;\r\n }\r\n if (typeof data === 'string') {\r\n passThroughContent += data;\r\n eventEmitter.emit(TLLMEvent.Content, data);\r\n }\r\n\r\n //passThroughContent += data;\r\n //this is currently used to handle agent callbacks when running local agents\r\n //this.emit('agentCallback', data);\r\n\r\n //this.emit('content', data);\r\n //this.emit('content', data);\r\n //eventEmitter.emit('content', data);\r\n };\r\n\r\n const toolProcessingTasks = toolsData.map(\r\n (tool: { index: number; name: string; type: string; arguments: Record<string, any> }) => async () => {\r\n const endpoint = endpoints?.get(tool?.name) || tool?.name;\r\n // Sometimes we have object response from the LLM such as Anthropic\r\n\r\n let args = typeof tool?.arguments === 'string' ? JSONContent(tool?.arguments).tryParse() || {} : tool?.arguments;\r\n\r\n if (args?.error) {\r\n throw new Error('[Tool] Arguments Parsing Error\\n' + JSON.stringify({ message: args?.error }));\r\n }\r\n\r\n //await beforeFunctionCall(llmMessage, toolsData[tool.index]);\r\n // TODO [Forhad]: Make sure toolsData[tool.index] and tool do the same thing\r\n this.emit('beforeToolCall', { tool, args }, llmMessage); //deprecated\r\n this.emit(TLLMEvent.ToolCall, { tool, _llmRequest: llmMessage });\r\n\r\n const toolArgs = {\r\n type: tool?.type,\r\n method: reqMethods?.get(tool?.name),\r\n endpoint,\r\n args,\r\n baseUrl,\r\n headers: toolHeaders,\r\n agentCallback: _agentCallback,\r\n };\r\n\r\n let { data: functionResponse, error } = await this.useTool(toolArgs, abortSignal);\r\n\r\n if (error) {\r\n functionResponse = typeof error === 'object' && typeof error !== null ? JSON.stringify(error) : error;\r\n }\r\n\r\n const result = functionResponse;\r\n\r\n functionResponse =\r\n typeof functionResponse === 'object' && typeof functionResponse !== null\r\n ? JSON.stringify(functionResponse)\r\n : functionResponse;\r\n\r\n //await afterFunctionCall(functionResponse, toolsData[tool.index]);\r\n this.emit('afterToolCall', { tool, args }, functionResponse); // Deprecated\r\n this.emit(TLLMEvent.ToolResult, { tool, result });\r\n\r\n return { ...tool, result: functionResponse };\r\n }\r\n );\r\n\r\n const processedToolsData = await processWithConcurrencyLimit<ToolData>(toolProcessingTasks, concurrentToolCalls);\r\n\r\n //if (!passThroughContent) {\r\n\r\n if (!passThroughContent) {\r\n this._context.addToolMessage(llmMessage, processedToolsData, message_id);\r\n //delete toolHeaders['x-passthrough'];\r\n } else {\r\n //this._context.addAssistantMessage(passThroughContent, message_id);\r\n llmMessage.content += '\\n' + passThroughContent;\r\n this._context.addToolMessage(llmMessage, processedToolsData, message_id);\r\n //this should not be stored in the persistent conversation store\r\n //it's just a workaround to avoid generating more content after passthrough content\r\n this._context.addUserMessage(passThroughtContinueMessage, message_id, { internal: true });\r\n //toolHeaders['x-passthrough'] = 'true';\r\n }\r\n\r\n this.streamPrompt(null, toolHeaders, concurrentToolCalls, abortSignal).then(resolve).catch(reject);\r\n\r\n //} else {\r\n //TODO : add passthrough content to the context window ??\r\n\r\n //if passThroughContent is not empty, it means that the current agent streamed content through components\r\n //resolve(passThroughContent);\r\n //}\r\n //const result = await resolve(await this.streamPrompt(null, toolHeaders, concurrentToolCalls));\r\n //console.log('Result after tool call: ', result);\r\n });\r\n\r\n eventEmitter.on(TLLMEvent.End, async (toolsData, usage_data, _finishReason) => {\r\n if (_finishReason) finishReason = _finishReason;\r\n if (usage_data) {\r\n //FIXME : normalize the usage data format\r\n this.emit(TLLMEvent.Usage, usage_data);\r\n }\r\n if (hasError) return;\r\n\r\n if (!hasTools || passThroughContent) {\r\n //console.log(' ===> resolved content no tool', _content);\r\n //this._context.push({ role: 'assistant', content: _content });\r\n const lastMessage = this._context?.messages?.[this._context?.messages?.length - 1];\r\n let metadata;\r\n if (lastMessage?.content?.includes(passThroughtContinueMessage) && lastMessage?.__smyth_data__?.internal) {\r\n metadata = { internal: true };\r\n }\r\n this._context.addAssistantMessage(_content, message_id, metadata);\r\n resolve(''); //the content were already emitted through 'content' event\r\n }\r\n });\r\n });\r\n\r\n const toolsContent = await toolsPromise.catch((error) => {\r\n console.error('Error in toolsPromise: ', error);\r\n //this.emit('error', error);\r\n this.emit(TLLMEvent.Error, error);\r\n return '';\r\n });\r\n _content += toolsContent;\r\n let content = JSONContent(_content).tryParse();\r\n\r\n // let streamPromise = new Promise((resolve, reject) => {\r\n // eventEmitter.on('end', async () => {\r\n // if (toolsPromise) await toolsPromise;\r\n\r\n // let content = JSONContent(_content).tryParse();\r\n // resolve({ content });\r\n // });\r\n // });\r\n\r\n // promises.push(streamPromise);\r\n\r\n //await Promise.all(promises);\r\n //return content;\r\n\r\n if (message) {\r\n //console.log('main content', content);\r\n //this._context.push({ role: 'assistant', content: content });\r\n\r\n if (finishReason !== 'stop') {\r\n this.emit(TLLMEvent.Interrupted, finishReason);\r\n }\r\n this.emit(TLLMEvent.End);\r\n } else {\r\n //console.log('tool content', content);\r\n }\r\n\r\n return content;\r\n }\r\n\r\n private resolveToolEndpoint(baseUrl: string, method: string, endpoint: string, params: Record<string, any>): string {\r\n //handle query params\r\n let templateParams = {};\r\n if (params) {\r\n const parameters = this._spec?.paths?.[endpoint]?.[method.toLowerCase()]?.parameters || [];\r\n for (let p of parameters) {\r\n if (p.in === 'path') {\r\n templateParams[p.name] = params[p.name] || '';\r\n delete params[p.name];\r\n }\r\n }\r\n }\r\n const parsedEndpoint = TemplateString(endpoint).parse(templateParams, Match.singleCurly).clean().result;\r\n\r\n // Create a new URL object using the base URL and endpoint\r\n const url = new URL(parsedEndpoint, baseUrl);\r\n\r\n // Iterate over the params object and append each key/value pair to the URL search parameters\r\n Object.keys(params).forEach((key) => {\r\n url.searchParams.append(key, params[key]);\r\n });\r\n\r\n // Return the full URL as a string\r\n return url.toString();\r\n }\r\n\r\n private async useTool(\r\n params: ToolParams,\r\n abortSignal?: AbortSignal\r\n ): Promise<{\r\n data: any;\r\n error;\r\n }> {\r\n if (this.stop) {\r\n return { data: null, error: 'Conversation Interrupted' };\r\n }\r\n\r\n const { type, endpoint, args, method, baseUrl, headers = {}, agentCallback } = params;\r\n\r\n if (type === 'function') {\r\n const toolHandler = this._customToolsHandlers[endpoint];\r\n if (toolHandler) {\r\n try {\r\n const result = await toolHandler(args);\r\n return { data: result, error: null };\r\n } catch (error) {\r\n return { data: null, error: error?.message || 'Custom tool handler failed' };\r\n }\r\n }\r\n try {\r\n const url = this.resolveToolEndpoint(baseUrl, method, endpoint, method == 'get' ? args : {});\r\n\r\n const reqConfig: AxiosRequestConfig = {\r\n method,\r\n url,\r\n headers: {\r\n ...headers,\r\n },\r\n signal: abortSignal,\r\n };\r\n\r\n if (method !== 'get') {\r\n if (Object.keys(args).length) {\r\n reqConfig.data = args;\r\n }\r\n //(reqConfig.headers as Record<string, unknown>)['Content-Type'] = 'application/json';\r\n reqConfig.headers['Content-Type'] = 'application/json';\r\n }\r\n\r\n console.debug('Calling tool: ', reqConfig);\r\n\r\n reqConfig.headers['X-CACHE-ID'] = this._context?.llmCache?.id;\r\n\r\n /*\r\n * Objective for the following conditions:\r\n * - In case it is not a debug call and there is no monitor id, then we need to run the agent locally to reduce latency\r\n * - but if it a debug call, we need to forward req to sre-builder-debugger since it holds the debug promises\r\n * - or if there is a monitor id, we need to forward req to sre-builder-debugger since it holds the monitor SSE connections.\r\n * - a remote call is often needed for file parsing be default agent we inject, it should not be loaded locally.\r\n * So the objecive is mainly reducing latency when possible\r\n */\r\n //TODO : implement a timeout for the tool call\r\n const requiresRemoteCall =\r\n reqConfig.headers['X-DEBUG'] !== undefined ||\r\n reqConfig.headers['X-MONITOR-ID'] !== undefined ||\r\n reqConfig.headers['X-AGENT-REMOTE-CALL'] !== undefined;\r\n if (\r\n reqConfig.url.includes('localhost') ||\r\n (reqConfig.headers['X-AGENT-ID'] && !requiresRemoteCall)\r\n //empty string is accepted\r\n\r\n // || reqConfig.url.includes('localagent') //* commented to allow debugging live sessions as the req needs to reach sre-builder-debugger\r\n ) {\r\n console.log('RUNNING AGENT LOCALLY');\r\n let agentProcess;\r\n if (this.agentData === this._specSource) {\r\n //the agent was loaded from data\r\n agentProcess = AgentProcess.load(this.agentData, this._agentVersion);\r\n } else {\r\n //the agent was loaded from a spec\r\n agentProcess = AgentProcess.load(\r\n reqConfig.headers['X-AGENT-ID'] || this._agentId,\r\n reqConfig.headers['X-AGENT-VERSION'] || this._agentVersion\r\n );\r\n }\r\n //if it's a local agent, invoke it directly\r\n\r\n const response = await agentProcess.run(reqConfig as TAgentProcessParams, agentCallback);\r\n return { data: response.data, error: null };\r\n } else {\r\n console.log('RUNNING AGENT REMOTELY');\r\n let eventSource;\r\n\r\n // if debug mode is on OR the user attached a monitor to the call, then we need to attach a monitor to the agent call\r\n if ((reqConfig.headers['X-DEBUG'] && reqConfig.headers['X-AGENT-ID']) || reqConfig.headers['X-MONITOR-ID']) {\r\n console.log('ATTACHING MONITOR TO REMOTE AGENT CALL');\r\n const monitUrl = reqConfig.url.split('/api')[0] + '/agent/' + reqConfig.headers['X-AGENT-ID'] + '/monitor';\r\n\r\n // Create custom fetch implementation that includes our headers\r\n const customFetch: FetchLike = (url, init) => {\r\n return fetch(url, {\r\n ...init,\r\n headers: {\r\n ...(init?.headers || {}),\r\n ...Object.fromEntries(Object.entries(reqConfig.headers).map(([k, v]) => [k, String(v)])),\r\n },\r\n });\r\n };\r\n\r\n const eventSource = new EventSource(monitUrl, {\r\n fetch: customFetch,\r\n });\r\n let monitorId = '';\r\n\r\n eventSource.addEventListener('init', (event) => {\r\n monitorId = event.data;\r\n console.log('monitorId', monitorId);\r\n if (reqConfig.headers['X-MONITOR-ID']) {\r\n // an external monitor was sent, so we do not override it\r\n reqConfig.headers['X-MONITOR-ID'] = `${reqConfig.headers['X-MONITOR-ID']},${monitorId}`;\r\n } else {\r\n reqConfig.headers['X-MONITOR-ID'] = monitorId;\r\n }\r\n });\r\n eventSource.addEventListener('llm/passthrough/content', (event: any) => {\r\n if (params.agentCallback) params.agentCallback({ content: event.data.replace(/\\\\n/g, '\\n') });\r\n });\r\n eventSource.addEventListener('llm/passthrough/thinking', (event: any) => {\r\n if (params.agentCallback) params.agentCallback({ thinking: event.data.replace(/\\\\n/g, '\\n') });\r\n });\r\n\r\n await new Promise((resolve) => {\r\n let maxTime = 5 * 1000; //5 seconds\r\n let itv = setInterval(() => {\r\n if (monitorId || maxTime <= 0) {\r\n clearInterval(itv);\r\n resolve(true);\r\n }\r\n maxTime -= 100;\r\n }, 100);\r\n });\r\n }\r\n\r\n //if it's a remote agent, call the API via HTTP\r\n const response = await axios.request(reqConfig);\r\n\r\n if (eventSource) {\r\n eventSource.close();\r\n console.log('eventSource closed');\r\n }\r\n return { data: response.data, error: null };\r\n }\r\n } catch (error: any) {\r\n console.warn('Failed to call Tool: ', baseUrl, endpoint);\r\n console.warn(' ====>', error);\r\n return { data: null, error: error?.response?.data || error?.message };\r\n }\r\n }\r\n\r\n return { data: null, error: `'${type}' tool type not supported at the moment` };\r\n }\r\n\r\n public async addTool(tool: {\r\n name: string;\r\n description: string;\r\n arguments?: Record<string, any> | string[];\r\n handler: (args: Record<string, any>) => Promise<any>;\r\n inputs?: any[];\r\n }) {\r\n if (!tool.arguments) {\r\n //if no arguments are provided, we need to extract them from the function\r\n const toolFunction = tool.handler as Function;\r\n const openApiArgs = this.extractArgsAsOpenAPI(toolFunction);\r\n const _arguments: any = {};\r\n for (let arg of openApiArgs) {\r\n _arguments[arg.name] = arg.schema;\r\n if (tool.inputs && arg.schema.properties) {\r\n const required = [];\r\n for (let prop in arg.schema.properties) {\r\n const input = tool.inputs?.find((i) => i.name === prop);\r\n if (!arg.schema.properties[prop].description) {\r\n arg.schema.properties[prop].description = input?.description;\r\n }\r\n if (!input?.optional) {\r\n required.push(prop);\r\n }\r\n }\r\n if (required.length) {\r\n arg.schema.required = required;\r\n }\r\n }\r\n }\r\n\r\n tool.arguments = _arguments;\r\n tool.handler = async (argsObj: any) => {\r\n const args = Object.values(argsObj);\r\n const result = await toolFunction(...args);\r\n return result;\r\n };\r\n }\r\n\r\n const requiredFields = Object.values(tool.arguments)\r\n .map((arg) => (arg.required ? arg.name : null))\r\n .filter((arg) => arg);\r\n\r\n const properties = {};\r\n for (let entry in tool.arguments) {\r\n properties[entry] = {\r\n type: tool.arguments[entry].type || 'string',\r\n properties: tool.arguments[entry].properties,\r\n description: tool.arguments[entry].description,\r\n ...(tool.arguments[entry].type === 'array' ? { items: { type: tool.arguments[entry].items?.type || 'string' } } : {}),\r\n };\r\n }\r\n const toolDefinition = {\r\n name: tool.name,\r\n description: tool.description,\r\n properties,\r\n requiredFields,\r\n };\r\n this._customToolsDeclarations.push(toolDefinition);\r\n this._customToolsHandlers[tool.name] = tool.handler;\r\n\r\n const llmInference: LLMInference = await LLMInference.getInstance(this.model, AccessCandidate.team(this._teamId));\r\n const toolsConfig: any = llmInference.connector.formatToolsConfig({\r\n type: 'function',\r\n toolDefinitions: [toolDefinition],\r\n toolChoice: this.toolChoice,\r\n });\r\n\r\n if (this._toolsConfig) this._toolsConfig.tools.push(...toolsConfig?.tools);\r\n else this._toolsConfig = toolsConfig;\r\n }\r\n /**\r\n * updates LLM model, if spec is available, it will update the tools config\r\n * @param model\r\n */\r\n // TODO [Forhad]: For now updateModel does not required await, but when we will have tools implementation in custom model then we need to await for it\r\n private async updateModel(model: string | TLLMModel) {\r\n try {\r\n this._model = model;\r\n\r\n if (this._spec) {\r\n this._reqMethods = OpenAPIParser.mapReqMethods(this._spec?.paths);\r\n this._endpoints = OpenAPIParser.mapEndpoints(this._spec?.paths);\r\n this._baseUrl = this._spec?.servers?.[0].url;\r\n\r\n const functionDeclarations = this.getFunctionDeclarations(this._spec);\r\n functionDeclarations.push(...this._customToolsDeclarations);\r\n const llmInference: LLMInference = await LLMInference.getInstance(this._model, AccessCandidate.team(this._teamId));\r\n if (!llmInference.connector) {\r\n this.emit('error', 'No connector found for model: ' + this._model);\r\n return;\r\n }\r\n this._toolsConfig = llmInference.connector.formatToolsConfig({\r\n type: 'function',\r\n toolDefinitions: functionDeclarations,\r\n toolChoice: this.toolChoice,\r\n });\r\n\r\n let messages = [];\r\n if (this._context) messages = this._context.messages; // preserve messages\r\n\r\n this._context = new LLMContext(llmInference, this.systemPrompt, this._llmContextStore);\r\n } else {\r\n this._toolsConfig = null;\r\n this._reqMethods = null;\r\n this._endpoints = null;\r\n this._baseUrl = null;\r\n }\r\n } catch (error) {\r\n this.emit('error', error);\r\n }\r\n }\r\n\r\n /**\r\n * this function is used to patch the spec with missing fields that are required for the tool to work\r\n * @param spec\r\n */\r\n private patchSpec(spec: Record<string, any>) {\r\n const paths = spec?.paths;\r\n for (const path in paths) {\r\n const pathData = paths[path];\r\n\r\n // it's possible we have multiple methods for a single path\r\n for (const key in pathData) {\r\n const data = pathData[key];\r\n if (!data?.operationId) {\r\n //normalize path and use it as operationId\r\n data.operationId = path.replace(/\\//g, '_').replace(/{|}/g, '').replace(/\\./g, '_');\r\n }\r\n }\r\n }\r\n return spec;\r\n }\r\n /**\r\n * Loads OpenAPI specification from source\r\n * @param specSource\r\n * @returns\r\n */\r\n private async loadSpecFromSource(specSource: string | Record<string, any>) {\r\n if (typeof specSource === 'object') {\r\n //is this a valid OpenAPI spec?\r\n if (OpenAPIParser.isValidOpenAPI(specSource)) {\r\n this.systemPrompt = specSource?.info?.description || '';\r\n return this.patchSpec(specSource);\r\n }\r\n //is this a valid agent data?\r\n if (typeof specSource?.behavior === 'string' && specSource?.components && specSource?.connections) {\r\n this.agentData = specSource; //agent loaded from data directly\r\n return await this.loadSpecFromAgent(specSource);\r\n }\r\n\r\n return null;\r\n }\r\n\r\n if (typeof specSource === 'string') {\r\n //is this an openAPI url?\r\n if (isUrl(specSource as string)) {\r\n const spec = await OpenAPIParser.getJsonFromUrl(specSource as string);\r\n\r\n if (spec.info?.description) this.systemPrompt = spec.info.description;\r\n\r\n // we always overwrite system prompt with user defined one\r\n if (this.userDefinedSystemPrompt) this.systemPrompt = this.userDefinedSystemPrompt;\r\n\r\n if (spec.info?.title) this.assistantName = spec.info.title;\r\n\r\n const specUrl = new URL(specSource as string);\r\n const defaultBaseUrl = specUrl.origin;\r\n\r\n if (!spec?.servers) spec.servers = [{ url: defaultBaseUrl }];\r\n if (spec.servers?.length == 0) spec.servers = [{ url: defaultBaseUrl }];\r\n\r\n if (this.assistantName) {\r\n this.systemPrompt = `Assistant Name : ${this.assistantName}\\n\\n${this.systemPrompt}`;\r\n }\r\n\r\n //this._agentId = specUrl.hostname; //just set an agent ID in order to identify the agent in SRE //FIXME: maybe this requires a better solution\r\n return this.patchSpec(spec);\r\n }\r\n //is this an agentId ?\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n const agentId = specSource as string;\r\n this._agentId = agentId;\r\n\r\n if (this._agentVersion === undefined) {\r\n const isDeployed = await agentDataConnector.isDeployed(agentId);\r\n this._agentVersion = isDeployed ? 'latest' : '';\r\n }\r\n\r\n this.agentData = await agentDataConnector.getAgentData(agentId, this._agentVersion).catch((error) => null);\r\n if (!this.agentData) return null;\r\n\r\n const spec = await this.loadSpecFromAgent(this.agentData);\r\n return spec;\r\n }\r\n }\r\n private async loadSpecFromAgent(agentData: Record<string, any>) {\r\n //handle the case where agentData object contains the agent schema directly\r\n //agents retrieved from the database have a wrapping object with agent name and version number\r\n //local agent might include the agent data directly\r\n if (agentData?.components) {\r\n agentData = { name: agentData?.name, data: agentData, version: '1.0.0' };\r\n }\r\n\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n this.systemPrompt = agentData?.data?.behavior || this.systemPrompt;\r\n\r\n // we always overwrite system prompt with user defined one\r\n if (this.userDefinedSystemPrompt) this.systemPrompt = this.userDefinedSystemPrompt;\r\n\r\n this.assistantName = agentData?.data?.name || agentData?.data?.templateInfo?.name || this.assistantName;\r\n if (this.assistantName) {\r\n this.systemPrompt = `Assistant Name : ${this.assistantName}\\n\\n${this.systemPrompt}`;\r\n }\r\n\r\n const spec = await agentDataConnector.getOpenAPIJSON(agentData, 'http://localhost/', this._agentVersion, true).catch((error) => null);\r\n return this.patchSpec(spec);\r\n }\r\n\r\n /**\r\n * Extracts function declarations from OpenAPI specification\r\n * @param spec\r\n * @returns\r\n */\r\n private getFunctionDeclarations(spec): FunctionDeclaration[] {\r\n const paths = spec?.paths;\r\n const reqMethods = OpenAPIParser.mapReqMethods(paths);\r\n\r\n let declarations: FunctionDeclaration[] = [];\r\n\r\n for (const path in paths) {\r\n const pathData = paths[path];\r\n\r\n // it's possible we have multiple methods for a single path\r\n for (const key in pathData) {\r\n const data = pathData[key];\r\n\r\n if (!data?.operationId) continue;\r\n\r\n const method = reqMethods.get(data?.operationId) || 'get';\r\n\r\n let properties = {};\r\n let requiredFields: string[] = [];\r\n\r\n if (method.toLowerCase() === 'get') {\r\n const params = data?.parameters || [];\r\n for (const prop of params) {\r\n properties[prop.name] = {\r\n ...prop.schema,\r\n description: prop.description,\r\n };\r\n\r\n if (prop.required === true) {\r\n requiredFields.push(prop?.name || '');\r\n }\r\n }\r\n } else {\r\n properties = data?.requestBody?.content?.['application/json']?.schema?.properties;\r\n requiredFields = data?.requestBody?.content?.['application/json']?.schema?.required;\r\n\r\n // Open AI doesn't support 'required' to be boolean inside property\r\n for (const prop in properties) {\r\n delete properties[prop]?.required;\r\n }\r\n }\r\n\r\n if (!properties) properties = {};\r\n if (!requiredFields) requiredFields = [];\r\n\r\n const declaration = {\r\n name: data?.operationId,\r\n description: data?.description || data?.summary || '',\r\n properties,\r\n requiredFields,\r\n };\r\n declarations.push(declaration);\r\n }\r\n }\r\n\r\n return declarations;\r\n }\r\n\r\n private async assignTeamIdFromAgentId(agentId: string) {\r\n if (agentId) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(AccessCandidate.agent(agentId))?.catch(() => '');\r\n this._teamId = teamId || '';\r\n }\r\n }\r\n\r\n private extractArgsAsOpenAPI(fn) {\r\n const ast = acorn.parse(`(${fn.toString()})`, { ecmaVersion: 'latest' });\r\n const params = (ast.body[0] as any).expression.params;\r\n\r\n let counter = 0;\r\n function handleParam(param) {\r\n if (param.type === 'Identifier') {\r\n return {\r\n name: param.name,\r\n in: 'query',\r\n required: true,\r\n schema: { type: 'string', name: param.name, required: true },\r\n };\r\n }\r\n\r\n if (param.type === 'AssignmentPattern' && param.left.type === 'Identifier') {\r\n return {\r\n name: param.left.name,\r\n in: 'query',\r\n required: false,\r\n schema: { type: 'string', name: param.left.name, required: false },\r\n };\r\n }\r\n\r\n if (param.type === 'RestElement' && param.argument.type === 'Identifier') {\r\n return {\r\n name: param.argument.name,\r\n in: 'query',\r\n required: false,\r\n schema: { type: 'array', items: { type: 'string' } },\r\n };\r\n }\r\n\r\n if (param.type === 'ObjectPattern') {\r\n // For destructured objects, output as a single parameter with nested fields\r\n const name = `[object_${counter++}]`;\r\n return {\r\n name,\r\n in: 'query',\r\n required: true,\r\n schema: {\r\n type: 'object',\r\n required: true,\r\n name,\r\n properties: Object.fromEntries(\r\n param.properties.map((prop) => {\r\n const keyName = prop.key.name || '[unknown]';\r\n return [keyName, { type: 'string' }]; // default to string\r\n })\r\n ),\r\n },\r\n };\r\n }\r\n\r\n const name = `[unknown_${counter++}]`;\r\n return {\r\n name,\r\n in: 'query',\r\n required: true,\r\n schema: { type: 'string', name, required: true },\r\n };\r\n }\r\n\r\n return params.map(handleParam);\r\n }\r\n}\r\n","import { isBase64, isBase64DataUrl } from '@sre/utils/base64.utils';\r\nimport dayjs from 'dayjs';\r\nimport { isPlainObject, isSmythFileObject, isSmythFsUrl, isUrl, uid } from '../utils';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { IAccessCandidate, TAccessRole } from '@sre/types/ACL.types';\r\nimport { BinaryInput } from './BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { JSONContent } from './JsonContent.helper';\r\nimport { Logger } from './Log.helper';\r\n\r\nexport const inputErrMsg = (type, name) => `Invalid ${type} value for Input: ${name}`;\r\nconst logger = Logger('TypeChecker.helper');\r\n\r\nconst InferenceStrategies = {\r\n any: inferAnyType,\r\n string: inferStringType,\r\n number: inferNumberType,\r\n integer: inferIntegerType,\r\n boolean: inferBooleanType,\r\n array: inferArrayType,\r\n object: inferObjectType,\r\n date: inferDateType,\r\n binary: inferBinaryType,\r\n text: inferStringType,\r\n image: inferBinaryType,\r\n audio: inferBinaryType,\r\n video: inferBinaryType,\r\n};\r\n\r\n/**\r\n * Performs type inference on the inputs based on the input config\r\n * @param inputs - The inputs to perform type inference on\r\n * @param inputConfig - The input config to perform type inference on\r\n * @param agent - The agent to perform type inference on\r\n * @returns The inputs with the inferred types\r\n */\r\nexport async function performTypeInference(\r\n inputs: Record<string, any>,\r\n inputConfig: Record<string, any>[],\r\n agent: Agent,\r\n): Promise<Record<string, any>> {\r\n try {\r\n if (!inputConfig || Object.keys(inputConfig)?.length === 0) return inputs;\r\n\r\n // Clone the input object to avoid modifying the original object\r\n const _inputs = { ...inputs };\r\n const _inputConfig = {};\r\n\r\n for (const input of inputConfig) {\r\n if (input?.name) {\r\n _inputConfig[input.name] = { ...input };\r\n }\r\n }\r\n\r\n for (const [key, config] of Object.entries(_inputConfig)) {\r\n let value = inputs?.[key] || '';\r\n\r\n if (!value) continue;\r\n\r\n const type = (config as any)?.type?.toLowerCase() || 'any';\r\n\r\n if (!InferenceStrategies[type]) {\r\n //* For backward compatibility, we don't throw an error if the type is not supported. instead, we return the value as it is.\r\n // throw new Error(`Invalid type: ${type} for Input: ${key}`);\r\n logger.warn(`Unsupported type: ${type} for Input: ${key} for agent: ${agent?.id} input: ${key}`);\r\n continue;\r\n }\r\n\r\n _inputs[key] = await InferenceStrategies[type](value, key, agent);\r\n }\r\n\r\n return _inputs;\r\n } catch (error) {\r\n throw error;\r\n }\r\n}\r\n\r\nasync function inferStringType(value: any, key?: string, agent?: Agent) {\r\n if (value === null || value === undefined || value === 'null' || value === 'undefined') {\r\n return '';\r\n } else if (isBase64(value) || isBase64DataUrl(value)) {\r\n // If the value is a base64 string then return the value as it is\r\n return value;\r\n } else if (isSmythFileObject(value)) {\r\n const file = await _createBinaryInput(value, key, agent);\r\n const buffer = await file.getBuffer();\r\n const base64 = buffer.toString('base64');\r\n return file.mimetype ? `data:${file.mimetype};base64,${base64}` : base64;\r\n } else if (typeof value === 'object' || Array.isArray(value)) {\r\n return JSON.stringify(value);\r\n } else {\r\n return String(value);\r\n }\r\n}\r\n\r\nasync function inferNumberType(value: any, key?: string, agent?: Agent) {\r\n const floatVal = parseFloat(value);\r\n\r\n if (isNaN(floatVal)) {\r\n throw new Error('Invalid Number value');\r\n }\r\n\r\n return floatVal;\r\n}\r\n\r\nasync function inferIntegerType(value: any, key?: string, agent?: Agent) {\r\n const intVal = parseInt(value);\r\n\r\n if (isNaN(intVal)) throw new Error('Invalid Integer value');\r\n\r\n return intVal;\r\n}\r\n\r\nasync function inferBooleanType(value: any, key?: string, agent?: Agent) {\r\n if (typeof value === 'boolean') {\r\n return value;\r\n } else if (typeof value === 'string' || typeof value === 'number') {\r\n const lowerCaseValue = String(value).toLowerCase();\r\n if (['true', '1'].includes(lowerCaseValue)) {\r\n return true;\r\n } else if (['false', '0'].includes(lowerCaseValue)) {\r\n return false;\r\n } else {\r\n throw new Error('Invalid Boolean value');\r\n }\r\n } else {\r\n throw new Error('Invalid Boolean value');\r\n }\r\n}\r\n\r\nasync function inferArrayType(value: any, key?: string, agent?: Agent) {\r\n try {\r\n if (Array.isArray(value)) return value;\r\n\r\n if (typeof value !== 'string') throw new Error('Invalid Array value');\r\n\r\n try {\r\n // We need to consider array with comma separated values like \"item1, item2, item3\", as it's provided by Swagger UI\r\n return value.trim().startsWith('[') ? JSONContent(value).tryParse() : value.split(',');\r\n } catch {\r\n throw new Error('Invalid Array value');\r\n }\r\n } catch (error) {\r\n throw new Error('Invalid Array value');\r\n }\r\n}\r\n\r\nasync function inferObjectType(value: any, key?: string, agent?: Agent) {\r\n try {\r\n // use parseJson instead of JSON.parse because the data may come from LLM responses\r\n const obj = isPlainObject(value) ? value : JSONContent(value).tryParse();\r\n if (!isPlainObject(obj)) throw new Error('Invalid Object value');\r\n return obj;\r\n } catch (error) {\r\n throw new Error('Invalid Object value');\r\n }\r\n}\r\n\r\n/**\r\n * Extracts the agent ID from a SmythFS URL\r\n * @param url - The SmythFS URL (e.g., smythfs://team.id/agent.id/_temp/filename.ext)\r\n * @returns The agent ID or null if the URL is invalid\r\n */\r\nfunction extractSmythFsAgentId(url: string): string | null {\r\n if (!url?.startsWith('smythfs://')) return null;\r\n\r\n try {\r\n // Split by '/' and get the agent ID (third segment)\r\n const segments = url.split('/');\r\n if (segments.length < 4) return null;\r\n\r\n return segments[3];\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\nasync function _createBinaryInput(value: any, key?: string, agent?: Agent) {\r\n // If the value is already a BinaryInput, just return it\r\n if (value instanceof BinaryInput) {\r\n return value;\r\n }\r\n\r\n let candidate: IAccessCandidate | undefined;\r\n let agentId: string = '';\r\n let data: unknown;\r\n let mimetype: string = '';\r\n let fileName = `${uid()}-${key}`;\r\n\r\n if (value && typeof value === 'object' && value?.url && value?.mimetype) {\r\n const url = value?.url;\r\n mimetype = value?.mimetype;\r\n\r\n if (value?.name) {\r\n fileName = value?.name;\r\n }\r\n\r\n if (url?.startsWith('smythfs://')) {\r\n // If the URL uses the smythfs:// protocol, we can use the binary object directly since it's already in our internal file system\r\n data = value;\r\n\r\n // Extract agent ID from smythfs:// URLs to create an access candidate to read the file\r\n agentId = extractSmythFsAgentId(url);\r\n } else {\r\n data = url;\r\n }\r\n } else {\r\n if (typeof value === 'string' && value.startsWith('smythfs://')) {\r\n // Extract agent ID from smythfs:// URLs to create an access candidate to read the file\r\n agentId = extractSmythFsAgentId(value);\r\n }\r\n data = value;\r\n }\r\n\r\n if (agentId) {\r\n candidate = AccessCandidate.agent(agentId);\r\n }\r\n\r\n const binaryInput = BinaryInput.from(data, fileName, mimetype, candidate);\r\n await binaryInput.ready();\r\n return binaryInput;\r\n}\r\n\r\nasync function inferBinaryType(value: string | string[], key?: string, agent?: Agent): Promise<BinaryInput | BinaryInput[]> {\r\n try {\r\n let binarySource: string | string[] = value;\r\n\r\n //#region Process string input\r\n if (typeof value === 'string') {\r\n const normalizedValue = value.trim();\r\n\r\n if (isUrl(normalizedValue) || isSmythFsUrl(normalizedValue) || isBase64(value) || isBase64DataUrl(value)) {\r\n // No transformation needed for a url, smythfs url, base64 or base64 data url\r\n binarySource = normalizedValue;\r\n } else {\r\n // Extract URLs from text content\r\n const extractedUrls = _extractUrls(value);\r\n if (extractedUrls.length > 0) {\r\n binarySource = extractedUrls;\r\n }\r\n }\r\n }\r\n //#endregion\r\n // Handle any array (original or created from extraction)\r\n if (Array.isArray(binarySource)) {\r\n return await Promise.all(binarySource.map((item) => _createBinaryInput(item, key, agent)));\r\n }\r\n\r\n // Handle single value case\r\n return await _createBinaryInput(binarySource, key, agent);\r\n } catch (error) {\r\n logger.warn('Error processing binary input', { key, error: error.message });\r\n return null;\r\n }\r\n}\r\n\r\nasync function inferDateType(value: any, key?: string, agent?: Agent) {\r\n const errMsg = `Invalid Date value\\nThe date string is expected to be in a format commonly used in English-speaking countries.`;\r\n\r\n // Make sure we only accept string or number to parse as date\r\n if (typeof value !== 'string' && typeof value !== 'number') throw new Error(errMsg);\r\n\r\n let date;\r\n if (typeof value === 'string' && isNaN(Number(value))) {\r\n date = dayjs(value).locale('en'); // parse as date string\r\n } else {\r\n // parse as Unix timestamp\r\n const timestamp = typeof value === 'number' ? value : Number(value);\r\n date = dayjs.unix(timestamp / 1000);\r\n }\r\n\r\n if (!date.isValid()) throw new Error(errMsg);\r\n\r\n return date.toISOString();\r\n}\r\n\r\nasync function inferAnyType(value: any) {\r\n return value;\r\n}\r\n\r\n/**\r\n * Extracts URLs from various string formats that may be returned by AI/LLM outputs.\r\n * The underscore prefix indicates this is an internal utility function.\r\n *\r\n * Handles the following formats:\r\n * - JSON stringified arrays or objects containing URLs\r\n * - Comma-separated URLs\r\n * - Newline-separated URLs\r\n * - Mixed formats (both comma and newline separators)\r\n * - Single URL strings\r\n *\r\n * @param value - String potentially containing one or more URLs (typically from AI/LLM outputs)\r\n * @returns Array of extracted URLs (empty array if none found)\r\n * @private\r\n */\r\nfunction _extractUrls(value: string): string[] {\r\n // Return empty array for non-string inputs\r\n if (typeof value !== 'string') return [];\r\n\r\n try {\r\n // Try parsing as JSON first\r\n const parsedValue = JSONContent(value).tryParse();\r\n if (typeof parsedValue === 'object') {\r\n return Object.values(parsedValue)\r\n .map((val) => String(val).trim())\r\n .filter((val) => isUrl(val) || isSmythFsUrl(val));\r\n }\r\n\r\n // Split by both delimiters and flatten the results\r\n const urls = new Set([\r\n // Split by commas\r\n ...value\r\n .split(',')\r\n .map((val) => val.trim())\r\n .filter((val) => val && (isUrl(val) || isSmythFsUrl(val))),\r\n\r\n // Split by newlines\r\n ...value\r\n .split('\\n')\r\n .map((val) => val.trim())\r\n .filter((val) => val && (isUrl(val) || isSmythFsUrl(val))),\r\n ]);\r\n\r\n return Array.from(urls);\r\n } catch (error) {\r\n logger.warn('Error extracting URLs from value', { error });\r\n return [];\r\n }\r\n}\r\n","import Joi from 'joi';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { performTypeInference } from '@sre/helpers/TypeChecker.helper';\r\nimport { hookAsync } from '@sre/Core/HookService';\r\n\r\nexport type ComponentSchema = {\r\n name: string;\r\n settings?: Record<string, any>;\r\n inputs?: Record<string, any>;\r\n outputs?: Record<string, any>;\r\n};\r\n\r\nexport class Component {\r\n public hasReadOutput = false;\r\n public hasPostProcess = true;\r\n public alwaysActive = false; //for components like readable memories\r\n public exclusive = false; //for components like writable memories : when exclusive components are active, they are processed in a run cycle bofore other components\r\n protected schema: ComponentSchema = {\r\n name: 'Component',\r\n settings: {},\r\n inputs: {},\r\n //outputs: {},\r\n };\r\n protected configSchema;\r\n constructor() {}\r\n init() {}\r\n\r\n createComponentLogger(agent: Agent, configuration: any) {\r\n const logger = Logger(configuration.name || this.constructor.name, agent?.agentRuntime?.debug);\r\n\r\n logger.on('logged', (info: { level: string; message: string }) => {\r\n if (agent.sse && configuration.eventId) {\r\n agent.sse.send('component', {\r\n eventId: configuration.eventId,\r\n action: 'log',\r\n name: configuration.name || this.constructor.name,\r\n title: configuration.title,\r\n logs: [{ level: info.level, message: info.message }],\r\n });\r\n }\r\n });\r\n return logger;\r\n }\r\n\r\n async validateConfig(config) {\r\n if (!this.configSchema) return {};\r\n if (config.data._templateVars) {\r\n //Accept dynamically added template data\r\n for (let tplVar in config.data._templateVars) {\r\n this.configSchema = this.configSchema.append({ [tplVar]: Joi.any() });\r\n }\r\n }\r\n const valid = await this.configSchema.validate(config.data);\r\n if (valid.error) {\r\n return {\r\n id: config.id,\r\n name: config.name,\r\n _error: `Schema Validation error: ${valid?.error?.message} on component ${config.displayName}:${config.title}`,\r\n _debug: `Schema Validation error: ${valid?.error?.message} on component ${config.displayName}:${config.title}`,\r\n };\r\n }\r\n\r\n return {};\r\n }\r\n\r\n @hookAsync('Component.process')\r\n async process(input, config, agent: Agent): Promise<any> {\r\n if (agent.isKilled()) {\r\n throw new Error('Agent killed');\r\n }\r\n const _input = await performTypeInference(input, config?.inputs, agent);\r\n\r\n // modify the input object for component's process method\r\n for (const [key, value] of Object.entries(_input)) {\r\n input[key] = value;\r\n }\r\n }\r\n async postProcess(output, config, agent: Agent): Promise<any> {\r\n if (output?.result) {\r\n delete output?.result?._debug;\r\n if (!output?.result?._error) delete output?.result?._error;\r\n }\r\n return output;\r\n }\r\n async enable(config, agent: Agent): Promise<any> {}\r\n async disable(config, agent: Agent): Promise<any> {}\r\n readOutput(id, config, agent: Agent): any {\r\n return null;\r\n }\r\n hasOutput(id, config, agent: Agent): any {\r\n return false;\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Conversation } from '@sre/helpers/Conversation.helper';\r\nimport { Component } from './Component.class';\r\n\r\nexport class AgentPlugin extends Component {\r\n protected configSchema = Joi.object({\r\n agentId: Joi.string().max(200).required(),\r\n openAiModel: Joi.string().max(200).optional(), // for backward compatibility\r\n model: Joi.string().max(200).optional(),\r\n descForModel: Joi.string().max(5000).allow('').label('Description for Model'),\r\n id: Joi.string().max(200),\r\n name: Joi.string().max(500),\r\n desc: Joi.string().max(5000).allow('').label('Description'),\r\n logoUrl: Joi.string().max(8192).allow(''),\r\n version: Joi.string().max(100).allow(''),\r\n domain: Joi.string().max(253).allow(''),\r\n });\r\n\r\n constructor() {\r\n super();\r\n }\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n logger.debug(`=== Agent Plugin Log ===`);\r\n\r\n try {\r\n const subAgentId = config.data?.agentId;\r\n\r\n if (!subAgentId) {\r\n return { _error: 'Agent Component ID is required!', _debug: logger.output };\r\n }\r\n\r\n //tag this request to tell the nested agent that the call comes from internal agent\r\n const reqTag = agent.agentRuntime?.reqTag;\r\n\r\n const model = config?.data?.model || config?.data?.openAiModel;\r\n const descForModel = TemplateString(config?.data?.descForModel).parse(input).result;\r\n const prompt = typeof input?.Prompt === 'string' ? input?.Prompt : JSON.stringify(input?.Prompt);\r\n\r\n const agentDataConnector = ConnectorService.getAgentDataConnector();\r\n\r\n //let subAgentDomain = await isDeployed(subAgentId);\r\n // when domain found for sub agent, that means it's deployed\r\n const isSubAgentDeployed = await agentDataConnector.isDeployed(subAgentId);\r\n\r\n let version = config.data?.version || '';\r\n\r\n logger.debug('Version: ', version);\r\n\r\n if (version === 'same-as-parent') {\r\n const isParentAgentDeployed = await agentDataConnector.isDeployed(agent?.id);\r\n\r\n if (isParentAgentDeployed) {\r\n if (isSubAgentDeployed) {\r\n version = 'latest';\r\n } else {\r\n return {\r\n _error: `Call failed, Agent '${config.data?.name}' (${subAgentId}) is not deployed. Please deploy the agent and try again.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n } else {\r\n version = ''; // empty string ('') means latest dev version\r\n }\r\n } else if (version === 'dev-latest') {\r\n version = '';\r\n } else if (version === 'prod-latest') {\r\n if (isSubAgentDeployed) {\r\n version = 'latest';\r\n } else {\r\n return {\r\n _error: `Call failed, Agent '${config.data?.name}' (${subAgentId}) is not deployed. Please deploy the agent and try again.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n }\r\n\r\n const conv = new Conversation(model, subAgentId, { systemPrompt: descForModel, agentVersion: version });\r\n\r\n const result = await conv.prompt(prompt, {\r\n 'X-AGENT-ID': subAgentId,\r\n 'X-AGENT-VERSION': version,\r\n 'X-REQUEST-TAG': reqTag, //request Tag identifies the request and tells the called agent that the call comes from internal agent\r\n 'x-caller-session-id': agent.callerSessionId,\r\n });\r\n\r\n logger.debug(`Response:\\n`, result, '\\n');\r\n\r\n return { Response: result, _debug: logger.output };\r\n } catch (error: any) {\r\n console.error('Error on running Agent Component: ', error);\r\n return { _error: `Error on running Agent Component!\\n${error?.message || JSON.stringify(error)}`, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nimport { jsonrepair } from 'jsonrepair';\r\nimport { AgentRequest } from '@sre/AgentManager/AgentRequest.class';\r\nimport { performTypeInference } from '@sre/helpers/TypeChecker.helper';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { uid } from '../utils';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\n\r\n// Utility function to check for empty values\r\nfunction isEmpty(value: any): boolean {\r\n return (\r\n value === undefined ||\r\n value === null ||\r\n (typeof value === 'string' && value.trim() === '') ||\r\n (Array.isArray(value) && value.length === 0) ||\r\n (typeof value === 'object' && value !== null && Object.keys(value).length === 0)\r\n );\r\n}\r\nfunction isTemplateVar(str: string = ''): boolean {\r\n if (!str || typeof str !== 'string') return false;\r\n return (str?.match(/{{(.*?)}}/g) ?? []).length > 0;\r\n}\r\nfunction isKeyTemplateVar(str: string = ''): boolean {\r\n if (!str || typeof str !== 'string') return false;\r\n return (str?.match(/{{KEY\\((.*?)\\)}}/g) ?? []).length > 0;\r\n}\r\n\r\nfunction parseKey(str: string = '', teamId: string): string {\r\n return str.replace(/{{KEY\\((.*?)\\)}}/g, (match, key) => {\r\n return key === 'teamid' ? teamId : '';\r\n });\r\n}\r\n\r\nexport class APIEndpoint extends Component {\r\n protected configSchema = Joi.object({\r\n endpoint: Joi.string()\r\n .pattern(/^[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*$/)\r\n .max(50)\r\n .required(),\r\n method: Joi.string().valid('POST', 'GET').allow(''), //we're accepting empty value because we consider it POST by default.\r\n description: Joi.string().max(5000).allow(''),\r\n summary: Joi.string().max(1000).allow(''),\r\n doc: Joi.string().max(1000).allow(''),\r\n ai_exposed: Joi.boolean().default(true),\r\n advancedModeEnabled: Joi.boolean().optional(),\r\n endpointLabel: Joi.string().max(100).allow('').optional(),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const req: AgentRequest = agent.agentRequest;\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n const headers = req ? req.headers : {};\r\n let body = req ? req.body : input; //handle debugger injection\r\n const params = req ? req.params : {};\r\n let query = req ? req.query : {};\r\n const _authInfo = req ? req._agent_authinfo : undefined;\r\n\r\n // parse template variables\r\n for (const [key, value] of Object.entries(body)) {\r\n if (isKeyTemplateVar(value as string)) {\r\n body[key] = await parseKey(value as string, agent?.teamId);\r\n } else if (isTemplateVar(value as string)) {\r\n //body[key] = parseTemplate(value as string, input, { escapeString: false });\r\n body[key] = TemplateString(value as string).parse(input).result;\r\n }\r\n }\r\n\r\n for (const [key, value] of Object.entries(query)) {\r\n if (isKeyTemplateVar(value as string)) {\r\n query[key] = await parseKey(value as string, agent?.teamId);\r\n } else if (isTemplateVar(value as string)) {\r\n //query[key] = parseTemplate(value as string, input, { escapeString: false });\r\n query[key] = TemplateString(value as string).parse(input).result;\r\n }\r\n }\r\n\r\n // set default value and agent variables\r\n const inputsWithDefaultValue = config.inputs.filter(\r\n (input) => input.defaultVal !== undefined && input.defaultVal !== '' && input.defaultVal !== null,\r\n );\r\n\r\n const bodyInputNames: string[] = [];\r\n const queryInputNames: string[] = [];\r\n\r\n for (const output of config.outputs) {\r\n const outputName = output?.expression || output?.name;\r\n const inputName = outputName?.split('.')[1];\r\n\r\n if (inputName) {\r\n if (outputName?.includes('body')) {\r\n bodyInputNames.push(inputName);\r\n }\r\n\r\n if (outputName?.includes('query')) {\r\n queryInputNames.push(inputName);\r\n }\r\n }\r\n }\r\n\r\n for (const _inputWithDefaultValue of inputsWithDefaultValue) {\r\n const inputName = _inputWithDefaultValue?.name;\r\n\r\n let inputValue = input[inputName];\r\n\r\n // We provide a default value for the OpenAPI Schema, which can detected by Anthropic. So we need to check if the default value is an Agent Variable. This is necessary for interactions with the Chatbot.\r\n\r\n if (bodyInputNames.includes(inputName) && isEmpty(body[inputName])) {\r\n body[inputName] = inputValue;\r\n }\r\n\r\n if (queryInputNames.includes(inputName) && isEmpty(query[inputName])) {\r\n query[inputName] = inputValue;\r\n }\r\n }\r\n\r\n //override debugger injection\r\n // if (agent.agentRuntime.debug && body?.[0]?.dbg) { // ! 'dbg' is DEPRECATED\r\n const isDbgInjection = req.header('X-Debug-Inj') !== undefined;\r\n if (isDbgInjection && agent.agentRuntime.debug && Object.values(input).length > 0) {\r\n switch (config.data.method) {\r\n case 'GET':\r\n for (const [key, value] of Object.entries(input)) {\r\n if (value instanceof BinaryInput) {\r\n logger.debug('[WARNING] Binary files are not supported for GET requests. Key:', key);\r\n } else {\r\n query[key] = value as string;\r\n }\r\n }\r\n break;\r\n case 'POST':\r\n default:\r\n body = input;\r\n break;\r\n }\r\n //body = input;\r\n }\r\n\r\n // ensure strong data type\r\n body = await performTypeInference(body, config.inputs, agent);\r\n query = await performTypeInference(query, config.inputs, agent);\r\n\r\n logger.debug('Parsing inputs');\r\n logger.debug(' Headers', headers);\r\n logger.debug(' Body', body);\r\n logger.debug(' Params', params);\r\n logger.debug(' Query', query);\r\n\r\n //Handle JSON Data\r\n //FIXME : this is a workaround that parses any json string in the body, we should only parse the json string in the body if the data type is explicitely set to JSON\r\n //TODO : Add data types to APIEndpoint inputs\r\n logger.debug('Parsing body json input');\r\n for (let key in body) {\r\n const value = body[key];\r\n if (typeof value === 'string' && value.trim().startsWith('{') && value.trim().endsWith('}')) {\r\n try {\r\n const obj = JSON.parse(jsonrepair(body[key]));\r\n body[key] = obj;\r\n } catch {\r\n //skip it if it's not a valid json\r\n }\r\n }\r\n }\r\n logger.debug('Parsed body json input', body);\r\n\r\n logger.debug('Parsing query json input');\r\n for (let key in query) {\r\n const value = query[key];\r\n if (typeof value === 'string' && value.trim().startsWith('{') && value.trim().endsWith('}')) {\r\n try {\r\n const obj = JSON.parse(jsonrepair(query[key] as string));\r\n query[key] = obj;\r\n } catch {\r\n //skip it if it's not a valid json\r\n }\r\n }\r\n }\r\n logger.debug('Parsed query json input', query);\r\n\r\n //Handle binary data\r\n for (let input of config.inputs) {\r\n if (!input.isFile && !['image', 'audio', 'video', 'binary'].includes(input?.type?.toLowerCase())) continue;\r\n\r\n const fieldname = input.name;\r\n\r\n logger.debug('Parsing file input ', fieldname);\r\n\r\n let binaryInputs = body[fieldname];\r\n\r\n // Ensure we're working with an array\r\n if (!Array.isArray(binaryInputs)) {\r\n binaryInputs = [binaryInputs];\r\n }\r\n\r\n // Process each binary input\r\n const processedInputs = await Promise.all(\r\n binaryInputs.map(async (binaryInput) => {\r\n if (!(binaryInput instanceof BinaryInput)) {\r\n // * when data sent with 'multipart/form-data' content type, we expect the files to be in req.files\r\n if (req.files?.length > 0) {\r\n const file = req.files.find((file) => file.fieldname === fieldname);\r\n if (!file) return null;\r\n binaryInput = new BinaryInput(file.buffer, uid() + '-' + file.originalname, file.mimetype);\r\n }\r\n }\r\n\r\n if (binaryInput instanceof BinaryInput) {\r\n return await binaryInput.getJsonData(AccessCandidate.agent(agent.id));\r\n }\r\n return null;\r\n }),\r\n );\r\n\r\n // Filter out null values and handle single/multiple results\r\n const validResults = processedInputs.filter((result) => result !== null);\r\n if (validResults.length > 0) {\r\n body[fieldname] = validResults.length === 1 ? validResults[0] : validResults;\r\n }\r\n //console.log('file', fieldname, body[fieldname]);\r\n }\r\n\r\n return { headers, body, query, params, _authInfo, _debug: logger.output };\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport Joi from 'joi';\r\n\r\nexport class APIOutput extends Component {\r\n protected configSchema = Joi.object({\r\n format: Joi.string().valid('full', 'minimal', 'raw').label('Output Format').required(),\r\n contentType: Joi.string().valid('application/json', 'text/plain', 'text/html', 'application/xml').optional().allow('').label('Content Type'),\r\n });\r\n public hasPostProcess = true;\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n const _error = undefined;\r\n let Output = {};\r\n logger.debug(` Processing outputs `);\r\n for (let key in input) {\r\n if (!config.inputs.find((i) => i.name == key)) continue; //exclude global variables\r\n Output[key] = input[key];\r\n }\r\n\r\n if (config.data.format === 'raw') {\r\n let rawOutput = '';\r\n for (let key in input) {\r\n if (!config.inputs.find((i) => i.name == key)) continue; //exclude global variables\r\n rawOutput += input[key];\r\n }\r\n Output = rawOutput;\r\n }\r\n return { Output, _error, _debug: logger.output };\r\n }\r\n async postProcess(output, config, agent: Agent): Promise<any> {\r\n let contentType = config.data.contentType || 'application/json';\r\n\r\n for (let agentVar in agent.agentVariables) {\r\n delete output?.result?.Output?.[agentVar]; //clean up agent variables from output\r\n }\r\n\r\n if (config?.data?.format == 'minimal' || contentType !== 'application/json') {\r\n if (output?.result?.Output) {\r\n return output?.result?.Output;\r\n }\r\n\r\n if (output?.result?._error) {\r\n return output?.result?._error;\r\n }\r\n\r\n delete output.id;\r\n delete output.name;\r\n }\r\n\r\n return output;\r\n }\r\n}\r\n","import { IAgent } from '@sre/types/Agent.types';\r\nimport { Agent } from './Agent.class';\r\nimport { AgentRequest } from './AgentRequest.class';\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { uid } from '@sre/utils';\r\nconst console = Logger('ForkedAgent');\r\n\r\n/**\r\n * This class creates a forked agent from a parent agent branch, it allows running a sub-branch of the parent agent asynchrounously by providing a separate agent context\r\n * We use composition instead of inheritance to avoid circular dependencies between Agent and ForkedAgent\r\n */\r\nexport class ForkedAgent {\r\n public agent: IAgent;\r\n public get agentRequest() {\r\n return this.agent.agentRequest;\r\n }\r\n public get components() {\r\n return this.agent.components;\r\n }\r\n public get agentRuntime() {\r\n return this.agent.agentRuntime;\r\n }\r\n public get jobID() {\r\n return this.agent.jobID;\r\n }\r\n constructor(\r\n private parent: IAgent,\r\n componentId: string, //the component to fork from\r\n ) {\r\n const data: any = fork(this.parent.data, componentId);\r\n data.variables = JSON.parse(JSON.stringify(this.parent?.data?.variables || {})); //copy parent Agent variables to forked agent\r\n data.teamId = this.parent.teamId;\r\n //TODO : we need to create a default APIEndpoint bound to the root component if root component is not an APIEndpoint\r\n const content = { name: this.parent.name, data, teamId: this.parent.teamId, debugSessionEnabled: false, version: this.parent.version };\r\n\r\n const agentRequest = new AgentRequest(this.parent.agentRequest.req);\r\n agentRequest.headers = []; //clear all headers from parent agent to conflict with child agent\r\n\r\n this.agent = new Agent(this.parent.id, content, this.parent.agentSettings, agentRequest);\r\n const JobID = componentId + '-' + uid();\r\n this.agent.jobID = JobID;\r\n //since the jobID was updated we need to create a different runtime\r\n //FIXME : we need to find a way to avoid creating default runtime for forked agents, then replace it\r\n //this.agent.agentRuntime = new AgentRuntime(this.agent);\r\n\r\n //super(parent.id, content, agentRequest);\r\n }\r\n\r\n process(path: string, input: any) {\r\n return this.agent.process(path, input);\r\n }\r\n}\r\n\r\n// Helper function to clone a component and update its ID\r\nfunction cloneComponent(component) {\r\n const newComponent = JSON.parse(JSON.stringify(component));\r\n newComponent.id = component.id;\r\n return newComponent;\r\n}\r\n\r\n// Helper function to recursively clone components and their connections\r\nfunction cloneRecursively(componentData, currentID, newIDMap, clonedComponents, clonedConnections) {\r\n const componentToClone = componentData.components.find((c) => c.id === currentID);\r\n if (!componentToClone) {\r\n return;\r\n }\r\n\r\n const clonedComponent = cloneComponent(componentToClone);\r\n newIDMap[currentID] = clonedComponent.id; // Map old ID to new ID\r\n clonedComponents.push(clonedComponent);\r\n\r\n // Find all outgoing connections for the current component\r\n const outgoingConnections = componentData.connections.filter((conn) => conn.sourceId === currentID);\r\n outgoingConnections.forEach((conn) => {\r\n // Clone the connection and update the IDs\r\n const clonedConnection = JSON.parse(JSON.stringify(conn));\r\n clonedConnection.sourceId = clonedComponent.id;\r\n if (!newIDMap[conn.targetId]) {\r\n // Recursively clone the connected component if it hasn't been cloned yet\r\n cloneRecursively(componentData, conn.targetId, newIDMap, clonedComponents, clonedConnections);\r\n }\r\n clonedConnection.targetId = newIDMap[conn.targetId];\r\n clonedConnections.push(clonedConnection);\r\n });\r\n}\r\n\r\nfunction fork(componentData, componentID) {\r\n const clonedComponents: any[] = [];\r\n const clonedConnections: any[] = [];\r\n const newIDMap = {}; // Map to keep track of old to new ID mappings\r\n\r\n // Start the cloning process from the specified component ID\r\n cloneRecursively(componentData, componentID, newIDMap, clonedComponents, clonedConnections);\r\n\r\n const rootComponentData = clonedComponents.find((e) => e.id == componentID);\r\n if (rootComponentData) {\r\n if (rootComponentData.name !== 'APIEndpoint') {\r\n const APIEndpointData: any = {\r\n id: `${componentID}_ENDPOINT`,\r\n name: 'APIEndpoint',\r\n outputs: [\r\n { name: 'headers', index: 0, default: true },\r\n { name: 'body', index: 1, default: true },\r\n { name: 'query', index: 2, default: true },\r\n ],\r\n inputs: [],\r\n data: { endpoint: componentID, description: '', method: 'POST' },\r\n displayName: 'APIEndpoint',\r\n title: 'APIEndpoint',\r\n description: '',\r\n };\r\n\r\n //APIEndpointData.inputs = JSON.parse(JSON.stringify(rootComponentData.inputs));\r\n clonedComponents.push(APIEndpointData);\r\n\r\n //find all previously connected forked inputs\r\n const incomingConnections = componentData.connections.filter((conn) => conn.targetId === componentID);\r\n // //deduplicate connections by targetId\r\n // const uniqueIncomingConnections = incomingConnections.filter(\r\n // (conn, index, self) => index === self.findIndex((t) => t.targetId === conn.targetId && t.sourceIndex === conn.sourceIndex && t.targetIndex === conn.targetIndex),\r\n // );\r\n\r\n let i = 3;\r\n for (let con of incomingConnections) {\r\n const input = rootComponentData.inputs.find((e) => e.index == con.targetIndex);\r\n const epInput = JSON.parse(JSON.stringify(input));\r\n APIEndpointData.inputs.push(epInput);\r\n\r\n const epOutput = {\r\n name: input.name,\r\n expression: `body.${input.name}`,\r\n optional: false,\r\n index: i++,\r\n default: false,\r\n };\r\n APIEndpointData.outputs.push(epOutput);\r\n\r\n clonedConnections.push({\r\n sourceId: APIEndpointData.id,\r\n targetId: rootComponentData.id,\r\n sourceIndex: epOutput.index,\r\n targetIndex: input.index,\r\n });\r\n }\r\n }\r\n }\r\n // Return the cloned sub-workflow\r\n return {\r\n components: clonedComponents,\r\n connections: clonedConnections,\r\n };\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { ForkedAgent } from '@sre/AgentManager/ForkedAgent.class';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport { delay } from '../utils';\r\n\r\nexport class Async extends Component {\r\n static JOBS = {};\r\n protected configSchema = null;\r\n static ForkedAgent;\r\n constructor() {\r\n super();\r\n // import('../ForkedAgent.class').then((ForkedAgent) => {\r\n // Async.ForkedAgent = ForkedAgent.default;\r\n // });\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n //we set data.forked to true in the forked component in order to refork it again.\r\n const forked = config.data.forked;\r\n let _error = null;\r\n\r\n try {\r\n //const runtimeData = agent.agentRuntime.getRuntimeData(config.id);\r\n\r\n if (!forked) {\r\n const forkedAgent: ForkedAgent = new ForkedAgent(agent, config.id);\r\n const JobID = forkedAgent.jobID;\r\n\r\n forkedAgent.agent.async = true;\r\n forkedAgent.agent.jobID = JobID;\r\n //clean JobID branch\r\n this.cleanJobIDBranch(forkedAgent.agent);\r\n\r\n const componentData = forkedAgent.components[config.id];\r\n componentData.data.forked = true;\r\n\r\n forkedAgent.agentRequest.body = { ...input };\r\n\r\n if (!Async.JOBS[agent.id]) Async.JOBS[agent.id] = {};\r\n Async.JOBS[agent.id][JobID] = {\r\n //forkedAgent,\r\n status: 'pending',\r\n };\r\n\r\n //We use this to inform the debugger about the list of components used by this job\r\n //this is only used to provide a visual feedback in the debugger UI\r\n if (agent.debugSessionEnabled) {\r\n const _job_components = Object.keys(forkedAgent.components);\r\n agent.agentRuntime.updateComponent(config.id, { _job_components });\r\n }\r\n\r\n forkedAgent\r\n .process(`/api/${config.id}`, input)\r\n .then((result) => {\r\n Async.JOBS[agent.id][JobID].result = result;\r\n Async.JOBS[agent.id][JobID].status = 'done';\r\n })\r\n .finally(async () => {\r\n if (Async.JOBS[agent.id][JobID].status !== 'done') {\r\n Async.JOBS[agent.id][JobID].status = 'failed';\r\n }\r\n if (agent.debugSessionEnabled) {\r\n await delay(1000); //wait for the debugger to update the UI\r\n //ctxData in agentRuntime might have been updated by the main component\r\n //we need to reload it in order to ensure that we're updating the latest version\r\n agent.agentRuntime.reloadCtxData();\r\n agent.agentRuntime.updateComponent(config.id, { _job_components: [] });\r\n }\r\n });\r\n\r\n return { JobID };\r\n } else {\r\n //const Input = input.Input;\r\n let result = { JobID: agent.jobID };\r\n for (let key in input) {\r\n result[key] = input[key];\r\n }\r\n\r\n return result;\r\n }\r\n } catch (error: any) {\r\n _error = error;\r\n }\r\n\r\n return {};\r\n }\r\n\r\n // private recursiveTagAsyncComponents(component, agent: Agent) {\r\n // for (let output of component.outputs) {\r\n // if (component.name == 'Async' && output.name === 'JobID') continue; //'JobID' is a special output\r\n // const connected = agent.connections.filter((c) => c.sourceId === component.id && c.sourceIndex === output.index);\r\n // if (!connected) continue;\r\n // for (let con of connected) {\r\n // const targetComponent = agent.components[con.targetId];\r\n // if (!targetComponent) continue;\r\n // targetComponent.async = true;\r\n // this.recursiveTagAsyncComponents(targetComponent, agent);\r\n // }\r\n // }\r\n // }\r\n // private tagAsyncComponents(agent: Agent) {\r\n // const componentsList: any[] = Object.values(agent.components);\r\n // const AsyncComponent = componentsList.find((c) => c.name === 'Async');\r\n // if (!AsyncComponent) return;\r\n // AsyncComponent.async = true;\r\n\r\n // this.recursiveTagAsyncComponents(AsyncComponent, agent);\r\n // }\r\n private cleanJobIDBranch(agent: Agent) {\r\n //this.tagAsyncComponents(agent);\r\n\r\n const componentsList: any[] = Object.values(agent.components);\r\n const AsyncComponent = componentsList.find((c) => c.name === 'Async');\r\n //const endpointComponent = componentsList.find((c) => c.name === 'APIEndpoint');\r\n if (!AsyncComponent) return;\r\n const jobIDOutputIndex = AsyncComponent.outputs.findIndex((o) => o.name === 'JobID');\r\n if (jobIDOutputIndex === -1) return;\r\n //delete connections where sourceId = AsyncComponent.id and sourceOutputIndex = jobIDOutputIndex and the component is not tagged as async\r\n agent.connections = agent.connections.filter((c) => {\r\n const toDelete = c.sourceId === AsyncComponent.id && c.sourceIndex === jobIDOutputIndex && !agent.components[c.targetId].async;\r\n return !toDelete;\r\n });\r\n\r\n //TODO : remove orphaned branches\r\n this.removeOrphanedBranches(agent);\r\n }\r\n\r\n private removeOrphanedBranches(agent: Agent) {\r\n const toDelete: any[] = [];\r\n for (let componentId in agent.components) {\r\n const component = agent.components[componentId];\r\n if (component.name === 'APIEndpoint') continue;\r\n const connected = agent.connections.some((c) => c.targetId === component.id);\r\n if (!connected) {\r\n //this.removeComponent(agent, component.id);\r\n toDelete.push(component.id);\r\n }\r\n }\r\n for (let id of toDelete) {\r\n this.removeComponent(agent, id);\r\n }\r\n }\r\n\r\n private removeComponent(agent: Agent, componentId: string) {\r\n const component = agent.components[componentId];\r\n delete agent.components[componentId];\r\n\r\n //delete connections where sourceId = componentId\r\n agent.connections = agent.connections.filter((c) => c.sourceId !== componentId);\r\n this.removeOrphanedBranches(agent);\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport axios from 'axios';\r\nimport Joi from 'joi';\r\nimport { Async } from './Async.class';\r\n\r\nexport class Await extends Component {\r\n static WAITS = {};\r\n\r\n protected configSchema = Joi.object({\r\n jobs_count: Joi.number().min(1).max(100).default(1).label('Jobs Count'),\r\n max_time: Joi.number().min(1).max(21600).default(1).label('Max time'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n let Results: any = {};\r\n const _error = null;\r\n let jobs_count = parseInt(config.data.jobs_count || 1);\r\n let max_time = parseInt(config.data.max_time || 1);\r\n\r\n const jobs = Array.isArray(input.Jobs) ? input.Jobs : [input.Jobs];\r\n\r\n if (!Await.WAITS[agent.id]) Await.WAITS[agent.id] = {};\r\n if (!Await.WAITS[agent.id][config.id]) Await.WAITS[agent.id][config.id] = {};\r\n if (!Await.WAITS[agent.id][config.id][agent.agentRuntime.workflowReqId])\r\n Await.WAITS[agent.id][config.id][agent.agentRuntime.workflowReqId] = [];\r\n\r\n //add jobs to the list\r\n for (let jobID of jobs) Await.WAITS[agent.id][config.id][agent.agentRuntime.workflowReqId].push(jobID);\r\n\r\n logger.debug('Jobs', jobs);\r\n logger.debug('Waiting for jobs to finish');\r\n\r\n let promise = new Promise((resolve, reject) => {\r\n let interval = setInterval(() => {\r\n if (max_time < 0) {\r\n clearInterval(interval);\r\n return resolve(true);\r\n }\r\n let done = true;\r\n let completed = 0;\r\n for (let jobID of jobs) {\r\n if (Async.JOBS?.[agent.id]?.[jobID]?.status == 'pending') {\r\n done = false;\r\n break;\r\n } else {\r\n completed++;\r\n }\r\n }\r\n if (completed >= jobs_count) {\r\n done = true;\r\n }\r\n\r\n if (done) {\r\n clearInterval(interval);\r\n return resolve(true);\r\n }\r\n\r\n max_time -= 1;\r\n }, 1000);\r\n });\r\n\r\n await promise;\r\n logger.debug('Jobs finished, collecting results');\r\n for (let jobID of jobs) {\r\n Results[jobID] = {\r\n output: Async.JOBS?.[agent.id]?.[jobID]?.result,\r\n status: Async.JOBS?.[agent.id]?.[jobID]?.status || 'unknown_job',\r\n };\r\n }\r\n delete Await.WAITS[agent.id][config.id][agent.agentRuntime.workflowReqId];\r\n\r\n logger.debug('Results', Results);\r\n return { Results, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error running code \\n${_error}\\n`);\r\n delete Await.WAITS[agent.id][config.id][agent.agentRuntime.workflowReqId];\r\n\r\n return { Output: undefined, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n }\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { JSONContentHelper } from '@sre/helpers/JsonContent.helper';\r\nimport { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nexport class Classifier extends Component {\r\n protected schema = {\r\n name: 'Classifier',\r\n settings: {\r\n model: {\r\n type: 'string',\r\n max: 200,\r\n required: true,\r\n },\r\n prompt: {\r\n type: 'string',\r\n max: 30000,\r\n allow: '',\r\n label: 'Prompt',\r\n },\r\n },\r\n\r\n inputs: {\r\n Input: {\r\n type: 'Any',\r\n default: true,\r\n },\r\n },\r\n };\r\n protected configSchema = Joi.object({\r\n model: Joi.string().max(200).required(),\r\n prompt: Joi.string().max(30000).allow('').label('Prompt'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n escapeJSONString(str: string) {\r\n return str.replace(/\\{/g, '<[<(').replace(/\\}/g, ')>]>').replace(/\"/g, '`');\r\n }\r\n unescapeJSONString(str: string) {\r\n return str\r\n .replace(/<\\[<\\(/g, '{')\r\n .replace(/\\)>]>/g, '}')\r\n .replace(/`/g, '\"');\r\n }\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n //let debugLog = agent.agentRuntime?.debug ? [] : undefined;\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n const inputCopy = JSON.parse(JSON.stringify(input));\r\n for (let key in inputCopy) {\r\n if (typeof inputCopy[key] === 'string') {\r\n inputCopy[key] = this.escapeJSONString(inputCopy[key]);\r\n } else if (typeof inputCopy[key] === 'object') {\r\n inputCopy[key] = JSON.stringify(inputCopy[key]);\r\n inputCopy[key] = this.escapeJSONString(inputCopy[key]);\r\n }\r\n }\r\n\r\n const _input = typeof input === 'string' ? input : JSON.stringify(inputCopy, null, 2);\r\n //const categories = config.outputs.map((output) => (output.name[0] != '[' ? output.name : null)).filter((e) => e);\r\n const categories = {};\r\n for (let con of config.outputs) categories[con.name] = con.description || '';\r\n\r\n const outputs = {};\r\n for (let con of config.outputs) {\r\n outputs[con.name] = '<Boolean|String>';\r\n }\r\n\r\n const model: string = config.data.model;\r\n const modelId = await agent.modelsProvider.getModelId(model);\r\n //const isStandardLLM = await agent.modelsProvider.isStandardLLM(model);\r\n\r\n logger.log(` Selected model : ${modelId || model}`);\r\n\r\n let prompt = '';\r\n const excludedKeys = ['_debug', '_error'];\r\n const outputKeys = Object.keys(outputs).filter((key) => !excludedKeys.includes(key));\r\n\r\n if (outputKeys.length > 0) {\r\n const outputFormat = {};\r\n outputKeys.forEach((key) => (outputFormat[key] = outputs[key]));\r\n\r\n prompt = `${config.data.prompt}\r\n${_input}\r\n\r\n---\r\nCategories: \r\n${JSON.stringify(categories, null, 2)}`;\r\n\r\n prompt = TemplateString(prompt).parse(input).result;\r\n }\r\n\r\n logger.log(` Enhanced prompt \\n${prompt}\\n`);\r\n\r\n if (!prompt) {\r\n logger.error(` Missing information, Cannot run classifier`);\r\n\r\n return { _error: 'Missing information, Cannot run classifier', _debug: logger.output };\r\n }\r\n\r\n const llmInference: LLMInference = await LLMInference.getInstance(model || 'echo', AccessCandidate.agent(agent.id));\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n try {\r\n let response = await llmInference\r\n .prompt({ query: prompt, params: { ...config, agentId: agent.id } })\r\n .catch((error) => ({ error: error }));\r\n\r\n if (response?.error) {\r\n const error = response?.error + ' ' + (response?.details || '');\r\n logger.error(` LLM Error=`, error);\r\n\r\n return { _error: error, _debug: logger.output };\r\n }\r\n\r\n // let parsed = parseJson(response);\r\n let parsed = typeof response === 'string' ? JSONContentHelper.create(response).tryParse() : response;\r\n\r\n for (let entry in parsed) {\r\n if (!parsed[entry]) delete parsed[entry];\r\n else {\r\n if (typeof parsed[entry] === 'string') {\r\n parsed[entry] = this.unescapeJSONString(parsed[entry]);\r\n // const parsedValue = parseJson(parsed[entry]);\r\n const parsedValue = JSONContentHelper.create(parsed[entry]).tryParse();\r\n if (typeof parsedValue === 'object' && !parsedValue.error) parsed[entry] = parsedValue;\r\n }\r\n }\r\n }\r\n\r\n if (parsed.error) {\r\n parsed._error = parsed.error;\r\n logger.warn(` Post process error=${parsed.error}`);\r\n delete parsed.error;\r\n }\r\n\r\n logger.log(' Classifier result\\n', parsed);\r\n\r\n parsed['_debug'] = logger.output;\r\n\r\n return parsed;\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\n/**\r\n * This component allows running components that are not natively shiped with SRE\r\n * it can be used to extend SRE components by registering custom component using ComponentService\r\n */\r\nexport class ComponentHost extends Component {\r\n protected configSchema = null;\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n //let debugLog = agent.agentRuntime?.debug ? [] : undefined;\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n try {\r\n const componentName = config.data._component;\r\n const componentConnector = ConnectorService.getComponentConnector();\r\n\r\n const component = await componentConnector.requester(AccessCandidate.agent(agent.id)).get(componentName);\r\n\r\n if (!component) {\r\n logger.debug(`Component ${componentName} not found`);\r\n return { _error: `Component ${componentName} not found`, _debug: logger.output };\r\n }\r\n\r\n return await component.process(input, config, agent);\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport { validateCharacterSet } from '@sre/utils/validation.utils';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { isUrl, detectURLSourceType } from '../utils';\r\nimport { SmythFS } from '@sre/IO/Storage.service/SmythFS.class';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\n\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nexport class DataSourceIndexer extends Component {\r\n private MAX_ALLOWED_URLS_PER_INPUT = 20;\r\n protected configSchema = Joi.object({\r\n namespace: Joi.string().max(50).allow(''),\r\n id: Joi.string().custom(validateCharacterSet, 'id custom validation').allow('').label('source identifier'),\r\n name: Joi.string().max(50).allow('').label('label'),\r\n metadata: Joi.string().allow(null).allow('').max(10000).label('metadata'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const teamId = agent.teamId;\r\n const agentId = agent.id;\r\n let debugOutput = agent.agentRuntime?.debug ? '== Source Indexer Log ==\\n' : null;\r\n\r\n try {\r\n const _config = {\r\n ...config.data,\r\n name: TemplateString(config.data.name).parse(input).result,\r\n id: TemplateString(config.data.id).parse(input).result,\r\n metadata: TemplateString(config.data.metadata).parse(input).result,\r\n };\r\n\r\n const outputs = {};\r\n for (let con of config.outputs) {\r\n if (con.default) continue;\r\n outputs[con.name] = con?.description ? `<${con?.description}>` : '';\r\n }\r\n\r\n const namespaceId = _config.namespace.split('_').slice(1).join('_') || _config.namespace;\r\n debugOutput += `[Selected namespace id] \\n${namespaceId}\\n\\n`;\r\n\r\n const vectorDbConnector =\r\n // (await vectorDBHelper.getTeamConnector(teamId)) ||\r\n ConnectorService.getVectorDBConnector();\r\n const nsExists = await vectorDbConnector.requester(AccessCandidate.team(teamId)).namespaceExists(namespaceId);\r\n\r\n if (!nsExists) {\r\n const newNs = await vectorDbConnector.requester(AccessCandidate.team(teamId)).createNamespace(namespaceId);\r\n debugOutput += `[Created namespace] \\n${newNs}\\n\\n`;\r\n }\r\n\r\n const inputSchema = this.validateInput(input);\r\n if (inputSchema.error) {\r\n throw new Error(`Input validation error: ${inputSchema.error}\\n EXITING...`);\r\n }\r\n\r\n const providedId = _config.id;\r\n // const isAutoId = _config.isAutoId;\r\n const idRegex = /^[a-zA-Z0-9\\-\\_\\.]+$/;\r\n\r\n if (!providedId) {\r\n // Assign a new ID if it's set to auto-generate or not provided\r\n // _config.id = crypto.randomBytes(16).toString('hex');\r\n throw new Error(`Id is required`);\r\n } else if (!idRegex.test(providedId)) {\r\n // Validate the provided ID if it's not auto-generated\r\n throw new Error(`Invalid id. Accepted characters: 'a-z', 'A-Z', '0-9', '-', '_', '.'`);\r\n }\r\n\r\n // check if the datasource already exists with the same id\r\n // await this.checkForRecordDuplicate(dsId, token);\r\n\r\n let indexRes: any = null;\r\n let parsedUrlArray: string[] | null = null;\r\n\r\n //! DISABLE URL ARRAY PARSING FOR NOW UNTIL WE HAVE A GOOD WAY TO HANDLE BULK INDEXING\r\n // if ((parsedUrlArray = parseUrlArray(inputSchema.value.Source))) {\r\n // debugOutput += `STEP: Parsing input as url array\\n\\n`;\r\n // if (parsedUrlArray.length > this.MAX_ALLOWED_URLS_PER_INPUT) {\r\n // throw new Error(`Too many urls in input. Max allowed: ${this.MAX_ALLOWED_URLS_PER_INPUT}`);\r\n // }\r\n\r\n // for (let url of parsedUrlArray) {\r\n // indexRes = await this.addDSFromUrl({\r\n // teamId,\r\n // namespaceId,\r\n // dsId, // WILL OVERRIDE EACH OTHER\r\n // type: detectURLSourceType(url),\r\n // url,\r\n // name: _config.name || 'Untitled',\r\n // });\r\n\r\n // debugOutput += `STEP: Created datasource for url: ${url}\\n\\n`;\r\n // }\r\n // } else\r\n\r\n const dsId = DataSourceIndexer.genDsId(providedId, teamId, namespaceId);\r\n\r\n if (isUrl(inputSchema.value.Source)) {\r\n debugOutput += `STEP: Parsing input as url\\n\\n`;\r\n throw new Error('URLs are not supported yet');\r\n // indexRes = await this.addDSFromUrl({\r\n // teamId,\r\n // namespaceId,\r\n // dsId,\r\n // type: detectURLSourceType(inputSchema.value.Source),\r\n // url: inputSchema.value.Source,\r\n // name: _config.name || 'Untitled',\r\n // metadata: _config.metadata || null,\r\n // });\r\n } else {\r\n debugOutput += `STEP: Parsing input as text\\n\\n`;\r\n indexRes = await this.addDSFromText({\r\n teamId,\r\n namespaceId: namespaceId,\r\n text: inputSchema.value.Source,\r\n name: _config.name || 'Untitled',\r\n metadata: _config.metadata || null,\r\n sourceId: dsId,\r\n });\r\n }\r\n\r\n debugOutput += `Created datasource successfully\\n\\n`;\r\n\r\n return {\r\n _debug: debugOutput,\r\n Success: {\r\n result: indexRes?.data?.dataSource || true,\r\n id: _config.id,\r\n },\r\n // _error,\r\n };\r\n } catch (err: any) {\r\n debugOutput += `Error: ${err?.message || \"Couldn't index data source\"}\\n\\n`;\r\n return {\r\n _debug: debugOutput,\r\n _error: err?.message || \"Couldn't index data source\",\r\n };\r\n }\r\n }\r\n\r\n validateInput(input: any) {\r\n return Joi.object({\r\n Source: Joi.any().required(),\r\n })\r\n .unknown(true)\r\n .validate(input);\r\n }\r\n\r\n private async addDSFromText({ teamId, sourceId, namespaceId, text, name, metadata }) {\r\n let vectorDbConnector = ConnectorService.getVectorDBConnector();\r\n // const isOnCustomStorage = await vectorDBHelper.isNamespaceOnCustomStorage(teamId, namespaceId);\r\n // if (isOnCustomStorage) {\r\n // const customTeamConnector = await vectorDBHelper.getTeamConnector(teamId);\r\n // if (customTeamConnector) {\r\n // vectorDbConnector = customTeamConnector;\r\n // }\r\n // }\r\n const id = await vectorDbConnector.requester(AccessCandidate.team(teamId)).createDatasource(namespaceId, {\r\n text,\r\n metadata,\r\n id: sourceId,\r\n label: name,\r\n });\r\n\r\n return id;\r\n }\r\n\r\n public static genDsId(providedId: string, teamId: string, namespaceId: string) {\r\n return `${teamId}::${namespaceId}::${providedId}`;\r\n }\r\n\r\n private async addDSFromUrl({ teamId, namespaceId, dsId, type, url, name, metadata }) {\r\n throw new Error('URLs are not supported yet');\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport Joi from 'joi';\r\nimport { validateCharacterSet } from '../utils';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nimport { DataSourceIndexer } from './DataSourceIndexer.class';\r\n\r\nexport class DataSourceCleaner extends Component {\r\n protected configSchema = Joi.object({\r\n namespaceId: Joi.string().max(50).allow('').label('namespace'),\r\n id: Joi.string().custom(validateCharacterSet, 'custom validation characterSet').allow('').label('source identifier'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const teamId = agent.teamId;\r\n const agentId = agent.id;\r\n let debugOutput = agent.agentRuntime?.debug ? '== Source Indexer Log ==\\n' : null;\r\n\r\n try {\r\n const configSchema = this.validateConfigData(config.data);\r\n if (configSchema.error) {\r\n throw new Error(`Config data validation error: ${configSchema.error}\\n EXITING...`);\r\n }\r\n\r\n const outputs = {};\r\n for (let con of config.outputs) {\r\n if (con.default) continue;\r\n outputs[con.name] = con?.description ? `<${con?.description}>` : '';\r\n }\r\n\r\n const inputSchema = this.validateInput(input);\r\n if (inputSchema.error) {\r\n throw new Error(`Input validation error: ${inputSchema.error}\\n EXITING...`);\r\n }\r\n\r\n const namespaceId = configSchema.value.namespaceId.split('_')?.slice(1).join('_') || configSchema.value.namespaceId;\r\n\r\n let vectorDbConnector = ConnectorService.getVectorDBConnector();\r\n\r\n let existingnamespace = await vectorDbConnector.requester(AccessCandidate.team(teamId)).namespaceExists(namespaceId);\r\n if (!existingnamespace) {\r\n throw new Error(`Namespace ${namespaceId} does not exist`);\r\n }\r\n\r\n const providedId = TemplateString(config.data.id).parse(input).result;\r\n const idRegex = /^[a-zA-Z0-9\\-\\_\\.]+$/;\r\n if (!idRegex.test(providedId)) {\r\n throw new Error(`Invalid id. Accepted characters: 'a-z', 'A-Z', '0-9', '-', '_', '.'`);\r\n }\r\n debugOutput += `Searching for data source with id: ${providedId}\\n`;\r\n\r\n const dsId = DataSourceIndexer.genDsId(providedId, teamId, namespaceId);\r\n\r\n await vectorDbConnector.requester(AccessCandidate.team(teamId)).deleteDatasource(namespaceId, dsId);\r\n\r\n debugOutput += `Deleted data source with id: ${providedId}\\n`;\r\n\r\n return {\r\n _debug: debugOutput,\r\n Success: true,\r\n // _error,\r\n };\r\n } catch (err: any) {\r\n debugOutput += `Failed to delete data source: \\n Error: ${err?.message}\\n`;\r\n\r\n return {\r\n _debug: debugOutput,\r\n _error: err?.message || \"Couldn't delete data source\",\r\n };\r\n }\r\n }\r\n\r\n validateInput(input: any) {\r\n return Joi.object({}).unknown(true).validate(input);\r\n }\r\n\r\n validateConfigData(data: any) {\r\n return Joi.object({\r\n namespaceId: Joi.string().required(),\r\n id: Joi.string().optional().allow('').allow(null),\r\n })\r\n .unknown(true)\r\n .validate(data);\r\n }\r\n}\r\n","import Joi from 'joi';\r\nimport { validateInteger } from '../utils';\r\nimport { jsonrepair } from 'jsonrepair';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\n// Note: LLMHelper renamed to LLMInference\r\nclass LLMInference {\r\n static async getInstance(model: string) {\r\n throw new Error('Method not implemented.');\r\n }\r\n}\r\n\r\nexport class DataSourceLookup extends Component {\r\n protected configSchema = Joi.object({\r\n topK: Joi.string()\r\n .custom(validateInteger({ min: 0 }), 'custom range validation')\r\n .label('Result Count'),\r\n model: Joi.string().valid('gpt-4o-mini', 'gpt-4', 'gpt-3.5-turbo', 'gpt-4', 'gpt-3.5-turbo-16k').optional(),\r\n prompt: Joi.string().max(30000).allow('').label('Prompt').optional(),\r\n postprocess: Joi.boolean().strict().optional(),\r\n includeMetadata: Joi.boolean().strict().optional(),\r\n namespace: Joi.string().allow('').max(80).messages({\r\n // Need to reserve 30 characters for the prefixed unique id\r\n 'string.max': `The length of the 'namespace' name must be 50 characters or fewer.`,\r\n }),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const componentId = config.id;\r\n const component = agent.components[componentId];\r\n const teamId = agent.teamId;\r\n let debugOutput = agent.agentRuntime?.debug ? '== Data Source Lookup Log ==\\n' : null;\r\n\r\n const outputs = {};\r\n for (let con of config.outputs) {\r\n if (con.default) continue;\r\n outputs[con.name] = '';\r\n }\r\n\r\n const namespace = config.data.namespace.split('_').slice(1).join('_') || config.data.namespace;\r\n const model = config.data?.model || 'gpt-4o-mini';\r\n const prompt = config.data?.prompt?.trim?.() || '';\r\n const postprocess = config.data?.postprocess || false;\r\n const includeMetadata = config.data?.includeMetadata || false;\r\n\r\n const _input = typeof input.Query === 'string' ? input.Query : JSON.stringify(input.Query);\r\n\r\n const topK = Math.max(config.data?.topK || 50, 50);\r\n\r\n let vectorDbConnector = ConnectorService.getVectorDBConnector();\r\n let existingNs = await vectorDbConnector.requester(AccessCandidate.team(teamId)).namespaceExists(namespace);\r\n\r\n if (!existingNs) {\r\n throw new Error(`Namespace ${namespace} does not exist`);\r\n }\r\n\r\n let results: string[] | { content: string; metadata: any }[];\r\n let _error;\r\n try {\r\n const response = await vectorDbConnector\r\n .requester(AccessCandidate.team(teamId))\r\n .search(namespace, _input, { topK, includeMetadata: true });\r\n results = response.slice(0, config.data.topK).map((result) => ({\r\n content: result.metadata?.text,\r\n metadata: result.metadata,\r\n }));\r\n\r\n if (includeMetadata) {\r\n // only show user-level metadata\r\n results = results.map((result) => ({\r\n content: result.content,\r\n //* legacy user-specific metadata key [result.metadata?.metadata]),\r\n metadata: this.parseMetadata(result.metadata || result.metadata?.metadata),\r\n }));\r\n } else {\r\n results = results.map((result) => result.content);\r\n }\r\n debugOutput += `[Results] \\nLoaded ${results.length} results from namespace: ${namespace}\\n\\n`;\r\n } catch (error) {\r\n _error = error.toString();\r\n }\r\n\r\n //is there a post processing LLM?\r\n\r\n //TODO : better handling of context window exceeding max length\r\n if (postprocess && prompt) {\r\n const promises: any = [];\r\n for (let result of results) {\r\n const _prompt = TemplateString(prompt.replace(/{{result}}/g, JSON.stringify(result))).parse(input).result;\r\n const llmInference = await LLMInference.getInstance(model);\r\n // const req = llmInference.prompt({ query: _prompt, params: { ...config, agentId: agent.id } }).catch((error) => ({ error: error }));\r\n // promises.push(req);\r\n }\r\n results = await Promise.all(promises);\r\n for (let i = 0; i < results.length; i++) {\r\n if (typeof results[i] === 'string') {\r\n // results[i] = parseJson(results[i]);\r\n results[i] = JSONContent(results[i] as string).tryParse();\r\n }\r\n }\r\n }\r\n\r\n const totalLength = JSON.stringify(results).length;\r\n debugOutput += `[Total Length] \\n${totalLength}\\n\\n`;\r\n return {\r\n Results: results,\r\n _error,\r\n _debug: debugOutput,\r\n //_debug: `Query: ${_input}. \\nTotal Length = ${totalLength} \\nResults: ${JSON.stringify(results)}`,\r\n };\r\n }\r\n\r\n // private async checkIfTeamOwnsNamespace(teamId: string, namespaceId: string, token: string) {\r\n // try {\r\n // const res = await SmythAPIHelper.fromAuth({ token }).mwSysAPI.get(`/vectors/namespaces/${namespaceId}`);\r\n // if (res.data?.namespace?.teamId !== teamId) {\r\n // throw new Error(`Namespace does not exist`);\r\n // }\r\n // return true;\r\n // } catch (err) {\r\n // throw new Error(`Namespace does not exist`);\r\n // }\r\n // }\r\n\r\n private parseMetadata(metadata: any) {\r\n try {\r\n return JSON.parse(jsonrepair(metadata));\r\n } catch (err) {\r\n return metadata;\r\n }\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\n\r\nexport class FEncDec extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const _error = undefined;\r\n\r\n const data = input.Data;\r\n const action = config.data.action || 'Encode';\r\n const encoding = config.data.encoding;\r\n logger.debug(`${encoding} ${action} data`);\r\n\r\n const Output = action == 'Encode' ? Buffer.from(data).toString(encoding) : Buffer.from(data, encoding).toString('utf8');\r\n\r\n return { Output, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error processing data \\n${_error}\\n`);\r\n return { hash: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport crypto from 'crypto';\r\n\r\nexport class FHash extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const _error = undefined;\r\n\r\n const data = input.Data;\r\n const algorithm = config.data.algorithm;\r\n const encoding = config.data.encoding;\r\n logger.debug(` Generating hash using ${algorithm} algorithm and ${encoding} encoding`);\r\n\r\n const hashAlgo = crypto.createHash(algorithm);\r\n hashAlgo.update(data);\r\n\r\n const Hash = hashAlgo.digest(encoding);\r\n logger.debug(` Generated hash: ${Hash}`);\r\n return { Hash, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error generating hash \\n${_error}\\n`);\r\n return { hash: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport _config from '@sre/config';\r\nimport { S3Storage } from '@sre/IO/Storage.service/connectors/S3Storage.class';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { SmythFS } from '@sre/IO/Storage.service/SmythFS.class';\r\n\r\nexport class FileStore extends Component {\r\n protected configSchema = Joi.object({\r\n name: Joi.string().max(1000).allow('').label('Name'),\r\n ttl: Joi.number().integer().label('TTL'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n logger.debug(`=== File Store Log ===`);\r\n let Output: any = {};\r\n let _error = undefined;\r\n let data = input.Data;\r\n const accessCandidate = AccessCandidate.agent(agent.id);\r\n const binaryData = await BinaryInput.from(data, null, null, accessCandidate);\r\n const fileData = await binaryData.getJsonData(accessCandidate);\r\n const buffer = await binaryData.getBuffer();\r\n const customFileName = TemplateString(config.data.name).parse(input).result;\r\n const metadata = {\r\n ContentType: fileData.mimetype,\r\n };\r\n const ttl = config.data.ttl || 86400;\r\n const extension = fileData.url?.split('.').pop();\r\n const s3StorageConnector = ConnectorService.getStorageConnector('S3') as S3Storage;\r\n const fileName = this.getFileName(customFileName, extension);\r\n try {\r\n const s3Key = `teams/${agent.teamId}/components_data/${fileName}`;\r\n\r\n await s3StorageConnector.requester(AccessCandidate.agent(agent.teamId)).write(s3Key, buffer, null, metadata);\r\n await s3StorageConnector.requester(AccessCandidate.agent(agent.teamId)).expire(s3Key, +ttl);\r\n const smythFSUrl = `smythfs://${agent.teamId}.team/components_data/${fileName}`;\r\n const url = await SmythFS.Instance.genResourceUrl(smythFSUrl, AccessCandidate.agent(agent.teamId));\r\n Output = {\r\n Url: url,\r\n };\r\n } catch (error: any) {\r\n logger.error(`Error saving file \\n${error}\\n`);\r\n _error = error?.response?.data || error?.message || error.toString();\r\n Output = undefined; //prevents running next component if the code execution failed\r\n }\r\n\r\n return { ...Output, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error saving file \\n${_error}\\n`);\r\n return { Output: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n\r\n getExtension(mimeType: string) {\r\n const extension = mimeType.split('/')[1];\r\n return extension;\r\n }\r\n\r\n getFileName(customName: string, extension: string) {\r\n const uniqueId = (() => btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(9)))).replace(/[+/=]/g, ''))();\r\n return `${uniqueId}${customName ? `.${customName}` : ''}.${extension}`;\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\n\r\nexport class ForEach extends Component {\r\n protected configSchema = null;\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n let Loop = {};\r\n let Result;\r\n let _temp_result;\r\n let _error = null;\r\n let _in_progress = true;\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const inputObject = input.Input;\r\n let inputArray;\r\n\r\n //Try to parse multiple arrays formats since forEach always expects and array\r\n if (Array.isArray(inputObject)) inputArray = inputObject;\r\n else {\r\n if (typeof inputObject === 'string') {\r\n inputArray = inputObject.trim().startsWith('[') ? JSONContent(inputObject).tryParse() : inputObject.split(',');\r\n } else {\r\n inputArray = [inputObject];\r\n }\r\n }\r\n\r\n if (!Array.isArray(inputArray) && typeof inputArray === 'object')\r\n //if json object, use the values\r\n inputArray = Object.values(inputArray);\r\n\r\n const runtimeData = agent.agentRuntime.getRuntimeData(config.id);\r\n const _ForEachData = runtimeData._LoopData || { parentId: config.id, loopIndex: 0, loopLength: inputArray.length };\r\n\r\n logger.debug(`Loop: ${_ForEachData.loopIndex} / ${_ForEachData.loopLength}`);\r\n delete _ForEachData.branches; //reset branches (the number of branches is calculated in CallComponent@Agent.class.ts )\r\n\r\n if (_ForEachData.result) {\r\n _temp_result = _ForEachData.result;\r\n logger.debug(` => Loop Result : ${JSON.stringify(Loop, null, 2)}`);\r\n logger.debug(`---------------------------------------------------`);\r\n }\r\n\r\n Loop = inputArray[_ForEachData.loopIndex];\r\n\r\n logger.debug(` => Loop Data : ${JSON.stringify(Loop, null, 2)}`);\r\n\r\n _in_progress = Loop !== undefined;\r\n if (_in_progress) {\r\n _ForEachData.loopIndex++;\r\n }\r\n _ForEachData._in_progress = _in_progress;\r\n\r\n agent.agentRuntime.updateRuntimeData(config.id, { _LoopData: _ForEachData });\r\n } catch (error: any) {\r\n _error = error;\r\n logger.error(error);\r\n }\r\n if (!_in_progress) {\r\n Result = _temp_result || [];\r\n\r\n switch (config?.data?.format) {\r\n case 'minimal':\r\n Result = Result.map((item) => cleanupResult(item.result));\r\n break;\r\n case 'results-array':\r\n Result = Result.map((item) => Object.values(cleanupResult(item.result))).flat(Infinity);\r\n break;\r\n }\r\n }\r\n\r\n return { Loop, Result, _temp_result, _error, _in_progress, _debug: logger.output };\r\n }\r\n async postProcess(output, config, agent: Agent): Promise<any> {\r\n output = await super.postProcess(output, config, agent);\r\n if (output?.result) {\r\n delete output.result._temp_result;\r\n delete output.result._in_progress;\r\n delete output.result.Loop;\r\n }\r\n return output;\r\n }\r\n}\r\nfunction cleanupResult(result) {\r\n if (typeof result !== 'object') return result;\r\n if (result._debug) delete result._debug;\r\n if (result._error) delete result._error;\r\n if (result._temp_result) delete result._temp_result;\r\n if (result._in_progress) delete result._in_progress;\r\n return result;\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport crypto from 'crypto';\r\nimport querystring from 'querystring';\r\n\r\nexport class FSign extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const _error = undefined;\r\n const teamId = agent ? agent.teamId : null;\r\n\r\n let data = input.Data;\r\n //if (typeof data === 'object') data = JSON.stringify(data);\r\n let signingKey = input.Key || config.data.key;\r\n // signingKey = parseTemplate(signingKey, input, { processUnmatched: false });\r\n // signingKey = await parseKey(signingKey, teamId);\r\n signingKey = await TemplateString(signingKey).parse(input).parseTeamKeysAsync(teamId).asyncResult;\r\n\r\n const signMethod = config.data.signMethod || 'HMAC';\r\n const dataTransform = config.data.dataTransform || 'None';\r\n const hashType = config.data.hashType || 'md5';\r\n const RSA_padding = config.data.RSA_padding;\r\n const RSA_saltLength = config.data.RSA_saltLength;\r\n const encoding = config.data.encoding || 'hex';\r\n\r\n if (typeof data != 'string') {\r\n switch (dataTransform) {\r\n case 'Stringify':\r\n data = JSON.stringify(data);\r\n break;\r\n case 'Querystring':\r\n data = querystring.stringify(data);\r\n break;\r\n }\r\n }\r\n logger.debug(' Data to sign = ', data);\r\n logger.debug(` Signing data using ${signMethod} algorithm and ${encoding} encoding`);\r\n const Signature = this.signData(data, signingKey, signMethod, encoding, { hashType, RSA_padding, RSA_saltLength });\r\n\r\n logger.debug(` Signature generated: ${Signature}`);\r\n return { Signature, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error generating hash \\n${_error}\\n`);\r\n return { hash: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n\r\n private signData(data, key, signMethod, encoding = 'hex', options: any = {}) {\r\n // Determine if the algorithm is for HMAC or RSA/DSA/ECDSA\r\n switch (signMethod) {\r\n case 'RSA':\r\n const algo = `${signMethod}-${options.hashType || 'md5'}`.toUpperCase();\r\n const sign = crypto.createSign(algo);\r\n sign.update(data);\r\n\r\n const sign_options = {\r\n key,\r\n padding: options.RSA_padding ? crypto.constants[options.RSA_padding] : undefined,\r\n saltLength: options.RSA_saltLength ? crypto.constants[options.RSA_saltLength] : undefined,\r\n };\r\n // For RSA/DSA/ECDSA, options may include padding and saltLength\r\n return sign.sign(sign_options, encoding.toLowerCase() as crypto.BinaryToTextEncoding);\r\n\r\n case 'HMAC':\r\n const hmac = crypto.createHmac(options.hashType, key);\r\n hmac.update(data);\r\n return hmac.digest(encoding as crypto.BinaryToTextEncoding);\r\n }\r\n\r\n return null;\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\n\r\nexport class FSleep extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const _error = undefined;\r\n const delay = parseInt(config.data.delay || 1);\r\n const Output = input.Input;\r\n logger.debug(`Sleeping for ${delay} seconds`);\r\n await new Promise((resolve) => setTimeout(resolve, delay * 1000));\r\n return { Output, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error processing data \\n${_error}\\n`);\r\n return { hash: undefined, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n }\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\n\r\nexport class FTimestamp extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n const _error = undefined;\r\n const format = config.data.format; //TODO set timestamp format\r\n const Timestamp = Date.now();\r\n logger.debug(`Timestamp : ${Timestamp}`);\r\n\r\n return { Timestamp, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n } catch (err: any) {\r\n const _error = err?.response?.data || err?.message || err.toString();\r\n logger.error(` Error processing data \\n${_error}\\n`);\r\n return { hash: undefined, _error, _debug: logger.output, _debug_time: logger.elapsedTime };\r\n }\r\n }\r\n}\r\n","import Joi from 'joi';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';\r\nimport { getMimeType } from '@sre/utils/data.utils';\r\nimport { Component } from './Component.class';\r\nimport { formatDataForDebug } from '@sre/utils/data.utils';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\n//TODO : better handling of context window exceeding max length\r\n\r\nexport class GenAILLM extends Component {\r\n protected schema = {\r\n name: 'GenAILLM',\r\n description: 'Use this component to generate a responses from an LLM',\r\n settings: {\r\n model: {\r\n type: 'string',\r\n max: 200,\r\n required: true,\r\n },\r\n prompt: {\r\n type: 'string',\r\n max: 8_000_000,\r\n label: 'Prompt',\r\n },\r\n temperature: {\r\n type: 'number',\r\n min: 0,\r\n max: 5,\r\n label: 'Temperature',\r\n },\r\n maxTokens: {\r\n type: 'number',\r\n min: 1,\r\n label: 'Maximum Tokens',\r\n },\r\n maxThinkingTokens: {\r\n type: 'number',\r\n min: 1,\r\n label: 'Maximum Thinking Tokens',\r\n },\r\n stopSequences: {\r\n type: 'string',\r\n max: 400,\r\n label: 'Stop Sequences',\r\n allowEmpty: true,\r\n },\r\n topP: {\r\n type: 'number',\r\n min: 0,\r\n max: 1,\r\n label: 'Top P',\r\n },\r\n topK: {\r\n type: 'number',\r\n min: 0,\r\n max: 500,\r\n label: 'Top K',\r\n },\r\n frequencyPenalty: {\r\n type: 'number',\r\n min: 0,\r\n max: 2,\r\n label: 'Frequency Penalty',\r\n },\r\n presencePenalty: {\r\n type: 'number',\r\n min: 0,\r\n max: 2,\r\n label: 'Presence Penalty',\r\n },\r\n responseFormat: {\r\n type: 'string',\r\n valid: ['json', 'text'],\r\n label: 'Response Format',\r\n },\r\n passthrough: {\r\n type: 'boolean',\r\n description: 'If true, the LLM response will be returned as is by the agent',\r\n label: 'Passthrough',\r\n },\r\n useSystemPrompt: {\r\n type: 'boolean',\r\n description: 'If true, the component will use parent agent system prompt',\r\n label: 'Use System Prompt',\r\n },\r\n useContextWindow: {\r\n type: 'boolean',\r\n description: 'If true, the component will use parent agent context window',\r\n label: 'Use Context Window',\r\n },\r\n maxContextWindowLength: {\r\n type: 'number',\r\n min: 0,\r\n description: 'The maximum number of messages to use from this component context window (if useContextWindow is true)',\r\n label: 'Maximum Context Window Length',\r\n },\r\n },\r\n inputs: {\r\n Input: {\r\n type: 'Any',\r\n description: 'An input that you can pass to the LLM',\r\n },\r\n Attachment: {\r\n type: 'Binary',\r\n description: 'An attachment that you can pass to the LLM',\r\n optional: true,\r\n },\r\n },\r\n outputs: {\r\n Reply: {\r\n default: true,\r\n },\r\n },\r\n };\r\n protected configSchema = Joi.object({\r\n model: Joi.string().max(200).required(),\r\n prompt: Joi.string().required().max(8_000_000).label('Prompt'), // 2M tokens is around 8M characters\r\n temperature: Joi.number().min(0).max(5).label('Temperature'), // max temperature is 2 for OpenAI and togetherAI but 5 for cohere\r\n maxTokens: Joi.number().min(1).label('Maximum Tokens'),\r\n stopSequences: Joi.string().allow('').max(400).label('Stop Sequences'),\r\n topP: Joi.number().min(0).max(1).label('Top P'),\r\n topK: Joi.number().min(0).max(500).label('Top K'), // max top_k is 100 for togetherAI but 500 for cohere\r\n frequencyPenalty: Joi.number().min(0).max(2).label('Frequency Penalty'),\r\n presencePenalty: Joi.number().min(0).max(2).label('Presence Penalty'),\r\n responseFormat: Joi.string().valid('json', 'text').optional().label('Response Format'),\r\n passthrough: Joi.boolean().optional().label('Passthrough'),\r\n useSystemPrompt: Joi.boolean().optional().label('Use System Prompt'),\r\n useContextWindow: Joi.boolean().optional().label('Use Context Window'),\r\n maxContextWindowLength: Joi.number().optional().min(0).label('Maximum Context Window Length'),\r\n\r\n // #region Search\r\n useWebSearch: Joi.boolean().optional().label('Use Search'),\r\n webSearchContextSize: Joi.string().valid('high', 'medium', 'low').optional().label('Search Content Size'),\r\n webSearchCity: Joi.string().max(100).optional().allow('').label('Search City'),\r\n webSearchCountry: Joi.string().max(100).optional().allow('').label('Search Country'),\r\n webSearchRegion: Joi.string().max(100).optional().allow('').label('Search Region'),\r\n webSearchTimezone: Joi.string().max(100).optional().allow('').label('Search Timezone'),\r\n // #endregion\r\n\r\n useReasoning: Joi.boolean().optional().label('Use Reasoning'),\r\n maxThinkingTokens: Joi.number().min(1).label('Maximum Thinking Tokens'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n //let debugLog = agent.agentRuntime?.debug ? [] : undefined;\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n try {\r\n logger.debug(`=== GenAILLM Log ===`);\r\n let teamId = agent?.teamId;\r\n\r\n const passThrough: boolean = config.data.passthrough || false;\r\n const useContextWindow: boolean = config.data.useContextWindow || false;\r\n const useSystemPrompt: boolean = config.data.useSystemPrompt || false;\r\n const useWebSearch: boolean = config.data.useWebSearch || false;\r\n const maxTokens: number = parseInt(config.data.maxTokens) || 1024;\r\n const maxContextWindowLength: number = parseInt(config.data.maxContextWindowLength) || 1024;\r\n const model: string = config.data.model || 'echo';\r\n const llmInference: LLMInference = await LLMInference.getInstance(model, AccessCandidate.agent(agent.id));\r\n\r\n // if the llm is undefined, then it means we removed the model from our system\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n //const team = AccessCandidate.team(teamId);\r\n //const llmRegistry = isStandardLLM ? LLMRegistry : await CustomLLMRegistry.getInstance(team);\r\n const modelId = await agent.modelsProvider.getModelId(model);\r\n\r\n logger.debug(` Model : ${modelId || model}`);\r\n\r\n let prompt: any = TemplateString(config.data.prompt).parse(input).result;\r\n\r\n let files: any[] = parseFiles(input, config);\r\n let isMultimodalRequest = false;\r\n const provider = await agent.modelsProvider.getProvider(model);\r\n const isEcho = provider === 'Echo';\r\n\r\n // Ignore files for Echo model\r\n if (files?.length > 0 && !isEcho) {\r\n // TODO: simplify the valid files checking logic\r\n const supportedFileTypes = SUPPORTED_MIME_TYPES_MAP?.[provider] || {};\r\n const modelInfo = await agent.modelsProvider.getModelInfo(model);\r\n const features = modelInfo?.features || [];\r\n const fileTypes = new Set(); // Set to avoid duplicates\r\n\r\n const validFiles = await Promise.all(\r\n files.map(async (file) => {\r\n const mimeType = file?.mimetype || (await getMimeType(file));\r\n const [requestFeature = ''] =\r\n Object.entries(supportedFileTypes).find(([key, value]) => (value as string[]).includes(mimeType)) || [];\r\n\r\n if (mimeType) {\r\n fileTypes.add(mimeType);\r\n }\r\n\r\n return features?.includes(requestFeature) ? file : null;\r\n })\r\n );\r\n\r\n files = validFiles.filter(Boolean);\r\n\r\n if (files.length === 0) {\r\n return {\r\n _error: `Model does not support ${fileTypes?.size > 0 ? Array.from(fileTypes).join(', ') : 'File(s)'}`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n isMultimodalRequest = true;\r\n }\r\n\r\n logger.debug(` Prompt\\n`, prompt, '\\n');\r\n\r\n if (!isEcho) {\r\n logger.debug(' Files\\n', await Promise.all(files.map((file) => formatDataForDebug(file))));\r\n }\r\n\r\n // default to json response format\r\n config.data.responseFormat = config.data?.responseFormat || 'json';\r\n\r\n // request to LLM\r\n let response: any;\r\n\r\n const _prompt = llmInference.connector.enhancePrompt(prompt, config);\r\n let messages = [];\r\n\r\n let systemPrompt = '';\r\n if (useSystemPrompt) {\r\n //first we try to grab the system prompt from llmCache (in case of a ConversationHelper implementing dynamic system prompt)\r\n const cachedPrompt = await agent.agentRuntime.llmCache.get('systemPrompt', 'text');\r\n //if not found, we can read the system prompt from agent data.\r\n systemPrompt = cachedPrompt || agent.data?.behavior || '';\r\n\r\n if (systemPrompt) {\r\n logger.debug(' Using Agent System Prompt\\n', systemPrompt);\r\n }\r\n if (systemPrompt) {\r\n messages = [{ role: 'system', content: systemPrompt }];\r\n }\r\n }\r\n\r\n if (useContextWindow) {\r\n const cachedMessages = await agent.agentRuntime.llmCache.get('messages', 'json');\r\n try {\r\n const messagesJSON = typeof cachedMessages === 'string' ? JSON.parse(cachedMessages) : cachedMessages;\r\n //const contextWindow = messagesJSON.filter((message) => message.role !== 'user');\r\n\r\n const convMessages = await llmInference.getContextWindow(systemPrompt, messagesJSON, maxContextWindowLength, maxTokens);\r\n\r\n if (convMessages.length > 0) {\r\n logger.debug(` Using Agent Context Window : ${convMessages.length - 1} messages will be used`);\r\n }\r\n\r\n messages = [...convMessages];\r\n //messages.push(...contextWindowJSON);\r\n } catch (error) {\r\n logger.warn('Error on parsing context window: ', error);\r\n console.warn(cachedMessages);\r\n }\r\n }\r\n\r\n if (messages[messages.length - 1]?.role == 'user') {\r\n messages[messages.length - 1].content = _prompt;\r\n } else {\r\n messages.push({ role: 'user', content: _prompt });\r\n }\r\n let finishReason = 'stop';\r\n const contentPromise = new Promise(async (resolve, reject) => {\r\n let _content = '';\r\n let eventEmitter;\r\n\r\n eventEmitter = await llmInference\r\n .promptStream({\r\n contextWindow: messages,\r\n files,\r\n params: {\r\n ...config.data,\r\n agentId: agent.id,\r\n },\r\n })\r\n .catch((error) => {\r\n console.error('Error on promptStream: ', error);\r\n reject(error);\r\n });\r\n\r\n eventEmitter.on('content', (content) => {\r\n if (passThrough) {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ content });\r\n }\r\n agent.sse.send('llm/passthrough/content', content.replace(/\\n/g, '\\\\n'));\r\n }\r\n _content += content;\r\n });\r\n\r\n eventEmitter.on('thinking', (thinking) => {\r\n if (passThrough) {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ thinking });\r\n }\r\n agent.sse.send('llm/passthrough/thinking', thinking.replace(/\\n/g, '\\\\n'));\r\n }\r\n });\r\n eventEmitter.on('end', () => {\r\n if (passThrough) {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ content: '\\n' });\r\n }\r\n agent.sse.send('llm/passthrough/content', '\\\\n');\r\n }\r\n resolve(_content);\r\n });\r\n eventEmitter.on('interrupted', (reason) => {\r\n finishReason = reason || 'stop';\r\n });\r\n\r\n eventEmitter.on('error', (error) => {\r\n reject(error);\r\n });\r\n });\r\n response = await contentPromise.catch((error) => {\r\n return { error: error.message || error };\r\n });\r\n // // If the model stopped before completing the response, this is usually due to output token limit reached.\r\n if (finishReason !== 'stop') {\r\n return {\r\n Reply: response,\r\n _error: 'The model stopped before completing the response, this is usually due to output token limit reached.',\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n // in case we have the response but it's empty string, undefined or null\r\n if (!response) {\r\n return { _error: ' LLM Error = Empty Response!', _debug: logger.output };\r\n }\r\n\r\n if (response?.error) {\r\n const error = response?.error + ' ' + (response?.details || '');\r\n logger.error(` LLM Error=`, error);\r\n\r\n return { Output: response?.data, _error: error, _debug: logger.output };\r\n }\r\n\r\n const Reply = llmInference.connector.postProcess(response);\r\n if (Reply.error) {\r\n logger.error(` LLM Error=`, Reply.error);\r\n return { _error: Reply.error, _debug: logger.output };\r\n }\r\n\r\n logger.debug(' Reply \\n', Reply);\r\n\r\n const result = { Reply };\r\n\r\n result['_debug'] = logger.output;\r\n\r\n return result;\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n }\r\n }\r\n}\r\n\r\nfunction parseFiles(input: any, config: any) {\r\n const mediaTypes = ['Image', 'Audio', 'Video', 'Binary'];\r\n\r\n // Parse media inputs from config\r\n const inputFiles =\r\n config.inputs\r\n ?.filter((_input) => mediaTypes.includes(_input.type))\r\n ?.flatMap((_input) => {\r\n const value = input[_input.name];\r\n\r\n if (Array.isArray(value)) {\r\n return value.map((item) => TemplateString(item).parseRaw(input).result);\r\n } else {\r\n return TemplateString(value).parseRaw(input).result;\r\n }\r\n })\r\n ?.filter((file) => file) || [];\r\n\r\n return inputFiles;\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { Conversation } from '@sre/helpers/Conversation.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\n\r\nimport { Component } from './Component.class';\r\n\r\nexport class GPTPlugin extends Component {\r\n protected configSchema = Joi.object({\r\n model: Joi.string().optional(),\r\n openAiModel: Joi.string().optional(), // for backward compatibility\r\n specUrl: Joi.string().max(2048).uri().required().description('URL of the OpenAPI specification'),\r\n descForModel: Joi.string().max(5000).required().allow('').label('Description for Model'),\r\n name: Joi.string().max(500).required().allow(''),\r\n desc: Joi.string().max(5000).required().allow('').label('Description'),\r\n logoUrl: Joi.string().max(8192).allow(''),\r\n id: Joi.string().max(200),\r\n version: Joi.string().max(100).allow(''),\r\n domain: Joi.string().max(253).allow(''),\r\n });\r\n\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n logger.debug(`=== Open API Log ===`);\r\n\r\n try {\r\n const specUrl = config?.data?.specUrl;\r\n\r\n if (!specUrl) {\r\n return { _error: 'Please provide a Open API Specification URL!', _debug: logger.output };\r\n }\r\n\r\n const model = config?.data?.model || config?.data?.openAiModel;\r\n const descForModel = TemplateString(config?.data?.descForModel).parse(input).result;\r\n let prompt = '';\r\n\r\n if (input?.Prompt) {\r\n prompt = typeof input?.Prompt === 'string' ? input?.Prompt : JSON.stringify(input?.Prompt);\r\n } else if (input?.Query) {\r\n prompt = typeof input?.Query === 'string' ? input?.Query : JSON.stringify(input?.Query);\r\n }\r\n\r\n if (!prompt) {\r\n return { _error: 'Please provide a prompt', _debug: logger.output };\r\n }\r\n\r\n // TODO [Forhad]: Need to check and validate input prompt token\r\n\r\n const conv = new Conversation(model, specUrl, { systemPrompt: descForModel, agentId: agent?.id });\r\n\r\n const result = await conv.prompt(prompt);\r\n\r\n logger.debug(`Response:\\n`, result, '\\n');\r\n\r\n return { Output: result, _debug: logger.output };\r\n } catch (error: any) {\r\n console.error('Error on running Open API: ', error);\r\n return { _error: `Error on running Open API!\\n${error?.message || JSON.stringify(error)}`, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { HfInference } from '@huggingface/inference';\r\nimport { Component } from './Component.class';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport hfParams from '../data/hugging-face.params.json';\r\nimport Joi from 'joi';\r\nimport { TemplateStringHelper } from '@sre/helpers/TemplateString.helper';\r\nimport { convertStringToRespectiveType, delay, isBase64, kebabToCapitalize, kebabToCamel } from '../utils';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nfunction shouldNestInputs(formatRequestPattern) {\r\n const trimmedPattern = formatRequestPattern?.trim();\r\n return /^(inputs|data):\\s*{(?![{])/.test(trimmedPattern);\r\n}\r\n\r\nfunction validateAndParseJson(value, helpers) {\r\n let parsedJson: any = null;\r\n\r\n // Try parsing the JSON string\r\n try {\r\n parsedJson = JSON.parse(value);\r\n } catch (error) {\r\n // If parsing fails, return an error\r\n return helpers.error('string.invalidJson', { value });\r\n }\r\n\r\n // Check if the result is an object\r\n if (typeof parsedJson !== 'object' || parsedJson === null) {\r\n return helpers.error('string.notJsonObject', { value });\r\n }\r\n\r\n // Check for empty keys\r\n for (const key in parsedJson) {\r\n if (key.trim() === '') {\r\n return helpers.error('object.emptyKey', { value });\r\n }\r\n }\r\n\r\n // Return the parsed JSON if all validations pass\r\n return parsedJson;\r\n}\r\n\r\nexport class HuggingFace extends Component {\r\n protected configSchema = Joi.object({\r\n accessToken: Joi.string().max(350).required().label('Access Token'),\r\n modelName: Joi.string().max(100).required(),\r\n modelTask: Joi.string().max(100).required(),\r\n inputConfig: Joi.string().allow(''),\r\n parameters: Joi.string().custom(validateAndParseJson, 'custom JSON validation').allow(''),\r\n name: Joi.string().max(100).required(),\r\n displayName: Joi.string().max(100).required(),\r\n desc: Joi.string().max(5000).required().allow(''),\r\n logoUrl: Joi.string().max(500).allow(''),\r\n disableCache: Joi.boolean().strict(),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n logger.debug(`=== Hugging Face Log ===`);\r\n\r\n const agentId = agent?.id;\r\n\r\n const teamId = agent?.teamId;\r\n // const accessToken = await parseKey(config?.data?.accessToken, teamId);\r\n const accessToken = (await TemplateStringHelper.create(config?.data?.accessToken).parseTeamKeysAsync(teamId).asyncResult) as string;\r\n\r\n if (!accessToken) {\r\n return { _error: 'Please provide a valid Hugging Face Access Token', _debug: logger.output };\r\n }\r\n\r\n const hf = new HfInference(accessToken);\r\n\r\n const task = config?.data?.modelTask;\r\n\r\n if (!task) {\r\n return { _error: 'Hugging Face Task is required!', _debug: logger.output };\r\n }\r\n\r\n logger.debug(`Task: ${kebabToCapitalize(task)}`);\r\n\r\n let hfFunc = kebabToCamel(task);\r\n\r\n // * Right now 'text2textGeneration' function is not available, so we are using 'textGeneration' for it.\r\n // Reference - https://huggingface.co/docs/api-inference/en/detailed_parameters#text2text-generation-task\r\n if (hfFunc === 'text2textGeneration') {\r\n hfFunc = 'textGeneration';\r\n }\r\n\r\n if (!hf?.[hfFunc]) {\r\n return { _error: `Inference API does not support for this task - ${kebabToCapitalize(task)}`, _debug: logger.output };\r\n }\r\n\r\n const modelName = config?.data?.modelName;\r\n\r\n if (!modelName) {\r\n return { _error: 'Hugging Face Model is required!', _debug: logger.output };\r\n }\r\n\r\n logger.debug(`Model Name: ${modelName}`);\r\n\r\n //const inputConfig = JSON.parse(config?.data?.inputConfig || '{}');\r\n\r\n let inputConfig: any = {};\r\n const formatRequest = hfParams?.[task]?.formatRequest;\r\n const _hfParams = hfParams?.[task]?.inputs;\r\n if (_hfParams && Object.keys(_hfParams).length > 0) {\r\n for (const key in _hfParams) {\r\n const config = _hfParams[key];\r\n inputConfig[key] = config;\r\n }\r\n if (typeof inputConfig === 'object' && inputConfig !== null) {\r\n inputConfig = { ...inputConfig, formatRequest };\r\n }\r\n }\r\n\r\n if (!inputConfig || Object.keys(inputConfig)?.length === 0) {\r\n console.log('No inputs config found for Hugging Face Model!');\r\n }\r\n\r\n let inputs = {};\r\n\r\n if (!input || Object.keys(input)?.length === 0) {\r\n return { _error: 'Please provide a valid input!', _debug: logger.output };\r\n }\r\n\r\n if (typeof input !== 'object') {\r\n return { _error: 'Invalid input!', _debug: logger.output };\r\n }\r\n\r\n if (typeof input == 'object' && Object.keys(input)?.length > 0) {\r\n for (const key in input) {\r\n if (inputConfig?.[key]) {\r\n let value = input[key];\r\n let name = inputConfig[key]['request_parameter_name'];\r\n let type = inputConfig[key]['request_parameter_type'];\r\n\r\n if (type && type?.includes('Blob')) {\r\n try {\r\n // const file = new SmythFile(value);\r\n // const blob = await file.toBlob(); // Converts to Blob for file inputs\r\n // inputs[name] = blob;\r\n const binaryFile = BinaryInput.from(value, undefined, undefined, AccessCandidate.agent(agentId));\r\n // const buffer = await binaryFile.readData(AccessCandidate.agent(agentId));\r\n const buffer = await binaryFile.getBuffer();\r\n const blob = new Blob([buffer]);\r\n inputs[name] = blob;\r\n } catch (error: any) {\r\n return { _error: error?.message || JSON.stringify(error), _debug: logger.output };\r\n }\r\n } else {\r\n inputs[name] = value;\r\n }\r\n }\r\n }\r\n }\r\n // Determine if inputs should be nested based on formatRequest\r\n const nestInputs = shouldNestInputs(inputConfig.formatRequest);\r\n // Apply the determined structure to newInputs\r\n const structuredInputs = nestInputs ? { inputs } : inputs;\r\n\r\n // Blob data will be converted to an empty object '{}', when stringified during logging. We need log something so that user can understand that it is a Blob\r\n let inputsLog;\r\n\r\n if (structuredInputs['inputs'] && typeof structuredInputs['inputs'] === 'object') {\r\n inputsLog = { ...structuredInputs['inputs'] };\r\n\r\n for (const [key, value] of Object.entries(structuredInputs['inputs'] || {})) {\r\n if (value instanceof Blob) {\r\n inputsLog[key] = `Blob size=${value.size}`;\r\n }\r\n }\r\n } else {\r\n inputsLog = structuredInputs;\r\n }\r\n\r\n logger.debug('Inputs: ', inputsLog);\r\n\r\n let params = JSON.parse(config?.data?.parameters || '{}');\r\n params = convertStringToRespectiveType(params);\r\n\r\n let parameters = {};\r\n\r\n if (params && Object.keys(params)?.length > 0) {\r\n for (const key in params) {\r\n const value = params[key];\r\n\r\n if (typeof value === 'string') {\r\n // if value is 'None' then skip it\r\n if (value?.toLowerCase() === 'none') continue;\r\n\r\n parameters[key] = TemplateStringHelper.create(value).parse(input).result;\r\n } else {\r\n parameters[key] = value;\r\n }\r\n }\r\n }\r\n\r\n let args = { model: modelName, ...structuredInputs };\r\n\r\n const options = {};\r\n\r\n // default value of use_cache is true, make it false if disableCache is true\r\n if (config?.data?.disableCache) {\r\n options['use_cache'] = false;\r\n }\r\n\r\n if (Object.keys(parameters)?.length > 0) {\r\n args['parameters'] = parameters;\r\n\r\n logger.debug('Parameters: \\n', parameters);\r\n }\r\n\r\n const modelCallWithRetry = async ({ retryCount = 0, retryLimit = 2, retryDelay = 1000 }) => {\r\n try {\r\n /*\r\n Provide the 'request' method when the method is not found and as a fallback for the following error:\r\n InferenceOutputError: Invalid inference output: Expected Array<{summary_text: string}>. Use the 'request' method with the same parameters to do a custom call with no type checking.\r\n */\r\n if (typeof hf[hfFunc] !== 'function' || retryCount === retryLimit) {\r\n hfFunc = 'request';\r\n }\r\n const result = await hf[hfFunc](args, options);\r\n let output;\r\n\r\n if (result instanceof Blob) {\r\n // Handle case where result is directly a Blob\r\n // const file = new SmythFile(result);\r\n // const fileObj = await file.toSmythFileObject({\r\n // metadata: {\r\n // teamid: teamId,\r\n // agentid: agentId,\r\n // },\r\n // baseUrl: agent?.baseUrl,\r\n // });\r\n // output = fileObj;\r\n // convert blob to base64\r\n\r\n const obj = await BinaryInput.from(result).getJsonData(AccessCandidate.agent(agent.id));\r\n output = obj;\r\n } else if (Array.isArray(result)) {\r\n // Handle case where result is an array of objects containing Blobs or base64 strings\r\n output = await Promise.all(\r\n result.map(async (item) => {\r\n if (item.blob instanceof Blob || (typeof item.blob === 'string' && isBase64(item.blob))) {\r\n let binaryInput: BinaryInput;\r\n\r\n if (item.blob instanceof Blob) {\r\n // file = new SmythFile(item.blob);\r\n\r\n binaryInput = BinaryInput.from(item.blob);\r\n } else {\r\n // file = new SmythFile(item.blob, item['content-type']);\r\n binaryInput = BinaryInput.from(item.blob, undefined, item['content-type']);\r\n }\r\n // const fileObj = await file.toSmythFileObject({\r\n // metadata: {\r\n // teamid: teamId,\r\n // agentid: agentId,\r\n // },\r\n // baseUrl: agent?.baseUrl,\r\n // });\r\n const fileObj = await binaryInput.getJsonData(AccessCandidate.agent(agent.id));\r\n return { ...item, blob: fileObj };\r\n } else {\r\n return item;\r\n }\r\n }),\r\n );\r\n } else {\r\n // Handle case where result is neither a Blob nor an array of Blob-containing objects\r\n output = result;\r\n }\r\n return output;\r\n } catch (error) {\r\n if (retryCount < retryLimit) {\r\n await delay(retryDelay);\r\n\r\n return modelCallWithRetry({\r\n retryCount: retryCount + 1,\r\n retryLimit,\r\n retryDelay: retryDelay * 2,\r\n });\r\n }\r\n\r\n throw error;\r\n }\r\n };\r\n\r\n try {\r\n const output = await modelCallWithRetry({\r\n retryCount: 0,\r\n retryLimit: 2,\r\n retryDelay: 5000,\r\n });\r\n\r\n logger.debug('Output: \\n', output);\r\n\r\n return { Output: output, _debug: logger.output };\r\n } catch (error: any) {\r\n console.log(`Error on running Hugging Face Model!`, error);\r\n console.log('Error: args, options ', args, options);\r\n\r\n return { _error: `Error from Hugging Face: \\n${error?.message || JSON.stringify(error)}`, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nexport const ImageSettingsConfig = {\r\n model: Joi.string().max(100).required(),\r\n\r\n positivePrompt: Joi.string().required().min(2).max(2000).label('Positive Prompt'),\r\n negativePrompt: Joi.string().optional().allow('').min(2).max(2000).label('Negative Prompt'),\r\n\r\n width: Joi.number().min(128).max(2048).multiple(64).optional().messages({\r\n 'number.multiple': '{{#label}} must be divisible by 64 (eg: 128...512, 576, 640...2048). Provided value: {{#value}}',\r\n }),\r\n height: Joi.number().min(128).max(2048).multiple(64).optional().messages({\r\n 'number.multiple': '{{#label}} must be divisible by 64 (eg: 128...512, 576, 640...2048). Provided value: {{#value}}',\r\n }),\r\n\r\n outputFormat: Joi.string().valid('JPG', 'PNG', 'WEBP').optional(),\r\n outputQuality: Joi.number().min(20).max(99).optional().label('Output Quality'),\r\n\r\n numberResults: Joi.number().min(1).max(20).optional().label('Number of Results'),\r\n steps: Joi.number().min(0).max(100).optional().label('Strength'),\r\n\r\n backgroundColor: Joi.array()\r\n .items(\r\n Joi.number()\r\n .when('$index', {\r\n is: 3, // when it's the alpha channel (4th item)\r\n then: Joi.number().min(0).max(1), // alpha validation\r\n otherwise: Joi.number().min(0).max(255).integer(), // RGB validation\r\n })\r\n .required()\r\n )\r\n .length(4)\r\n .optional()\r\n .allow('')\r\n .label('Background Color')\r\n .description('RGBA color array [red, green, blue, alpha]. RGB values must be between 0-255, alpha must be between 0-1'),\r\n\r\n strength: Joi.number().min(0).max(1).optional().label('Strength'),\r\n upscaleFactor: Joi.number().min(2).max(4).optional().label('Upscale Factor'),\r\n confidence: Joi.number().min(0).max(1).optional().label('Confidence'),\r\n maxDetections: Joi.number().min(1).max(20).optional().label('Max Detections'),\r\n maskPadding: Joi.number()\r\n .min(0)\r\n .max(100) // Guessed max value\r\n .optional()\r\n .label('Mask Padding'),\r\n maskBlur: Joi.number()\r\n .min(0)\r\n .max(100) // Guessed max value\r\n .optional()\r\n .label('Mask Blur'),\r\n preProcessorType: Joi.string()\r\n .valid('canny', 'depth', 'mlsd', 'normalbae', 'openpose', 'tile', 'seg', 'lineart', 'lineart_anime', 'shuffle', 'scribble', 'softedge')\r\n .optional()\r\n .label('Pre-Processor Type'),\r\n ipAdapters: Joi.array()\r\n .items(\r\n Joi.object({\r\n model: Joi.string().required().label('IP Adapter Model'),\r\n guideImage: Joi.string()\r\n .required()\r\n .min(2)\r\n .max(10_485_760) // Approximately 10MB in base64\r\n .label('Guide Image'),\r\n weight: Joi.number().required().min(0).max(1).label('IP Adapter Weight'),\r\n })\r\n )\r\n .optional()\r\n .label('IP Adapters'),\r\n};\r\n","import { AccessCandidate } from '../..';\r\nimport { ConnectorService } from '../../Core/ConnectorsService';\r\n\r\nexport type TCredentialsRequest = {\r\n vaultProvider?: string;\r\n keyName: string;\r\n mapping?: {\r\n [key: string]: string;\r\n };\r\n};\r\n\r\n/**\r\n * Get credentials from a vault\r\n *\r\n * @param candidate - The candidate requesting the credentials\r\n * @param credentialsRequest - The credentials request\r\n * @returns The credentials\r\n */\r\nexport async function getCredentials(\r\n candidate: AccessCandidate,\r\n credentialsRequest: TCredentialsRequest | string\r\n): Promise<string | Record<string, any>> {\r\n if (typeof credentialsRequest === 'string') {\r\n credentialsRequest = {\r\n vaultProvider: '', //default vault provider\r\n keyName: credentialsRequest, //default key name\r\n };\r\n }\r\n\r\n const vaultConnector = ConnectorService.getVaultConnector(credentialsRequest.vaultProvider || '');\r\n const vaultRequester = vaultConnector.requester(candidate);\r\n const credentials = await vaultRequester.get(credentialsRequest.keyName);\r\n\r\n if (!credentialsRequest.mapping) return credentials;\r\n\r\n const mappedCredentials = {};\r\n for (const [key, value] of Object.entries(credentialsRequest.mapping)) {\r\n mappedCredentials[key] = JSONExpression(credentials, value);\r\n }\r\n\r\n return mappedCredentials;\r\n}\r\n\r\n/**\r\n * @param obj - The object to extract the property from\r\n * @param propertyString - The property to extract from the object\r\n * @returns The property value\r\n */\r\nfunction JSONExpression(obj, propertyString) {\r\n const properties = propertyString.split(/\\.|\\[|\\]\\.|\\]\\[|\\]/).filter(Boolean);\r\n let currentProperty = obj;\r\n\r\n for (let property of properties) {\r\n if (currentProperty === undefined || currentProperty === null) {\r\n return undefined;\r\n }\r\n\r\n currentProperty = currentProperty[property];\r\n }\r\n\r\n return currentProperty;\r\n}\r\n","//TODO: this component need to be fully refactored to use the same approach as GenAI LLM\r\n\r\nimport { IRequestImage, Runware } from '@runware/sdk-js';\r\nimport { OpenAI } from 'openai';\r\n\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { APIKeySource, GenerateImageConfig } from '@sre/types/LLM.types';\r\nimport Joi from 'joi';\r\nimport { Component } from './Component.class';\r\n\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nimport appConfig from '@sre/config';\r\nimport { BUILT_IN_MODEL_PREFIX, SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { normalizeImageInput } from '@sre/utils/data.utils';\r\nimport { ImageSettingsConfig } from './Image/imageSettings.config';\r\nimport { getCredentials } from '../subsystems/Security/Credentials.helper';\r\n\r\nenum DALL_E_MODELS {\r\n DALL_E_2 = 'dall-e-2',\r\n DALL_E_3 = 'dall-e-3',\r\n}\r\n\r\nconst IMAGE_GEN_COST_MAP = {\r\n [DALL_E_MODELS.DALL_E_3]: {\r\n standard: {\r\n '1024x1024': 0.04,\r\n '1024x1792': 0.08,\r\n '1792x1024': 0.08,\r\n },\r\n hd: {\r\n '1024x1024': 0.08,\r\n '1024x1792': 0.12,\r\n '1792x1024': 0.12,\r\n },\r\n },\r\n [DALL_E_MODELS.DALL_E_2]: {\r\n '256x256': 0.016,\r\n '512x512': 0.018,\r\n '1024x1024': 0.02,\r\n },\r\n};\r\n\r\nexport class ImageGenerator extends Component {\r\n protected configSchema = Joi.object({\r\n model: Joi.string().max(100).required(),\r\n prompt: Joi.string().optional().min(2).max(2000).label('Prompt'),\r\n\r\n // #region OpenAI (DALL·E)\r\n sizeDalle2: Joi.string().valid('256x256', '512x512', '1024x1024').optional(),\r\n sizeDalle3: Joi.string().valid('1024x1024', '1792x1024', '1024x1792').optional(),\r\n quality: Joi.string().valid('standard', 'hd', 'auto', 'high', 'medium', 'low').allow('').optional(),\r\n style: Joi.string().valid('vivid', 'natural').optional(),\r\n isRawInputPrompt: Joi.boolean().strict().optional(),\r\n // #endregion\r\n\r\n // #region Runware\r\n negativePrompt: Joi.string().optional().allow('').min(2).max(2000).label('Negative Prompt'),\r\n width: Joi.number().min(128).max(2048).multiple(64).optional().messages({\r\n 'number.multiple': '{{#label}} must be divisible by 64 (eg: 128...512, 576, 640...2048). Provided value: {{#value}}',\r\n }),\r\n height: Joi.number().min(128).max(2048).multiple(64).optional().messages({\r\n 'number.multiple': '{{#label}} must be divisible by 64 (eg: 128...512, 576, 640...2048). Provided value: {{#value}}',\r\n }),\r\n outputFormat: Joi.string().valid('PNG', 'JPEG', 'WEBP', 'auto', 'jpeg', 'png', 'webp').optional(),\r\n strength: ImageSettingsConfig.strength,\r\n // #endregion\r\n\r\n // #region GPT model\r\n size: Joi.string().optional().allow('').max(100).label('Size'),\r\n // #endregion\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n logger.debug(`=== Image Generator Log ===`);\r\n\r\n let model = config?.data?.model;\r\n\r\n if (!model) {\r\n return { _error: 'Model Not Found: ', _debug: logger.output };\r\n }\r\n\r\n logger.debug(`Model: ${model}`);\r\n\r\n let prompt = config.data?.prompt || input?.Prompt;\r\n prompt = typeof prompt === 'string' ? prompt : JSON.stringify(prompt);\r\n prompt = TemplateString(prompt).parse(input).result;\r\n\r\n if (!prompt) {\r\n return { _error: 'Please provide a prompt or Image', _debug: logger.output };\r\n }\r\n\r\n logger.debug(`Prompt: \\n`, prompt);\r\n\r\n const modelFamily = await getModelFamily(model, agent);\r\n\r\n if (typeof imageGenerator[modelFamily] !== 'function') {\r\n return { _error: `The model '${model}' is not available. Please try a different one.`, _debug: logger.output };\r\n }\r\n\r\n try {\r\n const { output } = await imageGenerator[modelFamily]({ model, config, input, logger, agent, prompt });\r\n\r\n logger.debug(`Output: `, output);\r\n\r\n return { Output: output, _debug: logger.output };\r\n } catch (error: any) {\r\n return { _error: `Generating Image(s)\\n${error?.message || JSON.stringify(error)}`, _debug: logger.output };\r\n }\r\n }\r\n}\r\n\r\n// TODO: Create a separate service for image generation, similar to LLM.service.\r\n\r\n// TODO: Hopefully we will have the proper type with new OpenAI SDK, then we can use their type\r\ntype TokenUsage = OpenAI.Completions.CompletionUsage & {\r\n prompt_tokens_details?: { cached_tokens?: number };\r\n input_tokens_details: { image_tokens?: number; text_tokens?: number };\r\n output_tokens: number;\r\n};\r\n\r\nenum MODEL_FAMILY {\r\n GPT = 'gpt',\r\n RUNWARE = 'runware',\r\n DALL_E = 'dall-e',\r\n}\r\n\r\nconst imageGenerator = {\r\n [MODEL_FAMILY.GPT]: async ({ model, prompt, config, logger, agent, input }) => {\r\n let args: GenerateImageConfig & { files?: BinaryInput[] } = {\r\n model,\r\n size: config?.data?.size || 'auto',\r\n quality: config?.data?.quality || 'auto',\r\n };\r\n\r\n try {\r\n const llmInference: LLMInference = await LLMInference.getInstance(model, AccessCandidate.agent(agent.id));\r\n\r\n // if the llm is undefined, then it means we removed the model from our system\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n const provider = await agent.modelsProvider.getProvider(model);\r\n\r\n const files: any[] = parseFiles(input, config);\r\n const validFiles = files.filter((file) => imageGenerator.isValidImageFile(provider, file.mimetype));\r\n\r\n if (files.length > 0 && validFiles.length === 0) {\r\n throw new Error('Supported image file types are: ' + SUPPORTED_MIME_TYPES_MAP[provider]?.imageGen?.join(', '));\r\n }\r\n\r\n let response;\r\n\r\n if (validFiles.length > 0) {\r\n response = await llmInference.imageEditRequest({ query: prompt, files: validFiles, params: { ...args, agentId: agent.id } });\r\n } else {\r\n response = await llmInference.imageGenRequest({ query: prompt, params: { ...args, agentId: agent.id } });\r\n }\r\n\r\n if (response?.usage) {\r\n imageGenerator.reportTokenUsage(response.usage, {\r\n modelEntryName: model,\r\n keySource: model.startsWith(BUILT_IN_MODEL_PREFIX) ? APIKeySource.Smyth : APIKeySource.User,\r\n agentId: agent.id,\r\n teamId: agent.teamId,\r\n });\r\n }\r\n\r\n let output = response?.data?.[0]?.b64_json;\r\n\r\n const binaryInput = BinaryInput.from(output);\r\n const agentId = typeof agent == 'object' && agent.id ? agent.id : agent;\r\n const smythFile = await binaryInput.getJsonData(AccessCandidate.agent(agentId));\r\n\r\n return { output: smythFile };\r\n } catch (error: any) {\r\n throw new Error(`OpenAI Image Generation Error: ${error?.message || JSON.stringify(error)}`);\r\n }\r\n },\r\n [MODEL_FAMILY.DALL_E]: async ({ model, prompt, config, logger, agent, input }) => {\r\n let _finalPrompt = prompt;\r\n\r\n const files: any[] = parseFiles(input, config);\r\n\r\n if (files.length > 0) {\r\n throw new Error('OpenAI Image Generation Error: DALL-E models do not support image editing or variations. Please use a different model.');\r\n }\r\n\r\n const responseFormat = config?.data?.responseFormat || 'url';\r\n\r\n let args: GenerateImageConfig & { responseFormat: 'url' | 'b64_json' } = {\r\n responseFormat,\r\n model,\r\n };\r\n\r\n let cost = 0;\r\n\r\n if (model === DALL_E_MODELS.DALL_E_3) {\r\n const size = config?.data?.sizeDalle3 || '1024x1024';\r\n const quality = config?.data?.quality || 'standard';\r\n const style = config?.data?.style || 'vivid';\r\n args.size = size;\r\n args.quality = quality;\r\n args.style = style;\r\n\r\n const isRawInputPrompt = config?.data?.isRawInputPrompt || false;\r\n\r\n if (isRawInputPrompt) {\r\n _finalPrompt = `I NEED to test how the tool works with extremely simple prompts. DO NOT add any detail, just use it AS-IS: ${prompt}`;\r\n }\r\n\r\n cost = IMAGE_GEN_COST_MAP[model][quality][size];\r\n } else if (model === DALL_E_MODELS.DALL_E_2) {\r\n const size = config?.data?.sizeDalle2 || '256x256';\r\n const numberOfImages = parseInt(config?.data?.numberOfImages) || 1;\r\n args.size = size;\r\n args.n = numberOfImages;\r\n\r\n cost = IMAGE_GEN_COST_MAP[model][size];\r\n }\r\n\r\n const llmInference: LLMInference = await LLMInference.getInstance(model, AccessCandidate.agent(agent.id));\r\n\r\n // if the llm is undefined, then it means we removed the model from our system\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n const response: any = await llmInference.imageGenRequest({ query: _finalPrompt, params: { ...args, agentId: agent.id } });\r\n\r\n let output = response?.data?.[0]?.[responseFormat];\r\n const revised_prompt = response?.data?.[0]?.revised_prompt;\r\n\r\n if (revised_prompt && prompt !== revised_prompt) {\r\n logger.debug(`Revised Prompt:\\n${revised_prompt}`);\r\n }\r\n\r\n imageGenerator.reportUsage({ cost }, { modelEntryName: model, keySource: APIKeySource.Smyth, agentId: agent.id, teamId: agent.teamId });\r\n\r\n return { output };\r\n },\r\n [MODEL_FAMILY.RUNWARE]: async ({ model, prompt, config, agent, input }) => {\r\n // Initialize Runware client\r\n const teamId = agent.teamId;\r\n const apiKey = (await getCredentials(AccessCandidate.team(teamId), 'runware')) as string;\r\n\r\n const runware = new Runware({ apiKey });\r\n await runware.ensureConnection();\r\n\r\n const negativePrompt = config?.data?.negativePrompt || '';\r\n\r\n const files: any[] = parseFiles(input, config);\r\n let seedImage = Array.isArray(files) ? files[0] : files;\r\n seedImage = await normalizeImageInput(seedImage);\r\n\r\n const modelId = await agent.modelsProvider.getModelId(model);\r\n const imageRequestArgs: IRequestImage = {\r\n model: modelId,\r\n positivePrompt: prompt,\r\n width: +config?.data?.width || 1024,\r\n height: +config?.data?.height || 1024,\r\n numberResults: 1, // For Image Generation we only need 1 image\r\n outputType: 'URL', // For Image Generation we only need the URL\r\n outputFormat: config?.data?.outputFormat || 'JPEG',\r\n includeCost: true,\r\n };\r\n\r\n if (seedImage) {\r\n imageRequestArgs.seedImage = seedImage;\r\n imageRequestArgs.strength = +config?.data?.strength || 0.5;\r\n }\r\n\r\n // If a negative prompt is provided, add it to the request args\r\n if (negativePrompt) {\r\n imageRequestArgs.negativePrompt = negativePrompt;\r\n }\r\n\r\n try {\r\n const response = await runware.requestImages(imageRequestArgs);\r\n\r\n // Get first image from response array\r\n const firstImage = response[0];\r\n\r\n // Map response to match expected format\r\n let output = firstImage.imageURL;\r\n\r\n imageGenerator.reportUsage(\r\n { cost: firstImage.cost },\r\n { modelEntryName: model, keySource: APIKeySource.Smyth, agentId: agent.id, teamId: agent.teamId }\r\n );\r\n\r\n return { output };\r\n } catch (error: any) {\r\n throw new Error(`Runware Image Generation Error: ${error?.message || JSON.stringify(error)}`);\r\n } finally {\r\n // Clean up connection\r\n await runware.disconnect();\r\n }\r\n },\r\n reportTokenUsage(usage: TokenUsage, metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `api:imagegen.${modelName}`,\r\n keySource: metadata.keySource,\r\n\r\n input_tokens_txt: usage?.input_tokens_details?.text_tokens || 0,\r\n input_tokens_img: usage?.input_tokens_details?.image_tokens || 0,\r\n output_tokens: usage?.output_tokens,\r\n input_tokens_cache_read: usage?.prompt_tokens_details?.cached_tokens || 0,\r\n\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:API', usageData);\r\n\r\n return usageData;\r\n },\r\n reportUsage(usage: { cost: number }, metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }) {\r\n const usageData = {\r\n sourceId: `api:imagegen.smyth`,\r\n keySource: metadata.keySource,\r\n\r\n cost: usage?.cost,\r\n\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:API', usageData);\r\n\r\n return usageData;\r\n },\r\n isValidImageFile(provider: string, mimetype: string) {\r\n return SUPPORTED_MIME_TYPES_MAP[provider]?.imageGen?.includes(mimetype);\r\n },\r\n};\r\n\r\nenum PROVIDERS {\r\n OPENAI = 'OpenAI',\r\n RUNWARE = 'Runware',\r\n}\r\n\r\n/**\r\n * Gets the model family from a model identifier\r\n * @param model The model identifier\r\n * @returns The model family or null if not recognized\r\n */\r\nasync function getModelFamily(model: string, agent: Agent): Promise<string | null> {\r\n if (await isGPTModel(model)) return MODEL_FAMILY.GPT;\r\n if (await isRunwareModel(model, agent)) return MODEL_FAMILY.RUNWARE;\r\n if (await isDallEModel(model)) return MODEL_FAMILY.DALL_E;\r\n\r\n return null;\r\n}\r\n\r\nfunction isGPTModel(model: string) {\r\n return model?.replace(BUILT_IN_MODEL_PREFIX, '')?.startsWith(MODEL_FAMILY.GPT);\r\n}\r\n\r\nasync function isRunwareModel(model: string, agent: Agent): Promise<boolean> {\r\n const provider = await agent.modelsProvider.getProvider(model);\r\n return provider === PROVIDERS.RUNWARE || provider.toLowerCase() === PROVIDERS.RUNWARE.toLowerCase();\r\n}\r\n\r\nfunction isDallEModel(model: string) {\r\n return model?.replace(BUILT_IN_MODEL_PREFIX, '')?.startsWith(MODEL_FAMILY.DALL_E);\r\n}\r\n\r\nfunction parseFiles(input: any, config: any) {\r\n const mediaTypes = ['Image', 'Audio', 'Video', 'Binary'];\r\n\r\n // Parse media inputs from config\r\n const inputFiles =\r\n config.inputs\r\n ?.filter((_input) => mediaTypes.includes(_input.type))\r\n ?.flatMap((_input) => {\r\n const value = input[_input.name];\r\n\r\n if (Array.isArray(value)) {\r\n return value.map((item) => TemplateString(item).parseRaw(input).result);\r\n } else {\r\n return TemplateString(value).parseRaw(input).result;\r\n }\r\n })\r\n ?.filter((file) => file) || [];\r\n\r\n return inputFiles;\r\n}\r\n","import Joi from 'joi';\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { Component } from './Component.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\n//TODO : better handling of context window exceeding max length\r\n\r\nexport class PromptGenerator extends Component {\r\n protected configSchema = Joi.object({\r\n model: Joi.string().max(200).required(),\r\n prompt: Joi.string().required().max(8_000_000).label('Prompt'), // 2M tokens is around 8M characters\r\n temperature: Joi.number().min(0).max(5).label('Temperature'), // max temperature is 2 for OpenAI and togetherAI but 5 for cohere\r\n maxTokens: Joi.number().min(1).label('Maximum Tokens'),\r\n stopSequences: Joi.string().allow('').max(400).label('Stop Sequences'),\r\n topP: Joi.number().min(0).max(1).label('Top P'),\r\n topK: Joi.number().min(0).max(500).label('Top K'), // max top_k is 100 for togetherAI but 500 for cohere\r\n frequencyPenalty: Joi.number().min(0).max(2).label('Frequency Penalty'),\r\n presencePenalty: Joi.number().min(0).max(2).label('Presence Penalty'),\r\n responseFormat: Joi.string().valid('json', 'text').optional().label('Response Format'),\r\n passthrough: Joi.boolean().optional().label('Passthrough'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n //let debugLog = agent.agentRuntime?.debug ? [] : undefined;\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n try {\r\n logger.debug(`=== LLM Prompt Log ===`);\r\n let teamId = agent?.teamId;\r\n\r\n const passThrough: boolean = config.data.passthrough || false;\r\n const model: string = config.data.model || 'echo';\r\n const llmInference: LLMInference = await LLMInference.getInstance(model, AccessCandidate.agent(agent.id));\r\n\r\n // if the llm is undefined, then it means we removed the model from our system\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n const modelId = await agent.modelsProvider.getModelId(model);\r\n logger.debug(` Model : ${modelId || model}`);\r\n\r\n let prompt: any = TemplateString(config.data.prompt).parse(input).result;\r\n\r\n logger.debug(` Prompt\\n`, prompt, '\\n');\r\n\r\n // default to json response format\r\n config.data.responseFormat = config.data?.responseFormat || 'json';\r\n\r\n // request to LLM\r\n let response: any;\r\n if (passThrough) {\r\n const contentPromise = new Promise(async (resolve, reject) => {\r\n let _content = '';\r\n const eventEmitter: any = await llmInference\r\n .promptStream({\r\n query: prompt,\r\n params: { ...config, model, agentId: agent.id },\r\n })\r\n .catch((error) => {\r\n console.error('Error on promptStream: ', error);\r\n reject(error);\r\n });\r\n eventEmitter.on('content', (content) => {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ content });\r\n }\r\n agent.sse.send('llm/passthrough/content', content);\r\n _content += content;\r\n });\r\n eventEmitter.on('thinking', (thinking) => {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ thinking });\r\n }\r\n agent.sse.send('llm/passthrough/thinking', thinking);\r\n });\r\n eventEmitter.on('end', () => {\r\n console.log('end');\r\n resolve(_content);\r\n });\r\n });\r\n response = await contentPromise;\r\n } else {\r\n response = await llmInference\r\n .prompt({ query: prompt, params: { ...config, agentId: agent.id } })\r\n .catch((error) => ({ error: error }));\r\n }\r\n\r\n // in case we have the response but it's empty string, undefined or null\r\n if (!response) {\r\n return { _error: ' LLM Error = Empty Response!', _debug: logger.output };\r\n }\r\n\r\n if (response?.error) {\r\n const error = response?.error + ' ' + (response?.details || '');\r\n logger.error(` LLM Error=`, error);\r\n\r\n return { Reply: response?.data, _error: error, _debug: logger.output };\r\n }\r\n\r\n logger.debug(' Response \\n', response);\r\n\r\n const result = { Reply: response };\r\n\r\n result['_debug'] = logger.output;\r\n\r\n return result;\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { REQUEST_CONTENT_TYPES } from '@sre/constants';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { AxiosHeaders } from 'axios';\r\n\r\nexport async function parseHeaders(input, config, agent: Agent) {\r\n const teamId = agent ? agent.teamId : null;\r\n const templateSettings = config?.template?.settings || {};\r\n const contentType = config?.data?.contentType || REQUEST_CONTENT_TYPES.none;\r\n let headers = typeof config?.data?.headers == 'object' ? JSON.stringify(config?.data?.headers) : config?.data?.headers || '{}';\r\n\r\n //parse component template vars\r\n if (config.data._templateVars && templateSettings) {\r\n headers = await TemplateString(headers).parseComponentTemplateVarsAsync(templateSettings).asyncResult; // replaces component template vars with their IDs (this turns the string parses into an async parser) // replaces IDs with actual values then returns parser promise\r\n\r\n headers = await TemplateString(headers).parse(config.data._templateVars).result;\r\n }\r\n\r\n //parse vault keys\r\n headers = await TemplateString(headers).parseTeamKeysAsync(teamId).asyncResult;\r\n\r\n //parse input variables and clean up the remaining unparsed values\r\n headers = TemplateString(headers).parse(input).clean().result;\r\n\r\n //parse headers as json\r\n let jsonHeaders: any = JSONContent(headers).tryParse();\r\n if (typeof jsonHeaders !== 'object') {\r\n jsonHeaders = { 'x-smyth-error': 'Error parsing headers' };\r\n }\r\n\r\n //normalize headers key names to lowercase\r\n jsonHeaders = Object.fromEntries(Object.entries(jsonHeaders).map(([key, value]) => [key.toLowerCase(), value]));\r\n\r\n //if headers does not contain content-type, add it\r\n if (!jsonHeaders['content-type'] && contentType !== 'none') {\r\n jsonHeaders['content-type'] = contentType;\r\n }\r\n\r\n return new AxiosHeaders(jsonHeaders);\r\n}\r\n","import { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SmythFS } from '@sre/IO/Storage.service/SmythFS.class';\r\n\r\nfunction decodeUriParts(url: string): string {\r\n try {\r\n const urlObj = new URL(url);\r\n urlObj.pathname = decodeURIComponent(urlObj.pathname);\r\n\r\n // Handle search params individually\r\n const searchParams = new URLSearchParams(urlObj.search);\r\n for (const [key, value] of searchParams.entries()) {\r\n try {\r\n const decodedKey = decodeURIComponent(key);\r\n const decodedValue = decodeURIComponent(value);\r\n searchParams.delete(key);\r\n searchParams.append(decodedKey, decodedValue);\r\n } catch (paramError) {\r\n console.warn(`Failed to decode search parameter: ${key}=${value}`, paramError);\r\n // Keep the original key-value pair\r\n }\r\n }\r\n urlObj.search = searchParams.toString();\r\n\r\n urlObj.hash = decodeURIComponent(urlObj.hash);\r\n return urlObj.toString();\r\n } catch (error) {\r\n console.warn('Failed to decode URL parts, proceeding with original value:', error);\r\n return url;\r\n }\r\n}\r\n\r\nexport async function parseUrl(input, config, agent: Agent) {\r\n const teamId = agent ? agent.teamId : null;\r\n const templateSettings = config?.template?.settings || {};\r\n\r\n let url = config?.data?.url.replace(/\\+/g, '%20'); // replace + with %20 from query params to make it a valid url\r\n\r\n // Decode URL parts\r\n //url = decodeURIComponent(url);\r\n\r\n //parse component template vars\r\n if (config.data._templateVars && templateSettings) {\r\n url = await TemplateString(url).parseComponentTemplateVarsAsync(templateSettings).asyncResult; // replaces component template vars with their IDs (this turns the string parses into an async parser) // replaces IDs with actual values then returns parser promise\r\n\r\n url = await TemplateString(url).parse(config.data._templateVars).result;\r\n }\r\n\r\n //parse vault keys\r\n url = await TemplateString(url).parseTeamKeysAsync(teamId).asyncResult;\r\n\r\n //parse input variables and clean up the remaining unparsed values\r\n url = TemplateString(url).parse(input).clean().result;\r\n\r\n // Decode URL parts again after all parsing is done\r\n //url = decodeURIComponent(url); //This seems to be causing issues with some variables being encoded while they should not be\r\n\r\n //URL will take care of encoding the url properly\r\n const urlObj = new URL(url);\r\n\r\n //urlObj.href will return the encoded url\r\n return urlObj.href;\r\n}\r\n\r\nexport async function parseSmythFsUrl(url: string, agent: Agent) {\r\n const urlObj = new URL(url);\r\n const searchParams = urlObj.searchParams;\r\n const publicUrls: string[] = [];\r\n\r\n for (const [key, value] of searchParams.entries()) {\r\n if (value.startsWith('smythfs://')) {\r\n const pubUrl = await SmythFS.Instance.genTempUrl(value, AccessCandidate.agent(agent.id));\r\n publicUrls.push(pubUrl);\r\n searchParams.set(key, pubUrl);\r\n }\r\n }\r\n\r\n return { url: urlObj.href, publicUrls };\r\n}\r\n\r\nexport async function destroyPublicUrls(publicUrls: string[]): Promise<boolean> {\r\n try {\r\n await Promise.all(publicUrls.map((url) => SmythFS.Instance.destroyTempUrl(url)));\r\n console.log('Successfully cleaned up all temp urls for API Call Component');\r\n } catch (error) {\r\n console.warn('Failed to clean up temp urls for API Call Component:', error);\r\n }\r\n\r\n return true;\r\n}\r\n","import { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { REQUEST_CONTENT_TYPES } from '@sre/constants';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport FormData from 'form-data';\r\nimport { Readable } from 'stream';\r\n\r\nexport async function parseData(input: any, config, agent: Agent): Promise<{ data: any; headers: any }> {\r\n const teamId = agent ? agent.teamId : null;\r\n const templateSettings = config?.template?.settings || {};\r\n const contentType = config?.data?.contentType || REQUEST_CONTENT_TYPES.none;\r\n\r\n let body = typeof config?.data?.body === 'string' ? config?.data?.body?.trim() : config?.data?.body;\r\n if (!body) {\r\n return { data: null, headers: {} };\r\n }\r\n\r\n // Parse component template variables\r\n if (config.data._templateVars && templateSettings) {\r\n //prettier-ignore\r\n body = await TemplateString(body) \r\n .parseComponentTemplateVarsAsync(templateSettings) // replace component template vars with their IDs (this turns the string parses into an async parser) \r\n .asyncResult; //returns parser promise\r\n }\r\n\r\n // Parse vault keys\r\n body = await TemplateString(body).parseTeamKeysAsync(teamId).asyncResult;\r\n\r\n // Handle different content types\r\n const handlers: Record<string, (parsedBody: any, input: any, config, agent: Agent) => any> = {\r\n [REQUEST_CONTENT_TYPES.json]: handleJson,\r\n [REQUEST_CONTENT_TYPES.urlEncodedFormData]: handleUrlEncoded,\r\n [REQUEST_CONTENT_TYPES.multipartFormData]: handleMultipartFormData,\r\n [REQUEST_CONTENT_TYPES.binary]: handleBinary,\r\n [REQUEST_CONTENT_TYPES.text]: handleText,\r\n [REQUEST_CONTENT_TYPES.none]: handleNone,\r\n };\r\n\r\n const handler = handlers[contentType] || handleNone;\r\n const { data = null, headers = {} } = await handler(body, input, config, agent);\r\n\r\n //const jsonBody: any = JSONContent(data).tryParse();\r\n return { data, headers };\r\n}\r\n\r\nasync function handleJson(body: any, input: any, config, agent: Agent) {\r\n // Parse template and input variables\r\n //prettier-ignore\r\n const data = TemplateString(body)\r\n .parse(config.data._templateVars) //parse Template variables first (if any)\r\n .parse(input) //parse inputs\r\n .clean().result; //clean up the remaining unparsed values\r\n\r\n const jsonBody: any = JSONContent(data).tryParse();\r\n return { data: jsonBody };\r\n}\r\n\r\nasync function handleUrlEncoded(body: any, input: any, config, agent: Agent) {\r\n const data = TemplateString(body)\r\n .parse(config.data._templateVars) //parse Template variables first (if any)\r\n .parse(input) //parse inputs\r\n .clean().result; //clean up the remaining unparsed values\r\n\r\n const jsonData: any = JSONContent(data).tryParse();\r\n\r\n if (typeof jsonData === 'object') {\r\n const params = new URLSearchParams();\r\n for (const key in jsonData) {\r\n params.append(key, String(jsonData[key]));\r\n }\r\n return { data: params.toString() };\r\n }\r\n\r\n return { data: jsonData };\r\n}\r\n\r\nasync function handleMultipartFormData(body: any, input: any, config, agent: Agent) {\r\n const formData = new FormData();\r\n\r\n const _body = typeof body === 'string' ? JSON.parse(body) : body;\r\n\r\n for (const key in _body) {\r\n let value = _body[key];\r\n value = typeof value === 'boolean' ? String(value) : value;\r\n\r\n value = TemplateString(value).parseRaw(input).result;\r\n\r\n // * Note: It's important to check if the value is an instance of BinaryInput first.\r\n // Otherwise, condition like (value && typeof value === 'object' && value?.url)\r\n // might be true and lead to incorrect results.\r\n if (value instanceof BinaryInput) {\r\n const buffer = await value.getBuffer();\r\n const bufferStream = new Readable();\r\n bufferStream.push(buffer || null);\r\n bufferStream.push(null);\r\n\r\n const filename = (await value.getName()) || key;\r\n formData.append(key, bufferStream, {\r\n filename,\r\n contentType: value.mimetype,\r\n });\r\n } else if (value && typeof value === 'object' && value?.url) {\r\n // Retro compatibility with old binary data structure {url: '...', mimetype: '...', url: 'http(s)://...'}\r\n const binaryInput = await BinaryInput.from(value.url, '', value?.mimetype);\r\n const buffer = await binaryInput.getBuffer();\r\n\r\n const bufferStream = new Readable();\r\n bufferStream.push(buffer || null);\r\n bufferStream.push(null);\r\n\r\n const filename = (await binaryInput.getName()) || key;\r\n formData.append(key, bufferStream, {\r\n filename,\r\n contentType: binaryInput.mimetype,\r\n });\r\n } else {\r\n value = TemplateString(value)\r\n .parse(config.data._templateVars) //parse Template variables first (if any)\r\n .parse(input)\r\n .clean().result;\r\n\r\n if (value) {\r\n formData.append(key, value);\r\n }\r\n\r\n //formData.append(key, typeof value === 'boolean' ? String(value) : value);\r\n }\r\n }\r\n return { data: formData, headers: formData.getHeaders() };\r\n}\r\n\r\nasync function handleBinary(body: any, input: any, config, agent: Agent) {\r\n const value: any = TemplateString(body).parseRaw(input).result;\r\n\r\n // * Note: It's important to check if the value is an instance of BinaryInput first.\r\n // Otherwise, condition like (value && typeof value === 'object' && value?.url)\r\n // might be true and lead to incorrect results.\r\n if (value && value instanceof BinaryInput) {\r\n const buffer = await value.getBuffer();\r\n return { data: buffer, headers: { 'Content-Type': value.mimetype } };\r\n } else if (value && typeof value === 'object' && value?.url) {\r\n // Retro compatibility with old binary data structure {url: '...', mimetype: '...', url: 'http(s)://...'}\r\n const binaryInput = await BinaryInput.from(value.url, '', value?.mimetype);\r\n const buffer = await binaryInput.getBuffer();\r\n\r\n return { data: buffer, headers: { 'Content-Type': binaryInput.mimetype } };\r\n }\r\n\r\n return { data: Buffer.from([]), headers: {} };\r\n}\r\n\r\nasync function handleNone(body: any, input: any, config, agent: Agent) {\r\n //FIXME: try to guess the content type from headers content-type and data\r\n\r\n return { data: typeof body === 'string' ? body : JSON.stringify(body), headers: {} };\r\n}\r\nfunction handleText(body: any, input: any, config: any, agent: Agent) {\r\n // Parse template and input variables\r\n //prettier-ignore\r\n const data = TemplateString(body)\r\n .parse(config.data._templateVars) //parse Template variables first (if any)\r\n .parse(input) //parse inputs\r\n .clean().result; //clean up the remaining unparsed values\r\n\r\n return { data };\r\n}\r\n","import { AxiosProxyConfig } from 'axios';\r\nimport { SocksProxyAgent } from 'socks-proxy-agent';\r\n\r\nimport { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\n\r\nexport async function parseProxy(input, config, agent: Agent): Promise<AxiosProxyConfig | SocksProxyAgent | false> {\r\n const teamId = agent ? agent.teamId : null;\r\n const templateSettings = config?.template?.settings || {};\r\n\r\n let proxy = config?.data?.proxy;\r\n\r\n if (!proxy) {\r\n return false;\r\n }\r\n\r\n proxy = decodeURIComponent(proxy); //decode the url in order to parse the template vars\r\n\r\n //parse component template vars\r\n if (config.data._templateVars && templateSettings) {\r\n proxy = await TemplateString(proxy)\r\n .parseComponentTemplateVarsAsync(templateSettings) // replaces component template vars with their IDs (this turns the string parses into an async parser)\r\n .parse(config.data._templateVars).asyncResult; // replaces IDs with actual values then returns parser promise\r\n }\r\n\r\n //parse vault keys\r\n proxy = await TemplateString(proxy).parseTeamKeysAsync(teamId).asyncResult;\r\n\r\n //parse input variables and clean up the remaining unparsed values\r\n proxy = TemplateString(proxy).parse(input).clean().result;\r\n\r\n const proxyList = proxy.split(/\\n|\\\\n/).filter((p) => p) || [];\r\n\r\n const randomIdx = Math.floor(Math.random() * proxyList?.length);\r\n const proxyUrl = proxyList[randomIdx]?.trim();\r\n\r\n //URL will take care of encoding the url properly\r\n const urlObj = new URL(proxyUrl);\r\n const protocol = urlObj.protocol.replace(':', ''); // As urlObj.protocol is like 'http:'\r\n\r\n let proxyConfig: AxiosProxyConfig | SocksProxyAgent;\r\n\r\n if (urlObj.protocol.startsWith('socks')) {\r\n let proxyUrlString = `${protocol}://${urlObj.hostname}:${urlObj.port}`;\r\n\r\n if ((protocol === 'socks4' || protocol === 'socks4a') && urlObj.username) {\r\n proxyUrlString = `${protocol}://${urlObj.username}@${urlObj.hostname}:${urlObj.port}`;\r\n } else if (protocol === 'socks5' && urlObj.username) {\r\n proxyUrlString = `${protocol}://${urlObj.username}:${urlObj.password}@${urlObj.hostname}:${urlObj.port}`;\r\n }\r\n\r\n proxyConfig = new SocksProxyAgent(proxyUrlString);\r\n } else {\r\n proxyConfig = {\r\n protocol,\r\n host: urlObj.hostname,\r\n port: parseInt(urlObj.port),\r\n auth: urlObj.username\r\n ? {\r\n username: urlObj.username,\r\n password: urlObj.password,\r\n }\r\n : undefined,\r\n };\r\n }\r\n\r\n return proxyConfig;\r\n}\r\n","const mimeTypeCategories = {\r\n binary: [\r\n 'image/',\r\n 'multipart/form-data',\r\n 'video/',\r\n 'application/msword',\r\n 'application/octet-stream',\r\n 'application/pdf',\r\n 'application/vnd.ms-excel',\r\n 'application/vnd.ms-powerpoint',\r\n 'application/vnd.oasis.opendocument.text',\r\n 'application/vnd.openxmlformats-officedocument',\r\n 'application/zip',\r\n 'application/x-7z-compressed',\r\n 'application/x-rar-compressed',\r\n 'application/x-tar',\r\n 'application/x-bzip',\r\n 'application/x-bzip2',\r\n 'application/x-gzip',\r\n 'application/vnd.android.package-archive',\r\n 'application/vnd.visio',\r\n 'application/x-deb',\r\n 'application/x-rpm',\r\n 'application/x-executable',\r\n 'font/ttf',\r\n 'font/otf',\r\n 'font/woff',\r\n 'font/woff2',\r\n 'model/',\r\n ],\r\n json: ['application/graphql', 'application/json', 'application/ld+json', 'application/vnd.api+json'],\r\n text: [\r\n 'text/', //all starting with text/\r\n 'application/xml',\r\n 'application/xhtml+xml',\r\n 'application/csv',\r\n 'application/x-www-form-urlencoded',\r\n 'application/x-yaml',\r\n 'application/yaml',\r\n 'application/javascript',\r\n 'application/sql',\r\n 'application/rtf',\r\n ],\r\n};\r\n\r\nexport default mimeTypeCategories;\r\n","import { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { isBinaryData, isBinaryMimeType } from '@sre/utils/data.utils';\r\nimport { AxiosResponse } from 'axios';\r\nimport mimeTypeCategories from './mimeTypeCategories';\r\n\r\nconst contentHandlers = {\r\n json: parseJson,\r\n text: parseText,\r\n binary: parseBinary,\r\n};\r\n\r\nfunction parseJson(data) {\r\n return JSON.parse(Buffer.from(data).toString('utf8') || '{}');\r\n}\r\n\r\nfunction parseText(data) {\r\n return Buffer.from(data).toString('utf8');\r\n}\r\n\r\nasync function parseBinary(data, contentType, agentId) {\r\n const binaryInput = BinaryInput.from(data, null, contentType);\r\n const smythFile = await binaryInput.getJsonData(AccessCandidate.agent(agentId));\r\n\r\n return smythFile;\r\n}\r\n\r\nexport async function parseArrayBufferResponse(response: AxiosResponse, agent: Agent): Promise<any> {\r\n if (!response?.data) {\r\n return null;\r\n }\r\n const data = response.data;\r\n const contentType = response.headers['content-type'];\r\n const cleanContentType = contentType?.split(';')[0];\r\n\r\n // Try to find an exact match first,\r\n let handlerType = Object.keys(mimeTypeCategories).find((type) => mimeTypeCategories[type].includes(cleanContentType));\r\n\r\n // If no exact match, try to find a match for the first part of the handlerTypes, some handlers are generic like text/ in that case we check if the handler is a substring of the contentType\r\n if (!handlerType) {\r\n handlerType = Object.keys(mimeTypeCategories).find((type) => mimeTypeCategories[type].some((prefix) => cleanContentType?.startsWith(prefix)));\r\n }\r\n\r\n const handler = contentHandlers[handlerType];\r\n\r\n if (handler) {\r\n return handler(data, contentType, agent.id);\r\n }\r\n\r\n // Fallback: if no content type matches then check if the data is binary\r\n // If so then parse it as binary, otherwise parse it as text\r\n if (isBinaryMimeType(contentType) || isBinaryData(data)) {\r\n return parseBinary(data, contentType, agent.id);\r\n } else {\r\n return parseText(data);\r\n }\r\n}\r\n","// accessTokenManager.ts\r\nimport { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport axios from 'axios';\r\n\r\nconst console = Logger('AccessTokenManager');\r\nlet managedVault: any;\r\n\r\nSystemEvents.on('SRE:Booted', () => {\r\n managedVault = ConnectorService.getManagedVaultConnector();\r\n});\r\nclass AccessTokenManager {\r\n private clientId: string;\r\n private clientSecret: string;\r\n private primaryToken: string; // accessToken || token\r\n private secondaryToken: string; // refreshToken || tokenSecret\r\n private tokenUrl: string; // tokenURL to refresh accessToken\r\n private expires_in: any;\r\n private data: any; // value of key(keyId) in teamSettings that needs to be updated if required\r\n private keyId: any; // key of object in teamSettings\r\n private logger: any; // Use to log console in debugger\r\n private agent: Agent;\r\n constructor(\r\n clientId: string,\r\n clientSecret: string,\r\n secondaryToken: string,\r\n tokenUrl: string,\r\n expires_in: any,\r\n primaryToken: string,\r\n data: any,\r\n keyId: any,\r\n logger: any,\r\n agent: Agent,\r\n ) {\r\n this.clientId = clientId;\r\n this.clientSecret = clientSecret;\r\n this.primaryToken = primaryToken;\r\n this.secondaryToken = secondaryToken;\r\n this.tokenUrl = tokenUrl;\r\n this.expires_in = expires_in;\r\n this.data = data;\r\n this.keyId = keyId;\r\n this.logger = logger;\r\n this.agent = agent;\r\n }\r\n\r\n async getAccessToken(): Promise<string> {\r\n try {\r\n const currentTime: any = new Date().getTime();\r\n\r\n // If there's no secondaryToken (refresh token) and no expires_in,\r\n // assume it's a long-lived token and return the primaryToken directly\r\n if (!this.secondaryToken && !this.expires_in) {\r\n console.log('Using long-lived access token');\r\n this.logger.debug('Using long-lived access token. If authentication failes, please re-authenticate and try again');\r\n return this.primaryToken;\r\n }\r\n\r\n // Regular token expiration check for tokens with expiration\r\n // should be alway currentTime >= Number(this.expires_in)\r\n if (!this.expires_in || currentTime >= Number(this.expires_in)) {\r\n if (!this.secondaryToken) {\r\n this.logger.debug('Refresh token is missing. Please re authenticate');\r\n console.log('Refresh token is missing. Please re authenticate...');\r\n // Redirect the user to the OAuth authorization URL or initiate the reauthentication flow\r\n throw new Error('Reauthentication required');\r\n }\r\n this.logger.debug('Access token is expired or missing. Refreshing access token...');\r\n console.log('Access token is expired or missing. Refreshing access token...');\r\n return await this.refreshAccessToken();\r\n } else {\r\n console.log('Access token is still valid');\r\n this.logger.debug('Access token is still valid.');\r\n return this.primaryToken;\r\n }\r\n } catch (error) {\r\n console.error('Error fetching access token:', error);\r\n this.logger.debug('Error fetching access token');\r\n throw error;\r\n }\r\n }\r\n\r\n async refreshAccessToken(): Promise<string> {\r\n try {\r\n const response = await axios.post(\r\n this.tokenUrl,\r\n new URLSearchParams({\r\n client_id: this.clientId,\r\n client_secret: this.clientSecret,\r\n refresh_token: this.secondaryToken,\r\n grant_type: 'refresh_token',\r\n }).toString(),\r\n {\r\n headers: {\r\n 'Content-Type': 'application/x-www-form-urlencoded',\r\n },\r\n },\r\n );\r\n\r\n const newAccessToken: string = response?.data?.access_token;\r\n console.log('Access token refreshed successfully.');\r\n this.logger.debug('Access token refreshed successfully.');\r\n const expiresInMilliseconds: number = response?.data?.expires_in ? response?.data?.expires_in * 1000 : response?.data?.expires_in;\r\n const expirationTimestamp: number = expiresInMilliseconds ? new Date().getTime() + expiresInMilliseconds : expiresInMilliseconds;\r\n this.data.primary = newAccessToken;\r\n this.data.expires_in = expirationTimestamp ? expirationTimestamp?.toString() : expirationTimestamp;\r\n //const oauthTeamSettings = new OauthTeamSettings();\r\n //const save: any = await oauthTeamSettings.update({ keyId: this.keyId, data: this.data });\r\n\r\n const save: any = await managedVault.user(AccessCandidate.agent(this.agent.id)).set(this.keyId, JSON.stringify(this.data));\r\n if (save && save.status === 200) {\r\n console.log('Access token value is updated successfully.');\r\n this.logger.debug('Access token value is updated successfully.');\r\n } else {\r\n console.log('Warning: new access token value is not updated.');\r\n this.logger.debug('Warning: new access token value is not updated.');\r\n }\r\n return newAccessToken;\r\n } catch (error) {\r\n console.error('Failed to refresh access token:', error);\r\n this.logger.debug(`Failed to refresh access token: ${error}`);\r\n throw new Error('Failed to refresh access token.');\r\n }\r\n }\r\n}\r\n\r\nexport default AccessTokenManager;\r\n","// helper.ts\r\nimport crypto from 'crypto';\r\nimport OAuth from 'oauth-1.0a';\r\nimport AccessTokenManager from './AccessTokenManager';\r\nimport { REQUEST_CONTENT_TYPES } from '@sre/constants';\r\nimport axios, { AxiosRequestConfig } from 'axios';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\nconst console = Logger('OAuth.helper');\r\nlet managedVault: any;\r\n\r\nSystemEvents.on('SRE:Booted', () => {\r\n try {\r\n managedVault = ConnectorService.getManagedVaultConnector();\r\n } catch (error) {\r\n console.warn('Could not find a compatible ManagedVault connector, OAuth APICalls will not work');\r\n }\r\n});\r\n\r\nexport function extractAdditionalParamsForOAuth1(reqConfig: AxiosRequestConfig = {}) {\r\n let additionalParams = {};\r\n // Parse URL parameters using URL and URLSearchParams\r\n const url = new URL(reqConfig.url);\r\n const searchParams = url.searchParams;\r\n additionalParams = Object.fromEntries(searchParams.entries());\r\n\r\n // Check content type and add required parameters for OAuth 1 signature\r\n const contentType = reqConfig.headers?.['Content-Type'] || '';\r\n if (contentType === REQUEST_CONTENT_TYPES.urlEncodedFormData) {\r\n // For form data, include the form parameters in the signature\r\n if (typeof reqConfig.data === 'string') {\r\n const formData = new URLSearchParams(reqConfig.data);\r\n additionalParams = { ...additionalParams, ...Object.fromEntries(formData) };\r\n }\r\n } else if (contentType === REQUEST_CONTENT_TYPES.json) {\r\n // For JSON data, include a hash of the request body\r\n if (reqConfig.data) {\r\n const hash = crypto.createHash('sha1').update(JSON.stringify(reqConfig.data)).digest('base64');\r\n additionalParams['oauth_body_hash'] = hash;\r\n }\r\n } else if (contentType === REQUEST_CONTENT_TYPES.multipartFormData) {\r\n const formData = reqConfig.data as FormData;\r\n for (const [key, value] of formData.entries()) {\r\n // Exclude binary form data (File, Blob, etc.)\r\n if (typeof value === 'object' && value !== null && 'size' in value && 'type' in value) {\r\n continue;\r\n }\r\n\r\n additionalParams[key] = value;\r\n }\r\n }\r\n\r\n return additionalParams;\r\n}\r\n\r\nexport const buildOAuth1Header = (url, method, oauth1Credentials, additionalParams = {}) => {\r\n const oauth = new OAuth({\r\n consumer: {\r\n key: oauth1Credentials.consumerKey,\r\n secret: oauth1Credentials.consumerSecret,\r\n },\r\n signature_method: 'HMAC-SHA1',\r\n hash_function(base_string, key) {\r\n return crypto.createHmac('sha1', key).update(base_string).digest('base64');\r\n },\r\n });\r\n\r\n // Include additional parameters if necessary (e.g., for non-standard providers)\r\n const requestData = {\r\n url,\r\n method,\r\n ...additionalParams,\r\n };\r\n const signedRequest = oauth.authorize(requestData, { key: oauth1Credentials.token, secret: oauth1Credentials.tokenSecret });\r\n return oauth.toHeader(signedRequest);\r\n};\r\n\r\nexport const retrieveOAuthTokens = async (agent, config) => {\r\n let tokenKey: any = null;\r\n try {\r\n tokenKey = `OAUTH_${config.componentId ?? config.id}_TOKENS`;\r\n\r\n try {\r\n const result: any = await managedVault.user(AccessCandidate.agent(agent.id)).get(tokenKey);\r\n const tokensData = typeof result === 'object' ? result : JSON.parse(result || '{}');\r\n\r\n if (!tokensData) {\r\n throw new Error('Failed to retrieve OAuth tokens from vault. Please authenticate ...');\r\n }\r\n\r\n const primaryToken = tokensData.primary; // accessToken or token\r\n const secondaryToken = tokensData.secondary; // refreshToken or tokenSecret\r\n const type = tokensData.type; // oauth || oauth2\r\n\r\n // Add warning logs for OAuth2\r\n if (type === 'oauth2' && config.data.oauthService !== 'OAuth2 Client Credentials') {\r\n if (!secondaryToken) {\r\n console.warn('Warning: refresh_token is missing for OAuth2');\r\n }\r\n if (!tokensData.expires_in) {\r\n console.warn('Warning: expires_in is missing for OAuth2.');\r\n }\r\n }\r\n\r\n // sometimes refreshToken is not available . e.g in case of linkedIn. so only add check for primary token\r\n if (config.data.oauthService !== 'OAuth2 Client Credentials') {\r\n if (!primaryToken) {\r\n throw new Error('Retrieved OAuth tokens do not exist, invalid OR incomplete. Please authenticate ...');\r\n }\r\n }\r\n\r\n const responseData: any = {\r\n primaryToken,\r\n secondaryToken,\r\n type,\r\n };\r\n\r\n if (type === 'oauth') {\r\n // Check and assign if present\r\n if ('consumerKey' in tokensData) responseData.consumerKey = tokensData.consumerKey;\r\n if ('consumerSecret' in tokensData) responseData.consumerSecret = tokensData.consumerSecret;\r\n responseData.team = tokensData.team;\r\n } else if (type === 'oauth2') {\r\n // Check and assign if present\r\n responseData.tokenURL = tokensData.tokenURL;\r\n if ('clientID' in tokensData) responseData.clientID = tokensData.clientID;\r\n if ('clientSecret' in tokensData) responseData.clientSecret = tokensData.clientSecret;\r\n responseData.expiresIn = tokensData.expires_in ?? 0; // Optional property, default to 0 if not present. time to expire access token\r\n responseData.team = tokensData.team;\r\n }\r\n\r\n return { responseData, data: tokensData, keyId: tokenKey };\r\n } catch (error) {\r\n throw new Error(`Failed to parse retrieved tokens: ${error}`);\r\n }\r\n } catch (error) {\r\n console.error('Error retrieving OAuth tokens:', error);\r\n throw error; // rethrow for potential handling by the calling code\r\n }\r\n};\r\n\r\nexport const handleOAuthHeaders = async (agent, config, reqConfig, logger, additionalParams = {}, rootUrl) => {\r\n let headers = {}; // Initialize headers as an empty object\r\n const { responseData: oauthTokens, data, keyId } = await retrieveOAuthTokens(agent, config);\r\n\r\n try {\r\n // Extract template variable key IDs for consumerKey, consumerSecret, clientID, and clientSecret\r\n const keys = ['consumerKey', 'consumerSecret', 'clientID', 'clientSecret'];\r\n let oAuthConfigString = JSON.stringify({\r\n consumerKey: config.data.consumerKey,\r\n consumerSecret: config.data.consumerSecret,\r\n clientID: config.data.clientID,\r\n clientSecret: config.data.clientSecret,\r\n tokenURL: config.data.tokenURL,\r\n });\r\n\r\n oAuthConfigString = await TemplateString(oAuthConfigString).parseTeamKeysAsync(oauthTokens.team || agent.teamId).asyncResult;\r\n\r\n const oAuthConfig = JSON.parse(oAuthConfigString);\r\n\r\n if (oAuthConfig.oauthService === 'OAuth2 Client Credentials') {\r\n const accessToken = await getClientCredentialToken(data, logger, keyId, oauthTokens, config, agent);\r\n headers['Authorization'] = `Bearer ${accessToken}`;\r\n } else {\r\n if (oauthTokens.type === 'oauth') {\r\n // For OAuth1, generate and replace the signature in headers\r\n const oauthHeader = buildOAuth1Header(\r\n rootUrl,\r\n reqConfig.method,\r\n {\r\n consumerKey: oAuthConfig.consumerKey,\r\n consumerSecret: oAuthConfig.consumerSecret,\r\n token: oauthTokens.primaryToken,\r\n tokenSecret: oauthTokens.secondaryToken,\r\n },\r\n additionalParams,\r\n );\r\n\r\n headers = { ...reqConfig.headers, ...oauthHeader };\r\n logger.debug('OAuth1 access token check success.');\r\n } else if (oauthTokens.type === 'oauth2') {\r\n // For OAuth2, add the 'Authorization' header with the bearer token\r\n const accessTokenManager = new AccessTokenManager(\r\n oAuthConfig.clientID,\r\n oAuthConfig.clientSecret,\r\n oauthTokens.secondaryToken,\r\n oAuthConfig.tokenURL,\r\n oauthTokens.expiresIn,\r\n oauthTokens.primaryToken,\r\n data,\r\n keyId,\r\n logger,\r\n agent,\r\n );\r\n\r\n const accessToken = await accessTokenManager.getAccessToken();\r\n headers['Authorization'] = `Bearer ${accessToken}`;\r\n }\r\n }\r\n return headers;\r\n } catch (error) {\r\n logger.error(`Access token check failed: ${error}`);\r\n throw error;\r\n }\r\n};\r\n\r\nconst getKeyIdsFromTemplateVars = (str: string): string[] => {\r\n if (!str) return [];\r\n\r\n const pattern = /{{KEY\\((.*?)\\)}}/g;\r\n const keyIds: any = [];\r\n let match: any = [];\r\n\r\n while ((match = pattern.exec(str)) !== null) {\r\n if (match?.length < 2) continue;\r\n keyIds.push(match[1]);\r\n }\r\n\r\n return keyIds;\r\n};\r\n\r\nasync function getClientCredentialToken(data, logger, keyId, oauthTokens, config, agent) {\r\n const logAndThrowError = (message) => {\r\n logger.debug(message);\r\n throw new Error(message);\r\n };\r\n\r\n try {\r\n data = data[keyId] || {};\r\n const { clientID, clientSecret, tokenURL } = config.data;\r\n const currentTime = new Date().getTime();\r\n // Check for token expiration\r\n if (!oauthTokens.expiresIn || currentTime >= Number(oauthTokens.expiresIn)) {\r\n // Verify required parameters\r\n if (!clientID || !clientSecret || !tokenURL) {\r\n logAndThrowError('Missing client_id, client_secret OR token_url');\r\n }\r\n\r\n const params = new URLSearchParams({\r\n grant_type: 'client_credentials',\r\n client_id: clientID,\r\n client_secret: clientSecret,\r\n });\r\n\r\n const response = await axios.post(tokenURL, params.toString(), {\r\n headers: { 'Content-Type': 'application/x-www-form-urlencoded' },\r\n });\r\n\r\n console.log('Access token refreshed successfully.');\r\n logger.debug('Access token refreshed successfully.');\r\n\r\n const newAccessToken = response.data.access_token;\r\n const expiresInMilliseconds = response.data.expires_in * 1000;\r\n const expirationTimestamp = currentTime + expiresInMilliseconds;\r\n\r\n // Set data if it's empty\r\n if (Object.keys(data).length === 0) {\r\n data = {\r\n primary: '',\r\n secondary: '',\r\n type: 'oauth2',\r\n tokenURL,\r\n expires_in: '',\r\n team: agent.teamId,\r\n oauth_info: {\r\n oauth_keys_prefix: `OAUTH_${config.componentId ?? config.id}`,\r\n service: 'oauth2_client_credentials',\r\n tokenURL,\r\n clientID,\r\n clientSecret,\r\n },\r\n };\r\n }\r\n\r\n data.primary = newAccessToken;\r\n data.expires_in = expirationTimestamp.toString();\r\n //const oauthTeamSettings = new OauthTeamSettings();\r\n //const save = await oauthTeamSettings.update({ keyId: keyId, data: data });\r\n await managedVault.user(AccessCandidate.agent(agent.id)).set(keyId, data);\r\n\r\n return newAccessToken;\r\n } else {\r\n console.log('Access token value is still valid.');\r\n logger.debug('Access token value is still valid.');\r\n return oauthTokens.primaryToken;\r\n }\r\n } catch (error) {\r\n logAndThrowError(`Failed to refresh access token: ${error}`);\r\n }\r\n}\r\n","import axios, { AxiosRequestConfig } from 'axios';\r\nimport Joi from 'joi';\r\n\r\nimport { Agent } from '@sre/AgentManager/Agent.class';\r\nimport { Component } from '../Component.class';\r\nimport { parseHeaders } from './parseHeaders';\r\nimport { parseUrl, parseSmythFsUrl, destroyPublicUrls } from './parseUrl';\r\nimport { parseData } from './parseData';\r\nimport { parseProxy } from './parseProxy';\r\nimport { parseArrayBufferResponse } from './ArrayBufferResponse.helper';\r\nimport { extractAdditionalParamsForOAuth1, handleOAuthHeaders as generateOAuthHeaders } from './OAuth.helper';\r\nimport { SocksProxyAgent } from 'socks-proxy-agent';\r\nimport { formatDataForDebug } from '@sre/utils/data.utils';\r\n\r\nexport class APICall extends Component {\r\n protected schema = {\r\n name: 'APICall',\r\n description: 'Use this component to make an API call',\r\n inputs: {},\r\n outputs: {\r\n Headers: {\r\n description: 'The headers of the API call response',\r\n default: true,\r\n },\r\n Response: {\r\n description: 'The response of the API call',\r\n default: true,\r\n },\r\n },\r\n };\r\n\r\n protected configSchema = Joi.object({\r\n method: Joi.string().valid('GET', 'POST', 'PUT', 'PATCH', 'DELETE', 'HEAD', 'OPTIONS').required().label('Method'),\r\n url: Joi.string()\r\n .max(8192) /*.custom(isUrlValid, 'URL validation')*/\r\n .required()\r\n .label('URL'),\r\n headers: Joi.any().allow('').label('Headers'),\r\n contentType: Joi.string()\r\n .valid('none', 'application/json', 'multipart/form-data', 'binary', 'application/x-www-form-urlencoded', 'text/plain', 'application/xml')\r\n .label('Content-Type'),\r\n body: Joi.any().allow('').label('Body'),\r\n _templateSettings: Joi.object().allow(null).label('Template Settings'),\r\n _templateVars: Joi.object().allow(null).label('Template Variables'),\r\n proxy: Joi.string().allow('').label('Proxy'),\r\n oauthService: Joi.string().allow('').label('OAuth Service'),\r\n scope: Joi.string().allow('').label('Scope'),\r\n authorizationURL: Joi.string().allow('').label('Authorization URL'),\r\n tokenURL: Joi.string().allow('').label('Token URL'),\r\n clientID: Joi.string().allow('').label('Client ID'),\r\n clientSecret: Joi.string().allow('').label('Client Secret'),\r\n oauth2CallbackURL: Joi.string().allow('').label('OAuth2 Callback URL'),\r\n callbackURL: Joi.string().allow('').label('Callback URL'), // !TEMP: prevent validation error\r\n requestTokenURL: Joi.string().allow('').label('Request Token URL'),\r\n accessTokenURL: Joi.string().allow('').label('Access Token URL'),\r\n userAuthorizationURL: Joi.string().allow('').label('User Authorization URL'),\r\n consumerKey: Joi.string().allow('').label('Consumer Key'),\r\n consumerSecret: Joi.string().allow('').label('Consumer Secret'),\r\n oauth1CallbackURL: Joi.string().allow('').label('OAuth1 Callback URL'),\r\n authenticate: Joi.string().allow('').label('Authenticate'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n let publicUrls: string[] = [];\r\n\r\n try {\r\n logger.debug(`=== API Call Log ===`);\r\n\r\n const method = config?.data?.method || 'get';\r\n\r\n const reqConfig: AxiosRequestConfig = {};\r\n reqConfig.method = method;\r\n\r\n reqConfig.url = await parseUrl(input, config, agent);\r\n\r\n // We generate public URLs for any resources specified with the smythfs protocol in the request URL.\r\n ({ url: reqConfig.url, publicUrls } = await parseSmythFsUrl(reqConfig.url, agent));\r\n\r\n const { data, headers } = await parseData(input, config, agent);\r\n\r\n // If the data is null, the request may fail. We encountered an issue where a request failed due to null data being provided.\r\n let dataForDebug;\r\n if (data) {\r\n reqConfig.data = data;\r\n\r\n dataForDebug = await formatDataForDebug(data);\r\n }\r\n\r\n reqConfig.headers = (await parseHeaders(input, config, agent)).concat({ ...headers });\r\n\r\n const proxyConfig = await parseProxy(input, config, agent);\r\n\r\n if (proxyConfig) {\r\n if (proxyConfig instanceof SocksProxyAgent) {\r\n const isSecureEndpoint = reqConfig.url?.startsWith('https://');\r\n reqConfig[isSecureEndpoint ? 'httpsAgent' : 'httpAgent'] = proxyConfig;\r\n } else {\r\n reqConfig.proxy = proxyConfig;\r\n }\r\n }\r\n\r\n let Response: any = {};\r\n let Headers: any = {};\r\n let _error: any = undefined;\r\n try {\r\n if (config?.data?.oauthService && config?.data?.oauthService !== 'None') {\r\n const rootUrl = new URL(reqConfig.url).origin;\r\n const additionalParams = extractAdditionalParamsForOAuth1(reqConfig);\r\n const oauthHeaders = await generateOAuthHeaders(agent, config, reqConfig, logger, additionalParams, rootUrl);\r\n //reqConfig.headers = { ...reqConfig.headers, ...oauthHeaders };\r\n reqConfig.headers = reqConfig.headers.concat({ ...oauthHeaders });\r\n }\r\n\r\n // in order to handle binary data automatically, we need to set responseType to 'arraybuffer' for all requests, then parse the response data based on content-type\r\n reqConfig.responseType = 'arraybuffer';\r\n\r\n logger.debug('Making API call', { ...reqConfig, data: dataForDebug });\r\n\r\n const response = await axios.request(reqConfig);\r\n\r\n const parsedRes = await parseArrayBufferResponse(response, agent);\r\n\r\n // log response headers\r\n logger.debug('API call Response Headers', response.headers);\r\n Response = parsedRes;\r\n\r\n logger.debug('API call Response\\n', Response);\r\n\r\n Headers = Object.fromEntries(Object.entries(response.headers));\r\n } catch (error) {\r\n logger.debug(`Error making API call: ${error.message}`);\r\n Headers = error?.response?.headers ? Object.fromEntries(Object.entries(error.response.headers)) : {};\r\n Response = await parseArrayBufferResponse(error.response, agent);\r\n _error = error.message;\r\n }\r\n\r\n return { Response, Headers, _error, _debug: logger.output };\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n } finally {\r\n if (publicUrls.length > 0) {\r\n await destroyPublicUrls(publicUrls);\r\n }\r\n }\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class JSONFilter extends Component {\r\n protected configSchema = Joi.object({\r\n fields: Joi.string().max(30000).allow('').label('Prompt'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n logger.debug(`=== JSONFilter Log ===`);\r\n let Output = {};\r\n let _error = null;\r\n try {\r\n const componentId = config.id;\r\n const fields = config.data.fields;\r\n const obj = input.Input;\r\n\r\n Output = filterFields(obj, fields);\r\n logger.debug(`Output filtered`);\r\n } catch (error: any) {\r\n _error = error;\r\n logger.error(` JSONFilter Error`, error);\r\n }\r\n return { Output, _error, _debug: logger.output };\r\n }\r\n}\r\n\r\nfunction filterFields(obj, fields) {\r\n const fieldList = fields?.split(',').map((field) => field.trim());\r\n\r\n function filterObject(obj) {\r\n if (Array.isArray(obj)) {\r\n return obj.map(filterObject);\r\n } else if (obj !== null && typeof obj === 'object') {\r\n return Object.keys(obj)\r\n .filter((key) => fieldList.includes(key))\r\n .reduce((acc, key) => {\r\n acc[key] = filterObject(obj[key]);\r\n return acc;\r\n }, {});\r\n }\r\n return obj;\r\n }\r\n\r\n return filterObject(obj);\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class LogicAND extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n const result: any = { Output: true };\r\n\r\n for (let cfgInput of config.inputs) {\r\n // check if all inputs are set (expected inputs are in \"config.inputs\" actual inputs are in \"input\")\r\n if (!input[cfgInput.name]) {\r\n result.Output = undefined;\r\n break;\r\n }\r\n }\r\n\r\n result.Verified = result.Output !== undefined;\r\n result.Unverified = !result.Verified;\r\n if (!result.Verified) delete result.Verified;\r\n if (!result.Unverified) delete result.Unverified;\r\n return result;\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class LogicOR extends Component {\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const result: any = { Output: undefined };\r\n console.log(input);\r\n console.log(config);\r\n for (let cfgInput of config.inputs) {\r\n // check if one of the inputs are set (expected inputs are in \"config.inputs\" actual inputs are in \"input\")\r\n if (input[cfgInput.name]) {\r\n result.Output = true;\r\n break;\r\n }\r\n }\r\n\r\n result.Verified = result.Output !== undefined;\r\n result.Unverified = !result.Verified;\r\n if (!result.Verified) delete result.Verified;\r\n if (!result.Unverified) delete result.Unverified;\r\n\r\n return result;\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class LogicXOR extends Component {\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const result: any = { Output: undefined };\r\n let trueCount = 0;\r\n\r\n for (let cfgInput of config.inputs) {\r\n // counts the number of set inputs\r\n if (input[cfgInput.name]) {\r\n trueCount++;\r\n }\r\n }\r\n // checks if only one input is set, to trigger output\r\n if (trueCount === 1) {\r\n result.Output = true;\r\n }\r\n\r\n result.Verified = result.Output !== undefined;\r\n result.Unverified = !result.Verified;\r\n if (!result.Verified) delete result.Verified;\r\n if (!result.Unverified) delete result.Unverified;\r\n\r\n return result;\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class LogicAtLeast extends Component {\r\n protected configSchema = Joi.object({\r\n // TODO (Forhad): Need to check if min and max work instead of the custom validateInteger\r\n minSetInputs: Joi.string()\r\n .custom(validateInteger({ min: 0, max: 9 }), 'custom range validation')\r\n .label('Minimum Inputs'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n const result: any = { Output: undefined };\r\n\r\n if (typeof config.data.minSetInputs !== 'string' || config.data.minSetInputs.trim() === '' || isNaN(Number(config.data.minSetInputs))) {\r\n return result;\r\n }\r\n\r\n const minSetInputs = Number(config.data.minSetInputs);\r\n if (config.inputs.length < minSetInputs) {\r\n return result;\r\n }\r\n\r\n let trueCount = 0;\r\n for (let cfgInput of config.inputs) {\r\n if (input[cfgInput.name]) {\r\n trueCount++;\r\n }\r\n }\r\n\r\n if (trueCount >= minSetInputs) {\r\n result.Output = true;\r\n }\r\n\r\n result.Verified = result.Output !== undefined;\r\n result.Unverified = !result.Verified;\r\n if (!result.Verified) delete result.Verified;\r\n if (!result.Unverified) delete result.Unverified;\r\n\r\n return result;\r\n }\r\n}\r\n\r\ninterface RangeValidationArgs {\r\n min?: number;\r\n max?: number;\r\n}\r\n\r\nfunction validateInteger(args: RangeValidationArgs) {\r\n return (value: string, helpers: any) => {\r\n const numValue = Number(value);\r\n const fieldName = helpers.schema._flags.label || helpers.state.path[helpers.state.path.length - 1];\r\n\r\n // Check if the value is a number\r\n if (isNaN(numValue)) {\r\n throw new Error(`The value for '${fieldName}' must be a number`);\r\n }\r\n\r\n // Range validations\r\n if (args.min !== undefined && args.max !== undefined) {\r\n if (numValue < args.min || numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be from ${args.min} to ${args.max}`);\r\n }\r\n } else if (args.min !== undefined) {\r\n if (numValue < args.min) {\r\n throw new Error(`The value for '${fieldName}' must be greater or equal to ${args.min}`);\r\n }\r\n } else if (args.max !== undefined) {\r\n if (numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be less or equal to ${args.max}`);\r\n }\r\n }\r\n\r\n return value; // Value is valid\r\n };\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\n\r\nexport class LogicAtMost extends Component {\r\n protected configSchema = Joi.object({\r\n // TODO (Forhad): Need to check if min and max work instead of the custom validateInteger\r\n maxSetInputs: Joi.string()\r\n .custom(validateInteger({ min: 0, max: 9 }), 'custom range validation')\r\n .label('Maximum Inputs'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const result: any = { Output: undefined };\r\n\r\n if (typeof config.data.maxSetInputs !== 'string' || config.data.maxSetInputs.trim() === '' || isNaN(Number(config.data.maxSetInputs))) {\r\n return result;\r\n }\r\n\r\n const maxSetInputs = Number(config.data.maxSetInputs);\r\n if (config.inputs.length < maxSetInputs) {\r\n return result;\r\n }\r\n\r\n let trueCount = 0;\r\n for (let cfgInput of config.inputs) {\r\n if (input[cfgInput.name]) {\r\n trueCount++;\r\n if (trueCount > maxSetInputs) {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if (trueCount <= maxSetInputs) {\r\n result.Output = true;\r\n }\r\n\r\n result.Verified = result.Output !== undefined;\r\n result.Unverified = !result.Verified;\r\n if (!result.Verified) delete result.Verified;\r\n if (!result.Unverified) delete result.Unverified;\r\n\r\n return result;\r\n }\r\n}\r\ninterface RangeValidationArgs {\r\n min?: number;\r\n max?: number;\r\n}\r\n\r\nfunction validateInteger(args: RangeValidationArgs) {\r\n return (value: string, helpers: any) => {\r\n const numValue = Number(value);\r\n const fieldName = helpers.schema._flags.label || helpers.state.path[helpers.state.path.length - 1];\r\n\r\n // Check if the value is a number\r\n if (isNaN(numValue)) {\r\n throw new Error(`The value for '${fieldName}' must be a number`);\r\n }\r\n\r\n // Range validations\r\n if (args.min !== undefined && args.max !== undefined) {\r\n if (numValue < args.min || numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be from ${args.min} to ${args.max}`);\r\n }\r\n } else if (args.min !== undefined) {\r\n if (numValue < args.min) {\r\n throw new Error(`The value for '${fieldName}' must be greater or equal to ${args.min}`);\r\n }\r\n } else if (args.max !== undefined) {\r\n if (numValue > args.max) {\r\n throw new Error(`The value for '${fieldName}' must be less or equal to ${args.max}`);\r\n }\r\n }\r\n\r\n return value; // Value is valid\r\n };\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { DEFAULT_MAX_TOKENS_FOR_LLM } from '@sre/constants';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { encode } from 'gpt-tokenizer';\r\nimport { Component } from './Component.class';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { LLMInference } from '@sre/LLMManager/LLM.inference';\r\nimport { TLLMMessageRole } from '@sre/types/LLM.types';\r\nimport { VaultHelper } from '@sre/Security/Vault.service/Vault.helper';\r\nimport path from 'path';\r\nimport config from '@sre/config';\r\nimport fs from 'fs/promises';\r\n\r\n//const sessions = {};\r\nlet cacheConnector: CacheConnector;\r\nfunction getCacheConnector() {\r\n if (!cacheConnector) {\r\n cacheConnector = ConnectorService.getCacheConnector();\r\n }\r\n return cacheConnector;\r\n}\r\n\r\nasync function saveMessagesToSession(agentId, userId, conversationId, messages, ttl?) {\r\n if (!userId && !conversationId) return;\r\n const cacheConnector = getCacheConnector();\r\n const conv_uid = `${agentId}:conv-u${userId}-c${conversationId}`;\r\n\r\n cacheConnector.requester(AccessCandidate.agent(agentId)).set(conv_uid, JSON.stringify(messages), null, null, ttl);\r\n}\r\n\r\nasync function readMessagesFromSession(agentId, userId, conversationId, maxTokens = DEFAULT_MAX_TOKENS_FOR_LLM) {\r\n if (!userId && !conversationId) return [];\r\n const cacheConnector = getCacheConnector();\r\n\r\n const conv_uid = `${agentId}:conv-u${userId}-c${conversationId}`;\r\n //read the last messages from a given session and ensure that the total chat tokens are within the limit\r\n //start from the last message and keep adding messages until the total tokens exceed the limit\r\n //if (!sessions[agentId]) return [];\r\n //if (!sessions[agentId][conv_uid]) return [];\r\n\r\n const sessionData = await cacheConnector.requester(AccessCandidate.agent(agentId))?.get(conv_uid);\r\n\r\n let messages = sessionData ? JSONContent(sessionData).tryParse() : [];\r\n\r\n //const messages = sessions[agentId][conv_uid].messages;\r\n\r\n const filteredMessages: any[] = [];\r\n\r\n let tokens = 0;\r\n if (messages[0]?.role == 'system') {\r\n const encoded = encode(messages[0]?.content);\r\n const messageTokens = encoded.length + 3;\r\n tokens += messageTokens;\r\n }\r\n\r\n for (let i = messages.length - 1; i >= 0; i--) {\r\n if (messages[i].role == 'system') continue;\r\n const message = messages[i];\r\n const encoded = encode(message?.content);\r\n const messageTokens = encoded.length + 3;\r\n if (tokens + messageTokens > maxTokens) break;\r\n filteredMessages.unshift(message);\r\n tokens += messageTokens;\r\n }\r\n\r\n if (messages[0]?.role == 'system') filteredMessages.unshift(messages[0]);\r\n\r\n return filteredMessages;\r\n}\r\n\r\n//TODO : update this implementation to use ConversationManager\r\n// This will allow better context management and support for tool calls\r\nexport class LLMAssistant extends Component {\r\n protected configSchema = Joi.object({\r\n model: Joi.string().max(200).required(),\r\n behavior: Joi.string().max(30000).allow('').label('Behavior'),\r\n passthrough: Joi.boolean().optional().label('Passthrough'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n logger.debug('== LLM Assistant Log ==\\n');\r\n\r\n const passThrough: boolean = config.data.passthrough || false;\r\n const model: string = config.data.model || 'echo';\r\n const ttl = config.data.ttl || undefined;\r\n let teamId = agent?.teamId;\r\n\r\n const llmInference: LLMInference = await LLMInference.getInstance(model, AccessCandidate.agent(agent.id));\r\n // if the llm is undefined, then it means we removed the model from our system\r\n if (!llmInference.connector) {\r\n return {\r\n _error: `The model '${model}' is not available. Please try a different one.`,\r\n _debug: logger.output,\r\n };\r\n }\r\n\r\n const modelId = await agent.modelsProvider.getModelId(model);\r\n logger.debug(` Model : ${modelId || model}`);\r\n\r\n const userInput = input.UserInput;\r\n const userId = input.UserId;\r\n const conversationId = input.ConversationId;\r\n\r\n let behavior = TemplateString(config.data.behavior).parse(input).result;\r\n logger.debug(`[Parsed Behavior] \\n${behavior}\\n\\n`);\r\n\r\n //#region get max tokens\r\n let maxTokens = 2048;\r\n\r\n const isStandardLLM = await agent.modelsProvider.isStandardLLM(model);\r\n const hasKey = true; //TODO : check if the user has a key\r\n //const modelInfo = await agent.modelsProvider.getModelInfo(model, hasKey);\r\n maxTokens = await agent.modelsProvider.getMaxCompletionTokens(model, hasKey);\r\n\r\n // if (isStandardLLM) {\r\n // const provider = LLMRegistry.getProvider(model);\r\n // const apiKey = await VaultHelper.getAgentKey(provider, agent?.id);\r\n // maxTokens = LLMRegistry.getMaxCompletionTokens(model, !!apiKey);\r\n // } else {\r\n // const team = AccessCandidate.team(teamId);\r\n // const customLLMRegistry = await CustomLLMRegistry.getInstance(team);\r\n // maxTokens = await customLLMRegistry.getMaxCompletionTokens(model);\r\n // }\r\n //#endregion get max tokens\r\n\r\n const messages: any[] = await readMessagesFromSession(agent.id, userId, conversationId, Math.round(maxTokens / 2));\r\n\r\n messages.push({ role: TLLMMessageRole.User, content: userInput });\r\n\r\n if (messages[0]?.role != TLLMMessageRole.System) {\r\n messages.unshift({ role: TLLMMessageRole.System, content: behavior });\r\n }\r\n\r\n const customParams = {\r\n messages,\r\n };\r\n\r\n let response: any;\r\n if (passThrough) {\r\n const contentPromise = new Promise(async (resolve, reject) => {\r\n let _content = '';\r\n const eventEmitter: any = await llmInference\r\n .promptStream({\r\n contextWindow: messages,\r\n params: { ...config, model, agentId: agent.id },\r\n })\r\n .catch((error) => {\r\n console.error('Error on promptStream: ', error);\r\n reject(error);\r\n });\r\n eventEmitter.on('content', (content) => {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ content });\r\n }\r\n agent.sse.send('llm/passthrough/content', content);\r\n _content += content;\r\n });\r\n eventEmitter.on('thinking', (thinking) => {\r\n if (typeof agent.callback === 'function') {\r\n agent.callback({ thinking });\r\n }\r\n agent.sse.send('llm/passthrough/thinking', thinking);\r\n });\r\n eventEmitter.on('end', () => {\r\n console.log('end');\r\n resolve(_content);\r\n });\r\n });\r\n response = await contentPromise;\r\n } else {\r\n response = await llmInference\r\n .prompt({ contextWindow: messages, params: { ...config, agentId: agent.id } })\r\n .catch((error) => ({ error: error }));\r\n }\r\n\r\n // in case we have the response but it's empty string, undefined or null\r\n if (!response) {\r\n return { _error: ' LLM Error = Empty Response!', _debug: logger.output };\r\n }\r\n\r\n if (response?.error) {\r\n const error = response?.error + ' ' + (response?.details || '');\r\n logger.error(` LLM Error=`, error);\r\n\r\n return { Response: response?.data, _error: error, _debug: logger.output };\r\n }\r\n\r\n messages.push({ role: 'assistant', content: response });\r\n saveMessagesToSession(agent.id, userId, conversationId, messages, ttl);\r\n\r\n logger.debug(' Response \\n', response);\r\n\r\n const result = { Response: response };\r\n\r\n result['_debug'] = logger.output;\r\n\r\n return result;\r\n } catch (error) {\r\n return { _error: error.message, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport SREConfig from '@sre/config';\r\nimport axios from 'axios';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { AccessCandidate } from '../subsystems/Security/AccessControl/AccessCandidate.class';\r\nimport { getCredentials } from '../subsystems/Security/Credentials.helper';\r\n// const CREDITS_PER_URL = 0.2;\r\n\r\nexport class ScrapflyWebScrape extends Component {\r\n protected configSchema = Joi.object({\r\n // includeImages: Joi.boolean().default(false).label('Include Image Results'),\r\n antiScrapingProtection: Joi.boolean().default(false).label('Enable Anti-Scraping Protection'),\r\n javascriptRendering: Joi.boolean().default(false).label('Enable JavaScript Rendering'),\r\n autoScroll: Joi.boolean().default(false).label('Enable Auto Scroll'),\r\n format: Joi.string().default('markdown').label('Format').optional(),\r\n });\r\n\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n logger.debug(`=== Web Scrape Log ===`);\r\n let Output: any = {};\r\n let _error = undefined;\r\n const scrapeUrls = this.extractUrls(input);\r\n logger.debug('Payload:', JSON.stringify(config.data));\r\n logger.debug(`Vaild URLs: ${JSON.stringify(scrapeUrls)}`);\r\n const teamId = agent.teamId;\r\n const key = await getCredentials(AccessCandidate.team(teamId), 'scrapfly');\r\n\r\n const scrapeResults = await Promise.all(scrapeUrls.map((url) => this.scrapeURL(url, config.data, key)));\r\n const results = scrapeResults\r\n .filter((result) => result.success)\r\n .map((result) => {\r\n return { url: result.url, content: result.content };\r\n });\r\n const failedResults = scrapeResults\r\n .filter((result) => !result.success)\r\n .map((result) => {\r\n return { url: result.url, error: result.error };\r\n });\r\n\r\n Output = { Results: results, FailedURLs: failedResults };\r\n const totalCredits = scrapeResults.reduce((acc, result) => acc + (result.cost || 0), 0);\r\n this.reportUsage({\r\n urlsScraped: results?.length,\r\n agentId: agent.id,\r\n teamId: agent.teamId,\r\n totalCredits,\r\n });\r\n return { ...Output, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.message || err?.response?.data || err.toString();\r\n logger.error(` Error scraping web \\n${_error}\\n`);\r\n return { Output: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n\r\n async scrapeURL(url, data, key) {\r\n try {\r\n const response = await axios({\r\n method: 'get',\r\n url: 'https://api.scrapfly.io/scrape',\r\n params: {\r\n url: encodeURIComponent(url),\r\n key,\r\n cost_budget: 80,\r\n ...(data.format ? { format: data.format } : { format: 'markdown' }),\r\n ...(data.antiScrapingProtection && { asp: true }),\r\n ...(data.javascriptRendering && { render_js: true }),\r\n ...(data.autoScroll && { auto_scroll: true, render_js: true }),\r\n },\r\n });\r\n return {\r\n content: response.data?.result?.content,\r\n success: true,\r\n url,\r\n cost: response.data?.context?.cost?.total || 0,\r\n };\r\n } catch (error) {\r\n return {\r\n content: undefined,\r\n success: false,\r\n error: error?.response?.data?.result?.error?.message || 'Failed to scrape URL',\r\n url,\r\n cost: 0,\r\n };\r\n }\r\n }\r\n\r\n extractUrls(input: any) {\r\n const scrapeUrls = [];\r\n for (const key in input) {\r\n if (Object.prototype.hasOwnProperty.call(input, key)) {\r\n const inputItem = input[key];\r\n if (typeof inputItem === 'string') {\r\n try {\r\n let urls = JSON.parse(inputItem);\r\n for (const url of urls) {\r\n if (this.isValidUrl(url)) {\r\n scrapeUrls.push(url.trim());\r\n }\r\n }\r\n } catch (error) {\r\n const commaSeparatedUrls = inputItem.split(',');\r\n for (const url of commaSeparatedUrls) {\r\n if (this.isValidUrl(url)) {\r\n scrapeUrls.push(url.trim());\r\n }\r\n }\r\n }\r\n } else if (typeof inputItem === 'object') {\r\n for (const url of inputItem) {\r\n if (this.isValidUrl(url)) {\r\n scrapeUrls.push(url.trim());\r\n }\r\n }\r\n }\r\n }\r\n }\r\n return scrapeUrls;\r\n }\r\n\r\n isValidUrl(urlString: string) {\r\n try {\r\n const urlToCheck = urlString;\r\n new URL(urlToCheck);\r\n return true;\r\n } catch (error) {\r\n return false;\r\n }\r\n }\r\n\r\n protected reportUsage({\r\n urlsScraped,\r\n agentId,\r\n teamId,\r\n totalCredits,\r\n }: {\r\n urlsScraped: number;\r\n agentId: string;\r\n teamId: string;\r\n totalCredits: number;\r\n }) {\r\n SystemEvents.emit('USAGE:API', {\r\n sourceId: 'api:webscrape.smyth',\r\n credits: totalCredits,\r\n agentId,\r\n teamId,\r\n });\r\n }\r\n}\r\n","import { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Component } from './Component.class';\r\nimport Joi from 'joi';\r\nimport SREConfig from '@sre/config';\r\nimport axios from 'axios';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { getCredentials } from '../subsystems/Security/Credentials.helper';\r\nimport { AccessCandidate } from '../subsystems/Security/AccessControl/AccessCandidate.class';\r\n\r\nexport class TavilyWebSearch extends Component {\r\n protected schema = {\r\n name: 'TavilyWebSearch',\r\n description: 'Use this component to generate a responses from an LLM',\r\n\r\n inputs: {\r\n SearchQuery: {\r\n type: 'Text',\r\n description: 'The search query to get the web search results of',\r\n default: true,\r\n },\r\n },\r\n outputs: {\r\n Results: {\r\n type: 'Array',\r\n description: 'The web search results',\r\n default: true,\r\n },\r\n },\r\n };\r\n\r\n protected configSchema = Joi.object({\r\n includeImages: Joi.boolean().default(false).label('Include Image Results'),\r\n sourcesLimit: Joi.number().integer().default(10).label('Sources Limit'),\r\n searchTopic: Joi.string().valid('general', 'news').label('Search Topic'),\r\n includeQAs: Joi.boolean().default(false).label('Include QAs'),\r\n timeRange: Joi.string().valid('None', 'day', 'week', 'month', 'year').label('Time Range'),\r\n includeRawContent: Joi.boolean().default(false).label('Include Raw Content'),\r\n excludeDomains: Joi.string().allow('').label('Exclude Domains'),\r\n });\r\n constructor() {\r\n super();\r\n }\r\n init() {}\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n\r\n const logger = this.createComponentLogger(agent, config);\r\n try {\r\n logger.debug(`=== Web Scrape Log ===`);\r\n let Output: any = {};\r\n let _error = undefined;\r\n let searchQuery = input['SearchQuery'];\r\n\r\n const teamId = agent.teamId;\r\n const api_key = await getCredentials(AccessCandidate.team(teamId), 'tavily');\r\n\r\n logger.debug('Payload:', JSON.stringify(config.data));\r\n const response = await axios({\r\n method: 'post',\r\n url: 'https://api.tavily.com/search',\r\n data: {\r\n api_key,\r\n query: searchQuery,\r\n topic: config.data.searchTopic,\r\n exclude_domains: config.data.excludeDomains?.length ? config.data.excludeDomains.split(',') : [],\r\n max_results: config.data.sourcesLimit,\r\n ...(config.data.timeRange !== 'None' ? { time_range: config.data.timeRange } : {}),\r\n ...(config.data.includeImages ? { include_images: true } : {}),\r\n ...(config.data.includeQAs ? { include_answer: true } : {}),\r\n ...(config.data.includeRawContent ? { include_raw_content: true } : {}),\r\n },\r\n });\r\n Output = {\r\n Results: response.data.results,\r\n ...(config.data.includeImages ? { Images: response.data.images } : {}),\r\n ...(config.data.includeQAs ? { Answer: response.data.answer } : {}),\r\n };\r\n this.reportUsage({\r\n agentId: agent.id,\r\n teamId: agent.teamId,\r\n });\r\n return { ...Output, _error, _debug: logger.output };\r\n } catch (err: any) {\r\n const _error = err?.message || err?.response?.data || err.toString();\r\n logger.error(` Error scraping web \\n${JSON.stringify(_error)}\\n`);\r\n return { Output: undefined, _error, _debug: logger.output };\r\n }\r\n }\r\n\r\n protected reportUsage({ agentId, teamId }: { agentId: string; teamId: string }) {\r\n SystemEvents.emit('USAGE:API', {\r\n sourceId: 'api:websearch.smyth',\r\n credits: 1,\r\n agentId,\r\n teamId,\r\n });\r\n }\r\n}\r\n","import Joi from 'joi';\r\n\r\nimport { IAgent as Agent } from '@sre/types/Agent.types';\r\nimport { Conversation } from '@sre/helpers/Conversation.helper';\r\nimport { TemplateString } from '@sre/helpers/TemplateString.helper';\r\n\r\nimport { Component } from './Component.class';\r\nimport { Client } from '@modelcontextprotocol/sdk/client/index.js';\r\nimport { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';\r\n\r\nexport class MCPClient extends Component {\r\n protected configSchema = Joi.object({\r\n model: Joi.string().optional(),\r\n openAiModel: Joi.string().optional(), // for backward compatibility\r\n mcpUrl: Joi.string().max(2048).uri().required().description('URL of the MCP'),\r\n descForModel: Joi.string().max(5000).required().allow('').label('Description for Model'),\r\n name: Joi.string().max(500).required().allow(''),\r\n desc: Joi.string().max(5000).required().allow('').label('Description'),\r\n logoUrl: Joi.string().max(8192).allow(''),\r\n id: Joi.string().max(200),\r\n version: Joi.string().max(100).allow(''),\r\n domain: Joi.string().max(253).allow(''),\r\n prompt: Joi.string().max(5000).optional().allow('').label('Prompt'),\r\n });\r\n\r\n constructor() {\r\n super();\r\n }\r\n\r\n init() {}\r\n\r\n async process(input, config, agent: Agent) {\r\n await super.process(input, config, agent);\r\n const logger = this.createComponentLogger(agent, config);\r\n\r\n logger.debug(`=== MCP Client Log ===`);\r\n\r\n try {\r\n const mcpUrl = config?.data?.mcpUrl;\r\n if (!mcpUrl) {\r\n return { _error: 'Please provide a MCP URL!', _debug: logger.output };\r\n }\r\n\r\n const model = config?.data?.model || config?.data?.openAiModel;\r\n const descForModel = TemplateString(config?.data?.descForModel).parse(input).result;\r\n let prompt = TemplateString(config?.data?.prompt).parse(input).result;\r\n\r\n if (!prompt) {\r\n return { _error: 'Please provide a prompt', _debug: logger.output };\r\n }\r\n\r\n // TODO [Forhad]: Need to check and validate input prompt token\r\n const baseUrl = new URL(mcpUrl);\r\n const transport = new SSEClientTransport(baseUrl);\r\n const client = new Client({\r\n name: 'sse-client',\r\n version: '1.0.0',\r\n });\r\n await client.connect(transport);\r\n const toolsData = await client.listTools();\r\n const conv = new Conversation(\r\n model,\r\n {\r\n openapi: '3.0.1',\r\n info: {\r\n title: `${agent?.name}`,\r\n version: `${agent?.version}`,\r\n description: descForModel,\r\n },\r\n servers: [\r\n {\r\n url: agent?.domain,\r\n },\r\n ],\r\n paths: {},\r\n },\r\n { agentId: agent?.id },\r\n );\r\n\r\n for (const tool of toolsData.tools) {\r\n let toolArgs = {};\r\n Object.entries(tool.inputSchema.properties).forEach(([propName, propDetails]) => {\r\n toolArgs[propName] = {\r\n description: '',\r\n required: ((tool.inputSchema.required as string[]) || []).includes(propName) || false,\r\n type: (propDetails as any).type,\r\n ...((propDetails as any).type === 'array' ? { items: { type: 'string' } } : {}),\r\n };\r\n });\r\n await conv.addTool({\r\n name: tool.name,\r\n description: tool.description,\r\n arguments: toolArgs,\r\n handler: async (input) => {\r\n const result = await client.callTool({\r\n name: tool.name,\r\n arguments: input,\r\n });\r\n return result;\r\n },\r\n });\r\n }\r\n const result = await conv.prompt(prompt);\r\n\r\n logger.debug(`Response:\\n`, result, '\\n');\r\n\r\n return { Output: result, _debug: logger.output };\r\n } catch (error: any) {\r\n return { _error: `Error on running MCP Client!\\n${error?.message || JSON.stringify(error)}`, _debug: logger.output };\r\n }\r\n }\r\n}\r\n","import { Component } from './Component.class';\r\nimport { APIEndpoint } from './APIEndpoint.class';\r\nimport { APIOutput } from './APIOutput.class';\r\nimport { PromptGenerator } from './PromptGenerator.class';\r\nimport { APICall } from './APICall/APICall.class';\r\nimport { FSleep } from './FSleep.class';\r\nimport { FHash } from './FHash.class';\r\nimport { FEncDec } from './FEncDec.class';\r\nimport { FTimestamp } from './FTimestamp.class';\r\nimport { DataSourceLookup } from './DataSourceLookup.class';\r\nimport { DataSourceIndexer } from './DataSourceIndexer.class';\r\nimport { DataSourceCleaner } from './DataSourceCleaner.class';\r\nimport { JSONFilter } from './JSONFilter.class';\r\nimport { LogicAND } from './LogicAND.class';\r\nimport { LogicOR } from './LogicOR.class';\r\nimport { LogicXOR } from './LogicXOR.class';\r\nimport { LogicAtLeast } from './LogicAtLeast.class';\r\nimport { LogicAtMost } from './LogicAtMost.class';\r\nimport { AgentPlugin } from './AgentPlugin.class';\r\nimport { LLMAssistant } from './LLMAssistant.class';\r\nimport { Async } from './Async.class';\r\nimport { Await } from './Await.class';\r\nimport { ForEach } from './ForEach.class';\r\nimport { HuggingFace } from './HuggingFace.class';\r\nimport { GPTPlugin } from './GPTPlugin.class';\r\nimport { Classifier } from './Classifier.class';\r\nimport { FSign } from './FSign.class';\r\nimport { GenAILLM } from './GenAILLM.class';\r\nimport { FileStore } from './FileStore.class';\r\nimport { ScrapflyWebScrape } from './ScrapflyWebScrape.class';\r\nimport { TavilyWebSearch } from './TavilyWebSearch.class';\r\nimport { ComponentHost } from './ComponentHost.class';\r\nimport { ImageGenerator } from './ImageGenerator.class'; // Legacy\r\nimport { MCPClient } from './MCPClient.class';\r\n\r\nconst components = {\r\n Component: new Component(),\r\n Note: new Component(), //this is a fake component\r\n APIEndpoint: new APIEndpoint(),\r\n APIOutput: new APIOutput(),\r\n PromptGenerator: new PromptGenerator(),\r\n LLMPrompt: new PromptGenerator(),\r\n APICall: new APICall(),\r\n FSleep: new FSleep(),\r\n FHash: new FHash(),\r\n FEncDec: new FEncDec(),\r\n FSign: new FSign(),\r\n FTimestamp: new FTimestamp(),\r\n DataSourceLookup: new DataSourceLookup(),\r\n DataSourceIndexer: new DataSourceIndexer(),\r\n DataSourceCleaner: new DataSourceCleaner(),\r\n JSONFilter: new JSONFilter(),\r\n LogicAND: new LogicAND(),\r\n LogicOR: new LogicOR(),\r\n LogicXOR: new LogicXOR(),\r\n LogicAtLeast: new LogicAtLeast(),\r\n LogicAtMost: new LogicAtMost(),\r\n AgentPlugin: new AgentPlugin(),\r\n LLMAssistant: new LLMAssistant(),\r\n Async: new Async(),\r\n Await: new Await(),\r\n ForEach: new ForEach(),\r\n HuggingFace: new HuggingFace(),\r\n GPTPlugin: new GPTPlugin(),\r\n Classifier: new Classifier(),\r\n GenAILLM: new GenAILLM(),\r\n FileStore: new FileStore(),\r\n WebSearch: new TavilyWebSearch(),\r\n WebScrape: new ScrapflyWebScrape(),\r\n TavilyWebSearch: new TavilyWebSearch(),\r\n ScrapflyWebScrape: new ScrapflyWebScrape(),\r\n ComponentHost: new ComponentHost(),\r\n ImageGenerator: new ImageGenerator(),\r\n MCPClient: new MCPClient(),\r\n};\r\n\r\nexport const ComponentInstances = components;\r\n","import { GetBucketLifecycleConfigurationCommandOutput, PutBucketLifecycleConfigurationCommand } from '@aws-sdk/client-s3';\r\n\r\nimport { GetBucketLifecycleConfigurationCommand } from '@aws-sdk/client-s3';\r\n\r\nimport { S3Client } from '@aws-sdk/client-s3';\r\n\r\nexport function generateLifecycleRules() {\r\n const rules = [];\r\n\r\n // Add rules for 1-100 days\r\n for (let i = 1; i < 100; i++) {\r\n rules.push({\r\n ID: `ExpireAfter${i}Days`,\r\n Filter: {\r\n // Prefix: '',\r\n Tag: {\r\n Key: 'Expiry',\r\n Value: 'ExpireAfter' + i + 'Days',\r\n },\r\n },\r\n Status: 'Enabled',\r\n Expiration: { Days: i },\r\n });\r\n }\r\n\r\n // Add rules for 110-1000 days with 10-day steps\r\n for (let i = 100; i < 1000; i += 10) {\r\n rules.push({\r\n ID: `ExpireAfter${i}Days`,\r\n Filter: {\r\n // Prefix: '',\r\n Tag: {\r\n Key: 'Expiry',\r\n Value: 'ExpireAfter' + i + 'Days',\r\n },\r\n },\r\n Status: 'Enabled',\r\n Expiration: { Days: i },\r\n });\r\n }\r\n\r\n // Add rules for 1000-10000 days with 100-day steps\r\n for (let i = 1000; i <= 10000; i += 100) {\r\n rules.push({\r\n ID: `ExpireAfter${i}Days`,\r\n Filter: {\r\n // Prefix: '',\r\n Tag: {\r\n Key: 'Expiry',\r\n Value: 'ExpireAfter' + i + 'Days',\r\n },\r\n },\r\n Status: 'Enabled',\r\n Expiration: { Days: i },\r\n });\r\n }\r\n\r\n return rules;\r\n}\r\n\r\n\r\nexport function generateExpiryMetadata(expiryDays) {\r\n let metadataValue;\r\n\r\n if (expiryDays >= 1 && expiryDays < 100) {\r\n metadataValue = `ExpireAfter${expiryDays}Days`;\r\n } else if (expiryDays >= 100 && expiryDays < 1000) {\r\n const roundedUpDays = Math.ceil(expiryDays / 10) * 10;\r\n metadataValue = `ExpireAfter${roundedUpDays}Days`;\r\n } else if (expiryDays >= 1000 && expiryDays <= 10000) {\r\n const roundedUpDays = Math.ceil(expiryDays / 100) * 100;\r\n metadataValue = `ExpireAfter${roundedUpDays}Days`;\r\n } else {\r\n throw new Error('Invalid expiry days. Please provide a valid expiry days value.');\r\n }\r\n\r\n return {\r\n Key: 'Expiry',\r\n Value: metadataValue,\r\n };\r\n}\r\n\r\nexport function getNonExistingRules(existingRules: any[], newRules: any[]) {\r\n return newRules.filter((rule) => !existingRules.some((existingRule) => existingRule.ID === rule.ID));\r\n}\r\n\r\nexport function ttlToExpiryDays(ttl: number) {\r\n // seconds\r\n return Math.ceil(ttl / (60 * 60 * 24));\r\n}\r\n\r\nexport async function checkAndInstallLifecycleRules(bucketName: string, s3Client: S3Client) {\r\n try {\r\n // Check existing lifecycle configuration\r\n const getLifecycleCommand = new GetBucketLifecycleConfigurationCommand({ Bucket: bucketName });\r\n const existingLifecycle: GetBucketLifecycleConfigurationCommandOutput = await s3Client.send(getLifecycleCommand);\r\n const existingRules = existingLifecycle.Rules;\r\n const newRules = generateLifecycleRules();\r\n const nonExistingNewRules = getNonExistingRules(existingRules, newRules);\r\n if (nonExistingNewRules.length > 0) {\r\n const params = {\r\n Bucket: bucketName,\r\n LifecycleConfiguration: { Rules: [...existingRules, ...nonExistingNewRules] },\r\n };\r\n const putLifecycleCommand = new PutBucketLifecycleConfigurationCommand(params);\r\n // Put the new lifecycle configuration\r\n await s3Client.send(putLifecycleCommand);\r\n } else {\r\n console.log('Lifecycle configuration already exists');\r\n }\r\n } catch (error) {\r\n if (error.code === 'NoSuchLifecycleConfiguration') {\r\n console.log('No lifecycle configuration found. Creating new configuration...');\r\n\r\n const lifecycleRules = generateLifecycleRules();\r\n\r\n const params = {\r\n Bucket: bucketName,\r\n LifecycleConfiguration: { Rules: lifecycleRules },\r\n };\r\n const putLifecycleCommand = new PutBucketLifecycleConfigurationCommand(params);\r\n // Put the new lifecycle configuration\r\n await s3Client.send(putLifecycleCommand);\r\n console.log('Lifecycle configuration created successfully.');\r\n } else {\r\n console.error('Error checking lifecycle configuration:', error);\r\n }\r\n }\r\n}\r\n","//==[ SRE: S3Storage ]======================\r\n\r\n//#region = [Polyfill for CommonJS] =================================\r\n\r\n//S3 Methods fail in CommonJS build because they expect a global 'crypto' object with a 'getRandomValues' method\r\n//getRandomValues is supposed to be for browser environments, but it seems that CommonJS build leaks some browser related code to the packaged AWS-SDK\r\nimport crypto from 'crypto';\r\n\r\nObject.defineProperty(global, 'crypto', {\r\n value: {\r\n getRandomValues: (arr: any) => crypto.randomBytes(arr.length),\r\n },\r\n});\r\n//#endregion\r\n\r\nimport {\r\n DeleteObjectCommand,\r\n GetObjectCommand,\r\n GetObjectCommandOutput,\r\n HeadObjectCommand,\r\n HeadObjectCommandOutput,\r\n PutObjectCommand,\r\n PutObjectTaggingCommand,\r\n S3Client,\r\n S3ClientConfig,\r\n} from '@aws-sdk/client-s3';\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { IStorageRequest, StorageConnector } from '@sre/IO/Storage.service/StorageConnector';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL, TAccessLevel, TAccessResult, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AWSRegionConfig, AWSCredentials } from '@sre/types/AWS.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\nimport { streamToBuffer } from '@sre/utils';\r\nimport type { Readable } from 'stream';\r\n\r\n//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { checkAndInstallLifecycleRules, generateExpiryMetadata, ttlToExpiryDays } from '@sre/helpers/S3Cache.helper';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\n\r\nconst console = Logger('S3Storage');\r\n\r\nexport type S3Config = AWSCredentials & AWSRegionConfig & { bucket: string };\r\n\r\nexport class S3Storage extends StorageConnector {\r\n public name = 'S3Storage';\r\n private client: S3Client;\r\n private bucket: string;\r\n private isInitialized: boolean = false;\r\n\r\n constructor(protected _settings: S3Config) {\r\n super(_settings);\r\n //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');\r\n this.bucket = _settings.bucket;\r\n const clientConfig: any = {};\r\n if (_settings.region) clientConfig.region = _settings.region;\r\n if (_settings.accessKeyId && _settings.secretAccessKey) {\r\n clientConfig.credentials = {\r\n accessKeyId: _settings.accessKeyId,\r\n secretAccessKey: _settings.secretAccessKey,\r\n };\r\n }\r\n\r\n this.client = new S3Client(clientConfig);\r\n this.initialize();\r\n }\r\n\r\n private async initialize() {\r\n await checkAndInstallLifecycleRules(this.bucket, this.client);\r\n this.isInitialized = true;\r\n }\r\n\r\n /**\r\n * Reads an object from the S3 bucket.\r\n *\r\n * @param {string} resourceId - The key of the object to be read.\r\n * @returns {Promise<any>} - A promise that resolves with the object data.\r\n */\r\n\r\n @SecureConnector.AccessControl\r\n public async read(acRequest: AccessRequest, resourceId: string) {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n const params = {\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n };\r\n\r\n const s3HeadCommand = new HeadObjectCommand(params);\r\n const s3HeadData: HeadObjectCommandOutput = await this.client.send(s3HeadCommand);\r\n\r\n const expirationHeader = s3HeadData?.Expiration;\r\n if (expirationHeader) {\r\n const expirationDateMatch = expirationHeader.match(/expiry-date=\"([^\"]+)\"/);\r\n if (expirationDateMatch) {\r\n const expirationDate = new Date(expirationDateMatch[1]);\r\n const currentDate = new Date();\r\n\r\n if (currentDate > expirationDate) {\r\n const s3DeleteCommand = new DeleteObjectCommand(params);\r\n await this.client.send(s3DeleteCommand);\r\n\r\n return undefined;\r\n }\r\n }\r\n }\r\n\r\n const command = new GetObjectCommand(params);\r\n\r\n try {\r\n const response: GetObjectCommandOutput = await this.client.send(command);\r\n //const metadata = response.Metadata;\r\n return await streamToBuffer(response.Body as Readable);\r\n } catch (error) {\r\n if (error.name === 'NotFound' || error.name === 'NoSuchKey') {\r\n return undefined;\r\n }\r\n console.error(`Error reading object from S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getMetadata(acRequest: AccessRequest, resourceId: string): Promise<StorageMetadata | undefined> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n const s3Metadata = await this.getS3Metadata(resourceId);\r\n return s3Metadata as StorageMetadata;\r\n } catch (error) {\r\n console.error(`Error getting access rights in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setMetadata(acRequest: AccessRequest, resourceId: string, metadata: StorageMetadata) {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n let s3Metadata = await this.getS3Metadata(resourceId);\r\n if (!s3Metadata) s3Metadata = {};\r\n //s3Metadata['x-amz-meta-data'] = metadata;\r\n s3Metadata = { ...s3Metadata, ...metadata };\r\n await this.setS3Metadata(resourceId, s3Metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in S3`, error);\r\n throw error;\r\n }\r\n }\r\n /**\r\n * Writes an object to the S3 bucket.\r\n *\r\n * @param {string} resourceId - The key of the object to be written.\r\n * @param {any} value - The value of the object to be written.\r\n * @param {Metadata} metadata - Optional metadata to be associated with the object.\r\n * @returns {Promise<void>} - A promise that resolves when the object has been written.\r\n */\r\n @SecureConnector.AccessControl\r\n async write(acRequest: AccessRequest, resourceId: string, value: StorageData, acl?: IACL, metadata?: StorageMetadata): Promise<void> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n if (!this.isInitialized) await this.initialize();\r\n const accessCandidate = acRequest.candidate;\r\n\r\n let amzACL = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n let s3Metadata = {\r\n ...metadata,\r\n 'x-amz-meta-acl': amzACL,\r\n };\r\n\r\n const command = new PutObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n Body: value,\r\n Metadata: this.serializeS3Metadata(s3Metadata),\r\n ContentType: s3Metadata['ContentType'],\r\n });\r\n\r\n try {\r\n const result: any = await this.client.send(command);\r\n } catch (error) {\r\n console.error(`Error writing object to S3`, error.name, error.message);\r\n //console.error(error);\r\n throw error;\r\n }\r\n }\r\n\r\n /**\r\n * Deletes an object from the S3 bucket.\r\n *\r\n * @param {string} resourceId - The key of the object to be deleted.\r\n * @returns {Promise<void>} - A promise that resolves when the object has been deleted.\r\n */\r\n @SecureConnector.AccessControl\r\n async delete(acRequest: AccessRequest, resourceId: string): Promise<void> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n const command = new DeleteObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n });\r\n\r\n try {\r\n await this.client.send(command);\r\n } catch (error) {\r\n console.error(`Error deleting object from S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async exists(acRequest: AccessRequest, resourceId: string): Promise<boolean> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n const command = new HeadObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n });\r\n\r\n try {\r\n await this.client.send(command);\r\n return true;\r\n } catch (error) {\r\n if (error.name === 'NotFound' || error.name === 'NoSuchKey') {\r\n return false;\r\n }\r\n\r\n console.error(`Error checking object existence in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n //this determines the access rights for the requested resource\r\n //the connector should check if the resource exists or not\r\n //if the resource exists we read it's ACL and return it\r\n //if the resource does not exist we return an write access ACL for the candidate\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const s3Metadata = await this.getS3Metadata(resourceId);\r\n const exists = s3Metadata !== undefined; //undefined metadata means the resource does not exist\r\n //let acl: ACL = ACL.from(s3Metadata?.['x-amz-meta-acl'] as IACL);\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(s3Metadata?.['x-amz-meta-acl'] as IACL);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, resourceId: string): Promise<ACL | undefined> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n const s3Metadata = await this.getS3Metadata(resourceId);\r\n return ACL.from(s3Metadata?.['x-amz-meta-acl'] as IACL);\r\n } catch (error) {\r\n console.error(`Error getting access rights in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, resourceId: string, acl: IACL) {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n let s3Metadata = await this.getS3Metadata(resourceId);\r\n if (!s3Metadata) s3Metadata = {};\r\n //when setting ACL make sure to not lose ownership\r\n s3Metadata['x-amz-meta-acl'] = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setS3Metadata(resourceId, s3Metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in S3`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async expire(acRequest: AccessRequest, resourceId: string, ttl: number) {\r\n const expiryMetadata = generateExpiryMetadata(ttlToExpiryDays(ttl)); // seconds to days\r\n const s3PutObjectTaggingCommand = new PutObjectTaggingCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n Tagging: { TagSet: [{ Key: expiryMetadata.Key, Value: expiryMetadata.Value }] },\r\n });\r\n await this.client.send(s3PutObjectTaggingCommand);\r\n }\r\n\r\n private migrateMetadata(metadata: Record<string, string>): Record<string, any> {\r\n if (!metadata.agentid && !metadata.teamid && !metadata.userid) return metadata as Record<string, any>;\r\n else {\r\n const convertibleItems = ['agentid', 'teamid', 'userid'];\r\n const aclHelper = new ACL();\r\n\r\n for (let key of convertibleItems) {\r\n if (!metadata[key]) continue;\r\n const role = key === 'agentid' ? TAccessRole.Agent : key === 'teamid' ? TAccessRole.Team : TAccessRole.User;\r\n aclHelper.addAccess(role, metadata[key].toString(), [TAccessLevel.Owner, TAccessLevel.Read, TAccessLevel.Write]);\r\n delete metadata[key];\r\n }\r\n aclHelper.migrated = true;\r\n const newMetadata: Record<string, any> = {\r\n 'x-amz-meta-acl': aclHelper.ACL,\r\n };\r\n //copy remaining metadata\r\n for (let key in metadata) {\r\n newMetadata[key] = metadata[key];\r\n }\r\n\r\n return newMetadata;\r\n }\r\n }\r\n\r\n private serializeS3Metadata(s3Metadata: Record<string, any>): Record<string, string> {\r\n let amzMetadata = {};\r\n if (s3Metadata['x-amz-meta-acl']) {\r\n //const acl: TACL = s3Metadata['x-amz-meta-acl'];\r\n if (s3Metadata['x-amz-meta-acl']) {\r\n amzMetadata['x-amz-meta-acl'] =\r\n typeof s3Metadata['x-amz-meta-acl'] == 'string'\r\n ? s3Metadata['x-amz-meta-acl']\r\n : ACL.from(s3Metadata['x-amz-meta-acl']).serializedACL;\r\n }\r\n\r\n delete s3Metadata['x-amz-meta-acl'];\r\n }\r\n\r\n for (let key in s3Metadata) {\r\n if (key == 'ContentType') continue; //skip ContentType as it can only be set when writing the object\r\n amzMetadata[key] = typeof s3Metadata[key] === 'string' ? s3Metadata[key] : JSON.stringify(s3Metadata[key]);\r\n }\r\n\r\n return amzMetadata;\r\n }\r\n\r\n private deserializeS3Metadata(amzMetadata: Record<string, string>): Record<string, any> {\r\n let metadata: Record<string, any> = {};\r\n\r\n for (let key in amzMetadata) {\r\n if (key === 'x-amz-meta-acl') {\r\n metadata[key] = ACL.from(amzMetadata[key]).ACL;\r\n continue;\r\n }\r\n\r\n try {\r\n metadata[key] = JSON.parse(amzMetadata[key]);\r\n } catch (error) {\r\n metadata[key] = amzMetadata[key];\r\n }\r\n }\r\n //TODO : Remove this migration code after all metadata is migrated\r\n // Context : an old ACL metadata format was used in initial implementation of Smyth Storage\r\n // We need to ensure compatibility with legacy format and seamlessly convert it when reading\r\n metadata = this.migrateMetadata(metadata) as Record<string, any>;\r\n\r\n return metadata;\r\n }\r\n\r\n private async getS3Metadata(resourceId: string): Promise<Record<string, any> | undefined> {\r\n try {\r\n const command = new HeadObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n });\r\n const response: HeadObjectCommandOutput = await this.client.send(command);\r\n const s3RawMetadata = response.Metadata;\r\n if (!s3RawMetadata || Object.keys(s3RawMetadata).length === 0) return {};\r\n\r\n let metadata: Record<string, any> = this.deserializeS3Metadata(s3RawMetadata);\r\n\r\n if (!metadata['ContentType']) metadata['ContentType'] = response.ContentType ? response.ContentType : 'application/octet-stream';\r\n return metadata;\r\n } catch (error) {\r\n if (error.name === 'NotFound' || error.name === 'NoSuchKey') {\r\n return undefined;\r\n }\r\n console.error(`Error reading object metadata from S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n private async setS3Metadata(resourceId: string, metadata: Record<string, any>): Promise<void> {\r\n try {\r\n // Get the current object content\r\n const getObjectCommand = new GetObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n });\r\n const objectData: GetObjectCommandOutput = await this.client.send(getObjectCommand);\r\n\r\n // Read the object's content\r\n const bufferBody = await streamToBuffer(objectData.Body as Readable);\r\n\r\n const amzMetadata = this.serializeS3Metadata(metadata);\r\n // Put the object back with the new metadata and the same content\r\n const putObjectCommand = new PutObjectCommand({\r\n Bucket: this.bucket,\r\n Key: resourceId,\r\n Body: bufferBody,\r\n Metadata: amzMetadata,\r\n });\r\n\r\n await this.client.send(putObjectCommand);\r\n } catch (error) {\r\n console.error(`Error setting object metadata in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n}\r\n","//==[ SRE: LocalStorage ]======================\r\n\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { StorageConnector } from '@sre/IO/Storage.service/StorageConnector';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL, TAccessLevel, TAccessResult, TAccessRole } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\n//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport fs, { existsSync } from 'fs';\r\nimport os from 'os';\r\nimport path from 'path';\r\n\r\nconst console = Logger('LocalStorage');\r\n\r\nexport type LocalStorageConfig = {\r\n /**\r\n * The folder to use for the local storage.\r\n *\r\n * If not provided, the default folder will be used.\r\n * The default folder is ~/.smyth/storage\r\n */\r\n folder?: string;\r\n};\r\n\r\nexport class LocalStorage extends StorageConnector {\r\n public name = 'LocalStorage';\r\n private folder: string;\r\n private storagePrefix = 'local';\r\n private metadataPrefix = '.local.metadata';\r\n private isInitialized = false;\r\n\r\n constructor(protected _settings?: LocalStorageConfig) {\r\n super(_settings);\r\n //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');\r\n\r\n this.folder = _settings?.folder || path.join(os.homedir(), '.smyth/storage');\r\n this.initialize();\r\n if (!fs.existsSync(this.folder)) {\r\n //throw new Error('Invalid folder provided');\r\n console.error(`Invalid folder provided: ${this.folder}`);\r\n }\r\n }\r\n\r\n /**\r\n * Reads an object from the local storage.\r\n *\r\n * @param {string} resourceId - The key of the object to be read.\r\n * @returns {Promise<any>} - A promise that resolves with the object data.\r\n */\r\n\r\n @SecureConnector.AccessControl\r\n public async read(acRequest: AccessRequest, resourceId: string) {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n try {\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, resourceId);\r\n if (!fs.existsSync(filePath)) return undefined;\r\n const data = fs.readFileSync(filePath, 'utf-8');\r\n return data;\r\n } catch (error) {\r\n console.error(`Error reading object from local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getMetadata(acRequest: AccessRequest, resourceId: string): Promise<StorageMetadata | undefined> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, resourceId);\r\n if (!fs.existsSync(metadataFilePath)) return undefined;\r\n const data = fs.readFileSync(metadataFilePath, 'utf-8');\r\n return this.deserializeMetadata(JSON.parse(data)) as StorageMetadata;\r\n } catch (error) {\r\n console.error(`Error reading metadata from LocalStorage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setMetadata(acRequest: AccessRequest, resourceId: string, metadata: StorageMetadata) {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n let fileMetadata = await this.getMetadata(acRequest, resourceId);\r\n if (!fileMetadata) fileMetadata = {};\r\n\r\n fileMetadata = { ...fileMetadata, ...metadata };\r\n\r\n //now we can write the metadata\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, resourceId, true);\r\n const serializedMetadata = this.serializeMetadata(fileMetadata);\r\n fs.writeFileSync(metadataFilePath, JSON.stringify(serializedMetadata));\r\n } catch (error) {\r\n console.error(`Error setting metadata in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n /**\r\n * Writes an object to the local storage.\r\n *\r\n * @param {string} resourceId - The key of the object to be written.\r\n * @param {any} value - The value of the object to be written.\r\n * @param {Metadata} metadata - Optional metadata to be associated with the object.\r\n * @returns {Promise<void>} - A promise that resolves when the object has been written.\r\n */\r\n @SecureConnector.AccessControl\r\n async write(acRequest: AccessRequest, resourceId: string, value: StorageData, acl?: IACL, metadata?: StorageMetadata): Promise<void> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const accessCandidate = acRequest.candidate;\r\n\r\n let amzACL = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n let fileMetadata = {\r\n ...metadata,\r\n acl: amzACL,\r\n };\r\n\r\n //now we can write the file\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, resourceId, true);\r\n fs.writeFileSync(filePath, value as Buffer);\r\n //now we can write the metadata\r\n await this.setMetadata(acRequest, resourceId, fileMetadata);\r\n }\r\n\r\n /**\r\n * Deletes an object from the local storage.\r\n *\r\n * @param {string} resourceId - The key of the object to be deleted.\r\n * @returns {Promise<void>} - A promise that resolves when the object has been deleted.\r\n */\r\n @SecureConnector.AccessControl\r\n async delete(acRequest: AccessRequest, resourceId: string): Promise<void> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, resourceId);\r\n if (fs.existsSync(filePath)) fs.unlinkSync(filePath);\r\n\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, resourceId);\r\n if (fs.existsSync(metadataFilePath)) fs.unlinkSync(metadataFilePath);\r\n } catch (error) {\r\n console.error(`Error deleting object from local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async exists(acRequest: AccessRequest, resourceId: string): Promise<boolean> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, resourceId);\r\n return !!fs.existsSync(filePath);\r\n }\r\n\r\n //this determines the access rights for the requested resource\r\n //the connector should check if the resource exists or not\r\n //if the resource exists we read it's ACL and return it\r\n //if the resource does not exist we return an write access ACL for the candidate\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const metadataFilePath = this.getMetadataFilePath(candidate.id, resourceId);\r\n\r\n if (!fs.existsSync(metadataFilePath)) return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n\r\n const metadata = fs.readFileSync(metadataFilePath, 'utf-8');\r\n const exists = metadata !== undefined; //undefined metadata means the resource does not exist\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n try {\r\n let metadataObject = JSON.parse(metadata);\r\n return ACL.from(metadataObject?.['acl'] as IACL);\r\n } catch (error) {\r\n console.error(`Error parsing metadata in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, resourceId: string): Promise<ACL | undefined> {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n const fileMetadata = await this.getMetadata(acRequest, resourceId);\r\n return ACL.from(fileMetadata?.['acl'] as IACL);\r\n } catch (error) {\r\n console.error(`Error getting access rights in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, resourceId: string, acl: IACL) {\r\n // const accessTicket = await this.getAccessTicket(resourceId, acRequest);\r\n // if (accessTicket.access !== TAccessResult.Granted) throw new Error('Access Denied');\r\n\r\n try {\r\n let fileMetadata = await this.getMetadata(acRequest, resourceId);\r\n if (!fileMetadata) fileMetadata = {};\r\n //when setting ACL make sure to not lose ownership\r\n fileMetadata['acl'] = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setMetadata(acRequest, resourceId, fileMetadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in local storage`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async expire(acRequest: AccessRequest, resourceId: string, ttl: number) {\r\n console.warn(`LocalStorage.expire is not implemented, request will be ignored for resource ${resourceId} and ttl ${ttl}`);\r\n }\r\n\r\n private async initialize() {\r\n const storageFolderPath = path.join(this.folder, this.storagePrefix);\r\n if (!existsSync(storageFolderPath)) {\r\n fs.mkdirSync(storageFolderPath, { recursive: true });\r\n }\r\n const metadataFolderPath = path.join(this.folder, this.metadataPrefix);\r\n if (!existsSync(metadataFolderPath)) {\r\n fs.mkdirSync(metadataFolderPath, { recursive: true });\r\n fs.writeFileSync(\r\n path.join(metadataFolderPath, 'README_IMPORTANT.txt'),\r\n 'This folder is used for smythOS metadata, do not delete it, it will break SmythOS local filesystem'\r\n );\r\n }\r\n this.isInitialized = true;\r\n }\r\n\r\n private getStorageFilePath(candidateId: string, resourceId: string, createFoldersIfNotExists: boolean = false) {\r\n const fullPath = path.join(this.folder, this.storagePrefix, resourceId);\r\n const folder = path.dirname(fullPath);\r\n if (createFoldersIfNotExists && !fs.existsSync(folder)) {\r\n fs.mkdirSync(folder, { recursive: true });\r\n }\r\n\r\n return fullPath;\r\n }\r\n\r\n private getMetadataFilePath(candidateId: string, resourceId: string, createFoldersIfNotExists: boolean = false) {\r\n const fullPath = path.join(this.folder, this.metadataPrefix, resourceId);\r\n const folder = path.dirname(fullPath);\r\n if (createFoldersIfNotExists && !fs.existsSync(folder)) {\r\n fs.mkdirSync(folder, { recursive: true });\r\n }\r\n\r\n return fullPath;\r\n }\r\n\r\n private serializeMetadata(metadata: Record<string, any>): Record<string, string> {\r\n let updatedMetadata = {};\r\n if (metadata['acl']) {\r\n if (metadata['acl']) {\r\n updatedMetadata['acl'] = typeof metadata['acl'] == 'string' ? metadata['acl'] : ACL.from(metadata['acl']).serializedACL;\r\n }\r\n\r\n delete metadata['acl'];\r\n }\r\n\r\n for (let key in metadata) {\r\n updatedMetadata[key] = typeof metadata[key] === 'string' ? metadata[key] : JSON.stringify(metadata[key]);\r\n }\r\n\r\n return updatedMetadata;\r\n }\r\n\r\n private deserializeMetadata(metadata: Record<string, string>): Record<string, any> {\r\n let deserializedMetadata: Record<string, any> = {};\r\n\r\n for (let key in metadata) {\r\n if (key === 'acl') {\r\n deserializedMetadata[key] = ACL.from(metadata[key]).ACL;\r\n continue;\r\n }\r\n\r\n try {\r\n deserializedMetadata[key] = JSON.parse(metadata[key]);\r\n } catch (error) {\r\n deserializedMetadata[key] = metadata[key];\r\n }\r\n }\r\n return deserializedMetadata;\r\n }\r\n}\r\n","//==[ SRE: Storage ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { S3Storage } from './connectors/S3Storage.class';\r\nimport { LocalStorage } from './connectors/LocalStorage.class';\r\n\r\nexport class StorageService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Storage, 'S3', S3Storage);\r\n ConnectorService.register(TConnectorService.Storage, 'LocalStorage', LocalStorage);\r\n }\r\n}\r\n","import config from '@sre/config';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { TBedrockSettings, TCustomLLMModel, TLLMCredentials, TLLMModel, TVertexAISettings } from '@sre/types/LLM.types';\r\n\r\nexport async function getLLMCredentials(candidate: AccessCandidate, modelInfo: TLLMModel | TCustomLLMModel) {\r\n //create a credentials list that we can iterate over\r\n //if the credentials are not provided, we will use None as a default in order to return empty credentials\r\n const credentialsList: any[] = !Array.isArray(modelInfo.credentials) ? [modelInfo.credentials] : modelInfo.credentials || [TLLMCredentials.None];\r\n\r\n for (let credentialsMode of credentialsList) {\r\n if (typeof credentialsMode === 'object') {\r\n //credentials passed directly\r\n return credentialsMode;\r\n }\r\n\r\n switch (credentialsMode) {\r\n case TLLMCredentials.None: {\r\n return { apiKey: '' };\r\n }\r\n case TLLMCredentials.Internal:\r\n case TLLMCredentials.Vault: {\r\n const credentials = await getStandardLLMCredentials(candidate, modelInfo as TLLMModel);\r\n if (credentials) return credentials;\r\n break;\r\n }\r\n case TLLMCredentials.BedrockVault: {\r\n const credentials = await getBedrockCredentials(candidate, modelInfo as TCustomLLMModel);\r\n if (credentials) return credentials;\r\n break;\r\n }\r\n case TLLMCredentials.VertexAIVault: {\r\n const credentials = await getVertexAICredentials(candidate, modelInfo as TCustomLLMModel);\r\n if (credentials) return credentials;\r\n break;\r\n }\r\n }\r\n }\r\n\r\n return {};\r\n}\r\n\r\n/**\r\n * Retrieves API key credentials for standard LLM providers from the vault\r\n * @param candidate - The access candidate requesting the credentials\r\n * @param provider - The LLM provider name (e.g., 'openai', 'anthropic')\r\n * @returns Promise resolving to an object containing the provider's API key\r\n * @throws {Error} If vault connector is unavailable (handled in parent method)\r\n * @remarks Returns an empty string as API key if vault access fails\r\n * @private\r\n */\r\nasync function getStandardLLMCredentials(candidate: AccessCandidate, modelInfo: TLLMModel): Promise<{ apiKey: string; isUserKey: boolean }> {\r\n const provider = (modelInfo.provider || modelInfo.llm)?.toLowerCase();\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n\r\n const apiKey = await vaultConnector\r\n .requester(candidate)\r\n .get(provider)\r\n .catch(() => '');\r\n\r\n if (!apiKey) return null;\r\n return { apiKey, isUserKey: true };\r\n}\r\n\r\n/**\r\n * Retrieves AWS Bedrock credentials from the vault for authentication\r\n * @param candidate - The access candidate requesting the credentials\r\n * @param modelInfo - The Bedrock model information containing credential key names in settings\r\n * @returns Promise resolving to AWS credentials object\r\n * @returns {Promise<Object>} credentials\r\n * @returns {string} credentials.accessKeyId - AWS access key ID\r\n * @returns {string} credentials.secretAccessKey - AWS secret access key\r\n * @returns {string} [credentials.sessionToken] - Optional AWS session token\r\n * @throws {Error} If vault connector is unavailable (handled in parent method)\r\n * @private\r\n */\r\nasync function getBedrockCredentials(\r\n candidate: AccessCandidate,\r\n modelInfo: TCustomLLMModel\r\n): Promise<{ accessKeyId: string; secretAccessKey: string; sessionToken?: string; isUserKey: boolean }> {\r\n const keyIdName = (modelInfo.settings as TBedrockSettings)?.keyIDName;\r\n const secretKeyName = (modelInfo.settings as TBedrockSettings)?.secretKeyName;\r\n const sessionKeyName = (modelInfo.settings as TBedrockSettings)?.sessionKeyName;\r\n\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n\r\n const [accessKeyId, secretAccessKey, sessionToken] = await Promise.all([\r\n vaultConnector\r\n .requester(candidate)\r\n .get(keyIdName)\r\n .catch(() => ''),\r\n vaultConnector\r\n .requester(candidate)\r\n .get(secretKeyName)\r\n .catch(() => ''),\r\n vaultConnector\r\n .requester(candidate)\r\n .get(sessionKeyName)\r\n .catch(() => ''),\r\n ]);\r\n\r\n let credentials: {\r\n accessKeyId: string;\r\n secretAccessKey: string;\r\n sessionToken?: string;\r\n isUserKey: boolean;\r\n } = {\r\n accessKeyId,\r\n secretAccessKey,\r\n isUserKey: true,\r\n };\r\n\r\n if (sessionToken) {\r\n credentials.sessionToken = sessionToken;\r\n }\r\n\r\n if (!accessKeyId || !secretAccessKey) return null;\r\n return credentials;\r\n}\r\n\r\n/**\r\n * Retrieves the credentials required for VertexAI authentication from the vault\r\n * @param candidate - The access candidate requesting the credentials\r\n * @param modelInfo - The VertexAI model information containing settings\r\n * @returns Promise resolving to the parsed JSON credentials for VertexAI\r\n * @throws {Error} If vault connector is unavailable (handled in parent method)\r\n * @throws {Error} If JSON parsing fails or credentials are malformed\r\n * @remarks Returns empty credentials if vault access fails\r\n * @private\r\n */\r\nasync function getVertexAICredentials(candidate: AccessCandidate, modelInfo: TCustomLLMModel): Promise<any> {\r\n const jsonCredentialsName = (modelInfo.settings as TVertexAISettings)?.jsonCredentialsName;\r\n\r\n const vaultConnector = ConnectorService.getVaultConnector();\r\n\r\n let jsonCredentials = await vaultConnector\r\n .requester(candidate)\r\n .get(jsonCredentialsName)\r\n .catch(() => '');\r\n\r\n const credentials = JSON.parse(jsonCredentials);\r\n\r\n if (!credentials) return null;\r\n return { ...credentials, isUserKey: true };\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport {\r\n TLLMParams,\r\n TLLMConnectorParams,\r\n TLLMMessageBlock,\r\n TLLMToolResultMessageBlock,\r\n ToolData,\r\n APIKeySource,\r\n TLLMModel,\r\n TLLMCredentials,\r\n TBedrockSettings,\r\n TVertexAISettings,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n TLLMRequestBody,\r\n} from '@sre/types/LLM.types';\r\nimport EventEmitter from 'events';\r\nimport { Readable } from 'stream';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { VaultConnector } from '@sre/Security/Vault.service/VaultConnector';\r\nimport { TCustomLLMModel } from '@sre/types/LLM.types';\r\nimport config from '@sre/config';\r\nimport { ModelsProviderConnector } from '@sre/LLMManager/ModelsProvider.service/ModelsProviderConnector';\r\nimport { getLLMCredentials } from './LLMCredentials.helper';\r\n\r\nconst console = Logger('LLMConnector');\r\n\r\nexport interface ILLMConnectorRequest {\r\n // chatRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n // visionRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n // multimodalRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n // toolRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n\r\n request(params: TLLMConnectorParams): Promise<TLLMChatResponse>;\r\n streamRequest(params: TLLMConnectorParams): Promise<EventEmitter>;\r\n\r\n imageGenRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n imageEditRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any>;\r\n}\r\n\r\nexport class LLMStream extends Readable {\r\n private dataQueue: any[];\r\n private toolsData: any[];\r\n private hasData: boolean;\r\n isReading: boolean;\r\n constructor(options?) {\r\n super(options);\r\n this.dataQueue = [];\r\n this.toolsData = [];\r\n this.isReading = true;\r\n }\r\n\r\n _read(size) {\r\n if (this.dataQueue.length > 0) {\r\n while (this.dataQueue.length > 0) {\r\n const chunk = this.dataQueue.shift();\r\n if (!this.push(chunk)) {\r\n break;\r\n }\r\n }\r\n } else {\r\n this.push(null); // No more data\r\n }\r\n }\r\n\r\n enqueueData(data) {\r\n this.dataQueue.push(data);\r\n this.read(0); // Trigger the _read method\r\n }\r\n\r\n endStream() {\r\n this.isReading = false;\r\n this.push(null); // End the stream\r\n }\r\n}\r\n\r\nexport abstract class LLMConnector extends Connector {\r\n public abstract name: string;\r\n\r\n protected abstract request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse>;\r\n protected abstract streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter>;\r\n protected abstract webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter>;\r\n\r\n protected abstract reqBodyAdapter(params: TLLMConnectorParams): Promise<TLLMRequestBody>;\r\n protected abstract reportUsage(usage: any, metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }): any;\r\n\r\n // Optional method - default implementation throws error. (It's a workaround. We will move image related methods to another subsystem.)\r\n protected imageGenRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any> {\r\n return Promise.reject(new Error('Image edit not supported by this model'));\r\n }\r\n protected imageEditRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any> {\r\n return Promise.reject(new Error('Image edit not supported by this model'));\r\n }\r\n\r\n private vaultConnector: VaultConnector;\r\n\r\n public requester(candidate: AccessCandidate): ILLMConnectorRequest {\r\n //if (candidate.role !== 'agent') throw new Error('Only agents can use LLM connector');\r\n\r\n this.vaultConnector = ConnectorService.getVaultConnector();\r\n\r\n if (!this.vaultConnector || !this.vaultConnector.valid) {\r\n console.warn(`Vault Connector unavailable for ${candidate.id} `);\r\n }\r\n\r\n const _request: ILLMConnectorRequest = {\r\n request: async (params: TLLMConnectorParams) => {\r\n const preparedParams = await this.prepareParams(candidate, params);\r\n\r\n const response = await this.request({\r\n acRequest: candidate.readRequest,\r\n body: preparedParams.body,\r\n context: {\r\n modelEntryName: preparedParams.modelEntryName,\r\n agentId: preparedParams.agentId,\r\n teamId: preparedParams.teamId,\r\n isUserKey: preparedParams.isUserKey,\r\n hasFiles: preparedParams.files?.length > 0,\r\n modelInfo: preparedParams.modelInfo,\r\n credentials: preparedParams.credentials,\r\n },\r\n });\r\n\r\n return response;\r\n },\r\n streamRequest: async (params: TLLMConnectorParams) => {\r\n const preparedParams = await this.prepareParams(candidate, params);\r\n\r\n const requestParams = {\r\n acRequest: candidate.readRequest,\r\n body: preparedParams.body,\r\n context: {\r\n modelEntryName: preparedParams.modelEntryName,\r\n agentId: preparedParams.agentId,\r\n teamId: preparedParams.teamId,\r\n isUserKey: preparedParams.isUserKey,\r\n hasFiles: preparedParams.files?.length > 0,\r\n modelInfo: preparedParams.modelInfo,\r\n credentials: preparedParams.credentials,\r\n },\r\n };\r\n\r\n let response;\r\n\r\n if (preparedParams.capabilities?.search === true && preparedParams.useWebSearch === true) {\r\n response = await this.webSearchRequest(requestParams);\r\n } else {\r\n response = await this.streamRequest(requestParams);\r\n }\r\n\r\n return response;\r\n },\r\n\r\n imageGenRequest: async (params: any) => {\r\n const preparedParams = await this.prepareParams(candidate, params);\r\n\r\n const response = await this.imageGenRequest({\r\n acRequest: candidate.readRequest,\r\n body: preparedParams.body,\r\n context: {\r\n modelEntryName: preparedParams.modelEntryName,\r\n isUserKey: preparedParams.isUserKey,\r\n agentId: preparedParams.agentId,\r\n teamId: preparedParams.teamId,\r\n hasFiles: preparedParams.files?.length > 0,\r\n modelInfo: preparedParams.modelInfo,\r\n credentials: preparedParams.credentials,\r\n },\r\n });\r\n\r\n return response;\r\n },\r\n imageEditRequest: async (params: any) => {\r\n const preparedParams = await this.prepareParams(candidate, params);\r\n\r\n const response = await this.imageEditRequest({\r\n acRequest: candidate.readRequest,\r\n body: preparedParams.body,\r\n context: {\r\n modelEntryName: preparedParams.modelEntryName,\r\n isUserKey: preparedParams.isUserKey,\r\n agentId: preparedParams.agentId,\r\n teamId: preparedParams.teamId,\r\n hasFiles: preparedParams.files?.length > 0,\r\n modelInfo: preparedParams.modelInfo,\r\n credentials: preparedParams.credentials,\r\n },\r\n });\r\n\r\n return response;\r\n },\r\n };\r\n\r\n return _request;\r\n }\r\n\r\n public enhancePrompt(prompt: string, config: any) {\r\n if (!prompt) return prompt;\r\n let newPrompt = prompt;\r\n const outputs = {};\r\n\r\n if (config?.outputs) {\r\n for (let con of config.outputs) {\r\n if (con.default) continue;\r\n outputs[con.name] = con?.description ? ` (${con?.description})` : '';\r\n }\r\n }\r\n\r\n const excludedKeys = ['_debug', '_error'];\r\n const outputKeys = Object.keys(outputs).filter((key) => !excludedKeys.includes(key));\r\n\r\n if (outputKeys.length > 0) {\r\n const outputFormat = {};\r\n outputKeys.forEach((key) => (outputFormat[key] = (config.name === 'Classifier' ? '<Boolean|String>' : '<value>') + (outputs[key] || '')));\r\n\r\n newPrompt +=\r\n '\\n##\\nExpected output format = ' +\r\n JSON.stringify(outputFormat) +\r\n '\\nThe output JSON should only use the entries from the output format.';\r\n\r\n //console.debug(` Enhanced prompt \\n`, prompt, '\\n');\r\n }\r\n\r\n return newPrompt;\r\n }\r\n\r\n public postProcess(response: string) {\r\n try {\r\n return JSONContent(response).tryParse();\r\n } catch (error) {\r\n return {\r\n error: 'Invalid JSON response',\r\n data: response,\r\n details: 'The response from the model is not a valid JSON object. Please check the model output and try again.',\r\n };\r\n }\r\n }\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n throw new Error('This model does not support tools');\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock;\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n throw new Error('This model does not support tools');\r\n }\r\n\r\n public getConsistentMessages(messages: TLLMMessageBlock[]) {\r\n return messages; // if a LLM connector does not implement this method, the messages will not be modified\r\n }\r\n\r\n private async prepareParams(candidate: AccessCandidate, params: TLLMConnectorParams): Promise<TLLMConnectorParams & { body: any }> {\r\n const modelsProvider: ModelsProviderConnector = ConnectorService.getModelsProviderConnector();\r\n // Assign file from the original parameters to avoid overwriting the original constructor\r\n const files = params?.files;\r\n delete params?.files; // need to remove files to avoid any issues during JSON.stringify() especially when we have large files\r\n\r\n const clonedParams = JSON.parse(JSON.stringify(params)); // Avoid mutation of the original params\r\n\r\n // Format the parameters to ensure proper type of values\r\n const _params: TLLMConnectorParams = this.formatParamValues(clonedParams);\r\n\r\n const model = _params.model;\r\n const teamId = await this.getTeamId(candidate);\r\n\r\n // We need the model entry name for usage reporting\r\n _params.modelEntryName = typeof model === 'string' ? model : (model as TLLMModel).modelId;\r\n _params.teamId = teamId;\r\n\r\n const modelProviderCandidate = modelsProvider.requester(candidate);\r\n const modelInfo: TLLMModel | TCustomLLMModel = await modelProviderCandidate.getModelInfo(model);\r\n\r\n //if the model has default params make sure to set them if they are not present\r\n if (modelInfo.params) {\r\n for (let key in modelInfo.params) {\r\n if (typeof _params[key] === 'undefined') {\r\n _params[key] = modelInfo.params[key];\r\n }\r\n }\r\n }\r\n\r\n const isStandardLLM = await modelProviderCandidate.isStandardLLM(model);\r\n\r\n const llmProvider = await modelProviderCandidate.getProvider(model);\r\n\r\n _params.credentials = await getLLMCredentials(candidate, modelInfo);\r\n\r\n //_params.model = (await modelProviderCandidate.getModelId(model)) || model;\r\n\r\n _params.baseURL = modelInfo?.baseURL;\r\n if (!isStandardLLM) _params.modelInfo = modelInfo as TCustomLLMModel; //only if custom LLM ?\r\n\r\n if (_params.maxTokens) {\r\n _params.maxTokens = await modelProviderCandidate.adjustMaxCompletionTokens(model, _params.maxTokens, _params?.isUserKey as boolean);\r\n } else {\r\n // max output tokens is mandatory for Anthropic models\r\n // We provide the default max output tokens here to avoid some complexity in reqBodyAdapter()\r\n _params.maxTokens = await modelProviderCandidate.getMaxCompletionTokens(model, _params?.isUserKey as boolean);\r\n }\r\n\r\n _params.model = await modelProviderCandidate.getModelId(model);\r\n // Attach the files again after formatting the parameters\r\n _params.files = files;\r\n\r\n const features = modelInfo?.features || [];\r\n\r\n _params.capabilities = {\r\n search: features.includes('search'),\r\n reasoning: features.includes('reasoning'),\r\n imageGeneration: features.includes('image-generation'),\r\n };\r\n\r\n // The input adapter transforms the standardized parameters into the specific format required by the target LLM provider\r\n _params.agentId = candidate.id;\r\n const body = await this.reqBodyAdapter(_params);\r\n\r\n return { ..._params, body };\r\n }\r\n\r\n // TODO [Forhad]: apply proper typing for _value and return value\r\n private formatParamValues(params: Record<string, string | number | TLLMMessageBlock[]>): any {\r\n let _params = {};\r\n\r\n for (const [key, value] of Object.entries(params)) {\r\n let _value: any = value;\r\n\r\n // When we have stopSequences, we need to split it into an array\r\n if (key === 'stopSequences') {\r\n _value = _value ? _value?.split(',') : null;\r\n }\r\n\r\n // When we have a string that is a number, we need to convert it to a number\r\n if (typeof _value === 'string' && !isNaN(Number(_value))) {\r\n _value = +_value;\r\n }\r\n\r\n //FIXME: to revisit by Alaa-eddine\r\n if (key === 'messages') {\r\n _value = this.getConsistentMessages(_value);\r\n }\r\n\r\n _params[key] = _value;\r\n }\r\n\r\n return _params;\r\n }\r\n\r\n /**\r\n * Retrieves the team ID associated with the given access candidate\r\n * @param candidate - The access candidate whose team ID needs to be retrieved\r\n * @returns Promise<string> - The unique identifier of the team associated with the candidate\r\n * @throws {Error} If the Account Connector service is unavailable or cannot be accessed\r\n * @throws {Error} If the candidate's team cannot be retrieved\r\n * @private\r\n * @remarks This method is used internally to determine the team context for custom LLM operations\r\n */\r\n private async getTeamId(candidate: AccessCandidate): Promise<string> {\r\n const accountConnector: AccountConnector = ConnectorService.getAccountConnector();\r\n\r\n if (!accountConnector) throw new Error('Account Connector unavailable, cannot proceed');\r\n\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n return teamId;\r\n }\r\n}\r\n","import { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport EventEmitter from 'events';\r\nimport { APIKeySource, ILLMRequestFuncParams, TLLMChatResponse, TLLMConnectorParams, TLLMParams } from '@sre/types/LLM.types';\r\n\r\nexport class EchoConnector extends LLMConnector {\r\n public name = 'LLM:Echo';\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n const content = body?.messages?.[0]?.content; // As Echo model only used in PromptGenerator so we can assume the first message is the user message to echo\r\n return {\r\n content,\r\n finishReason: 'stop',\r\n useTool: false,\r\n toolsData: [],\r\n message: { content, role: 'assistant' },\r\n usage: {},\r\n } as TLLMChatResponse;\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const emitter = new EventEmitter();\r\n let content = '';\r\n\r\n if (Array.isArray(body?.messages)) {\r\n content = body?.messages?.filter((m) => m.role === 'user').pop()?.content;\r\n }\r\n //params?.messages?.[0]?.content;\r\n\r\n // Process stream asynchronously as we need to return emitter immediately\r\n (async () => {\r\n // Simulate streaming by splitting content into chunks\r\n const chunks = content.split(' ');\r\n\r\n for (let i = 0; i < chunks.length; i++) {\r\n // Simulate network delay\r\n await new Promise((resolve) => setTimeout(resolve, 50));\r\n\r\n const isLastChunk = i === chunks.length - 1;\r\n // Add space between chunks except for the last one to avoid trailing space in file URLs\r\n const delta = { content: chunks[i] + (isLastChunk ? '' : ' ') };\r\n emitter.emit('data', delta);\r\n emitter.emit('content', delta.content);\r\n }\r\n\r\n // Emit end event after all chunks are processed\r\n setTimeout(() => {\r\n emitter.emit('end', [], []); // Empty arrays for toolsData and usage_data\r\n }, 100);\r\n })();\r\n\r\n return emitter;\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search is not supported for Echo');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<any> {\r\n return params;\r\n }\r\n\r\n public enhancePrompt(prompt: string, config: any) {\r\n //Echo model does not require enhancements, because we are just echoing the prompt as is.\r\n return prompt;\r\n }\r\n\r\n public postProcess(response: any) {\r\n try {\r\n const result = JSONContent(response).tryFullParse();\r\n if (result?.error) {\r\n return response;\r\n }\r\n return result;\r\n } catch (error) {\r\n return response;\r\n }\r\n }\r\n\r\n protected reportUsage(usage: any, metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }) {}\r\n}\r\n","import { type TLLMMessageBlock, TLLMMessageRole } from '@sre/types/LLM.types';\r\n\r\nimport axios from 'axios';\r\nimport imageSize from 'image-size';\r\nimport { encode } from 'gpt-tokenizer';\r\nimport { isBase64FileUrl, isUrl } from '@sre/utils';\r\n\r\nexport class LLMHelper {\r\n /**\r\n * Checks if the given array of messages contains a system message.\r\n *\r\n * @param {any} messages - The array of messages to check.\r\n * @returns {boolean} True if a system message is found, false otherwise.\r\n *\r\n * @example\r\n * const messages = [\r\n * { role: 'user', content: 'Hello' },\r\n * { role: 'system', content: 'You are a helpful assistant' }\r\n * ];\r\n * const hasSystem = LLMHelper.hasSystemMessage(messages);\r\n * console.log(hasSystem); // true\r\n */\r\n public static hasSystemMessage(messages: any): boolean {\r\n if (!Array.isArray(messages)) return false;\r\n return messages?.some((message) => message.role === 'system');\r\n }\r\n\r\n /**\r\n * Separates system messages from other messages in an array of LLM message blocks.\r\n *\r\n * @param {TLLMMessageBlock[]} messages - The array of message blocks to process.\r\n * @returns {Object} An object containing the system message (if any) and an array of other messages.\r\n * @property {TLLMMessageBlock | {}} systemMessage - The first system message found, or an empty object if none.\r\n * @property {TLLMMessageBlock[]} otherMessages - An array of all non-system messages.\r\n *\r\n * @example\r\n * const messages = [\r\n * { role: 'system', content: 'You are a helpful assistant' },\r\n * { role: 'user', content: 'Hello' },\r\n * { role: 'assistant', content: 'Hi there!' }\r\n * ];\r\n * const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(messages);\r\n * console.log(systemMessage); // { role: 'system', content: 'You are a helpful assistant' }\r\n * console.log(otherMessages); // [{ role: 'user', content: 'Hello' }, { role: 'assistant', content: 'Hi there!' }]\r\n */\r\n public static separateSystemMessages(messages: TLLMMessageBlock[]): {\r\n systemMessage: TLLMMessageBlock | {};\r\n otherMessages: TLLMMessageBlock[];\r\n } {\r\n const systemMessage = messages.find((message) => message.role === 'system') || {};\r\n const otherMessages = messages.filter((message) => message.role !== 'system');\r\n\r\n return { systemMessage, otherMessages };\r\n }\r\n\r\n /**\r\n * Counts the total number of tokens in a vision prompt, including both text and image tokens.\r\n *\r\n * @param {any} prompt - The vision prompt object containing text and image items.\r\n * @returns {Promise<number>} A promise that resolves to the total number of tokens in the prompt.\r\n *\r\n * @description\r\n * This method processes a vision prompt by:\r\n * 1. Counting tokens in the text portion of the prompt.\r\n * 2. Calculating tokens for each image in the prompt based on its dimensions.\r\n * 3. Summing up text and image tokens to get the total token count.\r\n *\r\n * @example\r\n * const prompt = [\r\n * { type: 'text', text: 'Describe this image:' },\r\n * { type: 'image_url', image_url: { url: 'https://example.com/image.jpg' } }\r\n * ];\r\n * const tokenCount = await countVisionPromptTokens(prompt);\r\n * console.log(tokenCount); // e.g., 150\r\n */\r\n public static async countVisionPromptTokens(prompt: any): Promise<number> {\r\n let tokens = 0;\r\n\r\n const textObj = prompt?.filter((item) => item.type === 'text');\r\n const textTokens = encode(textObj?.[0]?.text).length;\r\n\r\n const images = prompt?.filter((item) => item.type === 'image_url');\r\n let imageTokens = 0;\r\n\r\n for (const image of images) {\r\n const imageUrl = image?.image_url?.url;\r\n const { width, height } = await this.getImageDimensions(imageUrl);\r\n const tokens = this.countImageTokens(width, height);\r\n imageTokens += tokens;\r\n }\r\n\r\n tokens = textTokens + imageTokens;\r\n return tokens;\r\n }\r\n\r\n /**\r\n * Retrieves the dimensions (width and height) of an image from a given URL or base64 encoded string.\r\n *\r\n * @param {string} imageUrl - The URL or base64 encoded string of the image.\r\n * @returns {Promise<{ width: number; height: number }>} A promise that resolves to an object containing the width and height of the image.\r\n * @throws {Error} If the provided imageUrl is invalid or if there's an error retrieving the image dimensions.\r\n *\r\n * @example\r\n * // Using a URL\r\n * const dimensions = await getImageDimensions('https://example.com/image.jpg');\r\n * console.log(dimensions); // { width: 800, height: 600 }\r\n *\r\n * @example\r\n * // Using a base64 encoded string\r\n * const dimensions = await getImageDimensions('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAACklEQVR4nGMAAQAABQABDQottAAAAABJRU5ErkJggg==');\r\n * console.log(dimensions); // { width: 1, height: 1 }\r\n */\r\n public static async getImageDimensions(imageUrl: string): Promise<{ width: number; height: number }> {\r\n try {\r\n let buffer: Buffer;\r\n\r\n if (isBase64FileUrl(imageUrl)) {\r\n const base64Data = imageUrl.replace(/^data:image\\/\\w+;base64,/, '');\r\n buffer = Buffer.from(base64Data, 'base64');\r\n } else if (isUrl(imageUrl)) {\r\n const response = await axios.get(imageUrl, { responseType: 'arraybuffer' });\r\n buffer = Buffer.from(response.data);\r\n } else {\r\n throw new Error('Please provide a valid image url!');\r\n }\r\n\r\n const dimensions = imageSize(buffer);\r\n\r\n return {\r\n width: dimensions?.width || 0,\r\n height: dimensions?.height || 0,\r\n };\r\n } catch (error) {\r\n console.error('Error getting image dimensions', error);\r\n throw new Error('Please provide a valid image url!');\r\n }\r\n }\r\n\r\n /**\r\n * Calculates the number of tokens required to process an image based on its dimensions and detail mode.\r\n *\r\n * @param {number} width - The width of the image in pixels.\r\n * @param {number} height - The height of the image in pixels.\r\n * @param {string} detailMode - The detail mode for processing the image. Defaults to 'auto'.\r\n * @returns {number} The number of tokens required to process the image.\r\n *\r\n * @description\r\n * This method estimates the token count for image processing based on the image dimensions and detail mode.\r\n * It uses a tiling approach to calculate the token count, scaling the image if necessary.\r\n *\r\n * - If detailMode is 'low', it returns a fixed token count of 85.\r\n * - For other modes, it calculates based on the image dimensions:\r\n * - Scales down images larger than 2048 pixels in any dimension.\r\n * - Adjusts the scaled dimension to fit within a 768x1024 aspect ratio.\r\n * - Calculates the number of 512x512 tiles needed to cover the image.\r\n * - Returns the total token count based on the number of tiles.\r\n *\r\n * @example\r\n * const tokenCount = countImageTokens(1024, 768);\r\n * console.log(tokenCount); // Outputs the calculated token count\r\n */\r\n public static countImageTokens(width: number, height: number, detailMode: string = 'auto'): number {\r\n if (detailMode === 'low') return 85;\r\n\r\n const maxDimension = Math.max(width, height);\r\n const minDimension = Math.min(width, height);\r\n let scaledMinDimension = minDimension;\r\n\r\n if (maxDimension > 2048) {\r\n scaledMinDimension = (2048 / maxDimension) * minDimension;\r\n }\r\n scaledMinDimension = Math.floor((768 / 1024) * scaledMinDimension);\r\n\r\n let tileSize = 512;\r\n let tiles = Math.ceil(scaledMinDimension / tileSize);\r\n\r\n if (minDimension !== scaledMinDimension) {\r\n tiles *= Math.ceil((scaledMinDimension * (maxDimension / minDimension)) / tileSize);\r\n }\r\n\r\n return tiles * 170 + 85;\r\n }\r\n\r\n /**\r\n * Removes duplicate user messages from the beginning and end of the messages array.\r\n *\r\n * This method checks if there are two consecutive user messages at the start or end of the array\r\n *\r\n * @param {Array<{ role: string; content: string }>} messages - The array of message objects to process.\r\n *\r\n * @example\r\n * const messages = [\r\n * { role: 'user', content: 'Hello' },\r\n * { role: 'user', content: 'Hello' },\r\n * { role: 'assistant', content: 'Hi there!' }\r\n * ];\r\n * LLMHelper.removeDuplicateUserMessages(messages);\r\n * console.log(messages); // [{ role: 'user', content: 'Hello' }, { role: 'assistant', content: 'Hi there!' }]\r\n *\r\n * @returns {TLLMMessageBlock[]} The modified array of message objects.\r\n */\r\n public static removeDuplicateUserMessages(messages: TLLMMessageBlock[]): TLLMMessageBlock[] {\r\n const _messages = JSON.parse(JSON.stringify(messages));\r\n\r\n // Check for two user messages at the beginning\r\n if (_messages.length > 1 && _messages[0].role === TLLMMessageRole.User && _messages[1].role === TLLMMessageRole.User) {\r\n _messages.shift(); // Remove the first user message\r\n }\r\n\r\n // Check for two user messages at the end\r\n if (\r\n _messages.length > 1 &&\r\n _messages[_messages.length - 1].role === TLLMMessageRole.User &&\r\n _messages[_messages.length - 2].role === TLLMMessageRole.User\r\n ) {\r\n _messages.pop(); // Remove the last user message\r\n }\r\n\r\n return _messages;\r\n }\r\n}\r\n","import EventEmitter from 'events';\r\nimport OpenAI, { toFile } from 'openai';\r\nimport type { Stream } from 'openai/streaming';\r\nimport { encodeChat } from 'gpt-tokenizer';\r\n\r\nimport { BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\nimport { JSON_RESPONSE_INSTRUCTION, SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';\r\n\r\nimport {\r\n TLLMParams,\r\n ToolData,\r\n TLLMMessageBlock,\r\n TLLMToolResultMessageBlock,\r\n TLLMMessageRole,\r\n APIKeySource,\r\n TLLMEvent,\r\n ILLMRequestFuncParams,\r\n TOpenAIRequestBody,\r\n TOpenAIResponseToolChoice,\r\n TLLMChatResponse,\r\n ILLMRequestContext,\r\n BasicCredentials,\r\n TLLMConnectorParams,\r\n TLLMModel,\r\n TCustomLLMModel,\r\n ILLMConnectorCredentials,\r\n} from '@sre/types/LLM.types';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\n\r\nconst MODELS_WITH_JSON_RESPONSE = ['gpt-4.5-preview', 'gpt-4o-2024-08-06', 'gpt-4o-mini-2024-07-18', 'gpt-4-turbo', 'gpt-3.5-turbo'];\r\n\r\ntype TSearchTool = 'web_search_preview';\r\ntype TSearchContextSize = 'low' | 'medium' | 'high';\r\ntype TSearchLocation = {\r\n type: 'approximate';\r\n city?: string;\r\n country?: string;\r\n region?: string;\r\n timezone?: string;\r\n};\r\n\r\n// per 1k requests\r\nconst costForNormalModels = {\r\n low: 30 / 1000,\r\n medium: 35 / 1000,\r\n high: 50 / 1000,\r\n};\r\nconst costForMiniModels = {\r\n low: 25 / 1000,\r\n medium: 27.5 / 1000,\r\n high: 30 / 1000,\r\n};\r\n\r\nconst SEARCH_TOOL = {\r\n type: 'web_search_preview' as TSearchTool,\r\n cost: {\r\n 'gpt-4.1': costForNormalModels,\r\n 'gpt-4o': costForNormalModels,\r\n 'gpt-4o-search': costForNormalModels,\r\n\r\n 'gpt-4.1-mini': costForMiniModels,\r\n 'gpt-4o-mini': costForMiniModels,\r\n 'gpt-4o-mini-search': costForMiniModels,\r\n },\r\n};\r\n\r\nexport class OpenAIConnector extends LLMConnector {\r\n public name = 'LLM:OpenAI';\r\n\r\n //private openai: OpenAI;\r\n private validImageMimeTypes = SUPPORTED_MIME_TYPES_MAP.OpenAI.image;\r\n private validDocumentMimeTypes = SUPPORTED_MIME_TYPES_MAP.OpenAI.document;\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<OpenAI> {\r\n const apiKey = (params.credentials as BasicCredentials)?.apiKey;\r\n const baseURL = params?.modelInfo?.baseURL;\r\n\r\n if (!apiKey) throw new Error('Please provide an API key for OpenAI');\r\n\r\n return new OpenAI({ baseURL, apiKey });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n const _body = body as OpenAI.ChatCompletionCreateParams;\r\n\r\n try {\r\n const openai = await this.getClient(context);\r\n // #region Validate token limit\r\n const messages = _body?.messages || [];\r\n const lastMessage = messages[messages.length - 1];\r\n\r\n const promptTokens = context?.hasFiles\r\n ? await LLMHelper.countVisionPromptTokens(lastMessage?.content)\r\n : encodeChat(messages as any, 'gpt-4')?.length;\r\n\r\n await this.validateTokenLimit({\r\n acRequest,\r\n promptTokens,\r\n context,\r\n maxTokens: _body.max_completion_tokens,\r\n });\r\n // #endregion Validate token limit\r\n\r\n const result = (await openai.chat.completions.create(_body)) as OpenAI.ChatCompletion;\r\n const message = result?.choices?.[0]?.message;\r\n const finishReason = result?.choices?.[0]?.finish_reason;\r\n\r\n let toolsData: ToolData[] = [];\r\n let useTool = false;\r\n\r\n if (finishReason === 'tool_calls') {\r\n toolsData =\r\n message?.tool_calls?.map((tool, index) => ({\r\n index,\r\n id: tool?.id,\r\n type: tool?.type,\r\n name: tool?.function?.name,\r\n arguments: tool?.function?.arguments,\r\n role: 'tool',\r\n })) || [];\r\n\r\n useTool = true;\r\n }\r\n\r\n const usage = result?.usage;\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n return {\r\n content: message?.content ?? '',\r\n finishReason,\r\n useTool,\r\n toolsData,\r\n message,\r\n usage,\r\n };\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const _body = body as OpenAI.ChatCompletionCreateParams;\r\n\r\n const emitter = new EventEmitter();\r\n const usage_data: any[] = [];\r\n const reportedUsage: any[] = [];\r\n\r\n try {\r\n const openai = await this.getClient(context);\r\n // #region Validate token limit\r\n const messages = _body?.messages || [];\r\n const lastMessage = messages[messages.length - 1];\r\n\r\n const promptTokens = context?.hasFiles\r\n ? await LLMHelper.countVisionPromptTokens(lastMessage?.content)\r\n : encodeChat(messages as any, 'gpt-4')?.length;\r\n\r\n await this.validateTokenLimit({\r\n acRequest,\r\n promptTokens,\r\n context,\r\n maxTokens: _body.max_completion_tokens,\r\n });\r\n // #endregion Validate token limit\r\n\r\n let finishReason = 'stop';\r\n\r\n const stream = await openai.chat.completions.create({ ..._body, stream: true, stream_options: { include_usage: true } });\r\n\r\n // Process stream asynchronously while as we need to return emitter immediately\r\n (async () => {\r\n let delta: Record<string, any> = {};\r\n\r\n let toolsData: any = [];\r\n\r\n for await (const part of stream) {\r\n delta = part.choices[0]?.delta;\r\n const usage = part.usage;\r\n\r\n if (usage) {\r\n usage_data.push(usage);\r\n }\r\n emitter.emit('data', delta);\r\n\r\n if (!delta?.tool_calls && delta?.content) {\r\n emitter.emit('content', delta?.content, delta?.role);\r\n }\r\n //_stream = toolCallsStream;\r\n if (delta?.tool_calls) {\r\n const toolCall = delta?.tool_calls?.[0];\r\n const index = toolCall?.index;\r\n\r\n toolsData[index] = {\r\n index,\r\n role: 'tool',\r\n id: (toolsData?.[index]?.id || '') + (toolCall?.id || ''),\r\n type: (toolsData?.[index]?.type || '') + (toolCall?.type || ''),\r\n name: (toolsData?.[index]?.name || '') + (toolCall?.function?.name || ''),\r\n arguments: (toolsData?.[index]?.arguments || '') + (toolCall?.function?.arguments || ''),\r\n };\r\n\r\n continue;\r\n }\r\n if (part.choices[0]?.finish_reason) {\r\n finishReason = part.choices[0]?.finish_reason;\r\n }\r\n }\r\n if (toolsData?.length > 0) {\r\n for (let tool of toolsData) {\r\n if (tool.type.includes('functionfunction')) {\r\n tool.type = 'function'; //path wrong tool call generated by LM Studio\r\n //FIXME: use cleaner method to fix wrong tool call formats\r\n }\r\n }\r\n emitter.emit(TLLMEvent.ToolInfo, toolsData);\r\n }\r\n\r\n usage_data.forEach((usage) => {\r\n // probably we can acc them and send them as one event\r\n const _reported = this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n reportedUsage.push(_reported);\r\n });\r\n if (finishReason !== 'stop') {\r\n emitter.emit('interrupted', finishReason);\r\n }\r\n\r\n setTimeout(() => {\r\n emitter.emit('end', toolsData, reportedUsage, finishReason);\r\n }, 100);\r\n })();\r\n return emitter;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const _body = body as OpenAI.Responses.ResponseCreateParams;\r\n\r\n const emitter = new EventEmitter();\r\n const usage_data = [];\r\n const reportedUsage = [];\r\n\r\n try {\r\n const openai = await this.getClient(context);\r\n let finishReason = 'stop';\r\n const stream = (await openai.responses.create(_body)) as Stream<OpenAI.Responses.ResponseStreamEvent>;\r\n\r\n // Process stream asynchronously while we need to return emitter immediately\r\n (async () => {\r\n let toolsData: any = [];\r\n let currentToolCall = null;\r\n\r\n for await (const part of stream) {\r\n // Handle different event types from the stream\r\n if ('type' in part) {\r\n const event = part.type;\r\n\r\n switch (event) {\r\n case 'response.output_text.delta': {\r\n if (part?.delta) {\r\n // Emit content in delta format for compatibility\r\n const deltaMsg = {\r\n role: 'assistant',\r\n content: part.delta,\r\n };\r\n emitter.emit('data', deltaMsg);\r\n emitter.emit('content', part.delta, 'assistant');\r\n }\r\n break;\r\n }\r\n // TODO: Handle other events\r\n default: {\r\n break;\r\n }\r\n }\r\n }\r\n\r\n if ('response' in part) {\r\n // Handle usage statistics\r\n if (part.response?.usage) {\r\n usage_data.push(part.response.usage);\r\n }\r\n }\r\n }\r\n\r\n // Report usage statistics\r\n const modelName = context.modelEntryName?.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const searchTool = _body.tools?.[0] as OpenAI.Responses.WebSearchTool;\r\n const cost = SEARCH_TOOL.cost?.[modelName]?.[searchTool?.search_context_size] || 0;\r\n\r\n this.reportUsage(\r\n {\r\n cost,\r\n\r\n // 👇 Just to avoid a TypeScript error.\r\n completion_tokens: 0,\r\n prompt_tokens: 0,\r\n total_tokens: 0,\r\n // 👆 Just to avoid a TypeScript error.\r\n },\r\n {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n }\r\n );\r\n\r\n // Emit interrupted event if finishReason is not 'stop'\r\n if (finishReason !== 'stop') {\r\n emitter.emit('interrupted', finishReason);\r\n }\r\n\r\n // Emit end event with same data structure as v1\r\n setTimeout(() => {\r\n emitter.emit('end', toolsData, reportedUsage, finishReason);\r\n }, 100);\r\n })();\r\n\r\n return emitter;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n // #region Image Generation, will be moved to a different subsystem\r\n protected async imageGenRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<OpenAI.ImagesResponse> {\r\n try {\r\n const openai = await this.getClient(context);\r\n const response = await openai.images.generate(body as OpenAI.Images.ImageGenerateParams);\r\n\r\n return response;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async imageEditRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<OpenAI.ImagesResponse> {\r\n const _body = body as OpenAI.Images.ImageEditParams;\r\n\r\n try {\r\n const openai = await this.getClient(context);\r\n const response = await openai.images.edit(_body);\r\n\r\n return response;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n private async processImageData(files: BinaryInput[], agentId: string): Promise<any[]> {\r\n const validSources = this.getValidImageFiles(files);\r\n if (validSources.length === 0) {\r\n return [];\r\n }\r\n return await this.getImageData(validSources, agentId);\r\n }\r\n\r\n private getValidDocumentFiles(files: BinaryInput[]): BinaryInput[] {\r\n const validSources = [];\r\n for (let file of files) {\r\n if (this.validDocumentMimeTypes.includes(file?.mimetype)) {\r\n validSources.push(file);\r\n }\r\n }\r\n\r\n return validSources;\r\n }\r\n\r\n private async processDocumentData(files: BinaryInput[], agentId: string): Promise<any[]> {\r\n const validSources = this.getValidDocumentFiles(files);\r\n if (validSources.length === 0) {\r\n return [];\r\n }\r\n return await this.getDocumentData(validSources, agentId);\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<TOpenAIRequestBody> {\r\n // if it's web search request and the model has search capability, then we need to prepare the request body for the web search request\r\n if (params?.useWebSearch && params.capabilities?.search === true) {\r\n return this.prepareBodyForWebSearchRequest(params);\r\n }\r\n\r\n if (params.capabilities?.imageGeneration === true) {\r\n if (params?.files?.length > 0) {\r\n return this.prepareBodyForImageEditRequest(params);\r\n } else {\r\n return this.prepareBodyForImageGenRequest(params);\r\n }\r\n }\r\n\r\n if (params.capabilities?.imageEditing === true) {\r\n }\r\n\r\n // In default, we will prepare the request body\r\n return this.prepareBody(params);\r\n }\r\n\r\n protected reportUsage(\r\n usage: OpenAI.Completions.CompletionUsage & {\r\n input_tokens?: number;\r\n output_tokens?: number;\r\n input_tokens_details?: { cached_tokens?: number };\r\n prompt_tokens_details?: { cached_tokens?: number };\r\n cost?: number; // for web search tool\r\n },\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }\r\n ) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const inputTokens = usage?.input_tokens || usage?.prompt_tokens - (usage?.prompt_tokens_details?.cached_tokens || 0); // Returned by the search tool\r\n\r\n const outputTokens =\r\n usage?.output_tokens || // Returned by the search tool\r\n usage?.completion_tokens ||\r\n 0;\r\n\r\n const cachedInputTokens =\r\n usage?.input_tokens_details?.cached_tokens || // Returned by the search tool\r\n usage?.prompt_tokens_details?.cached_tokens ||\r\n 0;\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: inputTokens,\r\n output_tokens: outputTokens,\r\n input_tokens_cache_write: 0,\r\n input_tokens_cache_read: cachedInputTokens,\r\n cost: usage?.cost || 0, // for web search tool\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n let tools: OpenAI.ChatCompletionTool[] = [];\r\n\r\n if (type === 'function') {\r\n tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n return {\r\n type: 'function',\r\n function: {\r\n name,\r\n description,\r\n parameters: {\r\n type: 'object',\r\n properties,\r\n required: requiredFields,\r\n },\r\n },\r\n };\r\n });\r\n }\r\n\r\n return tools?.length > 0 ? { tools, tool_choice: toolChoice || 'auto' } : {};\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock;\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n const messageBlocks: TLLMToolResultMessageBlock[] = [];\r\n\r\n if (messageBlock) {\r\n const transformedMessageBlock = {\r\n ...messageBlock,\r\n content: typeof messageBlock.content === 'object' ? JSON.stringify(messageBlock.content) : messageBlock.content,\r\n };\r\n if (transformedMessageBlock.tool_calls) {\r\n for (let toolCall of transformedMessageBlock.tool_calls) {\r\n toolCall.function.arguments =\r\n typeof toolCall.function.arguments === 'object' ? JSON.stringify(toolCall.function.arguments) : toolCall.function.arguments;\r\n }\r\n }\r\n messageBlocks.push(transformedMessageBlock);\r\n }\r\n\r\n const transformedToolsData = toolsData.map((toolData) => ({\r\n tool_call_id: toolData.id,\r\n role: TLLMMessageRole.Tool, // toolData.role as TLLMMessageRole, //should always be 'tool' for OpenAI\r\n name: toolData.name,\r\n content: typeof toolData.result === 'string' ? toolData.result : JSON.stringify(toolData.result), // Ensure content is a string\r\n }));\r\n\r\n return [...messageBlocks, ...transformedToolsData];\r\n }\r\n\r\n public getConsistentMessages(messages) {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n const _message = { ...message };\r\n let textContent = '';\r\n\r\n if (message?.parts) {\r\n textContent = message.parts.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (Array.isArray(message?.content)) {\r\n textContent = message.content.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (message?.content) {\r\n textContent = message.content;\r\n }\r\n\r\n _message.content = textContent;\r\n\r\n return _message;\r\n });\r\n }\r\n\r\n private getValidImageFiles(files: BinaryInput[]) {\r\n const validSources = [];\r\n\r\n for (let file of files) {\r\n if (this.validImageMimeTypes.includes(file?.mimetype)) {\r\n validSources.push(file);\r\n }\r\n }\r\n\r\n return validSources;\r\n }\r\n\r\n private async getImageData(\r\n files: BinaryInput[],\r\n agentId: string\r\n ): Promise<\r\n {\r\n type: string;\r\n image_url: { url: string };\r\n }[]\r\n > {\r\n try {\r\n const imageData = [];\r\n\r\n for (let file of files) {\r\n const bufferData = await file.readData(AccessCandidate.agent(agentId));\r\n const base64Data = bufferData.toString('base64');\r\n const url = `data:${file.mimetype};base64,${base64Data}`;\r\n\r\n imageData.push({\r\n type: 'image_url',\r\n image_url: { url },\r\n });\r\n }\r\n\r\n return imageData;\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n private async getDocumentData(\r\n files: BinaryInput[],\r\n agentId: string\r\n ): Promise<\r\n {\r\n type: string;\r\n file: {\r\n filename: string;\r\n file_data: string;\r\n };\r\n }[]\r\n > {\r\n try {\r\n const documentData = [];\r\n\r\n // Note: We're embedding the file data in the prompt, but we should ideally be uploading the files to OpenAI first\r\n // in case we start to support bigger files. Refer to this guide: https://platform.openai.com/docs/guides/pdf-files?api-mode=chat\r\n for (let file of files) {\r\n const bufferData = await file.readData(AccessCandidate.agent(agentId));\r\n const base64Data = bufferData.toString('base64');\r\n const fileData = `data:${file.mimetype};base64,${base64Data}`;\r\n\r\n documentData.push({\r\n type: 'file',\r\n file: {\r\n file_data: fileData,\r\n filename: await file.getName(),\r\n },\r\n });\r\n }\r\n\r\n return documentData;\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n private getWebSearchTool(params: TLLMParams) {\r\n const searchCity = params?.webSearchCity;\r\n const searchCountry = params?.webSearchCountry;\r\n const searchRegion = params?.webSearchRegion;\r\n const searchTimezone = params?.webSearchTimezone;\r\n\r\n const location: {\r\n type: 'approximate';\r\n city?: string;\r\n country?: string;\r\n region?: string;\r\n timezone?: string;\r\n } = {\r\n type: 'approximate', // Required, always be 'approximate' when we implement location\r\n };\r\n\r\n if (searchCity) location.city = searchCity;\r\n if (searchCountry) location.country = searchCountry;\r\n if (searchRegion) location.region = searchRegion;\r\n if (searchTimezone) location.timezone = searchTimezone;\r\n\r\n const searchTool: {\r\n type: TSearchTool;\r\n search_context_size: TSearchContextSize;\r\n user_location?: TSearchLocation;\r\n } = {\r\n type: SEARCH_TOOL.type,\r\n search_context_size: params?.webSearchContextSize || 'medium',\r\n };\r\n\r\n // Add location only if any location field is provided. Since 'type' is always present, we check if the number of keys in the location object is greater than 1.\r\n if (Object.keys(location).length > 1) {\r\n searchTool.user_location = location;\r\n }\r\n\r\n return searchTool;\r\n }\r\n\r\n private async validateTokenLimit({\r\n acRequest,\r\n maxTokens,\r\n promptTokens,\r\n context,\r\n }: {\r\n acRequest: AccessRequest;\r\n maxTokens: number;\r\n promptTokens: number;\r\n context: ILLMRequestContext;\r\n }): Promise<void> {\r\n const provider = await this.getProvider(acRequest, context.modelEntryName);\r\n\r\n await provider.validateTokensLimit({\r\n model: context.modelEntryName,\r\n promptTokens,\r\n completionTokens: maxTokens,\r\n hasAPIKey: context.isUserKey,\r\n });\r\n }\r\n\r\n private async getProvider(acRequest: AccessRequest, modelEntryName: string) {\r\n const modelsProviderConnector = ConnectorService.getModelsProviderConnector();\r\n const modelsProvider = modelsProviderConnector.requester(acRequest.candidate as AccessCandidate);\r\n\r\n return modelsProvider;\r\n }\r\n\r\n private async prepareBodyForWebSearchRequest(params: TLLMParams): Promise<OpenAI.Responses.ResponseCreateParams> {\r\n const body: OpenAI.Responses.ResponseCreateParams = {\r\n model: params.model as string,\r\n input: params.messages,\r\n stream: true,\r\n };\r\n\r\n if (params?.max_output_tokens !== undefined) {\r\n body.max_output_tokens = params.max_output_tokens;\r\n }\r\n\r\n // #region Handle tools configuration\r\n\r\n const searchTool = this.getWebSearchTool(params);\r\n body.tools = [searchTool];\r\n\r\n if (params?.toolsConfig?.tool_choice) {\r\n body.tool_choice = params.toolsConfig.tool_choice as TOpenAIResponseToolChoice;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n private async prepareBodyForImageGenRequest(params: TLLMParams): Promise<OpenAI.Images.ImageGenerateParams> {\r\n const { model, size, quality, n, responseFormat, style } = params;\r\n\r\n const body: OpenAI.Images.ImageGenerateParams = {\r\n prompt: params.prompt,\r\n model: model as string,\r\n size: size as OpenAI.Images.ImageGenerateParams['size'],\r\n n: n || 1,\r\n };\r\n\r\n if (quality) {\r\n body.quality = quality;\r\n }\r\n\r\n // * Models like 'gpt-image-1' do not support the 'response_format' parameter, so we only set it when explicitly specified.\r\n if (responseFormat) {\r\n body.response_format = responseFormat;\r\n }\r\n\r\n if (style) {\r\n body.style = style;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n private async prepareBodyForImageEditRequest(params: TLLMParams): Promise<OpenAI.Images.ImageEditParams> {\r\n const { model, size, n, responseFormat } = params;\r\n\r\n const body: OpenAI.Images.ImageEditParams = {\r\n prompt: params.prompt,\r\n model: model as string,\r\n size: size as OpenAI.Images.ImageEditParams['size'],\r\n n: n || 1,\r\n image: null,\r\n };\r\n\r\n // * Models like 'gpt-image-1' do not support the 'response_format' parameter, so we only set it when explicitly specified.\r\n if (responseFormat) {\r\n body.response_format = responseFormat;\r\n }\r\n\r\n const files: BinaryInput[] = params?.files || [];\r\n\r\n if (files.length > 0) {\r\n const images = await Promise.all(\r\n files.map(\r\n async (file) =>\r\n await toFile(await file.getReadStream(), await file.getName(), {\r\n type: file.mimetype,\r\n })\r\n )\r\n );\r\n\r\n body.image = images;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n private async prepareBody(params: TLLMParams): Promise<OpenAI.ChatCompletionCreateParams> {\r\n const messages = await this.prepareMessages(params);\r\n\r\n //#region Handle JSON response format\r\n // TODO: We have better parameter to have structured response, need to implement it.\r\n const responseFormat = params?.responseFormat || '';\r\n if (responseFormat === 'json') {\r\n // We assume that the system message is first item in messages array\r\n if (messages?.[0]?.role === TLLMMessageRole.System) {\r\n messages[0].content += JSON_RESPONSE_INSTRUCTION;\r\n } else {\r\n messages.unshift({ role: TLLMMessageRole.System, content: JSON_RESPONSE_INSTRUCTION });\r\n }\r\n\r\n if (MODELS_WITH_JSON_RESPONSE.includes(params.model as string)) {\r\n params.responseFormat = { type: 'json_object' };\r\n } else {\r\n params.responseFormat = undefined; // We need to reset it, otherwise 'json' will be passed as a parameter to the OpenAI API\r\n }\r\n }\r\n //#endregion Handle JSON response format\r\n\r\n const body: OpenAI.ChatCompletionCreateParams = {\r\n model: params.model as string,\r\n messages,\r\n };\r\n\r\n if (params?.toolsConfig?.tools && params?.toolsConfig?.tools?.length > 0) {\r\n body.tools = params?.toolsConfig?.tools as OpenAI.ChatCompletionTool[];\r\n }\r\n\r\n if (params?.toolsConfig?.tool_choice) {\r\n body.tool_choice = params?.toolsConfig?.tool_choice as OpenAI.ChatCompletionToolChoiceOption;\r\n }\r\n\r\n if (params?.maxTokens !== undefined) body.max_completion_tokens = params.maxTokens;\r\n if (params?.temperature !== undefined) body.temperature = params.temperature;\r\n if (params?.topP !== undefined) body.top_p = params.topP;\r\n if (params?.frequencyPenalty !== undefined) body.frequency_penalty = params.frequencyPenalty;\r\n if (params?.presencePenalty !== undefined) body.presence_penalty = params.presencePenalty;\r\n if (params?.responseFormat !== undefined) body.response_format = params.responseFormat;\r\n if (params?.stopSequences?.length) body.stop = params.stopSequences;\r\n\r\n return body;\r\n }\r\n\r\n private async prepareMessages(params: TLLMParams) {\r\n const messages = params?.messages || [];\r\n\r\n const files: BinaryInput[] = params?.files || []; // Assign file from the original parameters to avoid overwriting the original constructor\r\n\r\n if (files.length > 0) {\r\n // #region Upload files\r\n const promises = [];\r\n const _files = [];\r\n\r\n for (let image of files) {\r\n const binaryInput = BinaryInput.from(image);\r\n promises.push(binaryInput.upload(AccessCandidate.agent(params.agentId)));\r\n\r\n _files.push(binaryInput);\r\n }\r\n\r\n await Promise.all(promises);\r\n // #endregion Upload files\r\n\r\n const validImageFiles = this.getValidImageFiles(_files);\r\n const validDocumentFiles = this.getValidDocumentFiles(_files);\r\n\r\n const imageData = validImageFiles.length > 0 ? await this.processImageData(validImageFiles, params.agentId) : [];\r\n const documentData = validDocumentFiles.length > 0 ? await this.processDocumentData(validDocumentFiles, params.agentId) : [];\r\n\r\n const userMessage = Array.isArray(messages) ? messages.pop() : {};\r\n const prompt = userMessage?.content || '';\r\n\r\n const promptData = [{ type: 'text', text: prompt || '' }, ...imageData, ...documentData];\r\n\r\n messages.push({ role: 'user', content: promptData });\r\n }\r\n\r\n return messages;\r\n }\r\n}\r\n","import os from 'os';\r\nimport path from 'path';\r\nimport EventEmitter from 'events';\r\nimport fs from 'fs';\r\n\r\nimport { GoogleGenerativeAI, ModelParams, GenerationConfig, GenerateContentRequest, UsageMetadata } from '@google/generative-ai';\r\nimport { GoogleAIFileManager, FileState } from '@google/generative-ai/server';\r\n\r\nimport { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { uid } from '@sre/utils';\r\n\r\nimport { processWithConcurrencyLimit } from '@sre/utils';\r\n\r\nimport {\r\n TLLMMessageBlock,\r\n ToolData,\r\n TLLMMessageRole,\r\n TLLMToolResultMessageBlock,\r\n APIKeySource,\r\n TLLMEvent,\r\n TLLMParams,\r\n BasicCredentials,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n TGoogleAIRequestBody,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n} from '@sre/types/LLM.types';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\n\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\n\r\nconst MODELS_SUPPORT_SYSTEM_INSTRUCTION = [\r\n 'gemini-1.5-pro-exp-0801',\r\n 'gemini-1.5-pro-latest',\r\n 'gemini-1.5-pro-latest',\r\n 'gemini-1.5-pro',\r\n 'gemini-1.5-pro-001',\r\n 'gemini-1.5-flash-latest',\r\n 'gemini-1.5-flash-001',\r\n 'gemini-1.5-flash',\r\n];\r\nconst MODELS_SUPPORT_JSON_RESPONSE = MODELS_SUPPORT_SYSTEM_INSTRUCTION;\r\n\r\n// Supported file MIME types for Google AI's Gemini models\r\nconst VALID_MIME_TYPES = [\r\n ...SUPPORTED_MIME_TYPES_MAP.GoogleAI.image,\r\n ...SUPPORTED_MIME_TYPES_MAP.GoogleAI.audio,\r\n ...SUPPORTED_MIME_TYPES_MAP.GoogleAI.video,\r\n ...SUPPORTED_MIME_TYPES_MAP.GoogleAI.document,\r\n];\r\n\r\n// will be removed after updating the SDK\r\ntype UsageMetadataWithThoughtsToken = UsageMetadata & { thoughtsTokenCount: number };\r\n\r\nexport class GoogleAIConnector extends LLMConnector {\r\n public name = 'LLM:GoogleAI';\r\n\r\n private validMimeTypes = {\r\n all: VALID_MIME_TYPES,\r\n image: SUPPORTED_MIME_TYPES_MAP.GoogleAI.image,\r\n };\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<GoogleGenerativeAI> {\r\n const apiKey = (params.credentials as BasicCredentials)?.apiKey;\r\n\r\n if (!apiKey) throw new Error('Please provide an API key for Google AI');\r\n\r\n return new GoogleGenerativeAI(apiKey);\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n try {\r\n const prompt = body.messages;\r\n delete body.messages;\r\n\r\n const genAI = await this.getClient(context);\r\n const $model = genAI.getGenerativeModel(body);\r\n\r\n const result = await $model.generateContent(prompt);\r\n\r\n const response = await result.response;\r\n const content = response.text();\r\n const finishReason = response.candidates[0].finishReason || 'stop';\r\n const usage = response?.usageMetadata as UsageMetadataWithThoughtsToken;\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n const toolCalls = response.candidates[0]?.content?.parts?.filter((part) => part.functionCall);\r\n\r\n let toolsData: ToolData[] = [];\r\n let useTool = false;\r\n\r\n if (toolCalls && toolCalls.length > 0) {\r\n toolsData = toolCalls.map((toolCall, index) => ({\r\n index,\r\n id: `tool-${index}`,\r\n type: 'function',\r\n name: toolCall.functionCall.name,\r\n arguments: JSON.stringify(toolCall.functionCall.args),\r\n role: TLLMMessageRole.Assistant,\r\n }));\r\n useTool = true;\r\n }\r\n\r\n return {\r\n content,\r\n finishReason,\r\n useTool,\r\n toolsData,\r\n message: { content, role: 'assistant' },\r\n usage,\r\n };\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const emitter = new EventEmitter();\r\n\r\n const prompt = body.messages;\r\n delete body.messages;\r\n\r\n const genAI = await this.getClient(context);\r\n const $model = genAI.getGenerativeModel(body);\r\n\r\n try {\r\n const result = await $model.generateContentStream(prompt);\r\n\r\n let toolsData: ToolData[] = [];\r\n let usage: UsageMetadataWithThoughtsToken;\r\n\r\n // Process stream asynchronously while as we need to return emitter immediately\r\n (async () => {\r\n for await (const chunk of result.stream) {\r\n const chunkText = chunk.text();\r\n emitter.emit('content', chunkText);\r\n\r\n if (chunk.candidates[0]?.content?.parts) {\r\n const toolCalls = chunk.candidates[0].content.parts.filter((part) => part.functionCall);\r\n if (toolCalls.length > 0) {\r\n toolsData = toolCalls.map((toolCall, index) => ({\r\n index,\r\n id: `tool-${index}`,\r\n type: 'function',\r\n name: toolCall.functionCall.name,\r\n arguments: JSON.stringify(toolCall.functionCall.args),\r\n role: TLLMMessageRole.Assistant,\r\n }));\r\n emitter.emit(TLLMEvent.ToolInfo, toolsData);\r\n }\r\n }\r\n\r\n // the same usage is sent on each emit. IMPORTANT: google does not send usage for each chunk but\r\n // rather just sends the same usage for the entire request.\r\n // notice that the output tokens are only sent in the last chunk usage metadata.\r\n // so we will just update a var to hold the latest usage and report it when the stream ends.\r\n // e.g emit1: { input_tokens: 500, output_tokens: undefined } -> same input_tokens\r\n // e.g emit2: { input_tokens: 500, output_tokens: undefined } -> same input_tokens\r\n // e.g emit3: { input_tokens: 500, output_tokens: 10 } -> same input_tokens, new output_tokens in the last chunk\r\n if (chunk?.usageMetadata) {\r\n usage = chunk.usageMetadata as UsageMetadataWithThoughtsToken;\r\n }\r\n }\r\n\r\n if (usage) {\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n }\r\n\r\n setTimeout(() => {\r\n emitter.emit('end', toolsData);\r\n }, 100);\r\n })();\r\n\r\n return emitter;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any> {\r\n throw new Error('Web search is not supported for Google AI');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<TGoogleAIRequestBody> {\r\n const model = params?.model;\r\n\r\n const messages = await this.prepareMessages(params);\r\n\r\n let body: ModelParams & { messages: string | TLLMMessageBlock[] | GenerateContentRequest } = {\r\n model: model as string,\r\n messages,\r\n };\r\n\r\n const responseFormat = params?.responseFormat || '';\r\n let responseMimeType = '';\r\n let systemInstruction = '';\r\n\r\n if (responseFormat === 'json') {\r\n systemInstruction += JSON_RESPONSE_INSTRUCTION;\r\n\r\n if (MODELS_SUPPORT_JSON_RESPONSE.includes(model as string)) {\r\n responseMimeType = 'application/json';\r\n }\r\n }\r\n\r\n const config: GenerationConfig = {};\r\n\r\n if (params.maxTokens !== undefined) config.maxOutputTokens = params.maxTokens;\r\n if (params.temperature !== undefined) config.temperature = params.temperature;\r\n if (params.topP !== undefined) config.topP = params.topP;\r\n if (params.topK !== undefined) config.topK = params.topK;\r\n if (params.stopSequences?.length) config.stopSequences = params.stopSequences;\r\n if (responseMimeType) config.responseMimeType = responseMimeType;\r\n\r\n if (systemInstruction) body.systemInstruction = systemInstruction;\r\n if (Object.keys(config).length > 0) {\r\n body.generationConfig = config;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(\r\n usage: UsageMetadataWithThoughtsToken,\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }\r\n ) {\r\n const modelEntryName = metadata.modelEntryName;\r\n let tier = '';\r\n\r\n const tierThresholds = {\r\n 'gemini-1.5-pro': 128_000,\r\n 'gemini-2.5-pro': 200_000,\r\n };\r\n\r\n const textInputTokens =\r\n usage?.['promptTokensDetails']?.find((detail) => detail.modality === 'TEXT')?.tokenCount || usage?.promptTokenCount || 0;\r\n const audioInputTokens = usage?.['promptTokensDetails']?.find((detail) => detail.modality === 'AUDIO')?.tokenCount || 0;\r\n\r\n // Find matching model and set tier based on threshold\r\n const modelWithTier = Object.keys(tierThresholds).find((model) => modelEntryName.includes(model));\r\n if (modelWithTier) {\r\n tier = textInputTokens < tierThresholds[modelWithTier] ? 'tier1' : 'tier2';\r\n }\r\n\r\n // #endregion\r\n\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: textInputTokens,\r\n output_tokens: usage.candidatesTokenCount,\r\n input_tokens_audio: audioInputTokens,\r\n input_tokens_cache_read: usage.cachedContentTokenCount || 0,\r\n input_tokens_cache_write: 0,\r\n reasoning_tokens: usage.thoughtsTokenCount,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n tier,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ toolDefinitions, toolChoice = 'auto' }) {\r\n const tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n // Ensure the function name is valid\r\n const validName = this.sanitizeFunctionName(name);\r\n\r\n // Ensure properties are non-empty for OBJECT type\r\n const validProperties = properties && Object.keys(properties).length > 0 ? properties : { dummy: { type: 'string' } };\r\n\r\n return {\r\n functionDeclarations: [\r\n {\r\n name: validName,\r\n description: description || '',\r\n parameters: {\r\n type: 'OBJECT',\r\n properties: validProperties,\r\n required: requiredFields || [],\r\n },\r\n },\r\n ],\r\n };\r\n });\r\n\r\n return {\r\n tools,\r\n toolChoice: {\r\n type: toolChoice,\r\n },\r\n };\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock;\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n const messageBlocks: TLLMToolResultMessageBlock[] = [];\r\n\r\n if (messageBlock) {\r\n const content = [];\r\n if (typeof messageBlock.content === 'string') {\r\n content.push({ text: messageBlock.content });\r\n } else if (Array.isArray(messageBlock.content)) {\r\n content.push(...messageBlock.content);\r\n }\r\n\r\n if (messageBlock.parts) {\r\n const functionCalls = messageBlock.parts.filter((part) => part.functionCall);\r\n if (functionCalls.length > 0) {\r\n content.push(\r\n ...functionCalls.map((call) => ({\r\n functionCall: {\r\n name: call.functionCall.name,\r\n args: JSON.parse(call.functionCall.args),\r\n },\r\n }))\r\n );\r\n }\r\n }\r\n\r\n messageBlocks.push({\r\n role: messageBlock.role,\r\n parts: content,\r\n });\r\n }\r\n\r\n const transformedToolsData = toolsData.map(\r\n (toolData): TLLMToolResultMessageBlock => ({\r\n role: TLLMMessageRole.Function,\r\n parts: [\r\n {\r\n functionResponse: {\r\n name: toolData.name,\r\n response: {\r\n name: toolData.name,\r\n content: typeof toolData.result === 'string' ? toolData.result : JSON.stringify(toolData.result),\r\n },\r\n },\r\n },\r\n ],\r\n })\r\n );\r\n\r\n return [...messageBlocks, ...transformedToolsData];\r\n }\r\n\r\n public getConsistentMessages(messages: TLLMMessageBlock[]): TLLMMessageBlock[] {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n const _message = { ...message };\r\n let textContent = '';\r\n\r\n // Map roles to valid Google AI roles\r\n switch (_message.role) {\r\n case TLLMMessageRole.Assistant:\r\n case TLLMMessageRole.System:\r\n _message.role = TLLMMessageRole.Model;\r\n break;\r\n case TLLMMessageRole.User:\r\n // User role is already valid\r\n break;\r\n default:\r\n _message.role = TLLMMessageRole.User; // Default to user for unknown roles\r\n }\r\n\r\n // * empty text causes error that's why we added '...'\r\n\r\n if (_message?.parts) {\r\n textContent = _message.parts.map((textBlock) => textBlock?.text || '...').join(' ');\r\n } else if (Array.isArray(_message?.content)) {\r\n textContent = _message.content.map((textBlock) => textBlock?.text || '...').join(' ');\r\n } else if (_message?.content) {\r\n textContent = (_message.content as string) || '...';\r\n }\r\n\r\n _message.parts = [{ text: textContent || '...' }];\r\n\r\n delete _message.content; // Remove content to avoid error\r\n\r\n return _message;\r\n });\r\n }\r\n\r\n private async prepareMessages(params: TLLMParams): Promise<string | TLLMMessageBlock[] | GenerateContentRequest> {\r\n let messages: string | TLLMMessageBlock[] | GenerateContentRequest = params?.messages || '';\r\n\r\n const files: BinaryInput[] = params?.files || [];\r\n\r\n if (files.length > 0) {\r\n messages = await this.prepareMessagesWithFiles(params);\r\n } else if (params?.toolsConfig?.tools?.length > 0) {\r\n messages = await this.prepareMessagesWithTools(params);\r\n } else {\r\n messages = await this.prepareMessagesWithTextQuery(params);\r\n }\r\n\r\n return messages;\r\n }\r\n\r\n private async prepareMessagesWithFiles(params: TLLMParams): Promise<string> {\r\n const model = params.model;\r\n\r\n let messages: string | TLLMMessageBlock[] = params?.messages || '';\r\n let systemInstruction = '';\r\n const files: BinaryInput[] = params?.files || [];\r\n\r\n // #region Upload files\r\n const promises = [];\r\n const _files = [];\r\n\r\n for (let image of files) {\r\n const binaryInput = BinaryInput.from(image);\r\n promises.push(binaryInput.upload(AccessCandidate.agent(params.agentId)));\r\n\r\n _files.push(binaryInput);\r\n }\r\n\r\n await Promise.all(promises);\r\n // #endregion Upload files\r\n\r\n // If user provide mix of valid and invalid files, we will only process the valid files\r\n const validFiles = this.getValidFiles(_files, 'all');\r\n\r\n const hasVideo = validFiles.some((file) => file?.mimetype?.includes('video'));\r\n\r\n // GoogleAI only supports one video file at a time\r\n if (hasVideo && validFiles.length > 1) {\r\n throw new Error('Only one video file is supported at a time.');\r\n }\r\n\r\n const fileUploadingTasks = validFiles.map((file) => async () => {\r\n try {\r\n const uploadedFile = await this.uploadFile({\r\n file,\r\n apiKey: (params.credentials as BasicCredentials).apiKey,\r\n agentId: params.agentId,\r\n });\r\n\r\n return { url: uploadedFile.url, mimetype: file.mimetype };\r\n } catch {\r\n return null;\r\n }\r\n });\r\n\r\n const uploadedFiles = await processWithConcurrencyLimit(fileUploadingTasks);\r\n\r\n // We throw error when there are no valid uploaded files,\r\n if (uploadedFiles && uploadedFiles?.length === 0) {\r\n throw new Error(`There is an issue during upload file in Google AI Server!`);\r\n }\r\n\r\n const fileData = this.getFileData(uploadedFiles);\r\n\r\n const userMessage: TLLMMessageBlock = Array.isArray(messages) ? messages.pop() : { role: TLLMMessageRole.User, content: '' };\r\n let prompt = userMessage?.content || '';\r\n\r\n // if the the model does not support system instruction, we will add it to the prompt\r\n if (!MODELS_SUPPORT_SYSTEM_INSTRUCTION.includes(model as string)) {\r\n prompt = `${prompt}\\n${systemInstruction}`;\r\n }\r\n //#endregion Separate system message and add JSON response instruction if needed\r\n\r\n // Adjust input structure handling for multiple image files to accommodate variations.\r\n messages = fileData.length === 1 ? ([...fileData, { text: prompt }] as any) : ([prompt, ...fileData] as any);\r\n\r\n return messages as string;\r\n }\r\n\r\n private async prepareMessagesWithTools(params: TLLMParams): Promise<GenerateContentRequest> {\r\n let formattedMessages: TLLMMessageBlock[];\r\n let systemInstruction = '';\r\n\r\n let messages = params?.messages || [];\r\n\r\n const hasSystemMessage = LLMHelper.hasSystemMessage(messages);\r\n\r\n if (hasSystemMessage) {\r\n const separateMessages = LLMHelper.separateSystemMessages(messages);\r\n const systemMessageContent = (separateMessages.systemMessage as TLLMMessageBlock)?.content;\r\n systemInstruction = typeof systemMessageContent === 'string' ? systemMessageContent : '';\r\n formattedMessages = separateMessages.otherMessages;\r\n } else {\r\n formattedMessages = messages;\r\n }\r\n\r\n const toolsPrompt: GenerateContentRequest = {\r\n contents: formattedMessages as any,\r\n };\r\n\r\n if (systemInstruction) {\r\n toolsPrompt.systemInstruction = systemInstruction;\r\n }\r\n\r\n if (params?.toolsConfig?.tools) toolsPrompt.tools = params?.toolsConfig?.tools as any;\r\n if (params?.toolsConfig?.tool_choice) {\r\n toolsPrompt.toolConfig = {\r\n functionCallingConfig: { mode: (params?.toolsConfig?.tool_choice as any) || 'auto' },\r\n };\r\n }\r\n\r\n return toolsPrompt;\r\n }\r\n\r\n private async prepareMessagesWithTextQuery(params: TLLMParams): Promise<string> {\r\n const model = params.model;\r\n let systemInstruction = '';\r\n let prompt = '';\r\n\r\n const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(params?.messages as TLLMMessageBlock[]);\r\n\r\n if ('content' in systemMessage) {\r\n systemInstruction = systemMessage.content as string;\r\n }\r\n\r\n const responseFormat = params?.responseFormat || '';\r\n let responseMimeType = '';\r\n\r\n if (responseFormat === 'json') {\r\n systemInstruction += JSON_RESPONSE_INSTRUCTION;\r\n\r\n if (MODELS_SUPPORT_JSON_RESPONSE.includes(model as string)) {\r\n responseMimeType = 'application/json';\r\n }\r\n }\r\n\r\n if (otherMessages?.length > 0) {\r\n // Concatenate messages with prompt and remove messages from params as it's not supported\r\n prompt += otherMessages.map((message) => message?.parts?.[0]?.text || '').join('\\n');\r\n }\r\n\r\n // if the the model does not support system instruction, we will add it to the prompt\r\n if (!MODELS_SUPPORT_SYSTEM_INSTRUCTION.includes(model as string)) {\r\n prompt = `${prompt}\\n${systemInstruction}`;\r\n }\r\n //#endregion Separate system message and add JSON response instruction if needed\r\n\r\n return prompt;\r\n }\r\n\r\n // Add this helper method to sanitize function names\r\n private sanitizeFunctionName(name: string): string {\r\n // Check if name is undefined or null\r\n if (name == null) {\r\n return '_unnamed_function';\r\n }\r\n\r\n // Remove any characters that are not alphanumeric, underscore, dot, or dash\r\n let sanitized = name.replace(/[^a-zA-Z0-9_.-]/g, '');\r\n\r\n // Ensure the name starts with a letter or underscore\r\n if (!/^[a-zA-Z_]/.test(sanitized)) {\r\n sanitized = '_' + sanitized;\r\n }\r\n\r\n // If sanitized is empty after removing invalid characters, use a default name\r\n if (sanitized === '') {\r\n sanitized = '_unnamed_function';\r\n }\r\n\r\n // Truncate to 64 characters if longer\r\n sanitized = sanitized.slice(0, 64);\r\n\r\n return sanitized;\r\n }\r\n\r\n private async uploadFile({ file, apiKey, agentId }: { file: BinaryInput; apiKey: string; agentId: string }): Promise<{ url: string }> {\r\n try {\r\n if (!apiKey || !file?.mimetype) {\r\n throw new Error('Missing required parameters to save file for Google AI!');\r\n }\r\n\r\n // Create a temporary directory\r\n const tempDir = os.tmpdir();\r\n const fileName = uid();\r\n const tempFilePath = path.join(tempDir, fileName);\r\n\r\n const bufferData = await file.readData(AccessCandidate.agent(agentId));\r\n\r\n // Write buffer data to temp file\r\n await fs.promises.writeFile(tempFilePath, new Uint8Array(bufferData));\r\n\r\n // Upload the file to the Google File Manager\r\n const fileManager = new GoogleAIFileManager(apiKey);\r\n\r\n const uploadResponse = await fileManager.uploadFile(tempFilePath, {\r\n mimeType: file.mimetype,\r\n displayName: fileName,\r\n });\r\n\r\n const name = uploadResponse.file.name;\r\n\r\n // Poll getFile() on a set interval (10 seconds here) to check file state.\r\n let uploadedFile = await fileManager.getFile(name);\r\n while (uploadedFile.state === FileState.PROCESSING) {\r\n process.stdout.write('.');\r\n // Sleep for 10 seconds\r\n await new Promise((resolve) => setTimeout(resolve, 10_000));\r\n // Fetch the file from the API again\r\n uploadedFile = await fileManager.getFile(name);\r\n }\r\n\r\n if (uploadedFile.state === FileState.FAILED) {\r\n throw new Error('File processing failed.');\r\n }\r\n\r\n // Clean up temp file\r\n await fs.promises.unlink(tempFilePath);\r\n\r\n return {\r\n url: uploadResponse.file.uri || '',\r\n };\r\n } catch (error) {\r\n throw new Error(`Error uploading file for Google AI: ${error.message}`);\r\n }\r\n }\r\n\r\n private getValidFiles(files: BinaryInput[], type: 'image' | 'all') {\r\n const validSources = [];\r\n\r\n for (let file of files) {\r\n if (this.validMimeTypes[type].includes(file?.mimetype)) {\r\n validSources.push(file);\r\n }\r\n }\r\n\r\n if (validSources?.length === 0) {\r\n throw new Error(`Unsupported file(s). Please make sure your file is one of the following types: ${this.validMimeTypes[type].join(', ')}`);\r\n }\r\n\r\n return validSources;\r\n }\r\n\r\n private getFileData(\r\n files: {\r\n url: string;\r\n mimetype: string;\r\n }[]\r\n ): {\r\n fileData: {\r\n mimeType: string;\r\n fileUri: string;\r\n };\r\n }[] {\r\n try {\r\n const imageData = [];\r\n\r\n for (let file of files) {\r\n imageData.push({\r\n fileData: {\r\n mimeType: file.mimetype,\r\n fileUri: file.url,\r\n },\r\n });\r\n }\r\n\r\n return imageData;\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n}\r\n","import EventEmitter from 'events';\r\nimport Anthropic from '@anthropic-ai/sdk';\r\n\r\nimport { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport { BinaryInput } from '@sre/helpers/BinaryInput.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport {\r\n TLLMParams,\r\n ToolData,\r\n TLLMMessageBlock,\r\n TLLMToolResultMessageBlock,\r\n TLLMMessageRole,\r\n APIKeySource,\r\n TLLMEvent,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n BasicCredentials,\r\n TAnthropicRequestBody,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n} from '@sre/types/LLM.types';\r\n\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\nimport { SUPPORTED_MIME_TYPES_MAP } from '@sre/constants';\r\n\r\nconst PREFILL_TEXT_FOR_JSON_RESPONSE = '{';\r\nconst LEGACY_THINKING_MODELS = ['smythos/claude-3.7-sonnet-thinking', 'claude-3.7-sonnet-thinking'];\r\n\r\n// Type aliases\r\ntype AnthropicMessageParams = Anthropic.MessageCreateParamsNonStreaming | Anthropic.Messages.MessageStreamParams;\r\n\r\n// TODO [Forhad]: implement proper typing\r\n\r\nexport class AnthropicConnector extends LLMConnector {\r\n public name = 'LLM:Anthropic';\r\n\r\n private validImageMimeTypes = SUPPORTED_MIME_TYPES_MAP.Anthropic.image;\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<Anthropic> {\r\n const apiKey = (params.credentials as BasicCredentials)?.apiKey;\r\n\r\n if (!apiKey) throw new Error('Please provide an API key for Anthropic');\r\n\r\n return new Anthropic({ apiKey });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n try {\r\n const anthropic = await this.getClient(context);\r\n const result = await anthropic.messages.create(body);\r\n const message: Anthropic.MessageParam = {\r\n role: (result?.role || TLLMMessageRole.User) as Anthropic.MessageParam['role'],\r\n content: result?.content || '',\r\n };\r\n const stopReason = result?.stop_reason;\r\n\r\n let toolsData: ToolData[] = [];\r\n let useTool = false;\r\n\r\n if ((stopReason as 'tool_use') === 'tool_use') {\r\n const toolUseContentBlocks = result?.content?.filter((c) => (c.type as 'tool_use') === 'tool_use');\r\n\r\n if (toolUseContentBlocks?.length === 0) return;\r\n\r\n toolUseContentBlocks.forEach((toolUseBlock: Anthropic.Messages.ToolUseBlock, index) => {\r\n toolsData.push({\r\n index,\r\n id: toolUseBlock?.id,\r\n type: 'function', // We call API only when the tool type is 'function' in `src/helpers/Conversation.helper.ts`. Even though Anthropic returns the type as 'tool_use', it should be interpreted as 'function'.\r\n name: toolUseBlock?.name,\r\n arguments: toolUseBlock?.input,\r\n role: result?.role,\r\n });\r\n });\r\n\r\n useTool = true;\r\n }\r\n\r\n const textBlock = result?.content?.find((block) => block.type === 'text');\r\n const content = textBlock?.text || '';\r\n\r\n const usage = result?.usage;\r\n\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n return {\r\n content,\r\n finishReason: result?.stop_reason,\r\n useTool,\r\n toolsData,\r\n message,\r\n usage,\r\n };\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n try {\r\n const emitter = new EventEmitter();\r\n const usage_data = [];\r\n\r\n const anthropic = await this.getClient(context);\r\n let stream = anthropic.messages.stream(body);\r\n\r\n let toolsData: ToolData[] = [];\r\n let thinkingBlocks: any[] = []; // To preserve thinking blocks\r\n\r\n stream.on('streamEvent', (event: any) => {\r\n if (event.message?.usage) {\r\n //console.log('usage', event.message?.usage);\r\n }\r\n });\r\n\r\n stream.on('error', (error) => {\r\n //console.log('error', error);\r\n\r\n emitter.emit('error', error);\r\n });\r\n stream.on('text', (text: string) => {\r\n emitter.emit('content', text);\r\n });\r\n\r\n stream.on('thinking', (thinking) => {\r\n // Handle thinking blocks during streaming\r\n emitter.emit('thinking', thinking);\r\n });\r\n\r\n stream.on('finalMessage', (finalMessage) => {\r\n let finishReason = 'stop';\r\n // Preserve thinking blocks for subsequent tool interactions\r\n thinkingBlocks = finalMessage.content.filter((block) => block.type === 'thinking' || block.type === 'redacted_thinking');\r\n\r\n // Process tool use blocks\r\n const toolUseContentBlocks = finalMessage.content.filter((c) => c.type === 'tool_use');\r\n\r\n if (toolUseContentBlocks?.length > 0) {\r\n toolUseContentBlocks.forEach((toolUseBlock: Anthropic.Messages.ToolUseBlock, index) => {\r\n toolsData.push({\r\n index,\r\n id: toolUseBlock?.id,\r\n type: 'function', // We call API only when the tool type is 'function' in `src/helpers/Conversation.helper.ts`. Even though Anthropic returns the type as 'tool_use', it should be interpreted as 'function'.\r\n name: toolUseBlock?.name,\r\n arguments: toolUseBlock?.input,\r\n role: finalMessage?.role,\r\n });\r\n });\r\n\r\n emitter.emit(TLLMEvent.ToolInfo, toolsData, thinkingBlocks);\r\n } else {\r\n finishReason = finalMessage.stop_reason;\r\n }\r\n\r\n if (finalMessage?.usage) {\r\n const usage = finalMessage.usage;\r\n\r\n const reportedUsage = this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n usage_data.push(reportedUsage);\r\n }\r\n if (finishReason !== 'stop' && finishReason !== 'end_turn') {\r\n emitter.emit('interrupted', finishReason);\r\n }\r\n\r\n //only emit end event after processing the final message\r\n setTimeout(() => {\r\n emitter.emit('end', toolsData, usage_data, finishReason);\r\n }, 100);\r\n });\r\n\r\n return emitter;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search requests are not supported by Anthropic');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<TAnthropicRequestBody> {\r\n const body = await this.prepareBody(params);\r\n\r\n const shouldUseThinking = await this.shouldUseThinkingMode(params);\r\n if (shouldUseThinking) {\r\n return await this.prepareBodyForThinkingRequest({\r\n body,\r\n maxThinkingTokens: params.maxThinkingTokens,\r\n toolChoice: params?.toolsConfig?.tool_choice as unknown as Anthropic.ToolChoice,\r\n });\r\n }\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(\r\n usage: Anthropic.Messages.Usage & { cache_creation_input_tokens?: number; cache_read_input_tokens?: number },\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string },\r\n ) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: usage.input_tokens,\r\n output_tokens: usage.output_tokens,\r\n input_tokens_cache_write: usage.cache_creation_input_tokens,\r\n input_tokens_cache_read: usage.cache_read_input_tokens,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n let tools: {\r\n name: string;\r\n description: string;\r\n input_schema: {\r\n type: 'object';\r\n properties: Record<string, unknown>;\r\n required: string[];\r\n };\r\n }[] = [];\r\n\r\n if (type === 'function') {\r\n tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n return {\r\n name,\r\n description,\r\n input_schema: {\r\n type: 'object',\r\n properties,\r\n required: requiredFields,\r\n },\r\n };\r\n });\r\n }\r\n\r\n return tools?.length > 0 ? { tools } : {};\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock & { thinkingBlocks?: { type: string; thinking: string }[] };\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n const messageBlocks: TLLMToolResultMessageBlock[] = [];\r\n\r\n if (messageBlock) {\r\n const content: any[] = []; // TODO: set proper type for content\r\n\r\n if (messageBlock.thinkingBlocks?.length > 0) {\r\n content.push(...messageBlock.thinkingBlocks);\r\n }\r\n\r\n if (Array.isArray(messageBlock.content)) {\r\n content.push(...messageBlock.content);\r\n } else {\r\n if (messageBlock.content) {\r\n //Anthropic does not accept empty text blocks\r\n content.push({ type: 'text', text: messageBlock.content });\r\n }\r\n }\r\n if (messageBlock.tool_calls) {\r\n const calls = messageBlock.tool_calls.map((toolCall: any) => {\r\n const args = toolCall?.function?.arguments;\r\n return {\r\n type: 'tool_use',\r\n id: toolCall.id,\r\n name: toolCall?.function?.name,\r\n input: typeof args === 'string' ? JSONContent(args || '{}').tryParse() : args || {},\r\n };\r\n });\r\n\r\n content.push(...calls);\r\n }\r\n\r\n messageBlocks.push({\r\n role: messageBlock?.role,\r\n content: content,\r\n });\r\n }\r\n\r\n // Combine all tool results into a single user message\r\n const toolResultsContent = toolsData.map((toolData): any => ({\r\n type: 'tool_result',\r\n tool_use_id: toolData.id,\r\n content: toolData.result,\r\n }));\r\n\r\n if (toolResultsContent.length > 0) {\r\n messageBlocks.push({\r\n role: TLLMMessageRole.User,\r\n content: toolResultsContent,\r\n });\r\n }\r\n\r\n return messageBlocks;\r\n }\r\n\r\n // TODO [Forhad]: This method is quite lengthy and complex. Consider breaking it down into smaller, more manageable functions for better readability and maintainability.\r\n public getConsistentMessages(messages) {\r\n let _messages = JSON.parse(JSON.stringify(messages));\r\n\r\n // Extract the system message from the start, as our logic expects 'user' to be the first message for checks and fixes. We will add it back later.\r\n let systemMessage = null;\r\n if (_messages[0]?.role === TLLMMessageRole.System) {\r\n systemMessage = _messages.shift();\r\n }\r\n\r\n _messages = LLMHelper.removeDuplicateUserMessages(_messages);\r\n\r\n _messages = _messages.map((message) => {\r\n let content;\r\n\r\n if (message?.parts) {\r\n content = message.parts.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (Array.isArray(message?.content)) {\r\n if (Array.isArray(message.content)) {\r\n const toolBlocks = message.content.filter(\r\n (item) => typeof item === 'object' && 'type' in item && (item.type === 'tool_use' || item.type === 'tool_result'),\r\n );\r\n\r\n if (toolBlocks?.length > 0) {\r\n content = message.content.map((item) => {\r\n if (item.type === 'text' && (!item.text || item.text.trim() === '')) {\r\n return { ...item, text: '...' }; // empty text causes error that's why we added '...'\r\n }\r\n return item;\r\n });\r\n } else {\r\n content = message.content\r\n .map((block) => block?.text || '')\r\n .join(' ')\r\n .trim();\r\n }\r\n } else {\r\n content = message.content;\r\n }\r\n } else if (message?.content) {\r\n content = message.content as string;\r\n }\r\n\r\n message.content = content || '...'; // empty content causes error that's why we added '...'\r\n\r\n return message;\r\n });\r\n\r\n //[FIXED] - `tool_result` block(s) provided when previous message does not contain any `tool_use` blocks\" (handler)\r\n if (_messages[0]?.role === TLLMMessageRole.User && Array.isArray(_messages[0].content)) {\r\n const hasToolResult = _messages[0].content.find((content) => 'type' in content && content.type === 'tool_result');\r\n\r\n //we found a tool result in the first message, so we need to remove the user message\r\n if (hasToolResult) {\r\n _messages.shift();\r\n }\r\n }\r\n\r\n // - Error: 400 {\"type\":\"error\",\"error\":{\"type\":\"invalid_request_error\",\"message\":\"messages: first message must use the \\\"user\\\" role\"}}\r\n if (_messages[0]?.role !== TLLMMessageRole.User) {\r\n _messages.unshift({ role: TLLMMessageRole.User, content: 'continue' }); //add an empty user message to keep the consistency\r\n }\r\n\r\n // Add the system message back to the start, as we extracted it earlier\r\n // Empty content is not allowed in Anthropic\r\n if (systemMessage && systemMessage.content) {\r\n _messages.unshift(systemMessage);\r\n }\r\n\r\n return _messages;\r\n }\r\n\r\n private async prepareBody(params: TLLMParams): Promise<Anthropic.MessageCreateParamsNonStreaming> {\r\n let messages = await this.prepareMessages(params);\r\n\r\n let body: Anthropic.MessageCreateParamsNonStreaming = {\r\n model: params.model as string,\r\n messages: messages as Anthropic.MessageParam[],\r\n max_tokens: params.maxTokens, // * max token is required\r\n };\r\n\r\n //#region Prepare system message and add JSON response instruction if needed\r\n // TODO: We have better parameter to have structured response, need to implement it.\r\n const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(messages);\r\n if ('content' in systemMessage) {\r\n body.system = systemMessage?.content as string;\r\n }\r\n messages = otherMessages;\r\n\r\n const responseFormat = params?.responseFormat || '';\r\n if (responseFormat === 'json') {\r\n body.system = body.system ? `${body.system} ${JSON_RESPONSE_INSTRUCTION}` : JSON_RESPONSE_INSTRUCTION;\r\n\r\n messages.push({ role: TLLMMessageRole.Assistant, content: PREFILL_TEXT_FOR_JSON_RESPONSE });\r\n }\r\n\r\n const hasSystemMessage = LLMHelper.hasSystemMessage(messages);\r\n if (hasSystemMessage) {\r\n // in Anthropic we need to provide system message separately\r\n const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(messages);\r\n\r\n if ('content' in systemMessage) {\r\n body.system = await this.prepareSystemPrompt(systemMessage, params);\r\n }\r\n\r\n messages = otherMessages as Anthropic.MessageParam[];\r\n }\r\n //#endregion Prepare system message and add JSON response instruction if needed\r\n\r\n if (params?.temperature !== undefined) body.temperature = params.temperature;\r\n if (params?.topP !== undefined) body.top_p = params.topP;\r\n if (params?.topK !== undefined) body.top_k = params.topK;\r\n if (params?.stopSequences?.length) body.stop_sequences = params.stopSequences;\r\n\r\n // #region Tools\r\n if (params?.toolsConfig?.tools && params?.toolsConfig?.tools.length > 0) {\r\n body.tools = params?.toolsConfig?.tools as unknown as Anthropic.Tool[];\r\n\r\n if (params?.cache) {\r\n body.tools[body.tools.length - 1]['cache_control'] = { type: 'ephemeral' };\r\n }\r\n }\r\n\r\n const toolChoice = params?.toolsConfig?.tool_choice as unknown as Anthropic.ToolChoice;\r\n if (toolChoice) {\r\n body.tool_choice = toolChoice;\r\n }\r\n // #endregion Tools\r\n\r\n body.messages = messages as Anthropic.MessageParam[];\r\n return body;\r\n }\r\n\r\n private async prepareBodyForThinkingRequest({\r\n body,\r\n maxThinkingTokens,\r\n toolChoice = null,\r\n }: {\r\n body: AnthropicMessageParams;\r\n maxThinkingTokens: number;\r\n toolChoice?: Anthropic.ToolChoice;\r\n }): Promise<Anthropic.MessageCreateParamsNonStreaming> {\r\n // Remove the assistant message with the prefill text for JSON response, it's not supported with thinking\r\n let messages = body.messages.filter(\r\n (message) => message?.role !== TLLMMessageRole.Assistant && message?.content !== PREFILL_TEXT_FOR_JSON_RESPONSE,\r\n );\r\n\r\n let budget_tokens = Math.min(maxThinkingTokens, body.max_tokens);\r\n\r\n // If budget_tokens is equal to max_tokens, we set it to 80% of max_tokens\r\n // to avoid the error: \"budget_tokens must be less than max_tokens\".\r\n //\r\n // Another way to ensure valid budget_tokens is to add max_tokens and budget_tokens together - max_tokens = max_tokens + budget_tokens,\r\n // then take the minimum, like: Math.min(max_tokens, allowedMaxTokens).\r\n // However, this approach requires additional information such as model details,\r\n // which would mean adding more arguments like acRequest and modelEntryName to get allowedMaxTokens.\r\n //\r\n // So for now, to keep it simple, if max_tokens equals budget_tokens,\r\n // just use 80% of max_tokens.\r\n\r\n if (budget_tokens === body.max_tokens) {\r\n budget_tokens = Math.floor(budget_tokens * 0.8);\r\n }\r\n\r\n const thinkingBody: Anthropic.MessageCreateParamsNonStreaming = {\r\n model: body.model,\r\n messages,\r\n max_tokens: body.max_tokens,\r\n thinking: {\r\n type: 'enabled',\r\n budget_tokens,\r\n },\r\n };\r\n\r\n if (toolChoice) {\r\n // any and tool are not supported with thinking, so we set it to auto\r\n if (['any', 'tool'].includes(toolChoice.type)) {\r\n thinkingBody.tool_choice = {\r\n type: 'auto',\r\n };\r\n } else {\r\n thinkingBody.tool_choice = toolChoice;\r\n }\r\n }\r\n\r\n return thinkingBody;\r\n }\r\n\r\n private async prepareMessages(params: TLLMParams) {\r\n const messages = params?.messages || [];\r\n\r\n const files: BinaryInput[] = params?.files || [];\r\n\r\n if (files?.length > 0) {\r\n // #region Upload files\r\n const promises = [];\r\n const _files = [];\r\n\r\n for (let image of files) {\r\n const binaryInput = BinaryInput.from(image);\r\n promises.push(binaryInput.upload(AccessCandidate.agent(params.agentId)));\r\n\r\n _files.push(binaryInput);\r\n }\r\n\r\n await Promise.all(promises);\r\n // #endregion Upload files\r\n\r\n const validSources = this.getValidImageFiles(_files);\r\n const imageData = await this.getImageData(validSources, params.agentId);\r\n\r\n const userMessage = Array.isArray(messages) ? messages.pop() : {};\r\n const prompt = userMessage?.content || '';\r\n\r\n const content = [{ type: 'text', text: prompt }, ...imageData];\r\n messages.push({ role: TLLMMessageRole.User, content });\r\n }\r\n\r\n return messages;\r\n }\r\n\r\n private async prepareSystemPrompt(systemMessage: TLLMMessageBlock, params: TLLMParams): Promise<string | Array<Anthropic.TextBlockParam>> {\r\n let systemPrompt = systemMessage?.content;\r\n\r\n if (typeof systemPrompt === 'string') {\r\n systemPrompt = [\r\n {\r\n type: 'text' as const,\r\n text: systemPrompt,\r\n //cache_control: { type: 'ephemeral' }, //TODO: @Forhad check this\r\n },\r\n ] as Array<Anthropic.TextBlockParam>;\r\n }\r\n\r\n (systemPrompt as Array<Anthropic.TextBlockParam>).unshift({\r\n type: 'text' as const,\r\n text: 'If you need to call a function, Do NOT inform the user that you are about to do so, and do not thank the user after you get the response. Just say something like \"Give me a moment...\", then when you get the response, Just continue answering the user without saying anything about the function you just called',\r\n });\r\n\r\n if (params?.cache) {\r\n (systemPrompt as Array<Anthropic.TextBlockParam>)[systemPrompt.length - 1]['cache_control'] = { type: 'ephemeral' };\r\n }\r\n\r\n return systemPrompt as Array<Anthropic.TextBlockParam>;\r\n }\r\n\r\n /**\r\n * Determines if thinking mode should be used based on model capabilities and parameters.\r\n */\r\n private async shouldUseThinkingMode(params: TLLMParams): Promise<boolean> {\r\n // Legacy thinking models always use thinking mode\r\n if (LEGACY_THINKING_MODELS.includes(params.modelEntryName)) {\r\n return true;\r\n }\r\n\r\n // Check if reasoning is explicitly requested and model supports it\r\n const useReasoning = params?.useReasoning && params.capabilities?.reasoning === true;\r\n\r\n return useReasoning;\r\n }\r\n\r\n private getValidImageFiles(files: BinaryInput[]) {\r\n const validSources = [];\r\n\r\n for (let file of files) {\r\n if (this.validImageMimeTypes.includes(file?.mimetype)) {\r\n validSources.push(file);\r\n }\r\n }\r\n\r\n if (validSources?.length === 0) {\r\n throw new Error(`Unsupported file(s). Please make sure your file is one of the following types: ${this.validImageMimeTypes.join(', ')}`);\r\n }\r\n\r\n return validSources;\r\n }\r\n\r\n private async getImageData(\r\n files: BinaryInput[],\r\n agentId: string,\r\n ): Promise<\r\n {\r\n type: string;\r\n source: { type: 'base64'; data: string; media_type: string };\r\n }[]\r\n > {\r\n try {\r\n const imageData = [];\r\n\r\n for (let file of files) {\r\n const bufferData = await file.readData(AccessCandidate.agent(agentId));\r\n const base64Data = bufferData.toString('base64');\r\n\r\n imageData.push({\r\n type: 'image',\r\n source: {\r\n type: 'base64',\r\n data: base64Data,\r\n media_type: file.mimetype,\r\n },\r\n });\r\n }\r\n\r\n return imageData;\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n}\r\n","import Groq from 'groq-sdk';\r\nimport EventEmitter from 'events';\r\n\r\nimport { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport {\r\n TLLMMessageBlock,\r\n ToolData,\r\n TLLMMessageRole,\r\n APIKeySource,\r\n TLLMEvent,\r\n BasicCredentials,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n TLLMParams,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n} from '@sre/types/LLM.types';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\ntype ChatCompletionCreateParams = {\r\n model: string;\r\n messages: any;\r\n max_tokens?: number;\r\n temperature?: number;\r\n stop?: string[];\r\n top_p?: number;\r\n tools?: any;\r\n tool_choice?: string;\r\n stream?: boolean;\r\n};\r\n\r\nexport class GroqConnector extends LLMConnector {\r\n public name = 'LLM:Groq';\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<Groq> {\r\n const apiKey = (params.credentials as BasicCredentials)?.apiKey;\r\n\r\n if (!apiKey) throw new Error('Please provide an API key for Groq');\r\n\r\n return new Groq({ apiKey });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n try {\r\n const groq = await this.getClient(context);\r\n const result = await groq.chat.completions.create(body);\r\n const message = result?.choices?.[0]?.message;\r\n const finishReason = result?.choices?.[0]?.finish_reason;\r\n const toolCalls = message?.tool_calls;\r\n const usage = result.usage;\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n let toolsData: ToolData[] = [];\r\n let useTool = false;\r\n\r\n if (toolCalls) {\r\n toolsData = toolCalls.map((tool, index) => ({\r\n index,\r\n id: tool.id,\r\n type: tool.type,\r\n name: tool.function.name,\r\n arguments: tool.function.arguments,\r\n role: TLLMMessageRole.Assistant,\r\n }));\r\n useTool = true;\r\n }\r\n\r\n return {\r\n content: message?.content ?? '',\r\n finishReason,\r\n useTool,\r\n toolsData,\r\n message,\r\n usage,\r\n };\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const emitter = new EventEmitter();\r\n const usage_data = [];\r\n\r\n try {\r\n const groq = await this.getClient(context);\r\n const stream = await groq.chat.completions.create({ ...body, stream: true, stream_options: { include_usage: true } });\r\n\r\n let toolsData: ToolData[] = [];\r\n\r\n (async () => {\r\n for await (const chunk of stream as any) {\r\n const delta = chunk.choices[0]?.delta;\r\n const usage = chunk['x_groq']?.usage || chunk['usage'];\r\n\r\n if (usage) {\r\n usage_data.push(usage);\r\n }\r\n emitter.emit('data', delta);\r\n\r\n if (delta?.content) {\r\n emitter.emit('content', delta.content);\r\n }\r\n\r\n if (delta?.tool_calls) {\r\n delta.tool_calls.forEach((toolCall, index) => {\r\n if (!toolsData[index]) {\r\n toolsData[index] = {\r\n index,\r\n id: toolCall.id,\r\n type: toolCall.type,\r\n name: toolCall.function?.name,\r\n arguments: toolCall.function?.arguments,\r\n role: 'assistant',\r\n };\r\n } else {\r\n toolsData[index].arguments += toolCall.function?.arguments || '';\r\n }\r\n });\r\n }\r\n }\r\n\r\n if (toolsData.length > 0) {\r\n emitter.emit(TLLMEvent.ToolInfo, toolsData);\r\n }\r\n\r\n usage_data.forEach((usage) => {\r\n // probably we can acc them and send them as one event\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n });\r\n\r\n setTimeout(() => {\r\n emitter.emit('end', toolsData);\r\n }, 100);\r\n })();\r\n\r\n return emitter;\r\n } catch (error: any) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search is not supported for Groq');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<ChatCompletionCreateParams> {\r\n const messages = params?.messages || [];\r\n\r\n const body: ChatCompletionCreateParams = {\r\n model: params.model as string,\r\n messages,\r\n };\r\n\r\n //#region Handle JSON response format\r\n const responseFormat = params?.responseFormat || '';\r\n if (responseFormat === 'json') {\r\n if (messages?.[0]?.role === 'system') {\r\n messages[0].content += JSON_RESPONSE_INSTRUCTION;\r\n } else {\r\n messages.unshift({ role: 'system', content: JSON_RESPONSE_INSTRUCTION });\r\n }\r\n }\r\n //#endregion Handle JSON response format\r\n\r\n if (params.maxTokens !== undefined) body.max_tokens = params.maxTokens;\r\n if (params.temperature !== undefined) body.temperature = params.temperature;\r\n if (params.topP !== undefined) body.top_p = params.topP;\r\n if (params.stopSequences?.length) body.stop = params.stopSequences;\r\n\r\n if (params.toolsConfig?.tools) body.tools = params.toolsConfig?.tools;\r\n if (params.toolsConfig?.tool_choice) body.tool_choice = params.toolsConfig?.tool_choice as any;\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(\r\n usage: Groq.Completions.CompletionUsage & { prompt_tokens_details?: { cached_tokens?: number } },\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }\r\n ) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: usage?.prompt_tokens - (usage?.prompt_tokens_details?.cached_tokens || 0),\r\n output_tokens: usage?.completion_tokens,\r\n input_tokens_cache_write: 0,\r\n input_tokens_cache_read: usage?.prompt_tokens_details?.cached_tokens || 0,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n let tools = [];\r\n\r\n if (type === 'function') {\r\n tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n return {\r\n type: 'function',\r\n function: {\r\n name,\r\n description,\r\n parameters: {\r\n type: 'object',\r\n properties,\r\n required: requiredFields,\r\n },\r\n },\r\n };\r\n });\r\n }\r\n\r\n return tools?.length > 0 ? { tools, tool_choice: toolChoice } : {};\r\n }\r\n\r\n public getConsistentMessages(messages: TLLMMessageBlock[]): TLLMMessageBlock[] {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n const _message = { ...message };\r\n let textContent = '';\r\n\r\n if (message?.parts) {\r\n textContent = message.parts.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (Array.isArray(message?.content)) {\r\n textContent = message.content.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (message?.content) {\r\n textContent = message.content as string;\r\n }\r\n\r\n _message.content = textContent;\r\n\r\n return _message;\r\n });\r\n }\r\n}\r\n","import {\r\n BedrockRuntimeClient,\r\n ConverseCommand,\r\n ConverseCommandInput,\r\n ConverseStreamCommand,\r\n ConverseStreamCommandOutput,\r\n TokenUsage,\r\n ConverseCommandOutput,\r\n} from '@aws-sdk/client-bedrock-runtime';\r\nimport EventEmitter from 'events';\r\n\r\nimport { BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport {\r\n TLLMParams,\r\n ToolData,\r\n TLLMMessageBlock,\r\n TLLMToolResultMessageBlock,\r\n TLLMMessageRole,\r\n APIKeySource,\r\n TLLMEvent,\r\n BedrockCredentials,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n TCustomLLMModel,\r\n} from '@sre/types/LLM.types';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\nimport { isJSONString } from '@sre/utils/general.utils';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { JSONContent } from '@sre/helpers/JsonContent.helper';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\n// TODO [Forhad]: Need to adjust some type definitions\r\n\r\nexport class BedrockConnector extends LLMConnector {\r\n public name = 'LLM:Bedrock';\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<BedrockRuntimeClient> {\r\n const credentials = params.credentials as BedrockCredentials;\r\n const region = (params.modelInfo as TCustomLLMModel).settings.region;\r\n\r\n if (!(Object.keys(credentials).length >= 2)) throw new Error('Access key ID and secret access key are required for Bedrock');\r\n\r\n return new BedrockRuntimeClient({\r\n region: region,\r\n credentials,\r\n });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n try {\r\n const bedrock = await this.getClient(context);\r\n const command = new ConverseCommand(body);\r\n const response: ConverseCommandOutput = await bedrock.send(command);\r\n\r\n const usage = response.usage;\r\n this.reportUsage(usage as any, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n const message = response.output?.message;\r\n const finishReason = response.stopReason;\r\n\r\n let toolsData: ToolData[] = [];\r\n let useTool = false;\r\n\r\n if (finishReason === 'tool_use') {\r\n const toolUseBlocks = message?.content?.filter((block) => block?.toolUse) || [];\r\n\r\n toolsData = toolUseBlocks.map((block, index) => ({\r\n index,\r\n id: block.toolUse?.toolUseId as string,\r\n type: 'function', // We call API only when the tool type is 'function' in src/helpers/Conversation.helper.ts`. Even though Claude returns the type as 'tool_use', it should be interpreted as 'function'.,\r\n name: _deserializeToolName(block.toolUse?.name as string),\r\n arguments: block.toolUse?.input as Record<string, any>,\r\n role: 'tool',\r\n }));\r\n useTool = true;\r\n }\r\n\r\n return {\r\n content: Array.isArray(message?.content) ? message?.content?.[0]?.text || '' : message?.content || '',\r\n finishReason,\r\n useTool,\r\n toolsData,\r\n message: message as any,\r\n usage,\r\n };\r\n } catch (error: any) {\r\n throw error?.error || error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n const emitter = new EventEmitter();\r\n\r\n try {\r\n const bedrock = await this.getClient(context);\r\n const command = new ConverseStreamCommand(body);\r\n const response: ConverseStreamCommandOutput = await bedrock.send(command);\r\n const stream = response.stream;\r\n\r\n if (stream) {\r\n (async () => {\r\n let currentMessage = {\r\n role: '',\r\n content: '',\r\n toolCalls: [] as any[],\r\n currentToolCall: null as any,\r\n currentToolInput: '' as string,\r\n };\r\n\r\n for await (const chunk of stream) {\r\n // Handle message start\r\n if (chunk.messageStart) {\r\n currentMessage.role = chunk.messageStart.role || '';\r\n emitter.emit('data', { role: currentMessage.role });\r\n }\r\n\r\n // Handle content deltas\r\n if (chunk.contentBlockDelta?.delta?.text) {\r\n currentMessage.content += chunk.contentBlockDelta.delta.text;\r\n emitter.emit('data', chunk.contentBlockDelta.delta.text);\r\n emitter.emit('content', chunk.contentBlockDelta.delta.text, currentMessage.role);\r\n }\r\n\r\n // Handle tool use start\r\n if (chunk.contentBlockStart?.start?.toolUse) {\r\n const toolUse = chunk.contentBlockStart.start.toolUse;\r\n if (toolUse.toolUseId && toolUse.name) {\r\n currentMessage.currentToolCall = {\r\n index: currentMessage.toolCalls.length,\r\n id: toolUse.toolUseId,\r\n type: 'function',\r\n name: _deserializeToolName(toolUse.name),\r\n arguments: '',\r\n role: 'tool',\r\n };\r\n currentMessage.currentToolInput = '';\r\n }\r\n }\r\n\r\n // Handle tool use input deltas\r\n if (chunk.contentBlockDelta?.delta?.toolUse?.input && currentMessage.currentToolCall) {\r\n currentMessage.currentToolInput += chunk.contentBlockDelta.delta.toolUse.input;\r\n currentMessage.currentToolCall.arguments = currentMessage.currentToolInput;\r\n }\r\n\r\n // Handle tool use block completion\r\n if (chunk.contentBlockStop && currentMessage.currentToolCall) {\r\n // Parse JSON arguments if possible\r\n if (\r\n typeof currentMessage.currentToolCall.arguments === 'string' &&\r\n isJSONString(currentMessage.currentToolCall.arguments)\r\n ) {\r\n currentMessage.currentToolCall.arguments = JSON.parse(currentMessage.currentToolCall.arguments);\r\n }\r\n\r\n currentMessage.toolCalls.push(currentMessage.currentToolCall);\r\n currentMessage.currentToolCall = null;\r\n currentMessage.currentToolInput = '';\r\n }\r\n\r\n // Handle message completion\r\n if (chunk.messageStop) {\r\n if (currentMessage.toolCalls.length > 0) {\r\n emitter.emit(TLLMEvent.ToolInfo, currentMessage.toolCalls);\r\n }\r\n emitter.emit(TLLMEvent.End, currentMessage.toolCalls);\r\n }\r\n\r\n if (chunk?.metadata?.usage) {\r\n const usage = chunk.metadata.usage;\r\n this.reportUsage(usage as any, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n }\r\n }\r\n })();\r\n }\r\n\r\n return emitter;\r\n } catch (error: unknown) {\r\n const typedError = error as Error;\r\n emitter.emit(TLLMEvent.Error, typedError?.['error'] || typedError);\r\n return emitter;\r\n }\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search is not supported for Bedrock');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<ConverseCommandInput> {\r\n const customModelInfo = params.modelInfo;\r\n\r\n let systemPrompt;\r\n let messages = params?.messages || [];\r\n\r\n const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(messages);\r\n\r\n if ('content' in systemMessage) {\r\n systemPrompt = typeof systemMessage?.content === 'string' ? [{ text: systemMessage?.content }] : systemMessage?.content;\r\n }\r\n\r\n messages = otherMessages;\r\n\r\n const body: ConverseCommandInput = {\r\n modelId: customModelInfo.settings?.customModel || customModelInfo.settings?.foundationModel,\r\n messages,\r\n };\r\n\r\n if (systemPrompt) {\r\n body.system = systemPrompt;\r\n }\r\n\r\n if (params?.toolsConfig?.tools?.length > 0) {\r\n body.toolConfig = {\r\n tools: params?.toolsConfig?.tools as any,\r\n ...(params?.toolsConfig?.tool_choice && { toolChoice: params?.toolsConfig?.tool_choice as any }),\r\n };\r\n }\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(\r\n usage: TokenUsage & { cacheReadInputTokenCount: number; cacheWriteInputTokenCount: number },\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }\r\n ) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: usage.inputTokens,\r\n output_tokens: usage.outputTokens,\r\n input_tokens_cache_write: usage.cacheWriteInputTokenCount || 0,\r\n input_tokens_cache_read: usage.cacheReadInputTokenCount || 0,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n let tools: any[] = [];\r\n\r\n if (type === 'function') {\r\n tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n return {\r\n toolSpec: {\r\n name: _serializeToolName(name),\r\n description,\r\n inputSchema: {\r\n json: {\r\n type: 'object',\r\n properties,\r\n required: requiredFields,\r\n },\r\n },\r\n },\r\n };\r\n });\r\n }\r\n\r\n return tools?.length > 0 ? { tools, toolChoice: toolChoice || 'auto' } : {};\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock;\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n const messageBlocks: any[] = [];\r\n\r\n if (messageBlock) {\r\n const content: any[] = []; // TODO: set proper type for content\r\n\r\n if (typeof messageBlock.content === 'string') {\r\n content.push({ text: messageBlock.content });\r\n } else if (Array.isArray(messageBlock.content)) {\r\n content.push(...messageBlock.content);\r\n }\r\n\r\n if (messageBlock.tool_calls?.length) {\r\n messageBlock.tool_calls.forEach((toolCall: Record<string, any>) => {\r\n const args = toolCall?.function?.arguments;\r\n content.push({\r\n toolUse: {\r\n toolUseId: toolCall.id,\r\n name: _serializeToolName(toolCall?.function?.name),\r\n input: typeof args === 'string' ? JSONContent(args || '{}').tryParse() : args || {},\r\n },\r\n });\r\n });\r\n }\r\n\r\n messageBlocks.push({\r\n role: messageBlock?.role,\r\n content,\r\n });\r\n }\r\n\r\n // Add tool results as user message\r\n if (toolsData?.length) {\r\n const toolResultsContent = toolsData\r\n .filter((tool) => tool.id && (tool.result || tool.error))\r\n .map((tool) => {\r\n let content;\r\n\r\n // * Note: We also have two other types of results: image and document. - https://docs.aws.amazon.com/AWSJavaScriptSDK/v3/latest/client/bedrock-runtime/command/ConverseStreamCommand/\r\n if (typeof tool?.result === 'string') {\r\n content = [{ text: tool.result as string }];\r\n } else if (typeof tool?.result === 'object') {\r\n content = [{ json: tool.result }];\r\n }\r\n\r\n return {\r\n toolResult: {\r\n toolUseId: tool.id,\r\n content: content,\r\n ...(tool.error && { status: 'error' }),\r\n },\r\n };\r\n });\r\n\r\n if (toolResultsContent.length > 0) {\r\n messageBlocks.push({\r\n role: TLLMMessageRole.User,\r\n content: toolResultsContent,\r\n });\r\n }\r\n }\r\n\r\n return messageBlocks;\r\n }\r\n\r\n public getConsistentMessages(messages: TLLMMessageBlock[]): TLLMMessageBlock[] {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n let textBlock = [];\r\n\r\n if (message?.parts) {\r\n // empty text causes error in Bedrock, so we add a placeholder\r\n textBlock = message.parts.map((part) => {\r\n if ('text' in part) {\r\n return { ...part, text: part.text || '...' };\r\n }\r\n\r\n return { ...part };\r\n });\r\n } else if (message?.content) {\r\n textBlock = Array.isArray(message.content)\r\n ? message.content.map((part) => {\r\n if ('text' in part) {\r\n return { ...part, text: part.text || '...' };\r\n }\r\n\r\n return { ...part };\r\n })\r\n : [{ text: (message?.content as string) || '...' }]; // empty text causes error in Bedrock, so we add a placeholder\r\n }\r\n\r\n return {\r\n role: message.role,\r\n content: textBlock,\r\n };\r\n });\r\n }\r\n}\r\n\r\n/**\r\n * Serializes a name by converting dashes to double underscores for Bedrock compatibility\r\n * @param name - The original name containing dashes\r\n * @returns The serialized name with dashes replaced by double underscores\r\n */\r\nfunction _serializeToolName(name: string): string {\r\n return name?.replace(/-/g, '__');\r\n}\r\n\r\n/**\r\n * Deserializes a Bedrock Tool name by converting double underscores back to dashes\r\n * @param name - The serialized name containing double underscores\r\n * @returns The deserialized name with double underscores replaced by dashes\r\n */\r\nfunction _deserializeToolName(name: string): string {\r\n return name?.replace(/__/g, '-');\r\n}\r\n","import { VertexAI, type GenerationConfig, type UsageMetadata } from '@google-cloud/vertexai';\r\nimport EventEmitter from 'events';\r\n\r\nimport { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\nimport {\r\n TLLMParams,\r\n TCustomLLMModel,\r\n APIKeySource,\r\n TVertexAISettings,\r\n ILLMRequestFuncParams,\r\n TGoogleAIRequestBody,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n} from '@sre/types/LLM.types';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\n//TODO: [AHMED/FORHAD]: test the usage reporting for VertexAI because by the time we were implementing the feature of usage reporting\r\n// we had no access to VertexAI so we assumed it is working (potential bug)\r\n\r\nexport class VertexAIConnector extends LLMConnector {\r\n public name = 'LLM:VertexAI';\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<VertexAI> {\r\n const credentials = params.credentials as any;\r\n const modelInfo = params.modelInfo as TCustomLLMModel;\r\n const projectId = (modelInfo?.settings as TVertexAISettings)?.projectId;\r\n const region = modelInfo?.settings?.region;\r\n\r\n return new VertexAI({\r\n project: projectId,\r\n location: region,\r\n googleAuthOptions: {\r\n credentials: credentials as any,\r\n },\r\n });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<any> {\r\n const messages = body.messages;\r\n delete body.messages;\r\n\r\n try {\r\n const vertexAI = await this.getClient(context);\r\n const generativeModel = vertexAI.getGenerativeModel(body);\r\n\r\n const result = await generativeModel.generateContent({ contents: messages });\r\n const content = result?.response?.candidates?.[0]?.content?.parts?.[0]?.text;\r\n const usage = result?.response?.usageMetadata;\r\n\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n return {\r\n content,\r\n finishReason: 'stop',\r\n useTool: false,\r\n toolsData: [],\r\n message: { content, role: 'assistant' },\r\n usage,\r\n };\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n // Simulate streaming similar to Perplexity's approach - fallback to regular request\r\n const emitter = new EventEmitter();\r\n\r\n setTimeout(() => {\r\n try {\r\n this.request({ acRequest, body, context })\r\n .then((response) => {\r\n const finishReason = response.finishReason;\r\n const usage = response.usage;\r\n\r\n // Emit the content as a stream-like response\r\n emitter.emit('interrupted', finishReason);\r\n emitter.emit('content', response.content);\r\n emitter.emit('end', undefined, usage, finishReason);\r\n })\r\n .catch((error) => {\r\n emitter.emit('error', error.message || error.toString());\r\n });\r\n } catch (error) {\r\n emitter.emit('error', error.message || error.toString());\r\n }\r\n }, 100);\r\n\r\n return emitter;\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search is not supported for Vertex AI');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<TGoogleAIRequestBody> {\r\n let messages = params?.messages || [];\r\n\r\n //#region Separate system message and add JSON response instruction if needed\r\n let systemInstruction;\r\n const { systemMessage, otherMessages } = LLMHelper.separateSystemMessages(messages);\r\n\r\n if ('content' in systemMessage) {\r\n systemInstruction = systemMessage.content;\r\n }\r\n\r\n messages = otherMessages;\r\n\r\n const responseFormat = params?.responseFormat || '';\r\n if (responseFormat === 'json') {\r\n systemInstruction = JSON_RESPONSE_INSTRUCTION;\r\n }\r\n //#endregion Separate system message and add JSON response instruction if needed\r\n\r\n const modelInfo = params.modelInfo as TCustomLLMModel;\r\n\r\n let body: TGoogleAIRequestBody = {\r\n model: modelInfo?.settings?.customModel || modelInfo?.settings?.foundationModel,\r\n messages,\r\n };\r\n\r\n const config: GenerationConfig = {};\r\n\r\n if (params?.maxTokens !== undefined) config.maxOutputTokens = params.maxTokens;\r\n if (params?.temperature !== undefined) config.temperature = params.temperature;\r\n if (params?.topP !== undefined) config.topP = params.topP;\r\n if (params?.topK !== undefined) config.topK = params.topK;\r\n if (params?.stopSequences?.length) config.stopSequences = params.stopSequences;\r\n\r\n if (systemInstruction) {\r\n body.systemInstruction = systemInstruction;\r\n }\r\n\r\n if (Object.keys(config).length > 0) {\r\n body.generationConfig = config as any;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(\r\n usage: UsageMetadata & { cachedContentTokenCount?: number },\r\n metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }\r\n ) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: usage.promptTokenCount || 0,\r\n output_tokens: usage.candidatesTokenCount || 0,\r\n input_tokens_cache_read: usage.cachedContentTokenCount || 0,\r\n input_tokens_cache_write: 0,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n throw new Error('Tool configuration is not currently implemented for Vertex AI');\r\n }\r\n\r\n public getConsistentMessages(messages) {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n let textBlock = [];\r\n\r\n if (message?.parts) {\r\n textBlock = message.parts;\r\n } else if (message?.content) {\r\n textBlock = Array.isArray(message.content) ? message.content : [{ text: message.content as string }];\r\n }\r\n\r\n return {\r\n role: message.role,\r\n parts: textBlock,\r\n };\r\n });\r\n }\r\n}\r\n","import EventEmitter from 'events';\r\nimport axios, { AxiosInstance } from 'axios';\r\n\r\nimport { JSON_RESPONSE_INSTRUCTION, BUILT_IN_MODEL_PREFIX } from '@sre/constants';\r\n\r\nimport {\r\n TLLMParams,\r\n ToolData,\r\n TLLMMessageBlock,\r\n TLLMToolResultMessageBlock,\r\n TLLMMessageRole,\r\n APIKeySource,\r\n BasicCredentials,\r\n ILLMRequestFuncParams,\r\n TLLMChatResponse,\r\n TLLMConnectorParams,\r\n ILLMRequestContext,\r\n} from '@sre/types/LLM.types';\r\nimport { LLMHelper } from '@sre/LLMManager/LLM.helper';\r\n\r\nimport { LLMConnector } from '../LLMConnector';\r\nimport { SystemEvents } from '@sre/Core/SystemEvents';\r\n\r\ntype ChatCompletionParams = {\r\n model: string;\r\n messages: any[];\r\n max_tokens?: number;\r\n temperature?: number;\r\n top_p?: number;\r\n top_k?: number;\r\n frequency_penalty?: number;\r\n presence_penalty?: number;\r\n response_format?: { type: string };\r\n};\r\ntype TUsage = {\r\n prompt_tokens: number;\r\n completion_tokens: number;\r\n total_tokens: number;\r\n prompt_tokens_details?: { cached_tokens?: number };\r\n reasoning_tokens?: number;\r\n};\r\n\r\n// TODO [Forhad]: Need to adjust some type definitions\r\n\r\nexport class PerplexityConnector extends LLMConnector {\r\n public name = 'LLM:Perplexity';\r\n\r\n private async getClient(params: ILLMRequestContext): Promise<AxiosInstance> {\r\n const apiKey = (params.credentials as BasicCredentials)?.apiKey;\r\n\r\n if (!apiKey) throw new Error('Please provide an API key for Perplexity');\r\n\r\n return axios.create({\r\n baseURL: params?.modelInfo?.baseURL,\r\n headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' },\r\n });\r\n }\r\n\r\n protected async request({ acRequest, body, context }: ILLMRequestFuncParams): Promise<TLLMChatResponse> {\r\n try {\r\n const perplexity = await this.getClient(context);\r\n const response = await perplexity.post('/chat/completions', body);\r\n\r\n const content = response?.data?.choices?.[0]?.message.content;\r\n const finishReason = response?.data?.choices?.[0]?.finish_reason;\r\n const usage = response?.data?.usage as any;\r\n\r\n this.reportUsage(usage, {\r\n modelEntryName: context.modelEntryName,\r\n keySource: context.isUserKey ? APIKeySource.User : APIKeySource.Smyth,\r\n agentId: context.agentId,\r\n teamId: context.teamId,\r\n });\r\n\r\n return {\r\n content,\r\n finishReason,\r\n useTool: false,\r\n toolsData: [],\r\n message: { content, role: 'assistant' },\r\n usage,\r\n };\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n protected async streamRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n //throw new Error('Multimodal request is not supported for Perplexity.');\r\n //fallback to chatRequest\r\n const emitter = new EventEmitter();\r\n\r\n setTimeout(() => {\r\n try {\r\n this.request({ acRequest, body, context })\r\n .then((respose) => {\r\n const finishReason = respose.finishReason;\r\n const usage = respose.usage;\r\n\r\n emitter.emit('interrupted', finishReason);\r\n emitter.emit('content', respose.content);\r\n emitter.emit('end', undefined, usage, finishReason);\r\n })\r\n .catch((error) => {\r\n emitter.emit('error', error.message || error.toString());\r\n });\r\n //emitter.emit('finishReason', respose.finishReason);\r\n } catch (error) {\r\n emitter.emit('error', error.message || error.toString());\r\n }\r\n }, 100);\r\n\r\n return emitter;\r\n }\r\n\r\n protected async webSearchRequest({ acRequest, body, context }: ILLMRequestFuncParams): Promise<EventEmitter> {\r\n throw new Error('Web search is not supported for Perplexity');\r\n }\r\n\r\n protected async reqBodyAdapter(params: TLLMParams): Promise<ChatCompletionParams> {\r\n const messages = params?.messages || [];\r\n\r\n //#region Handle JSON response format\r\n // TODO: For now attach JSON response instruction, Perplexity has option to provide response_format as parameter. We'll check it later\r\n const responseFormat = params?.responseFormat || '';\r\n if (responseFormat === 'json') {\r\n // We assume that the system message is first item in messages array\r\n if (messages?.[0]?.role === TLLMMessageRole.System) {\r\n messages[0].content += JSON_RESPONSE_INSTRUCTION;\r\n } else {\r\n messages.unshift({ role: TLLMMessageRole.System, content: JSON_RESPONSE_INSTRUCTION });\r\n }\r\n\r\n delete params.responseFormat;\r\n }\r\n //#endregion Handle JSON response format\r\n\r\n const body: ChatCompletionParams = {\r\n model: params.model as string,\r\n messages,\r\n };\r\n\r\n if (params?.maxTokens !== undefined) body.max_tokens = params.maxTokens;\r\n if (params?.temperature !== undefined) body.temperature = params.temperature;\r\n if (params?.topP !== undefined) body.top_p = params.topP;\r\n if (params?.topK !== undefined) body.top_k = params.topK;\r\n if (params?.frequencyPenalty) body.frequency_penalty = params.frequencyPenalty;\r\n if (params?.presencePenalty !== undefined) body.presence_penalty = params.presencePenalty;\r\n\r\n if (params.responseFormat) {\r\n body.response_format = params.responseFormat;\r\n }\r\n\r\n return body;\r\n }\r\n\r\n protected reportUsage(usage: TUsage, metadata: { modelEntryName: string; keySource: APIKeySource; agentId: string; teamId: string }) {\r\n // SmythOS (built-in) models have a prefix, so we need to remove it to get the model name\r\n const modelName = metadata.modelEntryName.replace(BUILT_IN_MODEL_PREFIX, '');\r\n\r\n const usageData = {\r\n sourceId: `llm:${modelName}`,\r\n input_tokens: usage?.prompt_tokens - (usage?.prompt_tokens_details?.cached_tokens || 0),\r\n output_tokens: usage?.completion_tokens,\r\n input_tokens_cache_write: 0,\r\n input_tokens_cache_read: usage?.prompt_tokens_details?.cached_tokens || 0,\r\n reasoning_tokens: usage?.reasoning_tokens || 0,\r\n keySource: metadata.keySource,\r\n agentId: metadata.agentId,\r\n teamId: metadata.teamId,\r\n };\r\n SystemEvents.emit('USAGE:LLM', usageData);\r\n\r\n return usageData;\r\n }\r\n\r\n public formatToolsConfig({ type = 'function', toolDefinitions, toolChoice = 'auto' }) {\r\n let tools: any[] = [];\r\n\r\n if (type === 'function') {\r\n tools = toolDefinitions.map((tool) => {\r\n const { name, description, properties, requiredFields } = tool;\r\n\r\n return {\r\n type: 'function',\r\n function: {\r\n name,\r\n description,\r\n parameters: {\r\n type: 'object',\r\n properties,\r\n required: requiredFields,\r\n },\r\n },\r\n };\r\n });\r\n }\r\n\r\n return tools?.length > 0 ? { tools, tool_choice: toolChoice || 'auto' } : {};\r\n }\r\n\r\n public transformToolMessageBlocks({\r\n messageBlock,\r\n toolsData,\r\n }: {\r\n messageBlock: TLLMMessageBlock;\r\n toolsData: ToolData[];\r\n }): TLLMToolResultMessageBlock[] {\r\n const messageBlocks: TLLMToolResultMessageBlock[] = [];\r\n\r\n if (messageBlock) {\r\n const transformedMessageBlock = {\r\n ...messageBlock,\r\n content: typeof messageBlock.content === 'object' ? JSON.stringify(messageBlock.content) : messageBlock.content,\r\n };\r\n if (transformedMessageBlock.tool_calls) {\r\n for (let toolCall of transformedMessageBlock.tool_calls) {\r\n toolCall.function.arguments =\r\n typeof toolCall.function.arguments === 'object' ? JSON.stringify(toolCall.function.arguments) : toolCall.function.arguments;\r\n }\r\n }\r\n messageBlocks.push(transformedMessageBlock);\r\n }\r\n\r\n const transformedToolsData = toolsData.map((toolData) => ({\r\n tool_call_id: toolData.id,\r\n role: TLLMMessageRole.Tool, // toolData.role as TLLMMessageRole, //should always be 'tool' for OpenAI\r\n name: toolData.name,\r\n content: typeof toolData.result === 'string' ? toolData.result : JSON.stringify(toolData.result), // Ensure content is a string\r\n }));\r\n\r\n return [...messageBlocks, ...transformedToolsData];\r\n }\r\n\r\n public getConsistentMessages(messages) {\r\n const _messages = LLMHelper.removeDuplicateUserMessages(messages);\r\n\r\n return _messages.map((message) => {\r\n const _message = { ...message };\r\n let textContent = '';\r\n\r\n if (message?.parts) {\r\n textContent = message.parts.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (Array.isArray(message?.content)) {\r\n textContent = message.content.map((textBlock) => textBlock?.text || '').join(' ');\r\n } else if (message?.content) {\r\n textContent = message.content;\r\n }\r\n\r\n _message.content = textContent;\r\n\r\n return _message;\r\n });\r\n }\r\n}\r\n","//==[ SRE: LLM ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { EchoConnector } from './connectors/Echo.class';\r\nimport { OpenAIConnector } from './connectors/OpenAI.class';\r\nimport { GoogleAIConnector } from './connectors/GoogleAI.class';\r\nimport { AnthropicConnector } from './connectors/Anthropic.class';\r\nimport { GroqConnector } from './connectors/Groq.class';\r\nimport { BedrockConnector } from './connectors/Bedrock.class';\r\nimport { VertexAIConnector } from './connectors/VertexAI.class';\r\nimport { PerplexityConnector } from './connectors/Perplexity.class';\r\n\r\nexport class LLMService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.LLM, 'Echo', EchoConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'OpenAI', OpenAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'DeepSeek', OpenAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'GoogleAI', GoogleAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'Anthropic', AnthropicConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'Groq', GroqConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'TogetherAI', OpenAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'Bedrock', BedrockConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'VertexAI', VertexAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'xAI', OpenAIConnector);\r\n ConnectorService.register(TConnectorService.LLM, 'Perplexity', PerplexityConnector);\r\n }\r\n\r\n public init() {\r\n //auto initialize built-in models\r\n ConnectorService.init(TConnectorService.LLM, 'Echo');\r\n ConnectorService.init(TConnectorService.LLM, 'OpenAI');\r\n ConnectorService.init(TConnectorService.LLM, 'DeepSeek');\r\n ConnectorService.init(TConnectorService.LLM, 'GoogleAI');\r\n ConnectorService.init(TConnectorService.LLM, 'Anthropic');\r\n ConnectorService.init(TConnectorService.LLM, 'Groq');\r\n ConnectorService.init(TConnectorService.LLM, 'TogetherAI');\r\n ConnectorService.init(TConnectorService.LLM, 'Bedrock');\r\n ConnectorService.init(TConnectorService.LLM, 'VertexAI');\r\n ConnectorService.init(TConnectorService.LLM, 'xAI');\r\n ConnectorService.init(TConnectorService.LLM, 'Perplexity');\r\n }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { IAccessCandidate, IACL, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { CacheMetadata } from '@sre/types/Cache.types';\r\nimport IORedis from 'ioredis';\r\nimport { CacheConnector } from '../CacheConnector';\r\n\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { RedisConfig } from '@sre/types/Redis.types';\r\n\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\n\r\nconst console = Logger('RedisCache');\r\n\r\nexport class RedisCache extends CacheConnector {\r\n public name: string = 'RedisCache';\r\n private redis: IORedis;\r\n private _prefix: string = 'smyth:cache';\r\n private _mdPrefix: string = 'smyth:metadata';\r\n\r\n constructor(protected _settings: RedisConfig) {\r\n super(_settings);\r\n const sentinels = parseSentinelHosts(_settings.hosts || process.env.REDIS_HOSTS);\r\n let host = sentinels.length === 1 ? sentinels[0].host : null;\r\n let port = sentinels.length === 1 ? sentinels[0].port : null;\r\n\r\n this.redis = new IORedis({\r\n ...(host ? { host, port } : { sentinels, name: _settings.name || process.env.REDIS_MASTER_NAME }),\r\n password: _settings.password || process.env.REDIS_PASSWORD,\r\n });\r\n\r\n this.redis.on('error', (error) => {\r\n console.error('Redis Error:', error);\r\n });\r\n\r\n this.redis.on('connect', () => {\r\n console.log('Redis connected!');\r\n });\r\n }\r\n\r\n public get client() {\r\n return this.redis;\r\n }\r\n\r\n public get prefix() {\r\n return this._prefix;\r\n }\r\n\r\n public get mdPrefix() {\r\n return this._mdPrefix;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async get(acRequest: AccessRequest, key: string): Promise<string | null> {\r\n const value = await this.redis.get(`${this._prefix}:${key}`);\r\n return value;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async set(acRequest: AccessRequest, key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number): Promise<boolean> {\r\n const accessCandidate = acRequest.candidate;\r\n const promises: any[] = [];\r\n\r\n const newMetadata: CacheMetadata = metadata || {};\r\n newMetadata.acl = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n\r\n if (ttl && ttl > 0) {\r\n promises.push(this.redis.set(`${this._prefix}:${key}`, data, 'EX', ttl));\r\n promises.push(this.setMetadataWithTTL(acRequest, key, newMetadata, ttl));\r\n } else {\r\n promises.push(this.redis.set(`${this._prefix}:${key}`, data));\r\n promises.push(this.setMetadata(acRequest, key, newMetadata));\r\n }\r\n\r\n await Promise.all(promises);\r\n\r\n // if (ttl) {\r\n // try {\r\n // await this.updateTTL(acRequest, key, ttl);\r\n // } catch (error) {\r\n // console.error(`Error setting TTL for key ${key}`, error);\r\n // }\r\n // }\r\n\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async delete(acRequest: AccessRequest, key: string): Promise<void> {\r\n //delete both the key and its metadata\r\n await Promise.all([this.redis.del(`${this._prefix}:${key}`), this.redis.del(`${this._mdPrefix}:${key}`)]);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async exists(acRequest: AccessRequest, key: string): Promise<boolean> {\r\n return !!(await this.redis.exists(`${this._prefix}:${key}`));\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getMetadata(acRequest: AccessRequest, key: string): Promise<CacheMetadata> {\r\n if (!this.exists(acRequest, key)) return undefined;\r\n try {\r\n const metadata = await this.redis.get(`${this._mdPrefix}:${key}`);\r\n return metadata ? (this.deserializeRedisMetadata(metadata) as CacheMetadata) : {};\r\n } catch (error) {\r\n return {};\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async setMetadata(acRequest: AccessRequest, key: string, metadata: CacheMetadata): Promise<void> {\r\n await this.setMetadataWithTTL(acRequest, key, metadata);\r\n }\r\n private async setMetadataWithTTL(acRequest: AccessRequest, key: string, metadata: CacheMetadata, ttl?: number): Promise<void> {\r\n if (ttl && ttl > 0) {\r\n await this.redis.set(`${this._mdPrefix}:${key}`, this.serializeRedisMetadata(metadata), 'EX', ttl);\r\n } else {\r\n await this.redis.set(`${this._mdPrefix}:${key}`, this.serializeRedisMetadata(metadata));\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async updateTTL(acRequest: AccessRequest, key: string, ttl?: number): Promise<void> {\r\n if (ttl) {\r\n await Promise.all([this.redis.expire(`${this._prefix}:${key}`, ttl), this.redis.expire(`${this._mdPrefix}:${key}`, ttl)]);\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getTTL(acRequest: AccessRequest, key: string): Promise<number> {\r\n return this.redis.ttl(`${this._prefix}:${key}`);\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n const _metadata: any = await this.redis.get(`${this._mdPrefix}:${resourceId}`).catch((error) => {});\r\n const exists = _metadata !== undefined && _metadata !== null; //null or undefined metadata means the resource does not exist\r\n const metadata = exists ? this.deserializeRedisMetadata(_metadata) : {};\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(metadata?.acl as IACL);\r\n }\r\n\r\n // async hasAccess(request: IAccessRequest): Promise<boolean> {\r\n // try {\r\n // const metadata = await this.getMetadata(request.resourceId);\r\n // const acl: IACL = metadata?.acl as IACL;\r\n // return ACL.from(acl).checkExactAccess(request);\r\n // } catch (error) {\r\n // if (error.name === 'NotFound') {\r\n // return false;\r\n // }\r\n // console.error(`Error checking access rights in S3`, error.name, error.message);\r\n // throw error;\r\n // }\r\n // }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, key: string): Promise<IACL> {\r\n try {\r\n const metadata = await this.getMetadata(acRequest, key);\r\n return (metadata?.acl as IACL) || {};\r\n } catch (error) {\r\n console.error(`Error getting access rights in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, key: string, acl: IACL) {\r\n try {\r\n let metadata = await this.getMetadata(acRequest, key);\r\n if (!metadata) metadata = {};\r\n //when setting ACL make sure to not lose ownership\r\n metadata.acl = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setMetadata(acRequest, key, metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in S3`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n private serializeRedisMetadata(redisMetadata: Record<string, any> | undefined): string {\r\n if (!redisMetadata) return '';\r\n if (redisMetadata.acl) {\r\n const acl: IACL = redisMetadata.acl;\r\n if (acl) {\r\n redisMetadata.acl = ACL.from(acl).serializedACL;\r\n }\r\n }\r\n\r\n return JSON.stringify(redisMetadata);\r\n }\r\n\r\n private deserializeRedisMetadata(strMetadata: string): Record<string, any> {\r\n try {\r\n const redisMetadata = JSON.parse(strMetadata);\r\n if (redisMetadata.acl) {\r\n const acl: IACL = ACL.from(redisMetadata.acl).ACL;\r\n redisMetadata.acl = acl;\r\n }\r\n\r\n return redisMetadata;\r\n } catch (error) {\r\n console.warn(`Error deserializing metadata`, strMetadata);\r\n return {};\r\n }\r\n }\r\n\r\n public async stop() {\r\n super.stop();\r\n await this.redis.quit();\r\n }\r\n}\r\n\r\n/**\r\n * hosts can take any of the following formats:\r\n * 1. A string with comma-separated host:port pairs\r\n * 2. An array of strings with host:port pairs\r\n * 3. An array of objects with host and port properties\r\n * @param hosts\r\n */\r\nfunction parseSentinelHosts(hosts: string | string[] | any[]) {\r\n //handle all possible formats of hosts\r\n if (typeof hosts === 'string') {\r\n return hosts.split(',').map((host) => {\r\n const [hostName, port] = host.split(':');\r\n return {\r\n host: hostName,\r\n port: Number(port),\r\n };\r\n });\r\n } else if (Array.isArray(hosts)) {\r\n return hosts.map((host) => {\r\n if (typeof host === 'string') {\r\n const [hostName, port] = host.split(':');\r\n return {\r\n host: hostName,\r\n port: Number(port),\r\n };\r\n } else {\r\n return host;\r\n }\r\n });\r\n } else {\r\n return [];\r\n }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { IAccessCandidate, IACL, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { CacheMetadata } from '@sre/types/Cache.types';\r\nimport { CacheConnector } from '../CacheConnector';\r\n\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\n\r\nimport {\r\n S3Client,\r\n GetObjectCommand,\r\n PutObjectCommand,\r\n PutObjectCommandInput,\r\n DeleteObjectCommand,\r\n HeadObjectCommand,\r\n CopyObjectCommand,\r\n GetObjectTaggingCommand,\r\n PutObjectTaggingCommand,\r\n HeadObjectCommandOutput,\r\n GetObjectTaggingCommandOutput,\r\n GetObjectCommandOutput,\r\n} from '@aws-sdk/client-s3';\r\nimport { checkAndInstallLifecycleRules, generateExpiryMetadata, ttlToExpiryDays } from '@sre/helpers/S3Cache.helper';\r\n\r\nconst console = Logger('S3Cache');\r\nexport type S3CacheConfig = {\r\n bucketName: string;\r\n region: string;\r\n accessKeyId: string;\r\n secretAccessKey: string;\r\n};\r\n\r\nexport class S3Cache extends CacheConnector {\r\n public name: string = 'S3Cache';\r\n private s3Client: S3Client;\r\n private bucketName: string;\r\n private isInitialized: boolean = false;\r\n private cachePrefix: string = '_smyth_cache';\r\n\r\n constructor(protected _settings: S3CacheConfig) {\r\n super(_settings);\r\n this.s3Client = new S3Client({\r\n region: _settings.region,\r\n credentials: {\r\n accessKeyId: _settings.accessKeyId,\r\n secretAccessKey: _settings.secretAccessKey,\r\n },\r\n });\r\n this.bucketName = _settings.bucketName;\r\n }\r\n\r\n public get client() {\r\n return this.s3Client;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async get(acRequest: AccessRequest, key: string): Promise<string | null> {\r\n const candidateId = acRequest.candidate.id;\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n try {\r\n const params = {\r\n Bucket: this.bucketName,\r\n Key: `${this.cachePrefix}/${candidateId}/${key}`,\r\n };\r\n\r\n const s3HeadCommand = new HeadObjectCommand(params);\r\n const headData: HeadObjectCommandOutput = await this.s3Client.send(s3HeadCommand);\r\n\r\n const expirationHeader = headData?.Expiration;\r\n if (expirationHeader) {\r\n const expirationDateMatch = expirationHeader.match(/expiry-date=\"([^\"]+)\"/);\r\n if (expirationDateMatch) {\r\n const expirationDate = new Date(expirationDateMatch[1]);\r\n const currentDate = new Date();\r\n\r\n if (currentDate > expirationDate) {\r\n const s3DeleteCommand = new DeleteObjectCommand(params);\r\n await this.s3Client.send(s3DeleteCommand);\r\n console.log(`Object ${key} expired and deleted.`);\r\n return null;\r\n }\r\n }\r\n }\r\n\r\n const s3GetCommand = new GetObjectCommand(params);\r\n const objectData: GetObjectCommandOutput = await this.s3Client.send(s3GetCommand);\r\n return objectData.Body.transformToString();\r\n } catch (error) {\r\n console.error(`Error reading object ${key}:`, error);\r\n throw null;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async set(acRequest: AccessRequest, key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number): Promise<boolean> {\r\n const accessCandidate = acRequest.candidate;\r\n const candidateId = accessCandidate.id;\r\n\r\n const newMetadata: CacheMetadata = metadata || {};\r\n newMetadata['acl'] = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n const serializedMetadata = this.serializeS3Metadata(newMetadata);\r\n\r\n const s3PutCommandConfig: PutObjectCommandInput = {\r\n Bucket: this.bucketName,\r\n Key: `${this.cachePrefix}/${candidateId}/${key}`,\r\n Body: data,\r\n Metadata: serializedMetadata,\r\n };\r\n if (ttl) {\r\n const expiryMetadata = generateExpiryMetadata(ttlToExpiryDays(ttl)); // seconds to days\r\n s3PutCommandConfig.Tagging = `${expiryMetadata.Key}=${expiryMetadata.Value}`;\r\n }\r\n\r\n const s3PutCommand = new PutObjectCommand(s3PutCommandConfig);\r\n await this.s3Client.send(s3PutCommand);\r\n\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async delete(acRequest: AccessRequest, key: string): Promise<void> {\r\n try {\r\n const candidateId = acRequest.candidate.id;\r\n const deleteCommand = new DeleteObjectCommand({ Bucket: this.bucketName, Key: `${this.cachePrefix}/${candidateId}/${key}` });\r\n await this.s3Client.send(deleteCommand);\r\n } catch (error) {\r\n console.log(`Error deleting object ${key}:`, error);\r\n return;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async exists(acRequest: AccessRequest, key: string): Promise<boolean> {\r\n const candidateId = acRequest.candidate.id;\r\n try {\r\n const params = {\r\n Bucket: this.bucketName,\r\n Key: `${this.cachePrefix}/${candidateId}/${key}`,\r\n };\r\n const s3HeadCommand = new HeadObjectCommand(params);\r\n const headData: HeadObjectCommandOutput = await this.s3Client.send(s3HeadCommand);\r\n\r\n const expirationHeader = headData?.Expiration;\r\n if (expirationHeader) {\r\n const expirationDateMatch = expirationHeader.match(/expiry-date=\"([^\"]+)\"/);\r\n if (expirationDateMatch) {\r\n const expirationDate = new Date(expirationDateMatch[1]);\r\n const currentDate = new Date();\r\n\r\n if (currentDate > expirationDate) {\r\n await this.delete(acRequest, key);\r\n console.log(`Object ${key} expired and deleted.`);\r\n return false;\r\n }\r\n }\r\n }\r\n\r\n return true;\r\n } catch (error) {\r\n console.error(`Error reading object ${key}:`, error);\r\n return false;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getMetadata(acRequest: AccessRequest, key: string): Promise<CacheMetadata> {\r\n const candidateId = acRequest.candidate.id;\r\n\r\n try {\r\n const s3Metadata = await this.getS3Metadata(`${this.cachePrefix}/${candidateId}/${key}`);\r\n return s3Metadata as CacheMetadata;\r\n } catch (error) {\r\n console.error(`Error getting access rights in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async setMetadata(acRequest: AccessRequest, key: string, metadata: CacheMetadata): Promise<void> {\r\n const candidateId = acRequest.candidate.id;\r\n\r\n try {\r\n let s3Metadata = await this.getS3Metadata(`${this.cachePrefix}/${candidateId}/${key}`);\r\n if (!s3Metadata) s3Metadata = {};\r\n //s3Metadata['x-amz-meta-data'] = metadata;\r\n s3Metadata = { ...s3Metadata, ...metadata };\r\n await this.setS3Metadata(`${this.cachePrefix}/${candidateId}/${key}`, s3Metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in S3`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async updateTTL(acRequest: AccessRequest, key: string, ttl?: number): Promise<void> {\r\n if (ttl) {\r\n const candidateId = acRequest.candidate.id;\r\n const expiryMetadata = generateExpiryMetadata(ttlToExpiryDays(ttl)); // seconds to days\r\n const s3PutObjectTaggingCommand = new PutObjectTaggingCommand({\r\n Bucket: this.bucketName,\r\n Key: `${this.cachePrefix}/${candidateId}/${key}`,\r\n Tagging: { TagSet: [{ Key: expiryMetadata.Key, Value: expiryMetadata.Value }] },\r\n });\r\n await this.s3Client.send(s3PutObjectTaggingCommand);\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getTTL(acRequest: AccessRequest, key: string): Promise<number> {\r\n const candidateId = acRequest.candidate.id;\r\n const s3HeadCommand = new HeadObjectCommand({ Bucket: this.bucketName, Key: `${this.cachePrefix}/${candidateId}/${key}` });\r\n const s3HeadObjectResponse: HeadObjectCommandOutput = await this.s3Client.send(s3HeadCommand);\r\n const expirationHeader = s3HeadObjectResponse?.Expiration;\r\n if (expirationHeader) {\r\n const expirationDateMatch = expirationHeader.match(/expiry-date=\"([^\"]+)\"/);\r\n if (expirationDateMatch) {\r\n const expirationDate = new Date(expirationDateMatch[1]);\r\n const currentDate = new Date();\r\n const timeDifference = expirationDate.getTime() - currentDate.getTime();\r\n return Math.floor(timeDifference / (1000 * 60 * 60 * 24)); // Convert to days\r\n }\r\n }\r\n return -1; // Return -1 if no expiration date is found\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n try {\r\n const s3HeadCommand = new HeadObjectCommand({ Bucket: this.bucketName, Key: `${this.cachePrefix}/${candidate.id}/${resourceId}` });\r\n const s3HeadObjectResponse: HeadObjectCommandOutput = await this.s3Client.send(s3HeadCommand);\r\n\r\n const metadata = s3HeadObjectResponse.Metadata;\r\n if (!metadata.acl) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(metadata?.acl as string);\r\n } catch (error) {\r\n if (error.name === 'NotFound') {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, key: string): Promise<IACL> {\r\n try {\r\n const metadata = await this.getMetadata(acRequest, key);\r\n return (metadata?.acl as IACL) || {};\r\n } catch (error) {\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, key: string, acl: IACL) {\r\n try {\r\n let metadata = await this.getMetadata(acRequest, key);\r\n if (!metadata) metadata = {};\r\n //when setting ACL make sure to not lose ownership\r\n metadata.acl = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setMetadata(acRequest, key, metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in S3`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n private async getS3Metadata(resourceId: string): Promise<Record<string, any> | undefined> {\r\n try {\r\n const command = new HeadObjectCommand({\r\n Bucket: this.bucketName,\r\n Key: resourceId,\r\n });\r\n const response: HeadObjectCommandOutput = await this.client.send(command);\r\n const s3RawMetadata = response.Metadata;\r\n if (!s3RawMetadata || Object.keys(s3RawMetadata).length === 0) return {};\r\n\r\n let metadata: Record<string, any> = this.deserializeS3Metadata(s3RawMetadata);\r\n\r\n if (!metadata['ContentType']) metadata['ContentType'] = response.ContentType ? response.ContentType : 'application/octet-stream';\r\n return metadata;\r\n } catch (error) {\r\n if (error.name === 'NotFound' || error.name === 'NoSuchKey') {\r\n return undefined;\r\n }\r\n console.error(`Error reading object metadata from S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n private async setS3Metadata(resourceId: string, metadata: Record<string, any>): Promise<void> {\r\n try {\r\n // Get the current object content\r\n const getObjectTaggingCommand = new GetObjectTaggingCommand({\r\n Bucket: this.bucketName,\r\n Key: resourceId,\r\n });\r\n const objectTagging: GetObjectTaggingCommandOutput = await this.client.send(getObjectTaggingCommand);\r\n const serializedMetadata = this.serializeS3Metadata(metadata);\r\n const copyObjectCommand = new CopyObjectCommand({\r\n Bucket: this.bucketName,\r\n CopySource: `${this.bucketName}/${resourceId}`,\r\n Key: resourceId,\r\n Metadata: serializedMetadata,\r\n MetadataDirective: 'REPLACE',\r\n Tagging: objectTagging.TagSet.map((tag) => `${tag.Key}=${tag.Value}`).join('&'),\r\n });\r\n\r\n await this.client.send(copyObjectCommand);\r\n } catch (error) {\r\n console.error(`Error setting object metadata in S3`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n private async initialize() {\r\n await checkAndInstallLifecycleRules(this.bucketName, this.s3Client);\r\n this.isInitialized = true;\r\n }\r\n\r\n private serializeS3Metadata(s3Metadata: Record<string, any>): Record<string, string> {\r\n let amzMetadata = {};\r\n if (s3Metadata['acl']) {\r\n amzMetadata['acl'] = typeof s3Metadata['acl'] == 'string' ? s3Metadata['acl'] : ACL.from(s3Metadata['acl']).serializedACL;\r\n delete s3Metadata['acl'];\r\n }\r\n\r\n for (let key in s3Metadata) {\r\n if (key == 'ContentType') continue; //skip ContentType as it can only be set when writing the object\r\n amzMetadata[key] = typeof s3Metadata[key] === 'string' ? s3Metadata[key] : JSON.stringify(s3Metadata[key]);\r\n }\r\n\r\n return amzMetadata;\r\n }\r\n\r\n private deserializeS3Metadata(amzMetadata: Record<string, string>): Record<string, any> {\r\n let metadata: Record<string, any> = {};\r\n\r\n for (let key in amzMetadata) {\r\n if (key === 'acl') {\r\n metadata[key] = ACL.from(amzMetadata[key]).ACL;\r\n continue;\r\n }\r\n\r\n try {\r\n metadata[key] = JSON.parse(amzMetadata[key]);\r\n } catch (error) {\r\n metadata[key] = amzMetadata[key];\r\n }\r\n }\r\n\r\n return metadata;\r\n }\r\n\r\n // async hasAccess(request: IAccessRequest): Promise<boolean> {\r\n // try {\r\n // const metadata = await this.getMetadata(request.resourceId);\r\n // const acl: IACL = metadata?.acl as IACL;\r\n // return ACL.from(acl).checkExactAccess(request);\r\n // } catch (error) {\r\n // if (error.name === 'NotFound') {\r\n // return false;\r\n // }\r\n // console.error(`Error checking access rights in S3`, error.name, error.message);\r\n // throw error;\r\n // }\r\n // }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { IAccessCandidate, IACL, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { CacheMetadata } from '@sre/types/Cache.types';\r\nimport { CacheConnector } from '../CacheConnector';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport os from 'os';\r\n\r\nimport { existsSync, mkdirSync, readFileSync, unlinkSync, writeFileSync } from 'fs';\r\nimport path from 'path';\r\nimport { LocalStorageConfig } from '@sre/IO/Storage.service/connectors/LocalStorage.class';\r\n\r\nconst console = Logger('LocalStorageCache');\r\n\r\nexport class LocalStorageCache extends CacheConnector {\r\n public name: string = 'LocalStorageCache';\r\n private folder: string;\r\n private _prefix: string = 'cache';\r\n private _mdPrefix: string = 'cache.metadata';\r\n private isInitialized: boolean = false;\r\n constructor(_settings: LocalStorageConfig) {\r\n super(_settings);\r\n this.folder = _settings.folder || `${os.tmpdir()}/.smyth/cache`;\r\n this.initialize();\r\n }\r\n\r\n private async initialize() {\r\n if (!existsSync(this.folder)) {\r\n mkdirSync(this.folder, { recursive: true });\r\n }\r\n const cacheFolderPath = path.join(this.folder, this._prefix);\r\n if (!existsSync(cacheFolderPath)) {\r\n mkdirSync(cacheFolderPath, { recursive: true });\r\n }\r\n const metadataFolderPath = path.join(this.folder, this._mdPrefix);\r\n if (!existsSync(metadataFolderPath)) {\r\n mkdirSync(metadataFolderPath, { recursive: true });\r\n writeFileSync(\r\n path.join(metadataFolderPath, 'README_IMPORTANT.txt'),\r\n 'This folder is used for smythOS metadata, do not delete it, it will break SmythOS cache functionality'\r\n );\r\n }\r\n this.isInitialized = true;\r\n }\r\n\r\n public get prefix() {\r\n return this._prefix;\r\n }\r\n\r\n public get mdPrefix() {\r\n return this._mdPrefix;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async get(acRequest: AccessRequest, key: string): Promise<string | null> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n try {\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, key);\r\n if (!existsSync(filePath)) return undefined;\r\n const data = readFileSync(filePath, 'utf-8');\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n const metadata = readFileSync(metadataFilePath, 'utf-8');\r\n const metadataObject = JSON.parse(metadata);\r\n if (metadataObject['expiresAt'] && metadataObject['expiresAt'] < Date.now()) {\r\n await this.delete(acRequest, key);\r\n return undefined;\r\n }\r\n return data;\r\n } catch (error) {\r\n console.error(`Error reading object from local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async set(acRequest: AccessRequest, key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number): Promise<boolean> {\r\n // ttl is in seconds\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const accessCandidate = acRequest.candidate;\r\n\r\n let amzACL = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n let fileMetadata = {\r\n ...metadata,\r\n acl: amzACL,\r\n ...(ttl ? { expiresAt: Date.now() + ttl * 1000 } : {}),\r\n };\r\n // To create the directories for the resource we need to know the full path of the resource\r\n const storageFolderPath = this.getStorageFilePath(acRequest.candidate.id, key, true);\r\n this.createDirectories(storageFolderPath, key);\r\n //now we can write the file\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, key);\r\n writeFileSync(filePath, data as Buffer);\r\n //now we can write the metadata\r\n await this.setMetadata(acRequest, key, fileMetadata);\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async delete(acRequest: AccessRequest, key: string): Promise<void> {\r\n try {\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, key);\r\n if (!existsSync(filePath)) return;\r\n unlinkSync(filePath);\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n unlinkSync(metadataFilePath);\r\n } catch (error) {\r\n console.error(`Error deleting object from local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n @SecureConnector.AccessControl\r\n public async exists(acRequest: AccessRequest, key: string): Promise<boolean> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const filePath = this.getStorageFilePath(acRequest.candidate.id, key);\r\n if (!existsSync(filePath)) return false;\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n if (!existsSync(metadataFilePath)) return false;\r\n const metadata = readFileSync(metadataFilePath, 'utf-8');\r\n const metadataObject = JSON.parse(metadata);\r\n if (metadataObject['expiresAt'] && metadataObject['expiresAt'] < Date.now()) {\r\n await this.delete(acRequest, key);\r\n return false;\r\n }\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getMetadata(acRequest: AccessRequest, key: string): Promise<CacheMetadata> {\r\n try {\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n if (!existsSync(metadataFilePath)) return undefined;\r\n const data = readFileSync(metadataFilePath, 'utf-8');\r\n return this.deserializeMetadata(JSON.parse(data)) as CacheMetadata;\r\n } catch (error) {\r\n console.error(`Error reading metadata from LocalStorage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async setMetadata(acRequest: AccessRequest, key: string, metadata: CacheMetadata): Promise<void> {\r\n try {\r\n let fileMetadata = await this.getMetadata(acRequest, key);\r\n if (!fileMetadata) fileMetadata = {};\r\n\r\n fileMetadata = { ...fileMetadata, ...metadata };\r\n // To create the directories for the resource we need to know the full path of the resource\r\n const metadataFolderPath = this.getMetadataFilePath(acRequest.candidate.id, key, true);\r\n this.createDirectories(metadataFolderPath, key);\r\n //now we can write the metadata\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n const serializedMetadata = this.serializeMetadata(fileMetadata);\r\n writeFileSync(metadataFilePath, JSON.stringify(serializedMetadata));\r\n } catch (error) {\r\n console.error(`Error setting metadata in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async updateTTL(acRequest: AccessRequest, key: string, ttl?: number): Promise<void> {\r\n // ttl is in seconds\r\n if (ttl) {\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n const metadata = readFileSync(metadataFilePath, 'utf-8');\r\n const metadataObject = JSON.parse(metadata);\r\n metadataObject['expiresAt'] = Date.now() + ttl * 1000;\r\n writeFileSync(metadataFilePath, JSON.stringify(metadataObject));\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getTTL(acRequest: AccessRequest, key: string): Promise<number> {\r\n const metadataFilePath = this.getMetadataFilePath(acRequest.candidate.id, key);\r\n const metadata = readFileSync(metadataFilePath, 'utf-8');\r\n const metadataObject = JSON.parse(metadata);\r\n return metadataObject['expiresAt'] && metadataObject['expiresAt'] > Date.now()\r\n ? Math.floor((metadataObject['expiresAt'] - Date.now()) / 1000)\r\n : 0;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n if (!this.isInitialized) {\r\n await this.initialize();\r\n }\r\n const metadataFilePath = this.getMetadataFilePath(candidate.id, resourceId);\r\n if (!existsSync(metadataFilePath)) return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n const metadata = readFileSync(metadataFilePath, 'utf-8');\r\n const exists = metadata !== undefined; //undefined metadata means the resource does not exist\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n try {\r\n let metadataObject = JSON.parse(metadata);\r\n return ACL.from(metadataObject?.['acl'] as IACL);\r\n } catch (error) {\r\n console.error(`Error parsing metadata in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, key: string): Promise<IACL> {\r\n try {\r\n const fileMetadata = await this.getMetadata(acRequest, key);\r\n return ACL.from(fileMetadata?.['acl'] as IACL);\r\n } catch (error) {\r\n console.error(`Error getting access rights in local storage`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, key: string, acl: IACL) {\r\n try {\r\n let fileMetadata = await this.getMetadata(acRequest, key);\r\n if (!fileMetadata) fileMetadata = {};\r\n //when setting ACL make sure to not lose ownership\r\n fileMetadata['acl'] = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setMetadata(acRequest, key, fileMetadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in local storage`, error);\r\n throw error;\r\n }\r\n }\r\n private serializeMetadata(metadata: Record<string, any>): Record<string, string> {\r\n let updatedMetadata = {};\r\n if (metadata['acl']) {\r\n if (metadata['acl']) {\r\n updatedMetadata['acl'] = typeof metadata['acl'] == 'string' ? metadata['acl'] : ACL.from(metadata['acl']).serializedACL;\r\n }\r\n\r\n delete metadata['acl'];\r\n }\r\n\r\n for (let key in metadata) {\r\n if (key == 'ContentType') continue; //skip ContentType as it can only be set when writing the object\r\n updatedMetadata[key] = typeof metadata[key] === 'string' ? metadata[key] : JSON.stringify(metadata[key]);\r\n }\r\n\r\n return updatedMetadata;\r\n }\r\n\r\n private deserializeMetadata(metadata: Record<string, string>): Record<string, any> {\r\n let deserializedMetadata: Record<string, any> = {};\r\n\r\n for (let key in metadata) {\r\n if (key === 'acl') {\r\n deserializedMetadata[key] = ACL.from(metadata[key]).ACL;\r\n continue;\r\n }\r\n\r\n try {\r\n deserializedMetadata[key] = JSON.parse(metadata[key]);\r\n } catch (error) {\r\n deserializedMetadata[key] = metadata[key];\r\n }\r\n }\r\n return deserializedMetadata;\r\n }\r\n\r\n private getStorageFilePath(teamId: string, resourceId: string, returnBasePath: boolean = false) {\r\n if (!existsSync(path.join(this.folder, this._prefix, teamId))) {\r\n mkdirSync(path.join(this.folder, this._prefix, teamId));\r\n }\r\n if (returnBasePath) return path.join(this.folder, this._prefix, teamId);\r\n return path.join(this.folder, this._prefix, teamId, resourceId);\r\n }\r\n\r\n private getMetadataFilePath(teamId: string, resourceId: string, returnBasePath: boolean = false) {\r\n if (!existsSync(path.join(this.folder, this._mdPrefix, teamId))) {\r\n mkdirSync(path.join(this.folder, this._mdPrefix, teamId));\r\n }\r\n if (returnBasePath) return path.join(this.folder, this._mdPrefix, teamId);\r\n return path.join(this.folder, this._mdPrefix, teamId, resourceId);\r\n }\r\n\r\n private createDirectories(basePath: string, resourceId: string) {\r\n const folders = resourceId.split('/').slice(0, -1);\r\n let currentPath = basePath;\r\n for (let folder of folders) {\r\n currentPath = path.join(currentPath, folder);\r\n if (!existsSync(currentPath)) {\r\n mkdirSync(currentPath);\r\n }\r\n }\r\n }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { IAccessCandidate, IACL, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { CacheMetadata } from '@sre/types/Cache.types';\r\nimport { CacheConnector } from '../CacheConnector';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { debounce } from '@sre/utils/general.utils';\r\n\r\nconst console = Logger('RAMCache');\r\n\r\ninterface CacheEntry {\r\n value: any;\r\n metadata: CacheMetadata;\r\n expiresAt?: number;\r\n}\r\n\r\nexport class RAMCache extends CacheConnector {\r\n public name: string = 'RAMCache';\r\n private _prefix: string = 'smyth:cache';\r\n private _mdPrefix: string = 'smyth:metadata';\r\n private cache: Map<string, CacheEntry> = new Map();\r\n private cleanupInterval: NodeJS.Timeout;\r\n\r\n constructor(protected _settings: any) {\r\n super(_settings);\r\n // Set up cleanup interval to remove expired entries\r\n\r\n this.cleanupInterval = setInterval(() => this.cleanupExpiredEntries(), 60000); // Clean up every minute\r\n this.cleanupInterval.unref();\r\n }\r\n\r\n public get prefix() {\r\n return this._prefix;\r\n }\r\n\r\n public get mdPrefix() {\r\n return this._mdPrefix;\r\n }\r\n\r\n private getFullKey(key: string): string {\r\n return `${this._prefix}:${key}`;\r\n }\r\n\r\n private getFullMetadataKey(key: string): string {\r\n return `${this._mdPrefix}:${key}`;\r\n }\r\n\r\n private cleanupExpiredEntries() {\r\n const now = Date.now();\r\n for (const [key, entry] of this.cache.entries()) {\r\n if (entry.expiresAt && entry.expiresAt < now) {\r\n this.cache.delete(key);\r\n }\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async get(acRequest: AccessRequest, key: string): Promise<string | null> {\r\n const fullKey = this.getFullKey(key);\r\n const entry = this.cache.get(fullKey);\r\n\r\n if (!entry) return null;\r\n\r\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\r\n this.cache.delete(fullKey);\r\n return null;\r\n }\r\n\r\n return entry.value;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async set(acRequest: AccessRequest, key: string, data: any, acl?: IACL, metadata?: CacheMetadata, ttl?: number): Promise<boolean> {\r\n const accessCandidate = acRequest.candidate;\r\n const fullKey = this.getFullKey(key);\r\n const fullMetadataKey = this.getFullMetadataKey(key);\r\n\r\n const newMetadata: CacheMetadata = metadata || {};\r\n newMetadata.acl = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n\r\n const entry: CacheEntry = {\r\n value: data,\r\n metadata: newMetadata,\r\n expiresAt: ttl ? Date.now() + ttl * 1000 : undefined,\r\n };\r\n\r\n this.cache.set(fullKey, entry);\r\n this.cache.set(fullMetadataKey, entry);\r\n\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async delete(acRequest: AccessRequest, key: string): Promise<void> {\r\n const fullKey = this.getFullKey(key);\r\n const fullMetadataKey = this.getFullMetadataKey(key);\r\n this.cache.delete(fullKey);\r\n this.cache.delete(fullMetadataKey);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async exists(acRequest: AccessRequest, key: string): Promise<boolean> {\r\n const fullKey = this.getFullKey(key);\r\n const entry = this.cache.get(fullKey);\r\n\r\n if (!entry) return false;\r\n\r\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\r\n this.cache.delete(fullKey);\r\n return false;\r\n }\r\n\r\n return true;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getMetadata(acRequest: AccessRequest, key: string): Promise<CacheMetadata> {\r\n if (!(await this.exists(acRequest, key))) return undefined;\r\n\r\n const fullMetadataKey = this.getFullMetadataKey(key);\r\n const entry = this.cache.get(fullMetadataKey);\r\n return entry?.metadata || {};\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async setMetadata(acRequest: AccessRequest, key: string, metadata: CacheMetadata): Promise<void> {\r\n const fullMetadataKey = this.getFullMetadataKey(key);\r\n const entry = this.cache.get(fullMetadataKey);\r\n\r\n if (entry) {\r\n entry.metadata = metadata;\r\n this.cache.set(fullMetadataKey, entry);\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async updateTTL(acRequest: AccessRequest, key: string, ttl?: number): Promise<void> {\r\n const fullKey = this.getFullKey(key);\r\n const fullMetadataKey = this.getFullMetadataKey(key);\r\n const entry = this.cache.get(fullKey);\r\n\r\n if (entry) {\r\n entry.expiresAt = ttl ? Date.now() + ttl * 1000 : undefined;\r\n this.cache.set(fullKey, entry);\r\n this.cache.set(fullMetadataKey, entry);\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getTTL(acRequest: AccessRequest, key: string): Promise<number> {\r\n const fullKey = this.getFullKey(key);\r\n const entry = this.cache.get(fullKey);\r\n\r\n if (!entry || !entry.expiresAt) return -1;\r\n\r\n const remaining = Math.ceil((entry.expiresAt - Date.now()) / 1000);\r\n return remaining > 0 ? remaining : -1;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n const fullMetadataKey = this.getFullMetadataKey(resourceId);\r\n const entry = this.cache.get(fullMetadataKey);\r\n\r\n if (!entry) {\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n\r\n return ACL.from(entry.metadata?.acl as IACL);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async getACL(acRequest: AccessRequest, key: string): Promise<IACL> {\r\n try {\r\n const metadata = await this.getMetadata(acRequest, key);\r\n return (metadata?.acl as IACL) || {};\r\n } catch (error) {\r\n console.error(`Error getting access rights in RAMCache`, error.name, error.message);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n async setACL(acRequest: AccessRequest, key: string, acl: IACL) {\r\n try {\r\n let metadata = await this.getMetadata(acRequest, key);\r\n if (!metadata) metadata = {};\r\n metadata.acl = ACL.from(acl).addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setMetadata(acRequest, key, metadata);\r\n } catch (error) {\r\n console.error(`Error setting access rights in RAMCache`, error);\r\n throw error;\r\n }\r\n }\r\n\r\n public async stop() {\r\n super.stop();\r\n clearInterval(this.cleanupInterval);\r\n this.cache.clear();\r\n }\r\n}\r\n","//==[ SRE: Cache ]======================\r\nimport { ConnectorServiceProvider, ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { RedisCache } from './connectors/RedisCache.class';\r\nimport { S3Cache } from './connectors/S3Cache.class';\r\nimport { LocalStorageCache } from './connectors/LocalStorageCache.class';\r\nimport { RAMCache } from './connectors/RAMCache.class';\r\nexport class CacheService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Cache, 'Redis', RedisCache);\r\n ConnectorService.register(TConnectorService.Cache, 'S3', S3Cache);\r\n ConnectorService.register(TConnectorService.Cache, 'LocalStorage', LocalStorageCache);\r\n ConnectorService.register(TConnectorService.Cache, 'RAM', RAMCache);\r\n }\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\n\r\nexport interface IVaultRequest {\r\n get(keyId: string): Promise<string>;\r\n exists(keyId: string): Promise<boolean>;\r\n listKeys(): Promise<string[]>;\r\n}\r\n\r\nexport abstract class VaultConnector extends SecureConnector {\r\n requester(candidate: AccessCandidate): IVaultRequest {\r\n return {\r\n get: async (keyId: string) => this.get(candidate.readRequest, keyId),\r\n exists: async (keyId: string) => this.exists(candidate.readRequest, keyId),\r\n listKeys: async () => this.listKeys(candidate.readRequest),\r\n };\r\n }\r\n\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n protected abstract get(acRequest: AccessRequest, keyId: string): Promise<string>;\r\n protected abstract exists(acRequest: AccessRequest, keyId: string): Promise<boolean>;\r\n protected abstract listKeys(acRequest: AccessRequest): Promise<string[]>;\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { EncryptionSettings } from '@sre/types/Security.types';\r\nimport { IVaultRequest, VaultConnector } from '../VaultConnector';\r\nimport os from 'os';\r\nimport crypto from 'crypto';\r\nimport fs from 'fs';\r\nimport * as readlineSync from 'readline-sync';\r\nimport path from 'path';\r\n\r\nconst console = Logger('JSONFileVault');\r\n\r\nexport type JSONFileVaultConfig = {\r\n file?: string;\r\n fileKey?: string;\r\n shared?: boolean;\r\n};\r\n\r\nexport class JSONFileVault extends VaultConnector {\r\n public name: string = 'JSONFileVault';\r\n private vaultData: any;\r\n private index: any;\r\n private sharedVault: boolean;\r\n\r\n constructor(protected _settings: JSONFileVaultConfig) {\r\n super(_settings);\r\n //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');\r\n\r\n this.sharedVault = _settings.shared || false; //if config.shared, all keys are accessible to all teams, and they are set under the 'shared' teamId\r\n\r\n let vaultFile = this.findVaultFile(_settings.file);\r\n this.vaultData = {};\r\n if (fs.existsSync(vaultFile)) {\r\n try {\r\n if (_settings.fileKey && fs.existsSync(_settings.fileKey)) {\r\n try {\r\n const privateKey = fs.readFileSync(_settings.fileKey, 'utf8');\r\n const encryptedVault = fs.readFileSync(vaultFile, 'utf8').toString();\r\n const decryptedBuffer = crypto.privateDecrypt(\r\n {\r\n key: privateKey,\r\n padding: crypto.constants.RSA_PKCS1_OAEP_PADDING,\r\n },\r\n Buffer.from(encryptedVault, 'base64')\r\n );\r\n this.vaultData = JSON.parse(decryptedBuffer.toString('utf8'));\r\n } catch (error) {\r\n throw new Error('Failed to decrypt vault');\r\n }\r\n } else {\r\n this.vaultData = JSON.parse(fs.readFileSync(vaultFile).toString());\r\n }\r\n } catch (e) {\r\n this.vaultData = {};\r\n }\r\n\r\n if (this.vaultData?.encrypted && this.vaultData?.algorithm && this.vaultData?.data) {\r\n //this is an encrypted vault we need to request the master key\r\n this.setInteraction(this.getMasterKeyInteractive.bind(this));\r\n }\r\n\r\n for (let teamId in this.vaultData) {\r\n for (let resourceId in this.vaultData[teamId]) {\r\n if (!this.index) this.index = {};\r\n if (!this.index[resourceId]) this.index[resourceId] = {};\r\n const value = this.vaultData[teamId][resourceId];\r\n this.index[resourceId][teamId] = value;\r\n }\r\n }\r\n }\r\n }\r\n\r\n private findVaultFile(vaultFile) {\r\n let _vaultFile = vaultFile;\r\n\r\n if (fs.existsSync(_vaultFile)) {\r\n return _vaultFile;\r\n }\r\n console.warn('Vault file not found in:', _vaultFile, 'trying to find in local .smyth directory');\r\n\r\n //try local directory\r\n _vaultFile = path.join(process.cwd(), '.smyth', '.sre', 'vault.json');\r\n if (fs.existsSync(_vaultFile)) {\r\n console.warn('Using alternative vault file found in : ', _vaultFile);\r\n return _vaultFile;\r\n }\r\n\r\n console.warn('Vault file not found in:', _vaultFile, 'trying to find in user home directory');\r\n //try to find the vault file in the .smyth directory\r\n _vaultFile = path.join(os.homedir(), '.smyth', '.sre', 'vault.json');\r\n if (fs.existsSync(_vaultFile)) {\r\n console.warn('Using alternative vault file found in : ', _vaultFile);\r\n return _vaultFile;\r\n }\r\n\r\n console.warn('Vault file not found in:', _vaultFile);\r\n console.warn('!!! All attempts to find the vault file failed !!!');\r\n console.warn('!!! Will continue without vault !!!');\r\n console.warn('!!! Many features might not work !!!');\r\n\r\n return null;\r\n }\r\n\r\n private getMasterKeyInteractive(): string {\r\n //read master key using readline-sync (blocking)\r\n\r\n process.stdout.write('\\x1b[1;37m===[ Encrypted Vault Detected ]=================================\\x1b[0m\\n');\r\n const masterKey = readlineSync.question('Enter master key: ', {\r\n hideEchoBack: true,\r\n mask: '*',\r\n });\r\n console.info('Master key entered');\r\n return masterKey;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, keyId: string) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n return this.vaultData?.[teamId]?.[keyId] || this.vaultData?.['shared']?.[keyId];\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, keyId: string) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);\r\n return !!(this.vaultData?.[teamId]?.[keyId] || this.vaultData?.['shared']?.[keyId]);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listKeys(acRequest: AccessRequest) {\r\n return Object.keys(this.vaultData);\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = /*this.sharedVault ? 'shared' : */ await accountConnector.getCandidateTeam(candidate);\r\n\r\n const acl = new ACL();\r\n\r\n if (resourceId && typeof this.vaultData?.[teamId]?.[resourceId] !== 'string') {\r\n if (this.sharedVault && typeof this.vaultData?.['shared']?.[resourceId] === 'string') {\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n }\r\n\r\n return acl;\r\n }\r\n\r\n acl.addAccess(TAccessRole.Team, teamId, TAccessLevel.Owner)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Read)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Write);\r\n\r\n if (this.sharedVault && typeof this.vaultData?.['shared']?.[resourceId] === 'string') {\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n }\r\n\r\n return acl;\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { VaultConnector } from '../VaultConnector';\r\nimport {\r\n SecretsManagerClient,\r\n GetSecretValueCommand,\r\n ListSecretsCommand,\r\n ListSecretsCommandOutput,\r\n GetSecretValueCommandOutput,\r\n} from '@aws-sdk/client-secrets-manager';\r\n\r\nconst console = Logger('SecretsManager');\r\n\r\nexport type SecretsManagerConfig = {\r\n region: string;\r\n awsAccessKeyId?: string;\r\n awsSecretAccessKey?: string;\r\n};\r\nexport class SecretsManager extends VaultConnector {\r\n public name: string = 'SecretsManager';\r\n private secretsManager: SecretsManagerClient;\r\n\r\n constructor(protected _settings: SecretsManagerConfig) {\r\n super(_settings);\r\n //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');\r\n\r\n this.secretsManager = new SecretsManagerClient({\r\n region: _settings.region,\r\n ...(_settings.awsAccessKeyId && _settings.awsSecretAccessKey\r\n ? {\r\n accessKeyId: _settings.awsAccessKeyId,\r\n secretAccessKey: _settings.awsSecretAccessKey,\r\n }\r\n : {}),\r\n });\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, secretName: string) {\r\n try {\r\n const secret = await this.getSecretByName(secretName);\r\n return secret?.SecretString;\r\n } catch (error) {\r\n console.error(error);\r\n throw error;\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, keyId: string) {\r\n const secret = await this.get(acRequest, keyId);\r\n return !!secret;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listKeys(acRequest: AccessRequest) {\r\n console.warn('SecretsManager.listKeys is not implemented');\r\n return [];\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n const acl = new ACL();\r\n\r\n acl.addAccess(TAccessRole.Team, teamId, TAccessLevel.Owner)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Read)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Write);\r\n\r\n return acl;\r\n }\r\n\r\n private async getSecretByName(secretName: string) {\r\n try {\r\n const secrets = [];\r\n let nextToken: string | undefined;\r\n do {\r\n const listResponse: ListSecretsCommandOutput = await this.secretsManager.send(\r\n new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: ['smyth-vault'] }] })\r\n );\r\n if (listResponse.SecretList) {\r\n for (const secret of listResponse.SecretList) {\r\n if (secret.Name) {\r\n secrets.push({\r\n ARN: secret.ARN,\r\n Name: secret.Name,\r\n CreatedDate: secret.CreatedDate,\r\n });\r\n }\r\n }\r\n }\r\n nextToken = listResponse.NextToken;\r\n } while (nextToken);\r\n\r\n const formattedSecrets = [];\r\n const $promises = [];\r\n for (const secret of secrets) {\r\n $promises.push(getSpecificSecret(secret, this.secretsManager));\r\n }\r\n const results = await Promise.all($promises);\r\n for (const result of results) {\r\n formattedSecrets.push(result);\r\n }\r\n const secret = formattedSecrets.find((s) => s.Name === secretName);\r\n return secret;\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n\r\n async function getSpecificSecret(secret, secretsManager: SecretsManagerClient) {\r\n const data: GetSecretValueCommandOutput = await secretsManager.send(new GetSecretValueCommand({ SecretId: secret.ARN }));\r\n let secretString = data.SecretString;\r\n let secretName = secret.Name;\r\n\r\n if (secretString) {\r\n try {\r\n let parsedSecret = JSON.parse(secretString);\r\n if (Object.keys(parsedSecret).length === 1) {\r\n secretName = Object.keys(parsedSecret)[0];\r\n secretString = parsedSecret[secretName];\r\n }\r\n } catch (error) {}\r\n }\r\n return {\r\n Name: secretName,\r\n ARN: secret.ARN,\r\n CreatedDate: secret.CreatedDate,\r\n SecretId: secret.Name,\r\n SecretString: secretString,\r\n };\r\n }\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\n\r\nimport { IVaultRequest, VaultConnector } from '../VaultConnector';\r\nimport crypto from 'crypto';\r\nimport fs from 'fs';\r\nimport * as readlineSync from 'readline-sync';\r\n\r\nconst console = Logger('NullVault');\r\nexport class NullVault extends VaultConnector {\r\n public name: string = 'NullVault';\r\n private vaultData: any;\r\n private index: any;\r\n private sharedVault: boolean;\r\n\r\n constructor(protected _settings: any) {\r\n super(_settings);\r\n console.warn('NullVault is used : Vault features will not be available');\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, keyId: string) {\r\n console.debug(`Ignored operation:NullVault.get: ${keyId}`);\r\n return 'NULLKEY';\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, keyId: string) {\r\n console.debug(`Ignored operation:NullVault.exists: ${keyId}`);\r\n return false;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listKeys(acRequest: AccessRequest) {\r\n console.debug(`Ignored operation:NullVault.listKeys`);\r\n return [];\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const acl = new ACL();\r\n\r\n //give just read access by default\r\n //Cannot write to null vault\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n\r\n return acl;\r\n }\r\n}\r\n","import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { JSONFileVault } from './connectors/JSONFileVault.class';\r\nimport { SecretsManager } from './connectors/SecretsManager.class';\r\nimport { NullVault } from './connectors/NullVault.class';\r\nexport class VaultService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Vault, 'JSONFileVault', JSONFileVault);\r\n ConnectorService.register(TConnectorService.Vault, 'SecretsManager', SecretsManager);\r\n ConnectorService.register(TConnectorService.Vault, 'NullVault', NullVault);\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { IAccessCandidate, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AccessCandidate } from '../AccessControl/AccessCandidate.class';\r\nimport { KeyValueObject } from '@sre/types/Common.types';\r\nimport { ACL } from '../AccessControl/ACL.class';\r\n\r\nexport interface ISmythAccountRequest {\r\n isTeamMember(teamId: string): Promise<boolean>;\r\n getCandidateTeam(): Promise<string | undefined>;\r\n getAllTeamSettings(): Promise<KeyValueObject>;\r\n getAllUserSettings(): Promise<KeyValueObject>;\r\n getTeamSetting(settingKey: string): Promise<string>;\r\n getUserSetting(settingKey: string): Promise<string>;\r\n getAgentSetting(settingKey: string): Promise<string>;\r\n getTeam(): Promise<string>;\r\n}\r\n\r\nexport abstract class AccountConnector extends Connector {\r\n public requester(candidate: AccessCandidate): ISmythAccountRequest {\r\n return {\r\n getAllUserSettings: async () => this.getAllUserSettings(candidate.readRequest, candidate.id),\r\n getUserSetting: async (settingKey: string) => this.getUserSetting(candidate.readRequest, candidate.id, settingKey),\r\n getAllTeamSettings: async () => this.getAllTeamSettings(candidate.readRequest, candidate.id),\r\n getTeamSetting: async (settingKey: string) => this.getTeamSetting(candidate.readRequest, candidate.id, settingKey),\r\n isTeamMember: async (teamId: string) => this.isTeamMember(teamId, candidate),\r\n getCandidateTeam: async () => this.getCandidateTeam(candidate),\r\n getTeam: async () => this.getCandidateTeam(candidate),\r\n getAgentSetting: async (settingKey: string) => this.getAgentSetting(candidate.readRequest, candidate.id, settingKey),\r\n };\r\n }\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n public abstract isTeamMember(teamId: string, candidate: IAccessCandidate): Promise<boolean>;\r\n public abstract getCandidateTeam(candidate: IAccessCandidate): Promise<string | undefined>;\r\n public abstract getAllTeamSettings(acRequest: AccessRequest, teamId: string): Promise<KeyValueObject>;\r\n public abstract getAllUserSettings(acRequest: AccessRequest, accountId: string): Promise<KeyValueObject>;\r\n public abstract getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string): Promise<string>;\r\n public abstract getUserSetting(acRequest: AccessRequest, accountId: string, settingKey: string): Promise<string>;\r\n public abstract getAgentSetting(acRequest: AccessRequest, agentId: string, settingKey: string): Promise<string>;\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { DEFAULT_TEAM_ID, IAccessCandidate, IACL, TAccessRole } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\nimport { AccountConnector } from '../AccountConnector';\r\nimport { KeyValueObject } from '@sre/types/Common.types';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n\r\nconst console = Logger('DummyAccount');\r\n\r\n/*\r\ndata format \r\n\r\n{\r\n \"team1\": {\r\n users: {\r\n \"user1\": {\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n },\r\n \"agents\": {\r\n \"agent1\": {\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n },\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n}\r\n\r\n*/\r\n\r\nexport class DummyAccount extends AccountConnector {\r\n public name = 'DummyAccount';\r\n public data: any = {};\r\n\r\n constructor(protected _settings?: any) {\r\n super(_settings);\r\n this.data = _settings?.data || {};\r\n if (!this.data[DEFAULT_TEAM_ID]) {\r\n this.data[DEFAULT_TEAM_ID] = {\r\n users: {},\r\n agents: { FAKE_AGENT_ID: {} },\r\n settings: {},\r\n };\r\n }\r\n if (!this.data[DEFAULT_TEAM_ID])\r\n console.warn(\r\n 'You are using the DummyAccount connector. This is a development tool and should not be used in production if you have security concerns.'\r\n );\r\n }\r\n\r\n public isTeamMember(team: string, candidate: IAccessCandidate): Promise<boolean> {\r\n if (team === DEFAULT_TEAM_ID) {\r\n return Promise.resolve(true);\r\n }\r\n\r\n switch (candidate.role) {\r\n case TAccessRole.Team:\r\n return Promise.resolve(team === candidate.id);\r\n case TAccessRole.User:\r\n return Promise.resolve(this.data[team]?.users?.[candidate.id]);\r\n case TAccessRole.Agent:\r\n return Promise.resolve(this.data[team]?.agents?.[candidate.id]);\r\n default:\r\n return Promise.resolve(false);\r\n }\r\n }\r\n public getCandidateTeam(candidate: IAccessCandidate): Promise<string | undefined> {\r\n if (candidate.role === TAccessRole.Team) {\r\n return Promise.resolve(candidate.id);\r\n }\r\n\r\n //lookup the team id for the user or agent\r\n for (const team in this.data) {\r\n if (candidate.role === TAccessRole.User && this.data[team]?.users?.[candidate.id]) {\r\n return Promise.resolve(team);\r\n }\r\n if (candidate.role === TAccessRole.Agent && this.data[team]?.agents?.[candidate.id]) {\r\n return Promise.resolve(team);\r\n }\r\n }\r\n return Promise.resolve(DEFAULT_TEAM_ID);\r\n }\r\n\r\n public getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n throw new Error('getResourceACL Method not implemented.');\r\n }\r\n public getAllTeamSettings(acRequest: AccessRequest, teamId: string): Promise<KeyValueObject[]> {\r\n return Promise.resolve(this.data[teamId]?.settings);\r\n }\r\n public getAllUserSettings(acRequest: AccessRequest, accountId: string): Promise<KeyValueObject[]> {\r\n for (const team in this.data) {\r\n if (this.data[team]?.users?.[accountId]) {\r\n return Promise.resolve(this.data[team]?.users?.[accountId]?.settings);\r\n }\r\n }\r\n return Promise.resolve([]);\r\n }\r\n public getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string): Promise<string> {\r\n return Promise.resolve(this.data[teamId]?.settings?.[settingKey]);\r\n }\r\n public getUserSetting(acRequest: AccessRequest, accountId: string, settingKey: string): Promise<string> {\r\n for (const team in this.data) {\r\n if (this.data[team]?.users?.[accountId]) {\r\n return Promise.resolve(this.data[team]?.users?.[accountId]?.settings?.[settingKey]);\r\n }\r\n }\r\n return Promise.resolve(undefined);\r\n }\r\n public getAgentSetting(acRequest: AccessRequest, agentId: string, settingKey: string): Promise<string> {\r\n for (const team in this.data) {\r\n if (this.data[team]?.agents?.[agentId]) {\r\n return Promise.resolve(this.data[team]?.agents?.[agentId]?.settings?.[settingKey]);\r\n }\r\n }\r\n return Promise.resolve(undefined);\r\n }\r\n}\r\n","import mysql from 'mysql2/promise';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { DEFAULT_TEAM_ID, IAccessCandidate, IACL, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AccountConnector } from '../AccountConnector';\r\nimport { KeyValueObject } from '@sre/types/Common.types';\r\n\r\nexport class AWSAccount extends AccountConnector {\r\n public name = 'AWSAccount';\r\n\r\n private pool: mysql.Pool;\r\n\r\n constructor(protected _settings: any) {\r\n super(_settings);\r\n\r\n this.pool = mysql.createPool({\r\n host: _settings.host,\r\n database: _settings.database || 'app',\r\n user: _settings.user || 'app',\r\n password: _settings.password,\r\n connectionLimit: 10,\r\n });\r\n }\r\n\r\n public isTeamMember(team: string, candidate: IAccessCandidate): Promise<boolean> {\r\n return Promise.resolve(true);\r\n }\r\n\r\n public getCandidateTeam(candidate: IAccessCandidate): Promise<string | undefined> {\r\n if (candidate.role === TAccessRole.Team) {\r\n return Promise.resolve(candidate.id);\r\n }\r\n\r\n return Promise.resolve(DEFAULT_TEAM_ID);\r\n }\r\n\r\n public async getAllTeamSettings(acRequest: AccessRequest, teamId: string): Promise<KeyValueObject[]> {\r\n try {\r\n const [rows] = await this.pool.execute('SELECT `key`, `value` FROM TeamSettings');\r\n const settings: KeyValueObject[] = [];\r\n if (Array.isArray(rows) && rows.length > 0) {\r\n settings.push(...rows.map((row) => ({ key: row.key, value: row.value })));\r\n }\r\n return settings;\r\n } catch (error) {\r\n console.error('Error in getTeamSetting:', error);\r\n return [] as KeyValueObject[];\r\n }\r\n }\r\n\r\n public async getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string): Promise<string> {\r\n try {\r\n const [rows] = await this.pool.execute('SELECT `value` FROM TeamSettings WHERE `key` = ? LIMIT 1', [settingKey]);\r\n if (Array.isArray(rows) && rows.length > 0 && 'value' in rows[0]) return rows[0].value;\r\n return '';\r\n } catch (error) {\r\n console.error('Error in getTeamSetting:', error);\r\n return '';\r\n }\r\n }\r\n\r\n // TODO: Implement this\r\n public getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n throw new Error('getResourceACL Method not implemented.');\r\n }\r\n public getAllUserSettings(acRequest: AccessRequest, accountId: string): Promise<KeyValueObject[]> {\r\n throw new Error('getAllUserSettings Method not implemented.');\r\n }\r\n public getUserSetting(acRequest: AccessRequest, accountId: string, settingKey: string): Promise<string> {\r\n throw new Error('getUserSetting Method not implemented.');\r\n }\r\n\r\n public getAgentSetting(acRequest: AccessRequest, agentId: string, settingKey: string): Promise<string> {\r\n throw new Error('getAgentSetting Method not implemented.');\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { DEFAULT_TEAM_ID, IAccessCandidate, IACL, TAccessRole } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\nimport { AccountConnector } from '../AccountConnector';\r\nimport { KeyValueObject } from '@sre/types/Common.types';\r\nimport * as fs from 'fs';\r\nimport * as path from 'path';\r\n\r\n/*\r\nJSONAccount format \r\n\r\n{\r\n \"team1\": {\r\n users: {\r\n \"user1\": {\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n },\r\n \"agents\": {\r\n \"agent1\": {\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n },\r\n \"settings\": {\r\n \"setting1\": \"value1\",\r\n \"setting2\": \"value2\"\r\n }\r\n }\r\n}\r\n\r\n*/\r\n\r\nexport type TJSONFileAccountSettings = {\r\n file: string;\r\n};\r\n\r\nexport class JSONFileAccount extends AccountConnector {\r\n public name = 'JSONFileAccount';\r\n private data: any = {};\r\n private file: string;\r\n\r\n constructor(protected _settings: TJSONFileAccountSettings) {\r\n super(_settings);\r\n this.file = _settings.file;\r\n this.loadData();\r\n }\r\n\r\n private loadData() {\r\n try {\r\n const fileContent = fs.readFileSync(this.file, 'utf-8');\r\n this.data = JSON.parse(fileContent);\r\n } catch (error) {\r\n console.error('Error loading JSON account data:', error);\r\n this.data = {};\r\n }\r\n }\r\n\r\n private saveData() {\r\n try {\r\n fs.writeFileSync(this.file, JSON.stringify(this.data, null, 2));\r\n } catch (error) {\r\n console.error('Error saving JSON account data:', error);\r\n }\r\n }\r\n\r\n public async isTeamMember(team: string, candidate: IAccessCandidate): Promise<boolean> {\r\n if (!this.data[team]) return false;\r\n\r\n if (candidate.role === TAccessRole.User) {\r\n return !!this.data[team].users?.[candidate.id];\r\n } else if (candidate.role === TAccessRole.Agent) {\r\n return !!this.data[team].agents?.[candidate.id];\r\n }\r\n\r\n return false;\r\n }\r\n\r\n public async getCandidateTeam(candidate: IAccessCandidate): Promise<string | undefined> {\r\n if (candidate.role === TAccessRole.Team) {\r\n return candidate.id;\r\n }\r\n\r\n // Search through all teams to find where the candidate belongs\r\n for (const [teamId, teamData] of Object.entries(this.data)) {\r\n const typedTeamData = teamData as { users?: Record<string, any>; agents?: Record<string, any> };\r\n if (candidate.role === TAccessRole.User && typedTeamData.users?.[candidate.id]) {\r\n return teamId;\r\n }\r\n if (candidate.role === TAccessRole.Agent && typedTeamData.agents?.[candidate.id]) {\r\n return teamId;\r\n }\r\n }\r\n\r\n return DEFAULT_TEAM_ID;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n throw new Error('getResourceACL Method not implemented.');\r\n }\r\n\r\n public async getAllTeamSettings(acRequest: AccessRequest, teamId: string): Promise<KeyValueObject[]> {\r\n if (!this.data[teamId]?.settings) return [];\r\n\r\n return Object.entries(this.data[teamId].settings).map(([key, value]) => ({\r\n key,\r\n value: value as string,\r\n }));\r\n }\r\n\r\n public async getAllUserSettings(acRequest: AccessRequest, accountId: string): Promise<KeyValueObject[]> {\r\n // Search through all teams to find user settings\r\n for (const teamData of Object.values(this.data)) {\r\n const typedTeamData = teamData as { users?: Record<string, { settings?: Record<string, any> }> };\r\n if (typedTeamData.users?.[accountId]?.settings) {\r\n return Object.entries(typedTeamData.users[accountId].settings).map(([key, value]) => ({\r\n key,\r\n value: value as string,\r\n }));\r\n }\r\n }\r\n return [];\r\n }\r\n\r\n public async getTeamSetting(acRequest: AccessRequest, teamId: string, settingKey: string): Promise<string> {\r\n return this.data[teamId]?.settings?.[settingKey] || '';\r\n }\r\n\r\n public async getUserSetting(acRequest: AccessRequest, accountId: string, settingKey: string): Promise<string> {\r\n // Search through all teams to find user setting\r\n for (const teamData of Object.values(this.data)) {\r\n const typedTeamData = teamData as { users?: Record<string, { settings?: Record<string, any> }> };\r\n if (typedTeamData.users?.[accountId]?.settings?.[settingKey]) {\r\n return typedTeamData.users[accountId].settings[settingKey];\r\n }\r\n }\r\n return '';\r\n }\r\n\r\n public async getAgentSetting(acRequest: AccessRequest, agentId: string, settingKey: string): Promise<string> {\r\n // Search through all teams to find agent setting\r\n for (const teamData of Object.values(this.data)) {\r\n const typedTeamData = teamData as { agents?: Record<string, { settings?: Record<string, any> }> };\r\n if (typedTeamData.agents?.[agentId]?.settings?.[settingKey]) {\r\n return typedTeamData.agents[agentId].settings[settingKey];\r\n }\r\n }\r\n return '';\r\n }\r\n}\r\n","//==[ SRE: LLM ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { DummyAccount } from './connectors/DummyAccount.class';\r\nimport { AWSAccount } from './connectors/AWSAccount.class';\r\nimport { JSONFileAccount } from './connectors/JSONFileAccount.class';\r\nexport class AccountService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Account, 'AWSAccount', AWSAccount);\r\n ConnectorService.register(TConnectorService.Account, 'DummyAccount', DummyAccount);\r\n ConnectorService.register(TConnectorService.Account, 'JSONFileAccount', JSONFileAccount);\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport config from '@sre/config';\r\nimport { escapeString, TemplateString } from '@sre/helpers/TemplateString.helper';\r\nimport { JSONContent, JSONContentHelper } from '@sre/helpers/JsonContent.helper';\r\n\r\nexport interface IAgentDataConnector {\r\n getAgentData(agentId: string, version?: string): Promise<any>;\r\n getAgentIdByDomain(domain: string): Promise<string>;\r\n getAgentSettings(agentId: string, version?: string): Promise<any>;\r\n listTeamAgents(teamId: string, deployedOnly?: boolean, includeData?: boolean): Promise<any[]>;\r\n getAgentConfig(agentId: string): { [key: string]: any };\r\n}\r\n\r\nconst openapiTemplate = JSON.stringify({\r\n openapi: '3.0.1',\r\n info: {\r\n title: '{{model_name}}',\r\n description: '{{model_description}}',\r\n version: '{{version}}',\r\n },\r\n servers: [\r\n {\r\n url: '{{server_url}}',\r\n },\r\n ],\r\n paths: {},\r\n components: {\r\n schemas: {},\r\n },\r\n});\r\n\r\nconst openapiEndpointTemplate = JSON.stringify({\r\n summary: '{{summary}}',\r\n operationId: '{{operationId}}',\r\n 'x-openai-isConsequential': false,\r\n requestBody: {\r\n required: true,\r\n content: {},\r\n },\r\n responses: {\r\n '200': {\r\n description: 'response',\r\n content: {\r\n 'text/plain': {\r\n schema: {\r\n type: 'string',\r\n },\r\n },\r\n },\r\n },\r\n },\r\n});\r\nexport abstract class AgentDataConnector extends Connector implements IAgentDataConnector {\r\n public name = 'AgentDataConnector';\r\n public abstract getAgentData(agentId: string, version?: string): Promise<any>;\r\n public abstract getAgentIdByDomain(domain: string): Promise<string>;\r\n public abstract getAgentSettings(agentId: string, version?: string): Promise<{ [key: string]: any }>;\r\n public abstract getAgentEmbodiments(agentId: string): Promise<any>;\r\n public abstract isDeployed(agentId: string): Promise<boolean>;\r\n public abstract listTeamAgents(teamId: string, deployedOnly?: boolean, includeData?: boolean): Promise<any[]>;\r\n public abstract getAgentConfig(agentId: string): { [key: string]: any };\r\n /**\r\n * Loads openAPI JSON for the agent\r\n * @param source this represents either the agentId or the agent data\r\n * @param domain\r\n * @param version\r\n * @param aiOnly\r\n * @returns\r\n */\r\n public async getOpenAPIJSON(source: string | Record<string, any>, server_url, version, aiOnly: boolean = false) {\r\n if (!source) {\r\n throw new Error('Agent not found');\r\n }\r\n\r\n const apiBasePath = version && version != 'latest' ? `/v${version}/api` : '/api';\r\n\r\n const agentData: any = typeof source === 'object' ? source : await this.getAgentData(source, version);\r\n const name = agentData.name;\r\n\r\n let description = aiOnly ? agentData.data.behavior : agentData.data.shortDescription;\r\n if (!description) description = agentData.data.description; //data.description is deprecated, we just use it as a fallback for now\r\n\r\n const _version = agentData.data.version || '1.0.0';\r\n\r\n const openAPITpl = TemplateString(openapiTemplate)\r\n .parse({\r\n model_name: escapeString(name),\r\n model_description: escapeString(description),\r\n server_url,\r\n version: _version,\r\n })\r\n .clean().result;\r\n const openAPIObj = JSON.parse(openAPITpl);\r\n\r\n const components = agentData.data.components.filter((component: any) => component.name === 'APIEndpoint');\r\n for (let component of components) {\r\n const ai_exposed = component.data.ai_exposed || typeof component.data.ai_exposed === 'undefined';\r\n if (aiOnly && !ai_exposed) continue;\r\n let method = (component.data.method || 'post').toLowerCase();\r\n let summary = aiOnly ? component.data.description || component.data.doc : component.data.doc || component.data.description;\r\n\r\n const openAPIEntry = JSONContent(\r\n TemplateString(openapiEndpointTemplate)\r\n .parse({\r\n summary: summary?.replace(/\"/g, '\\\\\"'),\r\n operationId: component?.data?.endpoint,\r\n })\r\n .clean().result,\r\n ).tryParse();\r\n\r\n if (typeof openAPIEntry !== 'object') {\r\n console.warn('Error on openAPIEntry: ', openAPIEntry);\r\n continue;\r\n }\r\n\r\n if (!openAPIObj.paths[apiBasePath + '/' + component.data.endpoint]) openAPIObj.paths[apiBasePath + '/' + component.data.endpoint] = {};\r\n //const componentsSchemas = openAPIObj.components.schemas;\r\n\r\n openAPIObj.paths[apiBasePath + '/' + component.data.endpoint][method] = openAPIEntry;\r\n\r\n if (component.inputs.length > 0) {\r\n if (method === 'get') {\r\n delete openAPIEntry.requestBody;\r\n\r\n openAPIEntry.parameters = [];\r\n\r\n for (let input of component.inputs) {\r\n const parameter: {\r\n name: string;\r\n in: string;\r\n description: string;\r\n required: boolean;\r\n schema: { type: string };\r\n style?: string;\r\n explode?: boolean;\r\n } = {\r\n name: input.name,\r\n in: 'query',\r\n description: input.description,\r\n required: !input.optional,\r\n schema: getOpenAPIInputSchema(input.type),\r\n };\r\n\r\n // for array and object types\r\n const { style, explode } = getOpenAPIParameterStyle(input.type);\r\n if (style) {\r\n parameter.style = style;\r\n parameter.explode = explode;\r\n }\r\n\r\n openAPIEntry.parameters.push(parameter);\r\n }\r\n } else {\r\n const requiredProps: any = [];\r\n\r\n const hasBinaryType = !aiOnly && component.inputs.some((input) => input.type.toLowerCase().trim() === 'binary');\r\n //if it's an AI format, we force application/json format, becauwe we want to receive binary data as a url\r\n const mimetype = hasBinaryType ? 'multipart/form-data' : 'application/json';\r\n openAPIEntry.requestBody.content[mimetype] = {};\r\n for (let input of component.inputs) {\r\n if (!input.optional) requiredProps.push(input.name);\r\n\r\n if (!openAPIEntry.requestBody.content[mimetype].schema)\r\n openAPIEntry.requestBody.content[mimetype].schema = { type: 'object' };\r\n\r\n const schema: any = openAPIEntry.requestBody.content[mimetype].schema || {\r\n type: 'object',\r\n };\r\n\r\n if (!schema.properties) schema.properties = {};\r\n schema.properties[input.name] = {\r\n ...getOpenAPIInputSchema(input.type),\r\n format: !aiOnly && input.type.toLowerCase().trim() === 'binary' ? 'binary' : undefined,\r\n description: input.description,\r\n default: input.defaultVal,\r\n };\r\n schema.required = requiredProps;\r\n\r\n if (!openAPIEntry.requestBody.content[mimetype].schema) openAPIEntry.requestBody.content['application/json'].schema = schema;\r\n }\r\n }\r\n } else {\r\n delete openAPIEntry.requestBody;\r\n }\r\n }\r\n\r\n return openAPIObj;\r\n }\r\n}\r\n\r\nfunction getOpenAPIInputSchema(input_type) {\r\n switch (input_type?.toLowerCase()) {\r\n case 'binary':\r\n case 'string':\r\n case 'any':\r\n return { type: 'string' };\r\n case 'number':\r\n case 'float':\r\n return { type: 'number' };\r\n case 'integer':\r\n return { type: 'integer' };\r\n case 'boolean':\r\n return { type: 'boolean' };\r\n case 'array':\r\n return { type: 'array', items: {} };\r\n case 'object':\r\n return { type: 'object', additionalProperties: {} };\r\n default:\r\n return { type: 'string' };\r\n }\r\n}\r\n\r\nfunction getOpenAPIParameterStyle(input_type) {\r\n switch (input_type.toLowerCase()) {\r\n case 'array':\r\n return {\r\n style: 'form',\r\n explode: false, // results in `ids=1,2,3`\r\n };\r\n case 'object':\r\n return {\r\n style: 'deepObject',\r\n explode: true, // results in `lat=value1&long=value2`\r\n };\r\n default:\r\n return { style: '', explode: false };\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { CLIConnector } from '@sre/IO/CLI.service/CLIConnector';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { AgentDataConnector } from '../AgentDataConnector';\r\n\r\ntype TArgs = { args: Record<string, any> };\r\nexport class CLIAgentDataConnector extends AgentDataConnector {\r\n public name: string = 'CLIAgentDataConnector';\r\n private argv;\r\n constructor(settings: TArgs) {\r\n super();\r\n this.argv = settings.args || process.argv;\r\n }\r\n\r\n public getAgentConfig(agentId: string): Partial<TArgs> {\r\n return {};\r\n }\r\n\r\n public async getAgentData(agentId: string, version?: string) {\r\n const cliConnector: CLIConnector = ConnectorService.getCLIConnector();\r\n\r\n const params: any = cliConnector.get('agent');\r\n\r\n //get current directory\r\n const __dirname = fs.realpathSync(process.cwd());\r\n const filePath = path.join(__dirname, params.agent);\r\n\r\n if (fs.existsSync(filePath)) {\r\n const data = fs.readFileSync(filePath, 'utf8');\r\n\r\n return { data: JSON.parse(data), version: version || '1.0' };\r\n }\r\n }\r\n\r\n public getAgentIdByDomain(domain: string): Promise<string> {\r\n return Promise.resolve('');\r\n }\r\n public async getAgentSettings(agentId: string, version?: string) {\r\n const cliConnector: CLIConnector = ConnectorService.getCLIConnector();\r\n\r\n const params: any = cliConnector.get('settings');\r\n let settings: any;\r\n\r\n if (typeof params.settings === 'string') {\r\n if (fs.existsSync(params.settings)) {\r\n settings = JSON.parse(fs.readFileSync(params.settings, 'utf8'));\r\n }\r\n } else {\r\n settings = params.settings;\r\n }\r\n return settings;\r\n }\r\n\r\n public async getAgentEmbodiments(agentId: string): Promise<any> {\r\n return [];\r\n }\r\n\r\n public async listTeamAgents(teamId: string, deployedOnly?: boolean): Promise<any[]> {\r\n console.warn(`listTeamAgents is not implemented for CLIAgentDataConnector`);\r\n return [];\r\n }\r\n public async isDeployed(agentId: string): Promise<boolean> {\r\n return true;\r\n }\r\n}\r\n","import fs from 'fs';\r\nimport path from 'path';\r\nimport { AgentDataConnector } from '../AgentDataConnector';\r\nimport { uid } from '@sre/utils/general.utils';\r\n\r\nexport type LocalAgentDataSettings = { devDir: string; prodDir: string };\r\n\r\n/**\r\n * This connector loads Agent data and settings from a provided directory, it then indexes the loaded agents and settings by agent IDs.\r\n * Agent data files should be in JSON format and contain an 'id' field with the agent ID and at least a 'components' field.\r\n * Settings files should be in JSON format and contain an 'id' field with the agent ID and the settings in a 'settings' field.\r\n * 'settings' field is a key-value object with the Agent settings.\r\n */\r\nexport class LocalAgentDataConnector extends AgentDataConnector {\r\n public name: string = 'LocalAgentDataConnector';\r\n private devDir;\r\n private prodDir;\r\n private agentsData = { dev: {}, prod: {} };\r\n private agentSettings = { dev: {}, prod: {} };\r\n\r\n constructor(settings: LocalAgentDataSettings) {\r\n super();\r\n this.devDir = settings.devDir;\r\n this.prodDir = settings.prodDir;\r\n }\r\n\r\n public getAgentConfig(agentId: string): Partial<LocalAgentDataSettings> {\r\n return {};\r\n }\r\n\r\n private indexDir(dir: string) {\r\n const agents = fs.readdirSync(dir);\r\n\r\n const agentsData = {};\r\n const agentSettings = {};\r\n for (const agent of agents) {\r\n if (!agent.endsWith('.smyth')) continue;\r\n\r\n const agentData = fs.readFileSync(path.join(dir, agent), 'utf8');\r\n let jsonData;\r\n try {\r\n jsonData = JSON.parse(agentData);\r\n\r\n if (!jsonData.components) {\r\n console.warn(`File ${agent} is not a valid agent data file, skipping...`);\r\n continue;\r\n }\r\n\r\n if (!jsonData.id) {\r\n console.warn(`Agent data for ${agent} does not contain an id, generating one...`);\r\n jsonData.id = 'tmp-' + uid();\r\n }\r\n } catch (e) {\r\n console.warn(`Error parsing agent data for ${agent}: ${e.message}`);\r\n }\r\n\r\n //is this an agent data file?\r\n if (jsonData.components) agentsData[jsonData.id] = jsonData;\r\n\r\n //does this file contain settings?\r\n if (jsonData.settings) agentSettings[jsonData.id] = jsonData.settings;\r\n }\r\n\r\n return { agentsData, agentSettings };\r\n }\r\n private indexAgentsData() {\r\n const { agentsData: devAgentsData, agentSettings: devAgentSettings } = this.indexDir(this.devDir);\r\n const { agentsData: prodAgentsData, agentSettings: prodAgentSettings } = this.indexDir(this.prodDir);\r\n this.agentsData = { dev: devAgentsData, prod: prodAgentsData };\r\n this.agentSettings = { dev: devAgentSettings, prod: prodAgentSettings };\r\n }\r\n\r\n public async start() {\r\n super.start();\r\n this.started = false;\r\n this.indexAgentsData();\r\n this.started = true;\r\n }\r\n\r\n /**\r\n * returns the agent data for the provided agent ID\r\n * if the version is not provided, it defaults to the dev version\r\n * otherwise it loads the corresponding prod version\r\n * @param agentId\r\n * @param version\r\n * @returns\r\n */\r\n public async getAgentData(agentId: string, version?: string) {\r\n const ready = await this.ready();\r\n if (!ready) {\r\n throw new Error('Connector not ready');\r\n }\r\n\r\n const data = version ? this.agentsData.prod[agentId] : this.agentsData.dev[agentId];\r\n\r\n if (data) {\r\n return { data, version: version || '1.0' };\r\n } else {\r\n throw new Error(`Agent with id ${agentId} not found`);\r\n }\r\n }\r\n\r\n public getAgentIdByDomain(domain: string): Promise<string> {\r\n return Promise.resolve('');\r\n }\r\n\r\n /**\r\n * returns the agent settings for the provided agent ID\r\n * if the version is not provided, it defaults to the dev version\r\n * otherwise it loads the corresponding prod version\r\n * @param agentId\r\n * @param version\r\n * @returns\r\n */\r\n public async getAgentSettings(agentId: string, version?: string) {\r\n const ready = await this.ready();\r\n if (!ready) {\r\n throw new Error('Connector not ready');\r\n }\r\n\r\n const settings = version ? this.agentSettings.prod[agentId] : this.agentSettings.dev[agentId];\r\n\r\n if (settings) {\r\n return settings;\r\n } else {\r\n throw new Error(`Settings for agent with id ${agentId} not found`);\r\n }\r\n }\r\n\r\n public async getAgentEmbodiments(agentId: string): Promise<any> {\r\n return [];\r\n }\r\n\r\n public async listTeamAgents(teamId: string, deployedOnly?: boolean): Promise<any[]> {\r\n console.warn(`listTeamAgents is not implemented for LocalAgentDataConnector`);\r\n return [];\r\n }\r\n\r\n public async isDeployed(agentId: string): Promise<boolean> {\r\n return !!this.agentsData.prod[agentId];\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { CLIConnector } from '@sre/IO/CLI.service/CLIConnector';\r\nimport fs from 'fs';\r\nimport path from 'path';\r\nimport { AgentDataConnector } from '../AgentDataConnector';\r\n\r\ntype TArgs = { args: Record<string, any> };\r\nexport class NullAgentData extends AgentDataConnector {\r\n public name: string = 'NullAgentData';\r\n constructor(settings: TArgs) {\r\n super();\r\n }\r\n\r\n public getAgentConfig(agentId: string): Partial<TArgs> {\r\n return {};\r\n }\r\n\r\n public async getAgentData(agentId: string, version?: string) {\r\n return { data: {}, version: '1.0' };\r\n }\r\n\r\n public getAgentIdByDomain(domain: string): Promise<string> {\r\n return Promise.resolve('');\r\n }\r\n public async getAgentSettings(agentId: string, version?: string) {\r\n return {};\r\n }\r\n\r\n public async getAgentEmbodiments(agentId: string): Promise<any> {\r\n return [];\r\n }\r\n\r\n public async listTeamAgents(teamId: string, deployedOnly?: boolean): Promise<any[]> {\r\n return [];\r\n }\r\n public async isDeployed(agentId: string): Promise<boolean> {\r\n return true;\r\n }\r\n}\r\n","//==[ SRE: LLM ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { CLIAgentDataConnector } from './connectors/CLIAgentDataConnector.class';\r\nimport { AgentDataConnector } from './AgentDataConnector';\r\nimport { LocalAgentDataConnector } from './connectors/LocalAgentDataConnector.class';\r\nimport { NullAgentData } from './connectors/NullAgentData.class';\r\nexport class AgentDataService extends ConnectorServiceProvider {\r\n public register() {\r\n //FIXME : register an actual account connector, not the abstract one\r\n ConnectorService.register(TConnectorService.AgentData, 'AgentData', AgentDataConnector);\r\n ConnectorService.register(TConnectorService.AgentData, 'CLI', CLIAgentDataConnector);\r\n ConnectorService.register(TConnectorService.AgentData, 'Local', LocalAgentDataConnector);\r\n\r\n ConnectorService.register(TConnectorService.AgentData, 'NullAgentData', NullAgentData);\r\n }\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessRole } from '@sre/types/ACL.types';\r\nimport { DatasourceDto, IStorageVectorDataSource, IVectorDataSourceDto, QueryOptions, VectorsResultData } from '@sre/types/VectorDB.types';\r\n\r\nexport type DeleteFilterOptions = {\r\n datasourceId?: string;\r\n};\r\n\r\nexport type DeleteTarget = string | string[] | DeleteFilterOptions;\r\n\r\nexport interface IVectorDBRequest {\r\n search(namespace: string, query: string | number[], options?: QueryOptions): Promise<VectorsResultData>;\r\n // insert(namespace: string, source: IVectorDataSourceDto | IVectorDataSourceDto[]): Promise<string[]>;\r\n // delete(namespace: string, id: string | string[]): Promise<void>;\r\n\r\n createDatasource(namespace: string, datasource: DatasourceDto): Promise<IStorageVectorDataSource>;\r\n deleteDatasource(namespace: string, datasourceId: string): Promise<void>;\r\n listDatasources(namespace: string): Promise<IStorageVectorDataSource[]>;\r\n getDatasource(namespace: string, datasourceId: string): Promise<IStorageVectorDataSource>;\r\n\r\n createNamespace(namespace: string, metadata?: { [key: string]: any }): Promise<void>;\r\n deleteNamespace(namespace: string): Promise<void>;\r\n namespaceExists(namespace: string): Promise<boolean>;\r\n}\r\n\r\nexport abstract class VectorDBConnector extends SecureConnector<IVectorDBRequest> {\r\n protected readonly USER_METADATA_KEY = 'user_metadata';\r\n\r\n public abstract id: string;\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n public requester(candidate: AccessCandidate): IVectorDBRequest {\r\n return {\r\n search: async (namespace: string, query: string | number[], options: QueryOptions) => {\r\n return await this.search(candidate.readRequest, namespace, query, options);\r\n },\r\n\r\n createDatasource: async (namespace: string, datasource: DatasourceDto) => {\r\n return await this.createDatasource(candidate.writeRequest, namespace, datasource);\r\n },\r\n deleteDatasource: async (namespace: string, datasourceId: string) => {\r\n await this.deleteDatasource(candidate.writeRequest, namespace, datasourceId);\r\n },\r\n listDatasources: async (namespace: string) => {\r\n return await this.listDatasources(candidate.readRequest, namespace);\r\n },\r\n getDatasource: async (namespace: string, datasourceId: string) => {\r\n return await this.getDatasource(candidate.readRequest, namespace, datasourceId);\r\n },\r\n\r\n createNamespace: async (namespace: string, metadata?: { [key: string]: any }) => {\r\n await this.createNamespace(candidate.writeRequest, namespace, metadata);\r\n },\r\n deleteNamespace: async (namespace: string) => {\r\n await this.deleteNamespace(candidate.writeRequest, namespace);\r\n },\r\n namespaceExists: async (namespace: string) => {\r\n return await this.namespaceExists(candidate.readRequest, namespace);\r\n },\r\n };\r\n }\r\n\r\n protected abstract search(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n query: string | number[],\r\n options: QueryOptions\r\n ): Promise<VectorsResultData>;\r\n\r\n protected abstract insert(acRequest: AccessRequest, namespace: string, source: IVectorDataSourceDto | IVectorDataSourceDto[]): Promise<string[]>;\r\n\r\n protected abstract delete(acRequest: AccessRequest, namespace: string, deleteTarget: DeleteTarget): Promise<void>;\r\n\r\n protected abstract createDatasource(acRequest: AccessRequest, namespace: string, datasource: DatasourceDto): Promise<IStorageVectorDataSource>;\r\n\r\n protected abstract deleteDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<void>;\r\n\r\n protected abstract listDatasources(acRequest: AccessRequest, namespace: string): Promise<IStorageVectorDataSource[]>;\r\n\r\n protected abstract getDatasource(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n datasourceId: string\r\n ): Promise<IStorageVectorDataSource | undefined>;\r\n\r\n protected abstract createNamespace(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n\r\n metadata?: { [key: string]: any }\r\n ): Promise<void>;\r\n\r\n protected abstract deleteNamespace(acRequest: AccessRequest, namespace: string): Promise<void>;\r\n\r\n protected abstract namespaceExists(acRequest: AccessRequest, namespace: string): Promise<boolean>;\r\n\r\n public constructNsName(candidate: AccessCandidate, name: string) {\r\n //normalise name\r\n const joinedName = name.trim().replace(/\\s/g, '_').toLowerCase();\r\n //add prefix = first letter of role + id\r\n let prefix = candidate.role[0] + '_' + candidate.id;\r\n\r\n return `${prefix}_${joinedName}`;\r\n }\r\n}\r\n","import { IVectorDataSourceDto, Source } from '@sre/types/VectorDB.types';\r\nimport { isUrl } from '@sre/utils/index';\r\nimport { SupportedProviders, SupportedModels } from './index';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nexport type TEmbeddings = {\r\n provider: SupportedProviders;\r\n model: SupportedModels[SupportedProviders];\r\n dimensions?: number;\r\n timeout?: number;\r\n chunkSize?: number;\r\n stripNewLines?: boolean;\r\n maxConcurrency?: number;\r\n credentials?: {\r\n apiKey: string;\r\n };\r\n};\r\n\r\ntype SupportedSources = 'text' | 'vector' | 'url';\r\n\r\nexport abstract class BaseEmbedding {\r\n model: string;\r\n modelName: string;\r\n chunkSize = 512;\r\n stripNewLines = true;\r\n dimensions?: number;\r\n timeout?: number;\r\n maxConcurrency?: number;\r\n\r\n constructor(fields?: Partial<TEmbeddings>) {\r\n this.model = fields?.model ?? this.model;\r\n this.chunkSize = fields?.chunkSize ?? this.chunkSize;\r\n this.stripNewLines = fields?.stripNewLines ?? this.stripNewLines;\r\n this.timeout = fields?.timeout;\r\n this.dimensions = fields?.dimensions;\r\n }\r\n\r\n /**\r\n * Embed multiple texts and return their vector representations\r\n */\r\n abstract embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]>;\r\n\r\n /**\r\n * Embed a single text and return its vector representation\r\n */\r\n abstract embedText(text: string, candidate: AccessCandidate): Promise<number[]>;\r\n\r\n /**\r\n * Utility method to chunk arrays into smaller batches\r\n */\r\n protected chunkArr<T>(arr: T[], sizePerChunk: number): T[][] {\r\n return arr.reduce((chunks, elem, index) => {\r\n const chunkIndex = Math.floor(index / sizePerChunk);\r\n const chunk = chunks[chunkIndex] || [];\r\n chunks[chunkIndex] = chunk.concat([elem]);\r\n return chunks;\r\n }, [] as T[][]);\r\n }\r\n\r\n /**\r\n * Utility method to process multiple texts based on stripNewLines setting\r\n */\r\n protected processTexts(texts: string[]): string[] {\r\n return this.stripNewLines ? texts.map((t) => t.replace(/\\n/g, ' ')) : texts;\r\n }\r\n\r\n public detectSourceType(source: Source): SupportedSources | 'unknown' {\r\n if (typeof source === 'string') {\r\n return isUrl(source) ? 'url' : 'text';\r\n } else if (Array.isArray(source) && source.every((v) => typeof v === 'number')) {\r\n return 'vector';\r\n } else {\r\n return 'unknown';\r\n }\r\n }\r\n\r\n public transformSource(source: IVectorDataSourceDto[], sourceType: SupportedSources, candidate: AccessCandidate) {\r\n //* as the accepted sources increases, you will need to implement the strategy pattern instead of a switch case\r\n switch (sourceType) {\r\n case 'text': {\r\n const texts = source.map((s) => s.source as string);\r\n\r\n return this.embedTexts(texts, candidate).then((vectors) => {\r\n return source.map((s, i) => ({\r\n ...s,\r\n source: vectors[i],\r\n metadata: { ...s.metadata, text: texts[i] },\r\n }));\r\n });\r\n }\r\n case 'vector': {\r\n return source;\r\n }\r\n }\r\n }\r\n\r\n // this is a dummy vector used to maximize search distance\r\n // we use it to create reserved vectors that store namespace data\r\n public get dummyVector(): number[] {\r\n //This is good for cosine similarity, but not for euclidean distance\r\n //TODO: detect current similarity metric and use the appropriate vector (e.g for euclidean distance, use a vector with all large values like [1e6, 1e6, ..., 1e6])\r\n return Array(this.dimensions - 1)\r\n .fill(0)\r\n .concat([1]);\r\n }\r\n}\r\n","import OpenAI, { type ClientOptions, OpenAI as OpenAIClient } from 'openai';\r\nimport { BaseEmbedding, TEmbeddings } from './BaseEmbedding';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { getLLMCredentials } from '@sre/LLMManager/LLM.service/LLMCredentials.helper';\r\nimport { TLLMCredentials, TLLMModel } from '@sre/types/LLM.types';\r\n\r\n// Helper function to create OpenAI API errors\r\nconst createOpenAIError = (statusCode: number, error: any) => {\r\n return new OpenAI.APIError(\r\n statusCode,\r\n {\r\n code: error?.errKey || error?.code,\r\n message: error?.message,\r\n type: error?.name,\r\n },\r\n error?.message,\r\n null\r\n );\r\n};\r\n\r\nconst DEFAULT_MODEL = 'text-embedding-ada-002';\r\n\r\nexport class OpenAIEmbeds extends BaseEmbedding {\r\n protected client: OpenAIClient;\r\n protected clientConfig: ClientOptions;\r\n\r\n public static models = ['text-embedding-ada-002', 'text-embedding-3-large'];\r\n public canSpecifyDimensions = true;\r\n\r\n constructor(private settings?: Partial<TEmbeddings>) {\r\n super({ maxConcurrency: 2, model: settings?.model ?? DEFAULT_MODEL, ...settings });\r\n\r\n this.clientConfig = {\r\n //apiKey: fields?.credentials?.apiKey || process.env.OPENAI_API_KEY || '',\r\n dangerouslyAllowBrowser: true,\r\n };\r\n\r\n if (this.model === 'text-embedding-ada-002') {\r\n this.canSpecifyDimensions = false; // special case for ada-002, it doesn't support dimensions passing\r\n }\r\n }\r\n\r\n async embedTexts(texts: string[], candidate: AccessCandidate): Promise<number[][]> {\r\n const batches = this.chunkArr(this.processTexts(texts), this.chunkSize);\r\n\r\n const batchRequests = batches.map((batch) => {\r\n const params: OpenAIClient.EmbeddingCreateParams = {\r\n model: this.model,\r\n input: batch,\r\n };\r\n if (this.dimensions && this.canSpecifyDimensions) {\r\n params.dimensions = this.dimensions;\r\n }\r\n return this.embed(params, candidate);\r\n });\r\n const batchResponses = await Promise.all(batchRequests);\r\n\r\n const embeddings: number[][] = [];\r\n for (let i = 0; i < batchResponses.length; i += 1) {\r\n const batch = batches[i];\r\n const { data: batchResponse } = batchResponses[i];\r\n for (let j = 0; j < batch.length; j += 1) {\r\n embeddings.push(batchResponse[j].embedding);\r\n }\r\n }\r\n return embeddings;\r\n }\r\n\r\n async embedText(text: string, candidate: AccessCandidate): Promise<number[]> {\r\n const params: OpenAIClient.EmbeddingCreateParams = {\r\n model: this.model,\r\n input: this.processTexts([text])[0],\r\n };\r\n if (this.dimensions && this.canSpecifyDimensions) {\r\n params.dimensions = this.dimensions;\r\n }\r\n const { data } = await this.embed(params, candidate);\r\n return data[0].embedding;\r\n }\r\n\r\n protected async embed(request: OpenAIClient.EmbeddingCreateParams, candidate: AccessCandidate) {\r\n const modelInfo: TLLMModel = {\r\n provider: 'OpenAI',\r\n modelId: this.model,\r\n credentials: this.settings?.credentials as unknown as TLLMCredentials,\r\n };\r\n const credentials = await getLLMCredentials(candidate, modelInfo);\r\n\r\n if (!this.client) {\r\n const params: ClientOptions = {\r\n ...this.clientConfig,\r\n apiKey: credentials.apiKey,\r\n timeout: this.timeout,\r\n maxRetries: 0,\r\n };\r\n\r\n this.client = new OpenAIClient(params);\r\n }\r\n try {\r\n const res = await this.client.embeddings.create(request);\r\n return res;\r\n } catch (e) {\r\n // const error = wrapOpenAIClientError(e);\r\n // import openapi error from openai and throw it\r\n const error = createOpenAIError(e.statusCode, e);\r\n throw error;\r\n }\r\n }\r\n}\r\n","import { OpenAIEmbeds } from './OpenAIEmbedding';\r\nimport { TEmbeddings } from './BaseEmbedding';\r\n\r\n// a factory to get the correct embedding provider based on the provider name\r\nconst supportedProviders = {\r\n OpenAI: {\r\n embedder: OpenAIEmbeds,\r\n models: OpenAIEmbeds.models,\r\n },\r\n} as const;\r\n\r\nexport type SupportedProviders = keyof typeof supportedProviders;\r\nexport type SupportedModels = {\r\n [K in SupportedProviders]: (typeof supportedProviders)[K]['models'][number];\r\n};\r\n\r\nexport class EmbeddingsFactory {\r\n public static create(provider: SupportedProviders, config: TEmbeddings) {\r\n return new supportedProviders[provider].embedder(config);\r\n }\r\n}\r\n","//==[ SRE: S3Storage ]======================\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { VectorDBConnector } from '../VectorDBConnector';\r\nimport {\r\n DatasourceDto,\r\n IStorageVectorDataSource,\r\n IStorageVectorNamespace,\r\n IVectorDataSourceDto,\r\n QueryOptions,\r\n VectorsResultData,\r\n} from '@sre/types/VectorDB.types';\r\nimport { Pinecone } from '@pinecone-database/pinecone';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { NKVConnector } from '@sre/IO/NKV.service/NKVConnector';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { JSONContentHelper } from '@sre/helpers/JsonContent.helper';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport crypto from 'crypto';\r\nimport { BaseEmbedding, TEmbeddings } from '../embed/BaseEmbedding';\r\nimport { EmbeddingsFactory, SupportedProviders, SupportedModels } from '../embed';\r\nimport { chunkText } from '@sre/utils/string.utils';\r\nimport { jsonrepair } from 'jsonrepair';\r\n\r\nconst console = Logger('Pinecone VectorDB');\r\n\r\nexport type PineconeConfig = {\r\n /**\r\n * The Pinecone API key\r\n */\r\n apiKey: string;\r\n /**\r\n * The Pinecone index name\r\n */\r\n indexName: string;\r\n /**\r\n * The embeddings model to use\r\n */\r\n embeddings: TEmbeddings;\r\n};\r\nexport class PineconeVectorDB extends VectorDBConnector {\r\n public name = 'PineconeVectorDB';\r\n public id = 'pinecone';\r\n private client: Pinecone;\r\n private indexName: string;\r\n private cache: CacheConnector;\r\n private accountConnector: AccountConnector;\r\n private nkvConnector: NKVConnector;\r\n public embedder: BaseEmbedding;\r\n\r\n constructor(protected _settings: PineconeConfig) {\r\n super(_settings);\r\n if (!_settings.apiKey) {\r\n console.warn('Missing Pinecone API key : returning empty Pinecone connector');\r\n return;\r\n }\r\n if (!_settings.indexName) {\r\n console.warn('Missing Pinecone index name : returning empty Pinecone connector');\r\n return;\r\n }\r\n\r\n this.client = new Pinecone({\r\n apiKey: _settings.apiKey,\r\n });\r\n console.info('Pinecone client initialized');\r\n console.info('Pinecone index name:', _settings.indexName);\r\n this.indexName = _settings.indexName;\r\n this.accountConnector = ConnectorService.getAccountConnector();\r\n this.cache = ConnectorService.getCacheConnector();\r\n this.nkvConnector = ConnectorService.getNKVConnector();\r\n if (!_settings.embeddings.dimensions) _settings.embeddings.dimensions = 1024;\r\n\r\n this.embedder = EmbeddingsFactory.create(_settings.embeddings.provider, _settings.embeddings);\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(AccessCandidate.clone(candidate));\r\n const preparedNs = this.constructNsName(candidate as AccessCandidate, resourceId);\r\n const acl = await this.getACL(AccessCandidate.clone(candidate), preparedNs);\r\n const exists = !!acl;\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(acl);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createNamespace(acRequest: AccessRequest, namespace: string, metadata?: { [key: string]: any }): Promise<void> {\r\n //* Since Pinecone does not create explicit namespaces,\r\n //* we create a zero or dummy vector in the namespace to trigger the namespace creation and filter it out\r\n\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner);\r\n\r\n const nsData = {\r\n acl: acl.serializedACL,\r\n displayName: namespace,\r\n ...metadata,\r\n };\r\n await this.client\r\n .Index(this.indexName)\r\n .namespace(preparedNs)\r\n .upsert([\r\n {\r\n id: `_reserved_${preparedNs}`,\r\n values: this.embedder.dummyVector,\r\n metadata: {\r\n isSkeletonVector: true,\r\n ...nsData,\r\n },\r\n },\r\n ]);\r\n\r\n await this.setACL(acRequest, preparedNs, acl.ACL);\r\n\r\n return new Promise<void>((resolve) => resolve());\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async namespaceExists(acRequest: AccessRequest, namespace: string): Promise<boolean> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const stats = await this.client.Index(this.indexName).describeIndexStats();\r\n return Object.keys(stats.namespaces).includes(this.constructNsName(acRequest.candidate as AccessCandidate, namespace));\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteNamespace(acRequest: AccessRequest, namespace: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n //const candidate = AccessCandidate.team(teamId);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n await this.client\r\n .Index(this.indexName)\r\n .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))\r\n .deleteAll()\r\n .catch((e) => {\r\n if (e?.name == 'PineconeNotFoundError') {\r\n console.warn(`Namespace ${namespace} does not exist and was requested to be deleted`);\r\n return;\r\n }\r\n throw e;\r\n });\r\n\r\n await this.deleteACL(AccessCandidate.clone(acRequest.candidate), namespace);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async search(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n query: string | number[],\r\n options: QueryOptions = {}\r\n ): Promise<VectorsResultData> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n const pineconeIndex = this.client.Index(this.indexName).namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace));\r\n let _vector = query;\r\n if (typeof query === 'string') {\r\n _vector = await this.embedder.embedText(query, acRequest.candidate as AccessCandidate);\r\n }\r\n\r\n const topK = (options.topK || 10) + 1; //* we increment one in case it included the skeleton vector\r\n\r\n const results = await pineconeIndex.query({\r\n topK,\r\n vector: _vector as number[],\r\n includeMetadata: true,\r\n includeValues: true,\r\n });\r\n\r\n let matches: VectorsResultData = [];\r\n\r\n for (const match of results.matches) {\r\n if (match.metadata?.isSkeletonVector) continue;\r\n\r\n if (match.metadata?.user) {\r\n match.metadata.user = JSONContentHelper.create(match.metadata.user.toString()).tryParse();\r\n }\r\n matches.push({\r\n id: match.id,\r\n values: match.values,\r\n metadata: match.metadata,\r\n });\r\n }\r\n\r\n // in the case where we did not filter out the skeleton vector, we need to remove the extra match from the results\r\n return matches.slice(0, options.topK);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async insert(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n sourceWrapper: IVectorDataSourceDto | IVectorDataSourceDto[]\r\n ): Promise<string[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n sourceWrapper = Array.isArray(sourceWrapper) ? sourceWrapper : [sourceWrapper];\r\n\r\n // make sure that all sources are of the same type (source.source)\r\n if (sourceWrapper.some((s) => this.embedder.detectSourceType(s.source) !== this.embedder.detectSourceType(sourceWrapper[0].source))) {\r\n throw new Error('All sources must be of the same type');\r\n }\r\n\r\n const sourceType = this.embedder.detectSourceType(sourceWrapper[0].source);\r\n if (sourceType === 'unknown' || sourceType === 'url') throw new Error('Invalid source type');\r\n const transformedSource = await this.embedder.transformSource(sourceWrapper, sourceType, acRequest.candidate as AccessCandidate);\r\n const preparedSource = transformedSource.map((s) => ({\r\n id: s.id,\r\n values: s.source as number[],\r\n metadata: s.metadata,\r\n }));\r\n\r\n // await pineconeStore.addDocuments(chunks, ids);\r\n await this.client\r\n .Index(this.indexName)\r\n .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))\r\n .upsert(preparedSource);\r\n\r\n const accessCandidate = acRequest.candidate;\r\n\r\n const isNewNs = !(await this.requester(AccessCandidate.clone(accessCandidate)).namespaceExists(namespace));\r\n if (isNewNs) {\r\n let acl = new ACL().addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;\r\n await this.setACL(acRequest, namespace, acl);\r\n }\r\n\r\n return preparedSource.map((s) => s.id);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async delete(acRequest: AccessRequest, namespace: string, id: string | string[]): Promise<void> {\r\n const _ids = Array.isArray(id) ? id : [id];\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n const res = await this.client\r\n .Index(this.indexName)\r\n .namespace(this.constructNsName(acRequest.candidate as AccessCandidate, namespace))\r\n .deleteMany(_ids);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createDatasource(acRequest: AccessRequest, namespace: string, datasource: DatasourceDto): Promise<IStorageVectorDataSource> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner);\r\n const dsId = datasource.id || crypto.randomUUID();\r\n\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n const chunkedText = chunkText(datasource.text, {\r\n chunkSize: datasource.chunkSize,\r\n chunkOverlap: datasource.chunkOverlap,\r\n });\r\n const ids = Array.from({ length: chunkedText.length }, (_, i) => `${dsId}_${crypto.randomUUID()}`);\r\n const source: IVectorDataSourceDto[] = chunkedText.map((doc, i) => {\r\n return {\r\n id: ids[i],\r\n source: doc,\r\n metadata: {\r\n acl: acl.serializedACL,\r\n namespaceId: formattedNs,\r\n datasourceId: dsId,\r\n user: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : undefined,\r\n },\r\n };\r\n });\r\n\r\n const _vIds = await this.insert(acRequest, namespace, source);\r\n\r\n const dsData: IStorageVectorDataSource = {\r\n namespaceId: formattedNs,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n name: datasource.label || 'Untitled',\r\n metadata: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : undefined,\r\n text: datasource.text,\r\n vectorIds: _vIds,\r\n id: dsId,\r\n };\r\n // const url = `smythfs://${teamId}.team/_datasources/${dsId}.json`;\r\n // await SmythFS.Instance.write(url, JSON.stringify(dsData), AccessCandidate.team(teamId));\r\n await this.nkvConnector\r\n .requester(acRequest.candidate as AccessCandidate)\r\n .set(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, dsId, JSON.stringify(dsData));\r\n // return { id: dsId, vectorIds: _vIds };\r\n return dsData;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n // const url = `smythfs://${teamId}.team/_datasources/${dsId}.json`;\r\n // await SmythFS.Instance.delete(url, AccessCandidate.team(teamId));\r\n let ds: IStorageVectorDataSource = JSONContentHelper.create(\r\n (\r\n await this.nkvConnector\r\n .requester(acRequest.candidate as AccessCandidate)\r\n .get(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, datasourceId)\r\n )?.toString()\r\n ).tryParse();\r\n\r\n if (!ds || typeof ds !== 'object') {\r\n throw new Error(`Data source not found with id: ${datasourceId}`);\r\n }\r\n\r\n await this.delete(acRequest, namespace, ds.vectorIds || []);\r\n\r\n await this.nkvConnector\r\n .requester(acRequest.candidate as AccessCandidate)\r\n .delete(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, datasourceId);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listDatasources(acRequest: AccessRequest, namespace: string): Promise<IStorageVectorDataSource[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n return (\r\n await this.nkvConnector\r\n .requester(acRequest.candidate as AccessCandidate)\r\n .list(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`)\r\n ).map((ds) => {\r\n return JSONContentHelper.create(ds.data?.toString()).tryParse() as IStorageVectorDataSource;\r\n });\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async getDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<IStorageVectorDataSource> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n return JSONContentHelper.create(\r\n (\r\n await this.nkvConnector\r\n .requester(acRequest.candidate as AccessCandidate)\r\n .get(`vectorDB:${this.id}:namespaces:${formattedNs}:datasources`, datasourceId)\r\n )?.toString()\r\n ).tryParse() as IStorageVectorDataSource;\r\n }\r\n\r\n private async setACL(acRequest: AccessRequest, preparedNs: string, acl: IACL): Promise<void> {\r\n await this.cache\r\n .requester(AccessCandidate.clone(acRequest.candidate))\r\n .set(`vectorDB:pinecone:namespace:${preparedNs}:acl`, JSON.stringify(acl));\r\n }\r\n\r\n private async getACL(ac: AccessCandidate, preparedNs: string): Promise<ACL | null | undefined> {\r\n let aclRes = await this.cache.requester(ac).get(`vectorDB:pinecone:namespace:${preparedNs}:acl`);\r\n const acl = JSONContentHelper.create(aclRes?.toString?.()).tryParse();\r\n return acl;\r\n }\r\n\r\n private async deleteACL(ac: AccessCandidate, preparedNs: string): Promise<void> {\r\n this.cache.requester(AccessCandidate.clone(ac)).delete(`vectorDB:pinecone:namespace:${preparedNs}:acl`);\r\n }\r\n\r\n public constructNsName(candidate: AccessCandidate, name: string) {\r\n const joinedName = name.trim().replace(/\\s/g, '_').toLowerCase();\r\n let prefix = candidate.id;\r\n\r\n if (candidate.role !== TAccessRole.Team) {\r\n //DO NOT add role prefix for teams to preserve backward compatibility\r\n prefix = candidate.role[0] + '_' + candidate.id;\r\n }\r\n\r\n return `${prefix}_${joinedName}`;\r\n }\r\n}\r\n","//==[ SRE: S3Storage ]======================\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { DeleteTarget, VectorDBConnector } from '../VectorDBConnector';\r\nimport { DatasourceDto, IStorageVectorDataSource, IVectorDataSourceDto, QueryOptions, VectorsResultData } from '@sre/types/VectorDB.types';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { JSONContentHelper } from '@sre/helpers/JsonContent.helper';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport crypto from 'crypto';\r\nimport { BaseEmbedding, TEmbeddings } from '../embed/BaseEmbedding';\r\nimport { EmbeddingsFactory, SupportedProviders, SupportedModels } from '../embed';\r\nimport { chunkText } from '@sre/utils/string.utils';\r\nimport { jsonrepair } from 'jsonrepair';\r\nimport { CreateIndexSimpleReq, DataType, ErrorCode, FieldType, MilvusClient } from '@zilliz/milvus2-sdk-node';\r\n\r\nconst console = Logger('Milvus');\r\n\r\nexport type IMilvusCredentials = { address: string; token: string } | { address: string; user: string; password: string; token?: string };\r\ntype IndexParams = Omit<CreateIndexSimpleReq, 'collection_name'>[] | Omit<CreateIndexSimpleReq, 'collection_name'>;\r\n\r\nexport type MilvusConfig = {\r\n credentials: IMilvusCredentials;\r\n embeddings: TEmbeddings;\r\n};\r\n\r\n// Define schema field names as a type for strong typing\r\ntype SchemaFieldNames = 'id' | 'text' | 'namespaceId' | 'datasourceId' | 'datasourceLabel' | 'vector' | 'acl' | 'user_metadata';\r\n\r\ntype SchemaField = FieldType & { name: SchemaFieldNames };\r\n\r\nexport class MilvusVectorDB extends VectorDBConnector {\r\n public name = 'MilvusVectorDB';\r\n public id = 'milvus';\r\n private client: MilvusClient;\r\n private cache: CacheConnector;\r\n private accountConnector: AccountConnector;\r\n public embedder: BaseEmbedding;\r\n private SCHEMA_DEFINITION: SchemaField[];\r\n private INDEX_PARAMS: IndexParams;\r\n\r\n constructor(protected _settings: MilvusConfig) {\r\n super(_settings);\r\n\r\n // Create client config based on credential type\r\n const clientConfig = {\r\n address: _settings.credentials.address,\r\n token: 'token' in _settings.credentials ? _settings.credentials.token : undefined,\r\n user: 'user' in _settings.credentials ? _settings.credentials.user : undefined,\r\n password: 'password' in _settings.credentials ? _settings.credentials.password : undefined,\r\n };\r\n\r\n console.log('clientConfig', clientConfig);\r\n\r\n this.client = new MilvusClient(clientConfig);\r\n console.info('Milvus client initialized');\r\n this.accountConnector = ConnectorService.getAccountConnector();\r\n this.cache = ConnectorService.getCacheConnector();\r\n if (!_settings.embeddings.dimensions) _settings.embeddings.dimensions = 1024;\r\n\r\n this.embedder = EmbeddingsFactory.create(_settings.embeddings.provider, _settings.embeddings);\r\n\r\n // Explicitly type the schema definition array\r\n this.SCHEMA_DEFINITION = [\r\n {\r\n name: 'id',\r\n data_type: DataType.VarChar,\r\n is_primary_key: true,\r\n max_length: 2048,\r\n },\r\n {\r\n name: 'text',\r\n data_type: DataType.VarChar,\r\n max_length: 65535, // max that milvus supports\r\n },\r\n {\r\n name: this.USER_METADATA_KEY, // user defined metadata\r\n data_type: DataType.VarChar,\r\n max_length: 65535,\r\n },\r\n {\r\n name: 'namespaceId',\r\n data_type: DataType.VarChar,\r\n max_length: 2048,\r\n },\r\n {\r\n name: 'datasourceId',\r\n data_type: DataType.VarChar,\r\n max_length: 2048,\r\n },\r\n {\r\n name: 'datasourceLabel',\r\n data_type: DataType.VarChar,\r\n max_length: 2048,\r\n },\r\n {\r\n name: 'vector',\r\n data_type: DataType.FloatVector,\r\n dim: this.embedder.dimensions, //* vector dimension\r\n },\r\n {\r\n name: 'acl',\r\n data_type: DataType.VarChar,\r\n max_length: 2048,\r\n },\r\n ];\r\n this.INDEX_PARAMS = {\r\n index_type: 'AUTOINDEX',\r\n metric_type: 'COSINE', //TODO: make it configurable\r\n field_name: 'vector',\r\n };\r\n // this.options = _settings.options;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createNamespace(acRequest: AccessRequest, namespace: string, metadata?: { [key: string]: any }): Promise<void> {\r\n //* Since Pinecone does not create explicit namespaces,\r\n //* we create a zero or dummy vector in the namespace to trigger the namespace creation and filter it out\r\n\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const res = await this.client.createCollection({\r\n collection_name: preparedNs,\r\n schema: this.SCHEMA_DEFINITION,\r\n index_params: this.INDEX_PARAMS,\r\n });\r\n\r\n // await this.client.createIndex({\r\n // collection_name: preparedNs,\r\n // field_name: 'datasourceId',\r\n // index_name: 'idx_datasourceId',\r\n // index_type: 'STL_SORT',\r\n // });\r\n\r\n const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n await this.setACL(acRequest, preparedNs, acl);\r\n\r\n return new Promise<void>((resolve) => resolve());\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async namespaceExists(acRequest: AccessRequest, namespace: string): Promise<boolean> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const res = await this.client.hasCollection({\r\n collection_name: this.constructNsName(acRequest.candidate as AccessCandidate, namespace),\r\n });\r\n\r\n if (res.status.error_code !== ErrorCode.SUCCESS) {\r\n throw new Error(`Error checking collection: ${res}`);\r\n }\r\n\r\n return Boolean(res.value);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteNamespace(acRequest: AccessRequest, namespace: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const res = await this.client.dropCollection({\r\n collection_name: preparedNs,\r\n });\r\n\r\n if (res.error_code !== ErrorCode.SUCCESS) {\r\n throw new Error(`Error dropping collection: ${res}`);\r\n }\r\n\r\n await this.deleteACL(AccessCandidate.clone(acRequest.candidate), namespace);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async search(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n query: string | number[],\r\n options: QueryOptions = {}\r\n ): Promise<VectorsResultData> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n let _vector = query;\r\n if (typeof query === 'string') {\r\n _vector = await this.embedder.embedText(query, acRequest.candidate as AccessCandidate);\r\n }\r\n\r\n const result = await this.client.search({\r\n vector: _vector as number[],\r\n collection_name: preparedNs,\r\n output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],\r\n limit: options.topK || 10,\r\n });\r\n\r\n return result.results.map((match) => {\r\n let _record = match;\r\n if (match?.[this.USER_METADATA_KEY]) {\r\n _record[this.USER_METADATA_KEY] = JSONContentHelper.create(match[this.USER_METADATA_KEY].toString()).tryParse();\r\n }\r\n return {\r\n id: _record.id,\r\n values: _record.vector,\r\n text: _record.text,\r\n metadata: _record[this.USER_METADATA_KEY] ?? {},\r\n score: _record.score,\r\n };\r\n });\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async insert(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n sourceWrapper: IVectorDataSourceDto | IVectorDataSourceDto[]\r\n ): Promise<string[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n sourceWrapper = Array.isArray(sourceWrapper) ? sourceWrapper : [sourceWrapper];\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n // make sure that all sources are of the same type (source.source)\r\n if (sourceWrapper.some((s) => this.embedder.detectSourceType(s.source) !== this.embedder.detectSourceType(sourceWrapper[0].source))) {\r\n throw new Error('All sources must be of the same type');\r\n }\r\n\r\n const sourceType = this.embedder.detectSourceType(sourceWrapper[0].source);\r\n if (sourceType === 'unknown' || sourceType === 'url') throw new Error('Unsupported source type');\r\n const transformedSource = await this.embedder.transformSource(sourceWrapper, sourceType, acRequest.candidate as AccessCandidate);\r\n const preparedSource: Record<SchemaFieldNames, any>[] = transformedSource.map((s) => ({\r\n id: s.id,\r\n text: s.metadata?.text,\r\n user_metadata: s.metadata?.[this.USER_METADATA_KEY],\r\n namespaceId: preparedNs,\r\n datasourceId: s.metadata?.datasourceId,\r\n datasourceLabel: s.metadata?.datasourceLabel,\r\n vector: s.source,\r\n acl: s.metadata?.acl,\r\n }));\r\n\r\n const res = await this.client.insert({\r\n collection_name: preparedNs,\r\n data: preparedSource,\r\n });\r\n if (res.status.error_code !== ErrorCode.SUCCESS) {\r\n console.error('Error inserting data: ', res);\r\n throw new Error(`Error inserting data: ${res?.status?.error_code}`);\r\n }\r\n\r\n return preparedSource.map((s) => s.id);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async delete(acRequest: AccessRequest, namespace: string, deleteTarget: DeleteTarget): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const isDeleteByFilter = typeof deleteTarget === 'object';\r\n if (isDeleteByFilter) {\r\n const supportedFields: SchemaFieldNames[] = ['datasourceId'];\r\n if (!supportedFields.some((field) => field in deleteTarget)) {\r\n throw new Error(`Unsupported field in delete target: ${Object.keys(deleteTarget).join(', ')}`);\r\n }\r\n // use boolean expression to delete the data\r\n const res = await this.client.deleteEntities({\r\n collection_name: preparedNs,\r\n expr: `datasourceId == \"${(deleteTarget as any).datasourceId}\"`,\r\n });\r\n if (res.status.error_code !== ErrorCode.SUCCESS) {\r\n throw new Error(`Error deleting data: ${res}`);\r\n }\r\n } else {\r\n const _ids = Array.isArray(deleteTarget) ? deleteTarget : [deleteTarget];\r\n\r\n const res = await this.client.delete({\r\n collection_name: preparedNs,\r\n ids: _ids as string[],\r\n });\r\n if (res.status.error_code !== ErrorCode.SUCCESS) {\r\n throw new Error(`Error deleting data: ${res}`);\r\n }\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createDatasource(acRequest: AccessRequest, namespace: string, datasource: DatasourceDto): Promise<IStorageVectorDataSource> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner);\r\n const dsId = datasource.id || crypto.randomUUID();\r\n\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n const chunkedText = chunkText(datasource.text, {\r\n chunkSize: datasource.chunkSize,\r\n chunkOverlap: datasource.chunkOverlap,\r\n });\r\n const ids = Array.from({ length: chunkedText.length }, (_, i) => crypto.randomUUID());\r\n const label = datasource.label || 'Untitled';\r\n const source: IVectorDataSourceDto[] = chunkedText.map<IVectorDataSourceDto>((doc, i) => {\r\n return {\r\n id: ids[i],\r\n source: doc,\r\n metadata: {\r\n acl: acl.serializedACL,\r\n namespaceId: formattedNs,\r\n datasourceId: dsId,\r\n datasourceLabel: label,\r\n user_metadata: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : JSON.stringify({}),\r\n },\r\n };\r\n });\r\n\r\n const _vIds = await this.insert(acRequest, namespace, source);\r\n\r\n return {\r\n namespaceId: formattedNs,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n name: label,\r\n metadata: datasource.metadata ? jsonrepair(JSON.stringify(datasource.metadata)) : undefined,\r\n text: datasource.text,\r\n vectorIds: _vIds,\r\n id: dsId,\r\n };\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n await this.delete(acRequest, namespace, { datasourceId });\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listDatasources(acRequest: AccessRequest, namespace: string): Promise<IStorageVectorDataSource[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n // Use queryIterator for memory-efficient pagination\r\n const batchSize = 1000; // Process 1000 records at a time\r\n const iterator = await this.client.queryIterator({\r\n collection_name: formattedNs,\r\n batchSize: batchSize,\r\n output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],\r\n });\r\n\r\n // Group records by datasourceId using Map for efficient lookups\r\n const datasourceMap = new Map<string, IStorageVectorDataSource>();\r\n\r\n try {\r\n // Iterate through all pages\r\n for await (const batch of iterator) {\r\n for (const record of batch) {\r\n const datasourceId = record.datasourceId;\r\n if (!datasourceMap.has(datasourceId)) {\r\n datasourceMap.set(datasourceId, {\r\n namespaceId: formattedNs,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n text: record.text,\r\n name: record.datasourceLabel,\r\n metadata: record[this.USER_METADATA_KEY]\r\n ? JSONContentHelper.create(record[this.USER_METADATA_KEY].toString()).tryParse()\r\n : undefined,\r\n vectorIds: [],\r\n id: datasourceId,\r\n });\r\n }\r\n datasourceMap.get(datasourceId)!.vectorIds.push(record.id);\r\n }\r\n }\r\n } finally {\r\n // Always close the iterator to free resources\r\n }\r\n\r\n return Array.from(datasourceMap.values());\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async getDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<IStorageVectorDataSource | undefined> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const formattedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n const res = await this.client.query({\r\n collection_name: formattedNs,\r\n expr: `datasourceId == \"${datasourceId}\"`,\r\n output_fields: ['id', 'text', this.USER_METADATA_KEY, 'namespaceId', 'datasourceId', 'datasourceLabel', 'vector'],\r\n });\r\n // if 0 results, throw error\r\n if (res.data.length === 0) {\r\n return undefined;\r\n }\r\n\r\n const referenceRecord = res.data[0] as Record<SchemaFieldNames, any>;\r\n const allIds = res.data.map((d) => d.id);\r\n\r\n return {\r\n namespaceId: formattedNs,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n text: referenceRecord.text,\r\n name: referenceRecord.datasourceLabel,\r\n metadata: referenceRecord[this.USER_METADATA_KEY]\r\n ? JSONContentHelper.create(referenceRecord[this.USER_METADATA_KEY].toString()).tryParse()\r\n : undefined,\r\n vectorIds: allIds,\r\n id: datasourceId,\r\n };\r\n }\r\n\r\n private async setACL(acRequest: AccessRequest, preparedNs: string, acl: IACL): Promise<void> {\r\n await this.cache\r\n .requester(AccessCandidate.clone(acRequest.candidate))\r\n .set(`vectorDB:pinecone:namespace:${preparedNs}:acl`, JSON.stringify(acl));\r\n }\r\n\r\n private async getACL(ac: AccessCandidate, preparedNs: string): Promise<ACL | null | undefined> {\r\n let aclRes = await this.cache.requester(ac).get(`vectorDB:pinecone:namespace:${preparedNs}:acl`);\r\n const acl = JSONContentHelper.create(aclRes?.toString?.()).tryParse();\r\n return acl;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(AccessCandidate.clone(candidate));\r\n const preparedNs = this.constructNsName(candidate as AccessCandidate, resourceId);\r\n const acl = await this.getACL(AccessCandidate.clone(candidate), preparedNs);\r\n const exists = !!acl;\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(acl);\r\n }\r\n\r\n private async deleteACL(ac: AccessCandidate, preparedNs: string): Promise<void> {\r\n this.cache.requester(AccessCandidate.clone(ac)).delete(`vectorDB:pinecone:namespace:${preparedNs}:acl`);\r\n }\r\n\r\n public constructNsName(candidate: AccessCandidate, name: string) {\r\n // MILVUS does not accept special chars like - @ etc. so we need to ensure teamid is\r\n // valid; for this, instead of using teamId, we use a hash of the teamId and take\r\n const joinedName = name.trim().replace(/\\s/g, '_').toLowerCase();\r\n let prefix = candidate.role[0] + '_' + candidate.id;\r\n // we also append a 'c' to the hash as milvus requires the coll name to start with a letter\r\n const hashTeamId = 'c' + crypto.createHash('sha256').update(prefix).digest('hex').slice(0, 8);\r\n return `${hashTeamId}_${joinedName}`;\r\n }\r\n}\r\n","//==[ SRE: RAMVectorDB ]======================\r\n\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { VectorDBConnector } from '../VectorDBConnector';\r\nimport {\r\n DatasourceDto,\r\n IStorageVectorDataSource,\r\n IStorageVectorNamespace,\r\n IVectorDataSourceDto,\r\n QueryOptions,\r\n VectorsResultData,\r\n} from '@sre/types/VectorDB.types';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport { OpenAIEmbeds } from '@sre/IO/VectorDB.service/embed/OpenAIEmbedding';\r\nimport crypto from 'crypto';\r\nimport { BaseEmbedding, TEmbeddings } from '../embed/BaseEmbedding';\r\nimport { EmbeddingsFactory } from '../embed';\r\n\r\nconst console = Logger('RAM VectorDB');\r\n\r\ninterface VectorData {\r\n id: string;\r\n values: number[];\r\n datasource: string;\r\n metadata?: { [key: string]: any };\r\n}\r\n\r\nexport type RAMVectorDBConfig = {\r\n embeddings: TEmbeddings;\r\n};\r\n\r\n/**\r\n * RAM Vector Database - stores everything in memory\r\n * Data structure:\r\n * - vectors: namespace -> VectorData[]\r\n * - namespaces: namespace -> IStorageVectorNamespace\r\n * - datasources: namespace -> datasourceId -> IStorageVectorDataSource\r\n * - acls: resourceId -> IACL\r\n */\r\n\r\nexport class RAMVectorDB extends VectorDBConnector {\r\n public name = 'RAMVec';\r\n public id = 'ram';\r\n //private openaiApiKey: string;\r\n private accountConnector: AccountConnector;\r\n //private embeddingsProvider: OpenAIEmbeds;\r\n\r\n // In-memory storage\r\n private vectors: Record<string, VectorData[]> = {};\r\n private namespaces: Record<string, IStorageVectorNamespace> = {};\r\n private datasources: Record<string, Record<string, IStorageVectorDataSource>> = {};\r\n private acls: Record<string, IACL> = {};\r\n public embedder: BaseEmbedding;\r\n\r\n constructor(protected _settings: RAMVectorDBConfig) {\r\n super(_settings);\r\n\r\n this.accountConnector = ConnectorService.getAccountConnector();\r\n\r\n if (!_settings.embeddings) {\r\n _settings.embeddings = { provider: 'OpenAI', model: 'text-embedding-3-large' };\r\n }\r\n if (!_settings.embeddings.dimensions) _settings.embeddings.dimensions = 1024;\r\n\r\n this.embedder = EmbeddingsFactory.create(_settings.embeddings.provider, _settings.embeddings);\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(AccessCandidate.clone(candidate));\r\n const preparedNs = this.constructNsName(candidate as AccessCandidate, resourceId);\r\n const acl = this.acls[preparedNs];\r\n const exists = !!acl;\r\n\r\n if (!exists) {\r\n //the resource does not exist yet, we grant write access to the candidate in order to allow the resource creation\r\n return new ACL().addAccess(candidate.role, candidate.id, TAccessLevel.Owner);\r\n }\r\n return ACL.from(acl);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createNamespace(acRequest: AccessRequest, namespace: string, metadata?: { [key: string]: any }): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n if (!this.namespaces[preparedNs]) {\r\n const nsData: IStorageVectorNamespace = {\r\n namespace: preparedNs,\r\n displayName: namespace,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n metadata: {\r\n ...metadata,\r\n storageType: 'RAM',\r\n },\r\n };\r\n\r\n // Store namespace metadata in memory\r\n this.namespaces[preparedNs] = nsData;\r\n\r\n // Initialize namespace vectors storage\r\n this.vectors[preparedNs] = [];\r\n\r\n // Initialize datasources storage for this namespace\r\n this.datasources[preparedNs] = {};\r\n }\r\n\r\n // Store ACL in memory\r\n const acl = new ACL().addAccess(acRequest.candidate.role, acRequest.candidate.id, TAccessLevel.Owner).ACL;\r\n this.acls[preparedNs] = acl;\r\n\r\n return new Promise<void>((resolve) => resolve());\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async namespaceExists(acRequest: AccessRequest, namespace: string): Promise<boolean> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n return !!this.namespaces[preparedNs];\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async getNamespace(acRequest: AccessRequest, namespace: string): Promise<IStorageVectorNamespace> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n const nsData = this.namespaces[preparedNs];\r\n if (!nsData) {\r\n throw new Error(`Namespace ${namespace} not found`);\r\n }\r\n return nsData;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listNamespaces(acRequest: AccessRequest): Promise<IStorageVectorNamespace[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n // Filter namespaces by team\r\n return Object.values(this.namespaces).filter((ns) => ns.candidateId === acRequest.candidate.id);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteNamespace(acRequest: AccessRequest, namespace: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n // Delete from memory\r\n delete this.vectors[preparedNs];\r\n delete this.namespaces[preparedNs];\r\n delete this.datasources[preparedNs];\r\n delete this.acls[preparedNs];\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async search(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n query: string | number[],\r\n options: QueryOptions = {}\r\n ): Promise<VectorsResultData> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n if (!this.namespaces[preparedNs]) {\r\n throw new Error('Namespace does not exist');\r\n }\r\n\r\n // Get query vector\r\n let queryVector = query;\r\n if (typeof query === 'string') {\r\n queryVector = await this.embedder.embedText(query, acRequest.candidate as AccessCandidate);\r\n }\r\n\r\n // Search in namespace data\r\n const namespaceData = this.vectors[preparedNs] || [];\r\n const results: Array<{ id: string; score: number; values: number[]; metadata?: any }> = [];\r\n\r\n for (const vector of namespaceData) {\r\n const similarity = this.cosineSimilarity(queryVector as number[], vector.values);\r\n results.push({\r\n id: vector.id,\r\n score: similarity,\r\n values: vector.values,\r\n metadata: options.includeMetadata ? vector.metadata : undefined,\r\n });\r\n }\r\n\r\n // Sort by similarity (highest first) and limit results\r\n const topK = options.topK || 10;\r\n const sortedResults = results.sort((a, b) => b.score - a.score).slice(0, topK);\r\n\r\n return sortedResults;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async insert(\r\n acRequest: AccessRequest,\r\n namespace: string,\r\n sourceWrapper: IVectorDataSourceDto | IVectorDataSourceDto[]\r\n ): Promise<string[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const sources = Array.isArray(sourceWrapper) ? sourceWrapper : [sourceWrapper];\r\n const insertedIds: string[] = [];\r\n\r\n if (!this.vectors[preparedNs]) {\r\n this.vectors[preparedNs] = [];\r\n }\r\n\r\n for (const source of sources) {\r\n let vector: number[] = [];\r\n\r\n if (typeof source.source === 'string') {\r\n // Text embedding\r\n\r\n vector = await this.embedder.embedText(source.source, acRequest.candidate as AccessCandidate);\r\n } else {\r\n // Direct vector\r\n vector = source.source;\r\n }\r\n\r\n const vectorData: VectorData = {\r\n id: source.id,\r\n values: vector,\r\n datasource: source.metadata?.datasource || 'unknown',\r\n metadata: source.metadata,\r\n };\r\n\r\n // Check if vector with this ID already exists and update it\r\n const existingIndex = this.vectors[preparedNs].findIndex((v) => v.id === source.id);\r\n if (existingIndex >= 0) {\r\n this.vectors[preparedNs][existingIndex] = vectorData;\r\n } else {\r\n this.vectors[preparedNs].push(vectorData);\r\n }\r\n\r\n insertedIds.push(source.id);\r\n }\r\n\r\n return insertedIds;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async delete(acRequest: AccessRequest, namespace: string, id: string | string[]): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const ids = Array.isArray(id) ? id : [id];\r\n\r\n if (this.vectors[preparedNs]) {\r\n this.vectors[preparedNs] = this.vectors[preparedNs].filter((vector) => !ids.includes(vector.id));\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async createDatasource(acRequest: AccessRequest, namespace: string, datasource: DatasourceDto): Promise<IStorageVectorDataSource> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n const datasourceId = datasource.id || crypto.randomUUID();\r\n\r\n // Ensure namespace exists\r\n if (!this.namespaces[preparedNs]) {\r\n await this.createNamespace(acRequest, namespace);\r\n }\r\n\r\n // Process text and create vectors\r\n const vectorIds: string[] = [];\r\n\r\n // Split text into chunks if needed\r\n const chunkSize = datasource.chunkSize || 1000;\r\n const chunkOverlap = datasource.chunkOverlap || 200;\r\n const chunks = this.splitTextIntoChunks(datasource.text, chunkSize, chunkOverlap);\r\n\r\n // Initialize namespace vectors if not exists (should already exist if namespace was created properly)\r\n if (!this.vectors[preparedNs]) {\r\n this.vectors[preparedNs] = [];\r\n }\r\n\r\n for (let i = 0; i < chunks.length; i++) {\r\n const chunkId = `${datasourceId}_chunk_${i}`;\r\n const vector = await this.embedder.embedText(chunks[i], acRequest.candidate as AccessCandidate);\r\n\r\n const vectorData: VectorData = {\r\n id: chunkId,\r\n values: vector,\r\n datasource: datasourceId,\r\n metadata: {\r\n ...datasource.metadata,\r\n text: chunks[i],\r\n chunkIndex: i,\r\n totalChunks: chunks.length,\r\n },\r\n };\r\n\r\n this.vectors[preparedNs].push(vectorData);\r\n vectorIds.push(chunkId);\r\n }\r\n\r\n const storageDataSource: IStorageVectorDataSource = {\r\n namespaceId: preparedNs,\r\n candidateId: acRequest.candidate.id,\r\n candidateRole: acRequest.candidate.role,\r\n name: datasource.label || `Datasource ${datasourceId}`,\r\n metadata: JSON.stringify(datasource.metadata || {}),\r\n text: datasource.text,\r\n vectorIds,\r\n id: datasourceId,\r\n };\r\n\r\n // Store datasource metadata in memory\r\n if (!this.datasources[preparedNs]) {\r\n this.datasources[preparedNs] = {};\r\n }\r\n if (!this.datasources[preparedNs][datasourceId]) {\r\n this.datasources[preparedNs][datasourceId] = storageDataSource;\r\n } else {\r\n this.datasources[preparedNs][datasourceId].vectorIds.push(...vectorIds);\r\n }\r\n\r\n return storageDataSource;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async deleteDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<void> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n // Ensure namespace exists\r\n if (!this.namespaces[preparedNs]) {\r\n throw new Error('Namespace does not exist');\r\n }\r\n\r\n // Get datasource info\r\n const datasource = this.datasources[preparedNs]?.[datasourceId];\r\n if (datasource) {\r\n // Delete all vectors belonging to this datasource\r\n if (this.vectors[preparedNs]) {\r\n this.vectors[preparedNs] = this.vectors[preparedNs].filter((vector) => vector.datasource !== datasourceId);\r\n }\r\n }\r\n\r\n // Delete datasource metadata\r\n if (this.datasources[preparedNs]) {\r\n delete this.datasources[preparedNs][datasourceId];\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listDatasources(acRequest: AccessRequest, namespace: string): Promise<IStorageVectorDataSource[]> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const namespaceDatasources = this.datasources[preparedNs] || {};\r\n return Object.values(namespaceDatasources);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async getDatasource(acRequest: AccessRequest, namespace: string, datasourceId: string): Promise<IStorageVectorDataSource> {\r\n //const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const preparedNs = this.constructNsName(acRequest.candidate as AccessCandidate, namespace);\r\n\r\n const datasource = this.datasources[preparedNs]?.[datasourceId];\r\n if (!datasource) {\r\n throw new Error(`Datasource ${datasourceId} not found`);\r\n }\r\n return datasource;\r\n }\r\n\r\n /**\r\n * Calculate cosine similarity between two vectors\r\n */\r\n private cosineSimilarity(vecA: number[], vecB: number[]): number {\r\n if (vecA.length !== vecB.length) {\r\n throw new Error('Vectors must have the same length');\r\n }\r\n\r\n let dotProduct = 0;\r\n let normA = 0;\r\n let normB = 0;\r\n\r\n for (let i = 0; i < vecA.length; i++) {\r\n dotProduct += vecA[i] * vecB[i];\r\n normA += vecA[i] * vecA[i];\r\n normB += vecB[i] * vecB[i];\r\n }\r\n\r\n normA = Math.sqrt(normA);\r\n normB = Math.sqrt(normB);\r\n\r\n if (normA === 0 || normB === 0) {\r\n return 0;\r\n }\r\n\r\n return dotProduct / (normA * normB);\r\n }\r\n\r\n /**\r\n * Split text into chunks with overlap\r\n */\r\n private splitTextIntoChunks(text: string, chunkSize: number, overlap: number): string[] {\r\n const chunks: string[] = [];\r\n let start = 0;\r\n\r\n while (start < text.length) {\r\n const end = Math.min(start + chunkSize, text.length);\r\n chunks.push(text.slice(start, end));\r\n\r\n if (end === text.length) break;\r\n start = end - overlap;\r\n }\r\n\r\n return chunks;\r\n }\r\n}\r\n","//==[ SRE: Storage ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { PineconeVectorDB } from './connectors/PineconeVectorDB.class';\r\nimport { MilvusVectorDB } from './connectors/MilvusVectorDB.class';\r\nimport { RAMVectorDB } from './connectors/RAMVecrtorDB.class';\r\nexport class VectorDBService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.VectorDB, 'Pinecone', PineconeVectorDB);\r\n ConnectorService.register(TConnectorService.VectorDB, 'RAMVec', RAMVectorDB);\r\n ConnectorService.register(TConnectorService.VectorDB, 'Milvus', MilvusVectorDB);\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { getMainArgs, parseCLIArgs } from '@sre/utils/cli.utils';\r\n\r\nexport class CLIConnector extends Connector {\r\n public name = 'CLI';\r\n public params: any;\r\n constructor(protected _settings?: any) {\r\n super(_settings);\r\n this.params = this.parse(process.argv);\r\n }\r\n\r\n /**\r\n * Parses the command line arguments, and returns the parsed arguments object\r\n * if args is provided, it will only parse the provided args\r\n * @param argv The command line arguments, usually process.argv\r\n * @param args The arguments to parse\r\n * @returns\r\n */\r\n public parse(argv: string[], args?: string | string[]) {\r\n let _keys = args;\r\n if (_keys && !Array.isArray(_keys)) _keys = [_keys];\r\n\r\n const argsList = _keys || getMainArgs(argv);\r\n const params = parseCLIArgs(argsList, argv);\r\n\r\n return params;\r\n }\r\n\r\n /**\r\n * Get the parsed arguments as an object\r\n * @param args The arguments to get\r\n * @returns\r\n */\r\n public get(args: string | string[]) {\r\n let _keys = args;\r\n if (!Array.isArray(_keys)) _keys = [_keys];\r\n\r\n const result = {};\r\n _keys.forEach((key) => {\r\n if (this.params[key]) {\r\n result[key] = this.params[key];\r\n }\r\n });\r\n\r\n return result;\r\n }\r\n}\r\n","import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { CLIConnector } from './CLIConnector';\r\n\r\nexport class CLIService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.CLI, 'CLI', CLIConnector);\r\n }\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\nimport { StorageData, StorageMetadata } from '@sre/types/Storage.types';\r\n\r\nexport interface INKVRequest {\r\n get(namespace: string, key: string): Promise<StorageData>;\r\n set(namespace: string, key: string, value: StorageData): Promise<void>;\r\n delete(namespace: string, key: string): Promise<void>;\r\n exists(namespace: string, key: string): Promise<boolean>;\r\n deleteAll(namespace: string): Promise<void>;\r\n list(namespace: string): Promise<{ key: string; data: StorageData }[]>;\r\n}\r\n\r\n/**\r\n * NKV = Namespace-Key-Value Connector\r\n */\r\nexport abstract class NKVConnector extends SecureConnector {\r\n public requester(candidate: AccessCandidate): INKVRequest {\r\n return {\r\n get: async (namespace: string, key: string) => this.get(candidate.readRequest, namespace, key),\r\n set: async (namespace: string, key: string, value: StorageData) => this.set(candidate.writeRequest, namespace, key, value),\r\n delete: async (namespace: string, key: string) => this.delete(candidate.writeRequest, namespace, key),\r\n exists: async (namespace: string, key: string) => this.exists(candidate.readRequest, namespace, key),\r\n deleteAll: async (namespace: string) => this.deleteAll(candidate.writeRequest, namespace),\r\n list: async (namespace: string) => this.list(candidate.readRequest, namespace),\r\n };\r\n }\r\n\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n protected abstract get(acRequest: AccessRequest, namespace: string, key: string): Promise<StorageData>;\r\n protected abstract set(acRequest: AccessRequest, namespace: string, key: string, value: StorageData): Promise<void>;\r\n\r\n protected abstract delete(acRequest: AccessRequest, namespace: string, key: string): Promise<void>;\r\n protected abstract exists(acRequest: AccessRequest, namespace: string, key: string): Promise<boolean>;\r\n protected abstract deleteAll(acRequest: AccessRequest, namespace: string): Promise<void>;\r\n protected abstract list(acRequest: AccessRequest, namespace: string): Promise<{ key: string; data: StorageData }[]>;\r\n}\r\n","import { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { INKVRequest, NKVConnector } from '../NKVConnector';\r\nimport { ACLAccessDeniedError, IAccessCandidate, TAccessLevel, TAccessResult } from '@sre/types/ACL.types';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { StorageData } from '@sre/types/Storage.types';\r\nimport { RedisCache } from '@sre/MemoryManager/Cache.service/connectors/RedisCache.class';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport Joi from 'joi';\r\n\r\nexport class NKVRedis extends NKVConnector {\r\n public name = 'Redis';\r\n private redisCacheConnector: RedisCache;\r\n private accountConnector: AccountConnector;\r\n constructor(protected _settings?: any) {\r\n super(_settings);\r\n this.redisCacheConnector = ConnectorService.getCacheConnector('Redis') as RedisCache;\r\n this.accountConnector = ConnectorService.getAccountConnector();\r\n }\r\n\r\n public key(...parts: string[]) {\r\n return parts.join(':');\r\n }\r\n\r\n public mdKey(...parts: string[]) {\r\n return parts.join(':');\r\n }\r\n\r\n @NKVRedis.Validate\r\n @NKVRedis.NamespaceAccessControl\r\n protected async get(acRequest: AccessRequest, namespace: string, key: string): Promise<StorageData> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n return await this.redisCacheConnector.requester(AccessCandidate.team(teamId)).get(this.key(`team_${teamId}`, namespace, key));\r\n }\r\n\r\n @NKVRedis.Validate\r\n @NKVRedis.NamespaceAccessControl\r\n protected async set(acRequest: AccessRequest, namespace: string, key: string, value: any) {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n\r\n const setKey = this.key(`team_${teamId}`, namespace, key);\r\n await this.redisCacheConnector.requester(AccessCandidate.team(teamId)).set(setKey, value);\r\n // to set namespace ownership\r\n const isNewNs = !(await this.redisCacheConnector.requester(AccessCandidate.team(teamId)).exists(namespace));\r\n if (isNewNs) {\r\n await this.redisCacheConnector\r\n .requester(AccessCandidate.team(teamId))\r\n .set(this.key(`team_${teamId}`, namespace), '', undefined, { ns: true });\r\n }\r\n }\r\n\r\n @NKVRedis.Validate\r\n @NKVRedis.NamespaceAccessControl\r\n protected async delete(acRequest: AccessRequest, namespace: string, key: string): Promise<void> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n await this.redisCacheConnector.requester(AccessCandidate.team(teamId)).delete(this.key(`team_${teamId}`, namespace, key));\r\n }\r\n\r\n @NKVRedis.Validate\r\n @NKVRedis.NamespaceAccessControl\r\n protected async exists(acRequest: AccessRequest, namespace: string, key: string): Promise<boolean> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n return await this.redisCacheConnector.requester(AccessCandidate.team(teamId)).exists(this.key(`team_${teamId}`, namespace, key));\r\n }\r\n\r\n @NKVRedis.NamespaceAccessControl\r\n public async list(acRequest: AccessRequest, namespace: string): Promise<{ key: string; data: StorageData }[]> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n let keys = await this.fetchKeysByPrefix(this.key(this.redisCacheConnector.prefix, `team_${teamId}`, namespace));\r\n\r\n // filter out metadata keys & namespace sentinel keys\r\n keys = keys.filter(\r\n (key) => key !== this.key(this.redisCacheConnector.prefix, `team_${teamId}`, namespace) // if not the namespace sentinel key\r\n );\r\n\r\n if (keys.length <= 0) return [];\r\n // Start a transaction\r\n const pipeline = this.redisCacheConnector.client.pipeline();\r\n\r\n // Add get commands for all keys to the transaction\r\n keys.forEach((key) => {\r\n pipeline.get(key);\r\n });\r\n\r\n // Execute the transaction\r\n const results = await pipeline.exec();\r\n\r\n // Combine the keys and their corresponding values\r\n return keys.map((key, index) => {\r\n return {\r\n key: key.replace(`${this.key(this.redisCacheConnector.prefix, `team_${teamId}`, namespace)}:`, ''),\r\n data: results[index][1] as StorageData,\r\n };\r\n });\r\n }\r\n\r\n @NKVRedis.NamespaceAccessControl\r\n public async deleteAll(acRequest: AccessRequest, namespace: string): Promise<void> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n let keys = await this.fetchKeysByPrefix(this.key(this.redisCacheConnector.prefix, `team_${teamId}`, namespace));\r\n // filter out namespace sentinel key + namespace metadata key metadata key\r\n keys = keys.filter((key) => {\r\n return ![this.key(this.redisCacheConnector.prefix, `team_${teamId}`, namespace)].includes(key);\r\n });\r\n await this.redisCacheConnector.client.del(keys);\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n return this.redisCacheConnector.getResourceACL(resourceId, candidate);\r\n }\r\n\r\n private async fetchKeysByPrefix(prefix: string): Promise<string[]> {\r\n let cursor = '0';\r\n const keys = [];\r\n\r\n do {\r\n // SCAN with match for the prefix and count for batch size (optional)\r\n const result = await this.redisCacheConnector.client.scan(cursor, 'MATCH', `${prefix}*`, 'COUNT', 10000);\r\n cursor = result[0];\r\n keys.push(...result[1]);\r\n } while (cursor !== '0');\r\n\r\n return keys;\r\n }\r\n\r\n static NamespaceAccessControl(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n // Store the original method in a variable\r\n const originalMethod = descriptor.value;\r\n\r\n // Modify the descriptor's value to wrap the original method\r\n descriptor.value = async function (...args: any[]) {\r\n // Extract the method arguments\r\n let [acRequest, namespace, key] = args;\r\n const isNamespaceSearch = key === undefined;\r\n\r\n // Inject the access control logic\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const resourceId = isNamespaceSearch ? namespace : `${namespace}:${key}`;\r\n const finalKey = this.key(this.redisCacheConnector.prefix, `team_${teamId}`, resourceId);\r\n const accessTicket = await this.getAccessTicket(finalKey, acRequest);\r\n\r\n if (accessTicket.access !== TAccessResult.Granted) throw new ACLAccessDeniedError('Access Denied');\r\n\r\n // Call the original method with the original arguments\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n // Return the modified descriptor\r\n return descriptor;\r\n }\r\n\r\n static Validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n // Store the original method in a variable\r\n const originalMethod = descriptor.value;\r\n\r\n // Modify the descriptor's value to wrap the original method\r\n descriptor.value = async function (...args: any[]) {\r\n // Extract the method arguments\r\n let [acRequest, namespace, key] = args;\r\n\r\n // Validate the arguments\r\n const schemaValidator = Joi.object().keys({\r\n namespace: Joi.string().min(1).required(),\r\n key: Joi.string().min(1).required(),\r\n });\r\n const validationResult = schemaValidator.validate({ namespace, key });\r\n\r\n if (validationResult.error) {\r\n throw new Error(`Validation Error: ${validationResult.error.message}`);\r\n }\r\n\r\n // Call the original method with the original arguments\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n // Return the modified descriptor\r\n return descriptor;\r\n }\r\n}\r\n","import { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { INKVRequest, NKVConnector } from '../NKVConnector';\r\nimport { ACLAccessDeniedError, IAccessCandidate, TAccessLevel, TAccessResult } from '@sre/types/ACL.types';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { CacheConnector } from '@sre/MemoryManager/Cache.service/CacheConnector';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { StorageData } from '@sre/types/Storage.types';\r\nimport { AccountConnector } from '@sre/Security/Account.service/AccountConnector';\r\nimport Joi from 'joi';\r\n\r\nexport class NKVRAM extends NKVConnector {\r\n public name = 'RAM';\r\n private storage: Map<string, any> = new Map();\r\n private namespaces: Set<string> = new Set();\r\n private accountConnector: AccountConnector;\r\n private cacheConnector: CacheConnector;\r\n\r\n constructor(protected _settings?: any) {\r\n super(_settings);\r\n this.accountConnector = ConnectorService.getAccountConnector();\r\n this.cacheConnector = ConnectorService.getCacheConnector('RAM');\r\n }\r\n\r\n public key(...parts: string[]) {\r\n return parts.join(':');\r\n }\r\n\r\n public mdKey(...parts: string[]) {\r\n return parts.join(':');\r\n }\r\n\r\n @NKVRAM.Validate\r\n @NKVRAM.NamespaceAccessControl\r\n protected async get(acRequest: AccessRequest, namespace: string, key: string): Promise<StorageData> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const storageKey = this.key(`team_${teamId}`, namespace, key);\r\n return this.storage.get(storageKey) || null;\r\n }\r\n\r\n @NKVRAM.Validate\r\n @NKVRAM.NamespaceAccessControl\r\n protected async set(acRequest: AccessRequest, namespace: string, key: string, value: any): Promise<void> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const storageKey = this.key(`team_${teamId}`, namespace, key);\r\n\r\n // Store the value\r\n this.storage.set(storageKey, value);\r\n\r\n // Track namespace\r\n const nsKey = this.key(`team_${teamId}`, namespace);\r\n if (!this.namespaces.has(nsKey)) {\r\n this.namespaces.add(nsKey);\r\n this.storage.set(nsKey, ''); // Namespace sentinel\r\n }\r\n }\r\n\r\n @NKVRAM.Validate\r\n @NKVRAM.NamespaceAccessControl\r\n protected async delete(acRequest: AccessRequest, namespace: string, key: string): Promise<void> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const storageKey = this.key(`team_${teamId}`, namespace, key);\r\n this.storage.delete(storageKey);\r\n }\r\n\r\n @NKVRAM.Validate\r\n @NKVRAM.NamespaceAccessControl\r\n protected async exists(acRequest: AccessRequest, namespace: string, key: string): Promise<boolean> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const storageKey = this.key(`team_${teamId}`, namespace, key);\r\n return this.storage.has(storageKey);\r\n }\r\n\r\n @NKVRAM.NamespaceAccessControl\r\n public async list(acRequest: AccessRequest, namespace: string): Promise<{ key: string; data: StorageData }[]> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const prefix = this.key(`team_${teamId}`, namespace);\r\n const results: { key: string; data: StorageData }[] = [];\r\n\r\n // Find all keys that start with the prefix\r\n for (const [storageKey, value] of this.storage.entries()) {\r\n if (storageKey.startsWith(prefix + ':')) {\r\n // Extract the actual key (remove prefix and separator)\r\n const actualKey = storageKey.substring(prefix.length + 1);\r\n results.push({\r\n key: actualKey,\r\n data: value as StorageData,\r\n });\r\n }\r\n }\r\n\r\n return results;\r\n }\r\n\r\n @NKVRAM.NamespaceAccessControl\r\n public async deleteAll(acRequest: AccessRequest, namespace: string): Promise<void> {\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const prefix = this.key(`team_${teamId}`, namespace);\r\n const keysToDelete: string[] = [];\r\n\r\n // Find all keys that start with the prefix (excluding the namespace sentinel)\r\n for (const storageKey of this.storage.keys()) {\r\n if (storageKey.startsWith(prefix + ':')) {\r\n keysToDelete.push(storageKey);\r\n }\r\n }\r\n\r\n // Delete all found keys\r\n for (const key of keysToDelete) {\r\n this.storage.delete(key);\r\n }\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n // Delegate ACL management to the cache connector (Redis)\r\n return this.cacheConnector.getResourceACL(resourceId, candidate);\r\n }\r\n\r\n /**\r\n * Get all keys matching a prefix (for internal use)\r\n */\r\n private getKeysByPrefix(prefix: string): string[] {\r\n const keys: string[] = [];\r\n for (const key of this.storage.keys()) {\r\n if (key.startsWith(prefix)) {\r\n keys.push(key);\r\n }\r\n }\r\n return keys;\r\n }\r\n\r\n /**\r\n * Clear all data (useful for testing)\r\n */\r\n public clearAll(): void {\r\n this.storage.clear();\r\n this.namespaces.clear();\r\n }\r\n\r\n /**\r\n * Get storage statistics\r\n */\r\n public getStats(): { totalKeys: number; totalNamespaces: number } {\r\n return {\r\n totalKeys: this.storage.size,\r\n totalNamespaces: this.namespaces.size,\r\n };\r\n }\r\n\r\n static NamespaceAccessControl(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n // Store the original method in a variable\r\n const originalMethod = descriptor.value;\r\n\r\n // Modify the descriptor's value to wrap the original method\r\n descriptor.value = async function (...args: any[]) {\r\n // Extract the method arguments\r\n let [acRequest, namespace, key] = args;\r\n const isNamespaceSearch = key === undefined;\r\n\r\n // Inject the access control logic\r\n const teamId = await this.accountConnector.getCandidateTeam(acRequest.candidate);\r\n const resourceId = isNamespaceSearch ? namespace : `${namespace}:${key}`;\r\n const finalKey = this.key(`team_${teamId}`, resourceId);\r\n const accessTicket = await this.getAccessTicket(finalKey, acRequest);\r\n\r\n if (accessTicket.access !== TAccessResult.Granted) throw new ACLAccessDeniedError('Access Denied');\r\n\r\n // Call the original method with the original arguments\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n // Return the modified descriptor\r\n return descriptor;\r\n }\r\n\r\n static Validate(target: any, propertyKey: string, descriptor: PropertyDescriptor) {\r\n // Store the original method in a variable\r\n const originalMethod = descriptor.value;\r\n\r\n // Modify the descriptor's value to wrap the original method\r\n descriptor.value = async function (...args: any[]) {\r\n // Extract the method arguments\r\n let [acRequest, namespace, key] = args;\r\n\r\n // Validate the arguments\r\n const schemaValidator = Joi.object().keys({\r\n namespace: Joi.string().min(1).required(),\r\n key: Joi.string().min(1).required(),\r\n });\r\n const validationResult = schemaValidator.validate({ namespace, key });\r\n\r\n if (validationResult.error) {\r\n throw new Error(`Validation Error: ${validationResult.error.message}`);\r\n }\r\n\r\n // Call the original method with the original arguments\r\n return originalMethod.apply(this, args);\r\n };\r\n\r\n // Return the modified descriptor\r\n return descriptor;\r\n }\r\n}\r\n","//==[ SRE: Storage ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { NKVRedis } from './connectors/NKVRedis.class';\r\nimport { NKVRAM } from './connectors/NKVRAM.class';\r\nexport class NKVService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.NKV, 'Redis', NKVRedis);\r\n ConnectorService.register(TConnectorService.NKV, 'RAM', NKVRAM);\r\n }\r\n}\r\n","import { Connector } from '@sre/Core/Connector.class';\r\nimport { SmythFS } from '../Storage.service/SmythFS.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\n\r\nexport type GenericRequestHandler = (...args: any[]) => void | Promise<void>;\r\n\r\n/*\r\nThis Connector is highly discouraged to be used because by design, SRE should not handle any kind of HTTP requests\r\nCurrently it is only used to serve the temp files for external services to retrieve them.\r\n*/\r\n\r\nexport abstract class RouterConnector extends Connector {\r\n public abstract baseUrl: string;\r\n\r\n abstract get(path: string, ...handlers: GenericRequestHandler[]): this;\r\n abstract post(path: string, ...handlers: GenericRequestHandler[]): this;\r\n abstract put(path: string, ...handlers: GenericRequestHandler[]): this;\r\n abstract delete(path: string, ...handlers: GenericRequestHandler[]): this;\r\n abstract useFn(...handlers: GenericRequestHandler[]): this;\r\n abstract use(path: string, ...handlers: GenericRequestHandler[]): this;\r\n}\r\n","import { Router } from 'express';\r\nimport { RouterConnector, GenericRequestHandler } from '../RouterConnector';\r\n\r\nexport class ExpressRouter extends RouterConnector {\r\n private router: Router;\r\n public baseUrl: string;\r\n\r\n constructor(protected _settings?: { router: Router; baseUrl: string }) {\r\n super(_settings);\r\n this.name = 'ExpressRouter';\r\n this.router = _settings.router;\r\n this.baseUrl = _settings.baseUrl;\r\n }\r\n\r\n get(path: string, ...handlers: GenericRequestHandler[]): this {\r\n this.router.get(path, ...handlers);\r\n return this;\r\n }\r\n\r\n post(path: string, ...handlers: GenericRequestHandler[]): this {\r\n this.router.post(path, ...handlers);\r\n return this;\r\n }\r\n\r\n put(path: string, ...handlers: GenericRequestHandler[]): this {\r\n this.router.put(path, ...handlers);\r\n return this;\r\n }\r\n\r\n delete(path: string, ...handlers: GenericRequestHandler[]): this {\r\n this.router.delete(path, ...handlers);\r\n return this;\r\n }\r\n\r\n useFn(...handlers: GenericRequestHandler[]): this {\r\n this.router.use(...handlers);\r\n return this;\r\n }\r\n\r\n use(path: string, ...handlers: GenericRequestHandler[]): this {\r\n this.router.use(path, ...handlers);\r\n return this;\r\n }\r\n\r\n getRouter(): Router {\r\n return this.router;\r\n }\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { RouterConnector, GenericRequestHandler } from '../RouterConnector';\r\n\r\nconst console = Logger('NullRouter');\r\nexport class NullRouter extends RouterConnector {\r\n public baseUrl: string;\r\n constructor(protected _settings?: any) {\r\n super(_settings);\r\n this.baseUrl = 'http://nullrouter.local';\r\n }\r\n\r\n get(path: string, ...handlers: GenericRequestHandler[]): this {\r\n console.debug(`Ignored operation:NullRouter.get: ${path}`);\r\n return this;\r\n }\r\n\r\n post(path: string, ...handlers: GenericRequestHandler[]): this {\r\n console.debug(`Ignored operation:NullRouter.post: ${path}`);\r\n return this;\r\n }\r\n\r\n put(path: string, ...handlers: GenericRequestHandler[]): this {\r\n console.debug(`Ignored operation:NullRouter.put: ${path}`);\r\n return this;\r\n }\r\n\r\n delete(path: string, ...handlers: GenericRequestHandler[]): this {\r\n console.debug(`Ignored operation:NullRouter.delete: ${path}`);\r\n return this;\r\n }\r\n\r\n useFn(...handlers: GenericRequestHandler[]): this {\r\n console.debug(`Ignored operation:NullRouter.useFn`);\r\n return this;\r\n }\r\n\r\n use(path: string, ...handlers: GenericRequestHandler[]): this {\r\n return this;\r\n }\r\n}\r\n","import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { ExpressRouter } from './connectors/ExpressRouter.class';\r\nimport { NullRouter } from './connectors/NullRouter.class';\r\n\r\nexport class RouterService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Router, 'ExpressRouter', ExpressRouter);\r\n ConnectorService.register(TConnectorService.Router, 'NullRouter', NullRouter);\r\n }\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\n\r\n/**\r\n * The managed vault is a vault that is managed by the SRE, its keys are not visible to the user.\r\n * it's used to store generated tokens at runtime, like OAuth tokens\r\n */\r\n\r\nexport interface IManagedVaultRequest {\r\n get(keyId: string): Promise<string>;\r\n set(keyId: string, value: string): Promise<void>;\r\n delete(keyId: string): Promise<void>;\r\n exists(keyId: string): Promise<boolean>;\r\n}\r\n\r\nexport abstract class ManagedVaultConnector extends SecureConnector {\r\n requester(candidate: AccessCandidate): IManagedVaultRequest {\r\n return {\r\n get: async (keyId: string) => this.get(candidate.readRequest, keyId),\r\n set: async (keyId: string, value: string) => this.set(candidate.writeRequest, keyId, value),\r\n delete: async (keyId: string) => this.delete(candidate.writeRequest, keyId),\r\n exists: async (keyId: string) => this.exists(candidate.readRequest, keyId),\r\n };\r\n }\r\n\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n protected abstract get(acRequest: AccessRequest, keyId: string): Promise<string>;\r\n protected abstract set(acRequest: AccessRequest, keyId: string, value: string): Promise<void>;\r\n protected abstract delete(acRequest: AccessRequest, keyId: string): Promise<void>;\r\n protected abstract exists(acRequest: AccessRequest, keyId: string): Promise<boolean>;\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\n\r\nimport {\r\n CreateSecretCommand,\r\n DeleteSecretCommand,\r\n GetSecretValueCommand,\r\n GetSecretValueCommandOutput,\r\n ListSecretsCommand,\r\n ListSecretsCommandOutput,\r\n PutSecretValueCommand,\r\n SecretsManagerClient,\r\n} from '@aws-sdk/client-secrets-manager';\r\nimport { randomUUID } from 'crypto';\r\nimport { ManagedVaultConnector } from '../ManagedVaultConnector';\r\nimport { SecretsManagerConfig } from '../../Vault.service/connectors/SecretsManager.class';\r\n\r\nconst console = Logger('SecretManagerManagedVault');\r\n\r\nexport class SecretManagerManagedVault extends ManagedVaultConnector {\r\n public name: string = 'SecretManagerManagedVault';\r\n public scope: string = 'smyth-managed-vault';\r\n private secretsManager: SecretsManagerClient;\r\n\r\n constructor(protected _settings: SecretsManagerConfig & { vaultName: string }) {\r\n super(_settings);\r\n //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');\r\n\r\n this.secretsManager = new SecretsManagerClient({\r\n region: _settings.region,\r\n ...(_settings.awsAccessKeyId && _settings.awsSecretAccessKey\r\n ? {\r\n accessKeyId: _settings.awsAccessKeyId,\r\n secretAccessKey: _settings.awsSecretAccessKey,\r\n }\r\n : {}),\r\n });\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, secretName: string) {\r\n const secret = await this.getSecretByName(secretName);\r\n return secret?.SecretString;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async set(acRequest: AccessRequest, secretName: string, value: string) {\r\n const secret = await this.getSecretByName(secretName);\r\n if (secret) {\r\n await this.secretsManager.send(new PutSecretValueCommand({ SecretId: secret.ARN, SecretString: value }));\r\n } else {\r\n await this.secretsManager.send(\r\n new CreateSecretCommand({\r\n Name: `smyth/${randomUUID()}`,\r\n SecretString: JSON.stringify({ [secretName]: value }),\r\n Tags: [{ Key: this.scope, Value: 'true' }],\r\n })\r\n );\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async delete(acRequest: AccessRequest, secretName: string) {\r\n const secret = await this.getSecretByName(secretName);\r\n if (secret) {\r\n await this.secretsManager.send(new DeleteSecretCommand({ SecretId: secret.ARN }));\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, secretName: string) {\r\n const secret = await this.get(acRequest, secretName);\r\n return !!secret;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n const acl = new ACL();\r\n\r\n acl.addAccess(TAccessRole.Team, teamId, TAccessLevel.Owner)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Read)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Write);\r\n\r\n return acl;\r\n }\r\n\r\n private async getSecretByName(secretName: string) {\r\n try {\r\n const secrets = [];\r\n let nextToken: string | undefined;\r\n do {\r\n const listResponse: ListSecretsCommandOutput = await this.secretsManager.send(\r\n new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: [this.scope] }] })\r\n );\r\n if (listResponse.SecretList) {\r\n for (const secret of listResponse.SecretList) {\r\n if (secret.Name) {\r\n secrets.push({\r\n ARN: secret.ARN,\r\n Name: secret.Name,\r\n CreatedDate: secret.CreatedDate,\r\n });\r\n }\r\n }\r\n }\r\n nextToken = listResponse.NextToken;\r\n } while (nextToken);\r\n\r\n const formattedSecrets = [];\r\n const $promises = [];\r\n for (const secret of secrets) {\r\n $promises.push(getSpecificSecret(secret, this.secretsManager));\r\n }\r\n const results = await Promise.all($promises);\r\n for (const result of results) {\r\n formattedSecrets.push(result);\r\n }\r\n const secret = formattedSecrets.find((s) => s.Name === secretName);\r\n return secret;\r\n } catch (error) {\r\n console.error(error);\r\n }\r\n\r\n async function getSpecificSecret(secret, secretsManager: SecretsManagerClient) {\r\n const data: GetSecretValueCommandOutput = await secretsManager.send(new GetSecretValueCommand({ SecretId: secret.ARN }));\r\n let secretString = data.SecretString;\r\n let secretName = secret.Name;\r\n\r\n if (secretString) {\r\n try {\r\n let parsedSecret = JSON.parse(secretString);\r\n if (Object.keys(parsedSecret).length === 1) {\r\n secretName = Object.keys(parsedSecret)[0];\r\n secretString = parsedSecret[secretName];\r\n }\r\n } catch (error) {}\r\n }\r\n return {\r\n Name: secretName,\r\n ARN: secret.ARN,\r\n CreatedDate: secret.CreatedDate,\r\n SecretId: secret.Name,\r\n SecretString: secretString,\r\n };\r\n }\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n//import { SmythRuntime } from '@sre/Core/SmythRuntime.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { OAuthConfig, SmythConfigs } from '@sre/types/Security.types';\r\n\r\nimport { getM2MToken } from '@sre/utils/oauth.utils';\r\nimport axios, { AxiosInstance } from 'axios';\r\nimport { ManagedVaultConnector } from '../ManagedVaultConnector';\r\n\r\nconst console = Logger('NullManagedVault');\r\nexport class NullManagedVault extends ManagedVaultConnector {\r\n public name: string = 'NullManagedVault';\r\n\r\n constructor(protected _settings: any) {\r\n super(_settings);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, keyId: string) {\r\n console.debug(`Ignored operation:NullManagedVault.get: ${keyId}`);\r\n return undefined;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async set(acRequest: AccessRequest, keyId: string, value: string) {\r\n console.debug(`Ignored operation:NullManagedVault.set: ${keyId} = ${value}`);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async delete(acRequest: AccessRequest, keyId: string) {\r\n console.debug(`Ignored operation:NullManagedVault.delete: ${keyId}`);\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, keyId: string) {\r\n console.debug(`Ignored operation:NullManagedVault.exists: ${keyId}`);\r\n return false;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n const acl = new ACL();\r\n\r\n //give just read access by default\r\n //Cannot write to null vault\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n\r\n return acl;\r\n }\r\n}\r\n","import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\n\r\nimport { SecretManagerManagedVault } from './connectors/SecretManagerManagedVault';\r\nimport { NullManagedVault } from './connectors/NullManagedVault.class';\r\n\r\nexport class ManagedVaultService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.ManagedVault, 'SecretManagerManagedVault', SecretManagerManagedVault);\r\n ConnectorService.register(TConnectorService.ManagedVault, 'NullManagedVault', NullManagedVault);\r\n }\r\n}\r\n","import { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { AgentCallLog } from '@sre/types/AgentLogger.types';\r\n\r\nexport interface ILogRequest {\r\n log(logData: AgentCallLog, callId?: string): Promise<any>;\r\n logTask(tasks: number, isUsingTestDomain: boolean): Promise<void>;\r\n}\r\n\r\nexport abstract class LogConnector extends SecureConnector {\r\n public abstract id: string;\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n public requester(candidate: AccessCandidate): ILogRequest {\r\n if (candidate.role !== 'agent') throw new Error('Only agents can use Log connector');\r\n\r\n return {\r\n log: async (logData: AgentCallLog, callId?: string) => {\r\n return await this.log(candidate.writeRequest, logData, callId);\r\n },\r\n logTask: async (tasks: number, isUsingTestDomain: boolean) => {\r\n await this.logTask(candidate.writeRequest, tasks, isUsingTestDomain);\r\n },\r\n };\r\n }\r\n\r\n protected abstract log(acRequest: AccessRequest, logData: AgentCallLog, callId?: string): Promise<any>;\r\n protected abstract logTask(acRequest: AccessRequest, tasks: number, isUsingTestDomain: boolean): Promise<void>;\r\n}\r\n","import { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport { LogConnector } from '../LogConnector';\r\nimport { AgentCallLog } from '@sre/types/AgentLogger.types';\r\n\r\nconst console = Logger('SmythLog');\r\n\r\nexport class ConsoleLog extends LogConnector {\r\n public id: string;\r\n public getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n return Promise.resolve(new ACL());\r\n }\r\n protected log(acRequest: AccessRequest, logData: AgentCallLog, callId?: string): Promise<any> {\r\n console.debug(`Log for agent ${acRequest.candidate.id}: ${typeof logData === 'string' ? logData : JSON.stringify(logData)}`);\r\n\r\n return Promise.resolve();\r\n }\r\n protected logTask(acRequest: AccessRequest, tasks: number, isUsingTestDomain: boolean): Promise<void> {\r\n console.debug(\r\n `${tasks} Task(s) Consumed by agent ${acRequest.candidate.id}: ${isUsingTestDomain ? 'Using Test Domain' : 'Using Production Domain'}`\r\n );\r\n\r\n return Promise.resolve();\r\n }\r\n public name: string;\r\n}\r\n","import { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n\r\nimport { ConsoleLog } from './connectors/ConsoleLog.class';\r\n\r\nconst console = Logger('LogService');\r\n\r\nexport class LogService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Log, 'ConsoleLog', ConsoleLog);\r\n }\r\n}\r\n","import { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\n\r\nexport interface IComponentRequest {\r\n register(componentName: string, componentInstance: any): Promise<void>;\r\n get(componentName: string): Promise<any>;\r\n getAll(): Promise<any>;\r\n}\r\n\r\nexport abstract class ComponentConnector extends SecureConnector {\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n protected abstract register(acRequest: AccessRequest, componentName: string, componentInstance: any): Promise<void>;\r\n protected abstract get(acRequest: AccessRequest, componentName: string): Promise<any>;\r\n protected abstract getAll(acRequest: AccessRequest): Promise<any>;\r\n\r\n public requester(candidate: AccessCandidate): IComponentRequest {\r\n return {\r\n register: async (componentName: string, componentInstance: any) => {\r\n return await this.register(candidate.readRequest, componentName, componentInstance);\r\n },\r\n get: async (componentName: string) => {\r\n return await this.get(candidate.readRequest, componentName);\r\n },\r\n getAll: async () => {\r\n return await this.getAll(candidate.readRequest);\r\n },\r\n } as IComponentRequest;\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\n\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\n\r\nimport { ComponentConnector } from '../ComponentConnector';\r\nimport { ComponentInstances } from '@sre/Components/index';\r\n\r\nconst console = Logger('LocalComponentConnector');\r\n\r\n//TODO : future : Candidate specific components access : we can rely on the ACL to isolate the components per user/agent/team\r\nexport class LocalComponentConnector extends ComponentConnector {\r\n public name: string = 'LocalComponentConnector';\r\n private components: any = {};\r\n\r\n constructor() {\r\n super();\r\n\r\n this.init();\r\n }\r\n\r\n async init() {\r\n for (const component in ComponentInstances) {\r\n this.components[component] = ComponentInstances[component];\r\n }\r\n console.debug('Registering Components :', Object.keys(this.components).join(', '));\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async register(acRequest: AccessRequest, componentName: string, componentInstance: any) {\r\n this.components[componentName] = componentInstance;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, componentName: string) {\r\n return this.components[componentName];\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async getAll(acRequest: AccessRequest) {\r\n return this.components;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n\r\n const acl = new ACL();\r\n\r\n //Grant read access by default\r\n acl.addAccess(TAccessRole.Team, teamId, TAccessLevel.Read).addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n\r\n return acl;\r\n }\r\n}\r\n","//==[ SRE: Component ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { LocalComponentConnector } from './connectors/LocalComponentConnector.class';\r\n\r\nexport class ComponentService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Component, 'LocalComponent', LocalComponentConnector);\r\n }\r\n}\r\n","/******************************************************\r\n * ! DO NOT MODIFY THIS FILE INDEPENDENTLY\r\n * ! TO ENSURE CONSISTENCY, THIS FILE IS SYNCED WITH\r\n * ! THE APP AND SRE VERSIONS\r\n ******************************************************/\r\n\r\n/**\r\n * * DEPRECATION NOTICE:\r\n * The following fields are being deprecated in favor of more semantic alternatives:\r\n *\r\n * - 'llm' -> 'provider' : Use 'provider' to specify the LLM service provider\r\n * - 'alias' -> 'modelId' : Use 'modelId' to specify the unique model identifier\r\n * - 'components' -> 'features' : Use 'features' to specify model capabilities\r\n *\r\n * * We will remove the 'legacy' and 'deprecated' models soon, for now we just hide them.\r\n */\r\n\r\n// * features we support ['text', 'image', 'audio', 'video', 'document', 'tools', 'image-generation', 'text-to-image', 'image-to-image', 'image-inpainting', 'image-outpainting']\r\n\r\nexport const models = {\r\n Echo: {\r\n llm: 'Echo',\r\n provider: 'Echo',\r\n },\r\n\r\n // #region [User Models] ==============================================================\r\n\r\n // #region DeepSeek ==========================\r\n\r\n /******************************************************\r\n * NOTE: From Alexander: About the DeepSeek API implementation\r\n * We're not allowing our users to send their data to China\r\n * Instead we use Deepseek from Groq and Together.ai - companies in the West\r\n ******************************************************/\r\n\r\n 'deepseek-v2.5': {\r\n llm: 'DeepSeek',\r\n\r\n label: 'DeepSeek Chat',\r\n modelId: 'deepseek-chat',\r\n provider: 'DeepSeek',\r\n features: ['text', 'image'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.deepseek.com/beta',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-chat': {\r\n llm: 'DeepSeek',\r\n baseURL: 'https://api.deepseek.com/beta',\r\n tokens: 128000,\r\n completionTokens: 8192,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192 },\r\n\r\n credentials: 'vault',\r\n },\r\n\r\n // #endregion DeepSeek ==========================\r\n\r\n // #region OpenAI Models ==========================\r\n\r\n // keep the gpt-4o-mini as default model for now\r\n 'gpt-4o-mini': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-4o-mini-2024-07-18',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GPTPlugin', 'GenAILLM'],\r\n\r\n label: 'GPT 4o Mini',\r\n modelId: 'gpt-4o-mini-2024-07-18',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image', 'search'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: {\r\n tokens: 128_000,\r\n completionTokens: 16_383,\r\n searchContextTokens: 128_000,\r\n enabled: true,\r\n },\r\n\r\n credentials: 'vault',\r\n },\r\n\r\n // #region GPT 4.1\r\n 'gpt-4.1-nano': {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT 4.1 Nano',\r\n modelId: 'gpt-4.1-nano',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_047_576, completionTokens: 32_768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gpt-4.1-mini': {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT 4.1 Mini',\r\n modelId: 'gpt-4.1-mini',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image', 'search'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: {\r\n tokens: 1_047_576,\r\n completionTokens: 32_768,\r\n searchContextTokens: 128_000,\r\n enabled: true,\r\n },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gpt-4.1': {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT 4.1',\r\n modelId: 'gpt-4.1',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image', 'search'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_047_576, completionTokens: 32_768, searchContextTokens: 128_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion\r\n\r\n // #region GPT 4o\r\n 'gpt-4o-mini-2024-07-18': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 128000, completionTokens: 16383, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gpt-4.5-preview': {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT 4.5 Preview',\r\n modelId: 'gpt-4.5-preview',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal', 'Deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gpt-4o': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-4o-2024-08-06',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GPTPlugin', 'GenAILLM'],\r\n\r\n label: 'GPT 4o',\r\n modelId: 'gpt-4o-2024-08-06',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image', 'search', 'document'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, searchContextTokens: 128_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gpt-4o-2024-08-06': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 128000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion GPT 4o\r\n\r\n // #region o3 models\r\n 'o4-mini': {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT o4 mini',\r\n modelId: 'o4-mini-2025-04-16',\r\n provider: 'OpenAI',\r\n features: ['text', 'reasoning'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n o3: {\r\n llm: 'OpenAI',\r\n\r\n label: 'GPT o3',\r\n modelId: 'o3-2025-04-16',\r\n provider: 'OpenAI',\r\n features: ['text', 'reasoning'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o3-mini': {\r\n llm: 'OpenAI',\r\n alias: 'o3-mini-2025-01-31',\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'GPT o3 mini',\r\n modelId: 'o3-mini-2025-01-31',\r\n provider: 'OpenAI',\r\n features: ['text', 'reasoning'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'o3-mini-2025-01-31': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion o3 models\r\n\r\n // #region o1 models\r\n o1: {\r\n llm: 'OpenAI',\r\n alias: 'o1-2024-12-17',\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'GPT o1',\r\n modelId: 'o1-2024-12-17',\r\n provider: 'OpenAI',\r\n features: ['text', 'reasoning'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o1-2024-12-17': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 100_000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o1-mini': {\r\n llm: 'OpenAI',\r\n alias: 'o1-mini-2024-09-12',\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'GPT o1 mini',\r\n modelId: 'o1-mini-2024-09-12',\r\n provider: 'OpenAI',\r\n features: ['text'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 65_536, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o1-mini-2024-09-12': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 65_536, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o1-preview': {\r\n llm: 'OpenAI',\r\n alias: 'o1-preview-2024-09-12',\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'GPT o1 Preview',\r\n modelId: 'o1-preview-2024-09-12',\r\n provider: 'OpenAI',\r\n features: ['text'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 32_768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'o1-preview-2024-09-12': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 32_768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion o1 models\r\n\r\n // #region GPT-4-turbo\r\n 'gpt-4-turbo-latest': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-4-turbo-2024-04-09',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier'],\r\n\r\n label: 'GPT 4 Turbo Latest',\r\n modelId: 'gpt-4-turbo-2024-04-09',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-4-turbo': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-4-turbo-2024-04-09',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'GPTPlugin', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'GPT 4 Turbo',\r\n modelId: 'gpt-4-turbo-2024-04-09',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-4-turbo-2024-04-09': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 128000, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion GPT-4-turbo\r\n\r\n // #region GPT-4\r\n 'gpt-4-latest': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-4-0613',\r\n components: ['PromptGenerator', 'LLMAssistant'],\r\n\r\n label: 'GPT 4 Latest',\r\n modelId: 'gpt-4-0613',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-4': {\r\n llm: 'OpenAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'GPTPlugin', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'GPT 4',\r\n modelId: 'gpt-4o-2024-08-06',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-4-0613': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n hidden: true,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion GPT-4\r\n\r\n // #region GPT-3.5\r\n 'gpt-3.5-turbo-latest': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-3.5-turbo-0125',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'GPTPlugin', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'GPT 3.5 Turbo Latest',\r\n modelId: 'gpt-3.5-turbo-0125',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 16385, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-3.5-turbo': {\r\n llm: 'OpenAI',\r\n alias: 'gpt-3.5-turbo-0125',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'GPTPlugin', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'GPT 3.5 Turbo',\r\n modelId: 'gpt-3.5-turbo-0125',\r\n provider: 'OpenAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 16385, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n },\r\n 'gpt-3.5-turbo-0125': {\r\n llm: 'OpenAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 16385, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion GPT-3.5\r\n\r\n // # region OpenAI embeddings\r\n\r\n 'text-embedding-ada-002': {\r\n label: 'OpenAI Embeddings Ada 002',\r\n modelId: 'text-embedding-ada-002',\r\n provider: 'OpenAI',\r\n features: ['embeddings'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n credentials: ['internal', 'vault'],\r\n },\r\n 'text-embedding-3-large': {\r\n label: 'OpenAI Embeddings 3 Large',\r\n modelId: 'text-embedding-3-large',\r\n provider: 'OpenAI',\r\n features: ['embeddings'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n credentials: ['internal', 'vault'],\r\n },\r\n\r\n // #endregion OpenAI Models ==========================\r\n\r\n // #region Anthropic Models ==========================\r\n 'claude-4-opus': {\r\n label: 'Claude 4 Opus',\r\n modelId: 'claude-opus-4-20250514',\r\n provider: 'Anthropic',\r\n features: ['text', 'image', 'tools', 'reasoning'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 32000, maxReasoningTokens: 32000, enabled: true },\r\n\r\n credentials: 'internal',\r\n },\r\n 'claude-4-sonnet': {\r\n label: 'Claude 4 Sonnet',\r\n modelId: 'claude-sonnet-4-20250514',\r\n provider: 'Anthropic',\r\n features: ['text', 'image', 'tools', 'reasoning'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 64000, maxReasoningTokens: 32000, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3.7-sonnet': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-7-sonnet-20250219',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3.7 Sonnet',\r\n modelId: 'claude-3-7-sonnet-20250219',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image', 'reasoning'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 8192, maxReasoningTokens: 16384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3.7-sonnet-thinking': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-7-sonnet-20250219',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3.7 Sonnet Thinking',\r\n modelId: 'claude-3-7-sonnet-20250219',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image', 'reasoning'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 16384, maxReasoningTokens: 16384, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3.5-haiku': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-5-haiku-latest',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3.5 Haiku',\r\n modelId: 'claude-3-5-haiku-latest',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-5-haiku-latest': {\r\n llm: 'Anthropic',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-5-sonnet-latest': {\r\n llm: 'Anthropic',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3.5 Sonnet Latest',\r\n modelId: 'claude-3-5-sonnet-latest',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3.5-sonnet': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-5-sonnet-20240620',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3.5 Sonnet Stable',\r\n modelId: 'claude-3-5-sonnet-20240620',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-5-sonnet-20240620': {\r\n llm: 'Anthropic',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-opus': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-opus-20240229',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot', 'GenAILLM'],\r\n\r\n label: 'Claude 3 Opus',\r\n modelId: 'claude-3-opus-20240229',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-opus-20240229': {\r\n llm: 'Anthropic',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200000, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-sonnet': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-sonnet-20240229',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'Claude 3 Sonnet',\r\n modelId: 'claude-3-sonnet-20240229',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-sonnet-20240229': {\r\n llm: 'Anthropic',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200000, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-haiku': {\r\n llm: 'Anthropic',\r\n alias: 'claude-3-haiku-20240307',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'VisionLLM', 'AgentPlugin', 'Chatbot'],\r\n\r\n label: 'Claude 3 Haiku',\r\n modelId: 'claude-3-haiku-20240307',\r\n provider: 'Anthropic',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-3-haiku-20240307': {\r\n llm: 'Anthropic',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 200000, completionTokens: 4096, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'claude-2.1': {\r\n llm: 'Anthropic',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier'],\r\n\r\n label: 'Claude 2.1',\r\n modelId: 'claude-2.1',\r\n provider: 'Anthropic',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 200_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n },\r\n 'claude-instant-1.2': {\r\n llm: 'Anthropic',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier'],\r\n\r\n label: 'Claude Instant 1.2',\r\n modelId: 'claude-instant-1.2',\r\n provider: 'Anthropic',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 100_000, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n\r\n // #endregion Anthropic Models ==========================\r\n\r\n // #region Google AI Models ==========================\r\n\r\n // #region Gemini 2.0 flash\r\n 'gemini-2.5-flash': {\r\n llm: 'GoogleAI',\r\n\r\n label: 'Gemini 2.5 Flash Preview',\r\n modelId: 'gemini-2.5-flash-preview-04-17',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 65_536, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-2.0-flash': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 2.0 Flash',\r\n modelId: 'gemini-2.0-flash',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 8_192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-2.0-flash-lite': {\r\n llm: 'GoogleAI',\r\n\r\n label: 'Gemini 2.0 Flash Lite',\r\n modelId: 'gemini-2.0-flash-lite',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 8_192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-2.5-pro': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 2.5 Pro Preview',\r\n modelId: 'gemini-2.5-pro-preview-03-25',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 65_536, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-2.5-pro-exp': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 2.5 Pro Experimental',\r\n modelId: 'gemini-2.5-pro-exp-03-25',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['New', 'Personal'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 65_536, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Gemini 2.0 flash\r\n\r\n // #region Gemini 1.5 pro\r\n 'gemini-1.5-pro-exp-0801': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 1.5 Pro Experimental',\r\n modelId: 'gemini-1.5-pro-exp-0801',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 2_097_152, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-pro-latest-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.5-pro',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 1.5 Pro Latest Stable',\r\n modelId: 'gemini-1.5-pro',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 2_097_152, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-pro-latest': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM'],\r\n\r\n label: 'Gemini 1.5 Pro',\r\n modelId: 'gemini-1.5-pro',\r\n provider: 'GoogleAI',\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 2_097_152, completionTokens: 8_192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-pro-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.5-pro-001',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 1.5 Pro Stable',\r\n modelId: 'gemini-1.5-pro',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 2_097_152, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-pro': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 2097152, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-pro-001': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 2097152, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Gemini 1.5 pro\r\n\r\n // #region Gemini 1.5 flash\r\n 'gemini-1.5-flash-latest': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM'],\r\n\r\n label: 'Gemini 1.5 Flash Latest',\r\n modelId: 'gemini-1.5-flash-latest',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-flash-latest-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.5-flash',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM'],\r\n\r\n label: 'Gemini 1.5 Flash Latest Stable',\r\n modelId: 'gemini-1.5-flash',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-flash-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.5-flash-001',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'MultimodalLLM', 'GenAILLM'],\r\n\r\n label: 'Gemini 1.5 Flash Stable',\r\n modelId: 'gemini-1.5-flash-001',\r\n provider: 'GoogleAI',\r\n features: ['text', 'image', 'audio', 'video', 'document'],\r\n tags: ['Personal', 'deprecated'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 1_048_576, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-flash': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 1048576, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.5-flash-001': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 1048576, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Gemini 1.5 flash\r\n\r\n // #region Gemini 1.0 pro\r\n 'gemini-1.0-pro-latest': {\r\n llm: 'GoogleAI',\r\n components: ['PromptGenerator', 'LLMAssistant'],\r\n\r\n label: 'Gemini 1.0 Pro Latest',\r\n modelId: 'gemini-1.0-pro-latest',\r\n provider: 'GoogleAI',\r\n features: ['text'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 30_720, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.0-pro-latest-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.0-pro',\r\n components: ['PromptGenerator', 'LLMAssistant'],\r\n\r\n label: 'Gemini 1.0 Pro Latest Stable',\r\n modelId: 'gemini-1.0-pro',\r\n provider: 'GoogleAI',\r\n features: ['text'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 30_720, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.0-pro-stable': {\r\n llm: 'GoogleAI',\r\n alias: 'gemini-1.0-pro-001',\r\n components: ['PromptGenerator', 'LLMAssistant'],\r\n\r\n label: 'Gemini 1.0 Pro Stable',\r\n modelId: 'gemini-1.0-pro-001',\r\n provider: 'GoogleAI',\r\n features: ['text'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 30_720, completionTokens: 8192, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.0-pro': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 30_720, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemini-1.0-pro-001': {\r\n llm: 'GoogleAI',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 30_720, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Gemini 1.0 pro\r\n\r\n // #region Gemini Pro Vision\r\n 'gemini-pro-vision': {\r\n llm: 'GoogleAI',\r\n components: ['VisionLLM'],\r\n\r\n label: 'Gemini Pro Vision',\r\n modelId: 'gemini-pro-vision',\r\n provider: 'GoogleAI',\r\n features: ['image'],\r\n tags: ['Personal', 'legacy'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 12_288, completionTokens: 4096, enabled: true },\r\n hidden: true,\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Gemini Pro Vision\r\n\r\n // #endregion Google AI Models ==========================\r\n\r\n // #region Groq Models ==========================\r\n\r\n // #region Groq - Production Models\r\n 'llama-3.3-70b': {\r\n llm: 'Groq',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.3 70B',\r\n modelId: 'llama-3.3-70b-versatile',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 32_768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'groq-llama3-70b': {\r\n llm: 'Groq',\r\n alias: 'llama3-70b-8192',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 70B',\r\n modelId: 'llama3-70b-8192',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama3-70b-8192': {\r\n llm: 'Groq',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'groq-llama-3.1-8b-instant': {\r\n llm: 'Groq',\r\n alias: 'llama-3.1-8b-instant',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.1 8B',\r\n modelId: 'llama-3.1-8b-instant',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.1-8b-instant': {\r\n llm: 'Groq',\r\n tokens: 8000,\r\n completionTokens: 8000,\r\n enabled: false,\r\n keyOptions: { tokens: 131072, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-guard-3-8b': {\r\n llm: 'Groq',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama Guard 3 8B',\r\n modelId: 'llama-guard-3-8b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'groq-llama3-8b': {\r\n llm: 'Groq',\r\n alias: 'llama3-8b-8192',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 8B',\r\n modelId: 'llama3-8b-8192',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama3-8b-8192': {\r\n llm: 'Groq',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'groq-gemma2-9b': {\r\n llm: 'Groq',\r\n alias: 'gemma2-9b-it',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Google - Gemma 2 9B',\r\n modelId: 'gemma2-9b-it',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'gemma2-9b-it': {\r\n llm: 'Groq',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'groq-mixtral-8x7b': {\r\n llm: 'Groq',\r\n alias: 'mixtral-8x7b-32768',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Mistral - Mixtral 8x7b',\r\n modelId: 'mixtral-8x7b-32768',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'mixtral-8x7b-32768': {\r\n llm: 'Groq',\r\n tokens: 2048,\r\n completionTokens: 2048,\r\n enabled: false,\r\n keyOptions: { tokens: 32768, completionTokens: 32768, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Groq - Production Models\r\n\r\n // #region Groq - Preview Models\r\n 'qwen-qwq-32b': {\r\n llm: 'Groq',\r\n\r\n label: 'Qwen - QWQ 32b Preview',\r\n modelId: 'qwen-qwq-32b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'mistral-saba-24b': {\r\n llm: 'Groq',\r\n\r\n label: 'Mistral - Saba 24b Preview',\r\n modelId: 'mistral-saba-24b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'qwen-2.5-coder-32b': {\r\n llm: 'Groq',\r\n\r\n label: 'Qwen - 2.5 Coder 32b Preview',\r\n modelId: 'qwen-2.5-coder-32b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'qwen-2.5-32b': {\r\n llm: 'Groq',\r\n\r\n label: 'Qwen - 2.5 32b Preview',\r\n modelId: 'qwen-2.5-32b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-r1-distill-qwen-32b': {\r\n llm: 'Groq',\r\n\r\n label: 'DeepSeek - R1 Distill Qwen 32b Preview',\r\n modelId: 'deepseek-r1-distill-qwen-32b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 16_384, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-r1-distill-llama-70b': {\r\n llm: 'Groq',\r\n\r\n label: 'DeepSeek - R1 Distill Llama 70b Preview',\r\n modelId: 'deepseek-r1-distill-llama-70b',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Groq - Meta Preview Models\r\n 'meta-llama/llama-4-scout-17b-16e-instruct': {\r\n llm: 'Groq',\r\n\r\n label: 'Meta - Llama 4 Scout 17B 16E Instruct',\r\n modelId: 'meta-llama/llama-4-scout-17b-16e-instruct',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.3-70b-specdec': {\r\n llm: 'Groq',\r\n\r\n label: 'Meta - Llama 3.3 70B SpecDec Preview',\r\n modelId: 'llama-3.3-70b-specdec',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.2-1b-preview': {\r\n llm: 'Groq',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.2 1B Preview',\r\n modelId: 'llama-3.2-1b-preview',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.2-3b-preview': {\r\n llm: 'Groq',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.2 3B Preview',\r\n modelId: 'llama-3.2-3b-preview',\r\n provider: 'Groq',\r\n features: ['text'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.2-11b-vision-preview': {\r\n llm: 'Groq',\r\n components: ['PromptGenerator', 'LLMAssistant', 'VisionLLM', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.2 11B Vision Preview',\r\n modelId: 'llama-3.2-11b-vision-preview',\r\n provider: 'Groq',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n hidden: true, // !TEMP: we need to support image input for Groq\r\n\r\n credentials: 'vault',\r\n },\r\n 'llama-3.2-90b-vision-preview': {\r\n llm: 'Groq',\r\n\r\n label: 'Meta - Llama 3.2 90b Vision Preview',\r\n modelId: 'llama-3.2-90b-vision-preview',\r\n provider: 'Groq',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'Groq'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 8192, enabled: true },\r\n hidden: true, // !TEMP: we need to support image input for Groq\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Groq - Meta Preview Models\r\n\r\n // #endregion Groq - Preview Models\r\n\r\n // #endregion Groq Models ==========================\r\n\r\n // #region Together AI Models ==========================\r\n\r\n // #region Together AI - DeepSeek\r\n 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'DeepSeek - R1 Distill Qwen 14B',\r\n modelId: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-14B',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'DeepSeek - R1 Distill Qwen 1.5B',\r\n modelId: 'deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-ai/DeepSeek-R1-Distill-Llama-70B': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'DeepSeek - R1 Distill Llama 70B',\r\n modelId: 'deepseek-ai/DeepSeek-R1-Distill-Llama-70B',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-ai/DeepSeek-R1': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'DeepSeek - R1',\r\n modelId: 'deepseek-ai/DeepSeek-R1',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 128_000, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-ai/DeepSeek-V3': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'DeepSeek - V3',\r\n modelId: 'deepseek-ai/DeepSeek-V3',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'deepseek-ai/deepseek-llm-67b-chat': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'DeepSeek - Llama 67B Chat',\r\n modelId: 'deepseek-ai/deepseek-llm-67b-chat',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 4096, completionTokens: 4096, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - DeepSeek\r\n\r\n // #region Together AI - Meta\r\n 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Meta - Llama 4 Maverick (17Bx128E)',\r\n modelId: 'meta-llama/Llama-4-Maverick-17B-128E-Instruct-FP8',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 524_288, completionTokens: 524_288, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-4-Scout-17B-16E-Instruct': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Meta - Llama 4 Scout (17Bx16E)',\r\n modelId: 'meta-llama/Llama-4-Scout-17B-16E-Instruct',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools', 'image'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 327_680, completionTokens: 327_680, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3.3-70B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Meta - Llama 3.3 70B Instruct Turbo',\r\n modelId: 'meta-llama/Llama-3.3-70B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 131_072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.1 8B Instruct Turbo',\r\n modelId: 'meta-llama/Meta-Llama-3.1-8B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 131_072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.1 70B Instruct Turbo',\r\n modelId: 'meta-llama/Meta-Llama-3.1-70B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 131_072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.1 405B Instruct Turbo',\r\n modelId: 'meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 130_815, completionTokens: 130_815, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3-8B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 8B Instruct Turbo',\r\n modelId: 'meta-llama/Meta-Llama-3-8B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3-70B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 70B Instruct Turbo',\r\n modelId: 'meta-llama/Meta-Llama-3-70B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3.2-3B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Meta - Llama 3.2 3B Instruct Turbo',\r\n modelId: 'meta-llama/Llama-3.2-3B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3-8B-Instruct-Lite': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 8B Instruct Lite',\r\n modelId: 'meta-llama/Meta-Llama-3-8B-Instruct-Lite',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Meta-Llama-3-70B-Instruct-Lite': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 70B Instruct Lite',\r\n modelId: 'meta-llama/Meta-Llama-3-70B-Instruct-Lite',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3-8b-chat-hf': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 8B Chat',\r\n modelId: 'meta-llama/Llama-3-8b-chat-hf',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3-70b-chat-hf': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3 70B Chat',\r\n modelId: 'meta-llama/Llama-3-70b-chat-hf',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-2-13b-chat-hf': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant'], // * Excluded from 'PromptGenerator' (has introductory text with JSON response)\r\n\r\n label: 'Meta - Llama 2 13B Chat',\r\n modelId: 'meta-llama/Llama-2-13b-chat-hf',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 4096, completionTokens: 4096, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-Vision-Free': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'VisionLLM', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama Vision Free',\r\n modelId: 'meta-llama/Llama-Vision-Free',\r\n provider: 'TogetherAI',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131072, completionTokens: 131072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'VisionLLM', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.2 11B Vision Instruct Turbo',\r\n modelId: 'meta-llama/Llama-3.2-11B-Vision-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131072, completionTokens: 131072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n components: ['LLMAssistant', 'PromptGenerator', 'VisionLLM', 'GenAILLM'],\r\n\r\n label: 'Meta - Llama 3.2 90B Vision Instruct Turbo',\r\n modelId: 'meta-llama/Llama-3.2-90B-Vision-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'image'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131072, completionTokens: 131072, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Meta\r\n\r\n // #region Together AI - Google\r\n 'google/gemma-2-27b-it': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Google - Gemma 2 27B',\r\n modelId: 'google/gemma-2-27b-it',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'google/gemma-2-9b-it': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Google - Gemma 2 9B',\r\n modelId: 'google/gemma-2-9b-it',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'google/gemma-2b-it': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Google - Gemma 2 2B',\r\n modelId: 'google/gemma-2b-it',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Google\r\n\r\n // #region Together AI - Mistral\r\n 'mistralai/Mistral-7B-Instruct-v0.3': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'GenAILLM'],\r\n\r\n label: 'Mistral - 7B Instruct v0.3',\r\n modelId: 'mistralai/Mistral-7B-Instruct-v0.3',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'mistralai/Mistral-7B-Instruct-v0.2': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Mistral - 7B Instruct v0.2',\r\n modelId: 'mistralai/Mistral-7B-Instruct-v0.2',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'mistralai/Mistral-7B-Instruct-v0.1': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Mistral - 7B Instruct v0.1',\r\n modelId: 'mistralai/Mistral-7B-Instruct-v0.1',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 8192, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'mistralai/Mixtral-8x7B-Instruct-v0.1': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'Classifier', 'GenAILLM'],\r\n\r\n label: 'Mistral - 8x7B Instruct v0.1',\r\n modelId: 'mistralai/Mixtral-8x7B-Instruct-v0.1',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'mistralai/Mixtral-8x22B-Instruct-v0.1': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Mistral - 8x22B Instruct v0.1',\r\n modelId: 'mistralai/Mixtral-8x22B-Instruct-v0.1',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 65_536, completionTokens: 65_536, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Mistral\r\n\r\n // #region Together AI - Qwen\r\n 'Qwen/Qwen2.5-Coder-32B-Instruct': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - 2.5 Coder 32B',\r\n modelId: 'Qwen/Qwen2.5-Coder-32B-Instruct',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'Qwen/QwQ-32B-Preview': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - QwQ 32B Preview',\r\n modelId: 'Qwen/QwQ-32B-Preview',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'Qwen/Qwen2.5-7B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - 2.5 7B Instruct Turbo',\r\n modelId: 'Qwen/Qwen2.5-7B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'Qwen/Qwen2.5-72B-Instruct-Turbo': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - 2.5 72B Instruct Turbo',\r\n modelId: 'Qwen/Qwen2.5-72B-Instruct-Turbo',\r\n provider: 'TogetherAI',\r\n features: ['text', 'tools'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'Qwen/Qwen2-72B-Instruct': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - 2 72B Instruct',\r\n modelId: 'Qwen/Qwen2-72B-Instruct',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'Qwen/Qwen2-VL-72B-Instruct': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Qwen - 2 VL 72B Instruct',\r\n modelId: 'Qwen/Qwen2-VL-72B-Instruct',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Qwen\r\n\r\n // #region Together AI - Nvidia\r\n 'nvidia/Llama-3.1-Nemotron-70B-Instruct-HF': {\r\n llm: 'TogetherAI',\r\n\r\n label: 'Nvidia - Llama 3.1 Nemotron 70B',\r\n modelId: 'nvidia/Llama-3.1-Nemotron-70B-Instruct-HF',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['New', 'Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Nvidia\r\n\r\n // #region Together AI - Microsoft\r\n 'microsoft/WizardLM-2-8x22B': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Microsoft - WizardLM 2 8x22B',\r\n modelId: 'microsoft/WizardLM-2-8x22B',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 65_536, completionTokens: 65_536, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Microsoft\r\n\r\n // #region Together AI - databricks\r\n 'databricks/dbrx-instruct': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Databricks - DBRX Instruct',\r\n modelId: 'databricks/dbrx-instruct',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - databricks\r\n\r\n // #region Together AI - NousResearch\r\n 'NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'NousResearch - Hermes 2 Mixtral 8x7B DPO',\r\n modelId: 'NousResearch/Nous-Hermes-2-Mixtral-8x7B-DPO',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - NousResearch\r\n\r\n // #region Together AI - Upstage\r\n 'upstage/SOLAR-10.7B-Instruct-v1.0': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Upstage - SOLAR 10.7B Instruct v1.0',\r\n modelId: 'upstage/SOLAR-10.7B-Instruct-v1.0',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 4096, completionTokens: 4096, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Upstage\r\n\r\n // #region Together AI - Gryphe\r\n 'Gryphe/MythoMax-L2-13b': {\r\n llm: 'TogetherAI',\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n\r\n label: 'Gryphe - MythoMax L2 13B',\r\n modelId: 'Gryphe/MythoMax-L2-13b',\r\n provider: 'TogetherAI',\r\n features: ['text'],\r\n tags: ['Personal', 'TogetherAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 4096, completionTokens: 4096, enabled: true },\r\n\r\n baseURL: 'https://api.together.xyz/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Together AI - Gryphe\r\n\r\n // #endregion Together AI Models ==========================\r\n\r\n // #region Image Generation Models ============================\r\n\r\n // #region OpenAI Models gpt-image-1\r\n 'smythos/gpt-image-1': {\r\n label: 'GPT Image 1',\r\n modelId: 'gpt-image-1',\r\n provider: 'OpenAI',\r\n features: ['image-generation'],\r\n tags: ['New', 'SmythOS'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'gpt-image-1': {\r\n label: 'GPT Image 1',\r\n modelId: 'gpt-image-1',\r\n provider: 'OpenAI',\r\n features: ['image-generation'],\r\n tags: ['New', 'Personal'],\r\n enabled: false,\r\n keyOptions: { enabled: true },\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion gpt-image-1\r\n\r\n // #region OpenAI Models DALL-E\r\n 'dall-e-3': {\r\n label: 'DALL·E 3',\r\n modelId: 'dall-e-3',\r\n provider: 'OpenAI',\r\n features: ['image-generation'],\r\n tags: ['Deprecated'],\r\n enabled: true,\r\n\r\n credentials: 'vault',\r\n },\r\n 'dall-e-2': {\r\n label: 'DALL·E 2',\r\n modelId: 'dall-e-2',\r\n provider: 'OpenAI',\r\n features: ['image-generation'],\r\n tags: ['Deprecated'],\r\n enabled: true,\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion OpenAI Models DALL-E\r\n\r\n // #region Runware Models\r\n 'smythos/flux.1-schnell': {\r\n label: 'FLUX Schnell',\r\n modelId: 'runware:100@1',\r\n provider: 'Runware',\r\n features: [\r\n 'image-generation', // Legacy\r\n 'text-to-image',\r\n 'image-to-image',\r\n ],\r\n tags: ['SmythOS', '1.0'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/flux.1-dev': {\r\n label: 'FLUX Dev',\r\n modelId: 'runware:101@1',\r\n provider: 'Runware',\r\n features: [\r\n 'image-generation', // Legacy\r\n 'text-to-image',\r\n 'image-to-image',\r\n ],\r\n tags: ['SmythOS', '1.0'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n // #region Full face detection models\r\n 'smythos/face_yolov8n': {\r\n label: 'Face YOLOv8n',\r\n modelId: 'runware:35@1',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Full face detection'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/face_yolov8s': {\r\n label: 'Face YOLOv8s',\r\n modelId: 'runware:35@2',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Full face detection'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/mediapipe_face_full': {\r\n label: 'MediaPipe Face Full',\r\n modelId: 'runware:35@6',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Full face detection'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/mediapipe_face_short': {\r\n label: 'MediaPipe Face Short',\r\n modelId: 'runware:35@7',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Full face detection'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/mediapipe_face_mesh': {\r\n label: 'MediaPipe Face Mesh',\r\n modelId: 'runware:35@8',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Full face detection'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n // #endregion Full face detection models\r\n\r\n // #region Facial features models\r\n 'smythos/mediapipe_face_mesh_eyes_only': {\r\n label: 'MediaPipe Face Mesh Eyes Only',\r\n modelId: 'runware:35@9',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/eyes_mesh_mediapipe': {\r\n label: 'Eyes Mesh MediaPipe',\r\n modelId: 'runware:35@15',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/nose_mesh_mediapipe': {\r\n label: 'Nose Mesh MediaPipe',\r\n modelId: 'runware:35@13',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/lips_mesh_mediapipe': {\r\n label: 'Lips Mesh MediaPipe',\r\n modelId: 'runware:35@14',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/eyes_lips_mesh': {\r\n label: 'Eyes & Lips Mesh',\r\n modelId: 'runware:35@10',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/nose_eyes_mesh': {\r\n label: 'Nose & Eyes Mesh',\r\n modelId: 'runware:35@11',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n 'smythos/nose_lips_mesh': {\r\n label: 'Nose & Lips Mesh',\r\n modelId: 'runware:35@12',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Facial features'],\r\n enabled: true,\r\n },\r\n // #endregion Facial features models\r\n\r\n // #region Other body parts models\r\n 'smythos/hand_yolov8n': {\r\n label: 'Hand YOLOv8n',\r\n modelId: 'runware:35@3',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Other body parts'],\r\n enabled: true,\r\n },\r\n 'smythos/person_yolov8n-seg': {\r\n label: 'Person YOLOv8n-seg',\r\n modelId: 'runware:35@4',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Other body parts'],\r\n enabled: true,\r\n },\r\n 'smythos/person_yolov8s-seg': {\r\n label: 'Person YOLOv8s-seg',\r\n modelId: 'runware:35@5',\r\n provider: 'Runware',\r\n features: ['image-inpainting'],\r\n tags: ['SmythOS', 'Other body parts'],\r\n enabled: true,\r\n\r\n credentials: 'internal',\r\n },\r\n // #endregion Runware Models\r\n\r\n // #region Retrocompatible Runware Models\r\n // TODO: Will be removed a few days later\r\n 'flux.1-schnell': {\r\n label: 'FLUX.1 (Schnell)',\r\n modelId: 'runware:100@1',\r\n provider: 'Runware',\r\n features: ['image-generation'],\r\n tags: ['SmythOS'],\r\n enabled: false,\r\n\r\n credentials: 'vault',\r\n },\r\n 'flux.1-dev': {\r\n label: 'FLUX.1 (Dev)',\r\n modelId: 'runware:101@1',\r\n provider: 'Runware',\r\n features: ['image-generation'],\r\n tags: ['SmythOS'],\r\n enabled: false,\r\n\r\n credentials: 'vault',\r\n },\r\n // #endregion Retrocompatible Runware Models\r\n\r\n // #endregion Image Generation Models ============================\r\n\r\n // xAI models\r\n grok: {\r\n llm: 'xAI',\r\n\r\n label: 'Grok',\r\n modelId: 'grok-2-latest',\r\n provider: 'xAI',\r\n features: ['text', 'tools'],\r\n tags: ['Personal', 'xAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n keyOptions: { tokens: 131_072, completionTokens: 8192, enabled: true },\r\n\r\n baseURL: 'https://api.x.ai/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n 'grok-2-vision': {\r\n llm: 'xAI',\r\n\r\n label: 'Grok Vision',\r\n modelId: 'grok-2-vision-latest',\r\n provider: 'xAI',\r\n features: ['image'],\r\n tags: ['New', 'Personal', 'xAI'],\r\n tokens: 0,\r\n completionTokens: 0,\r\n enabled: false,\r\n hidden: true,\r\n keyOptions: { tokens: 32_768, completionTokens: 32_768, enabled: true },\r\n\r\n baseURL: 'https://api.x.ai/v1',\r\n\r\n credentials: 'vault',\r\n },\r\n\r\n // #endregion [User Models] ==============================================================\r\n};\r\n\r\n/******************************************************\r\n * ! DO NOT MODIFY THIS FILE INDEPENDENTLY\r\n * ! TO ENSURE CONSISTENCY, THIS FILE IS SYNCED WITH\r\n * ! THE APP AND SRE VERSIONS\r\n ******************************************************/\r\n","//! ***IMPORTANT***\r\n// * WE HAVE SAME FILE IN THREE PLACE, SO ANY CHANGES SHOULD BE SYNCED\r\n// * - /smyth-builder-ui/src/shared/custom-models.ts\r\n// * - /smyth-builder-server/src/services/LLMHelper/custom-models.ts\r\n// * - /smyth-runtime/src/subsystems/LLMManager/custom-models.ts\r\n//! ***IMPORTANT***\r\n/**\r\n * Custom model configurations for various AI providers.\r\n * This template is useful for maintaining up-to-date model aliases and token information,\r\n * even though we store custom model data in the database.\r\n */\r\n\r\nexport const customModels = {\r\n /**************************************************\r\n * AWS Bedrock Models\r\n **************************************************/\r\n\r\n /*\r\n Context token information sourced from the AWS Bedrock Console:\r\n https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/overview\r\n \r\n Completion token information sourced from the AWS Bedrock Text Playground:\r\n https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/text-playground\r\n\r\n Supported model features information sourced from - https://docs.aws.amazon.com/bedrock/latest/userguide/conversation-inference-supported-models-features.html\r\n */\r\n\r\n //#region AI21 Labs Models\r\n 'ai21.jamba-1-5-mini-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'AI21 Labs - Jamba 1.5 Mini',\r\n tokens: 256000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'GenAILLM'],\r\n tags: ['new'],\r\n },\r\n 'ai21.jamba-1-5-large-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'AI21 Labs - Jamba 1.5 Large',\r\n tokens: 256000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'GenAILLM'],\r\n tags: ['new'],\r\n },\r\n 'ai21.jamba-instruct-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'AI21 Labs - Jamba-Instruct',\r\n tokens: 256000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'ai21.j2-ultra-v1': {\r\n llm: 'Bedrock',\r\n label: 'AI21 Labs - Jurassic-2 Ultra',\r\n tokens: 8191,\r\n completionTokens: 8191,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'ai21.j2-mid-v1': {\r\n llm: 'Bedrock',\r\n label: 'AI21 Labs - Jurassic-2 Mid',\r\n tokens: 8191,\r\n completionTokens: 8191,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n //#endregion AI21 Labs Models\r\n\r\n //#region Amazon Models\r\n 'amazon.titan-text-premier-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Amazon - Titan Text Premier',\r\n tokens: 32000,\r\n completionTokens: 3000,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'amazon.titan-text-express-v1': {\r\n llm: 'Bedrock',\r\n label: 'Amazon - Titan Text G1 - Express',\r\n tokens: 8192,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'amazon.titan-text-lite-v1': {\r\n llm: 'Bedrock',\r\n label: 'Amazon - Titan Text G1 - Lite',\r\n tokens: 4096,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n // 'Amazon - Titan Embeddings G1 - Text': { alias: 'amazon.titan-embed-text-v1' }, // Converse API doesn't support\r\n // 'Amazon - Titan Embedding Text v2': { alias: 'amazon.titan-embed-text-v2:0' }, // Converse API doesn't support\r\n // 'Amazon - Titan Multimodal Embeddings G1': { alias: 'amazon.titan-embed-image-v1' }, // Converse API doesn't support\r\n // 'Amazon - Titan Image Generator G1 V1': { alias: 'amazon.titan-image-generator-v1' }, // Converse API doesn't support\r\n // 'Amazon - Titan Image Generator G1 V2': { alias: 'amazon.titan-image-generator-v2:0' }, // Converse API doesn't support\r\n\r\n //#endregion Amazon Models\r\n\r\n //#region Anthropic Models\r\n // * NOTE: It's required to submit business info to get access for Anthropic models\r\n // * @Ref of Anthropic tokens and completionTokens - https://docs.anthropic.com/en/docs/about-claude/models\r\n 'us.anthropic.claude-3-5-haiku-20241022-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3.5 Haiku',\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v1:0', 'new'],\r\n },\r\n 'us.anthropic.claude-3-5-sonnet-20241022-v2:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3.5 Sonnet',\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v2:0', 'new'],\r\n },\r\n 'anthropic.claude-3-5-sonnet-20240620-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3.5 Sonnet',\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v1:0'],\r\n },\r\n 'anthropic.claude-3-sonnet-20240229-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3 Sonnet',\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v1:0'],\r\n },\r\n 'anthropic.claude-3-haiku-20240307-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3 Haiku',\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v1:0'],\r\n },\r\n 'anthropic.claude-3-opus-20240229-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 3 Opus',\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n tags: ['v1:0'],\r\n },\r\n 'anthropic.claude-v2:1': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 2.1',\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n tags: ['v2:1'],\r\n },\r\n 'anthropic.claude-v2': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude 2.0',\r\n tokens: 100000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'anthropic.claude-instant-v1': {\r\n llm: 'Bedrock',\r\n label: 'Anthropic - Claude Instant',\r\n tokens: 100000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n //#endregion Anthropic Models\r\n\r\n //#region Cohere Models\r\n 'cohere.command-r-plus-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Cohere - Command R+',\r\n tokens: 128000,\r\n completionTokens: 4000, // Found 4000 Max tokens in the Playground\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n },\r\n 'cohere.command-r-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Cohere - Command R',\r\n tokens: 128000,\r\n completionTokens: 4000, // Found 4000 Max tokens in the Playground\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: true,\r\n components: ['PromptGenerator', 'LLMAssistant', 'AgentPlugin', 'Chatbot'],\r\n },\r\n 'cohere.command-text-v14': {\r\n llm: 'Bedrock',\r\n label: 'Cohere - Command',\r\n tokens: 4000, // Found 4k\r\n completionTokens: 4000, // Found 4000 Max tokens in the Playground\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'cohere.command-light-text-v14': {\r\n llm: 'Bedrock',\r\n label: 'Cohere - Command Light',\r\n tokens: 4000, // 4k tokens\r\n completionTokens: 4000, // Found 4000 Max tokens in the Playground\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n // 'Cohere - Embed English': { alias: 'cohere.embed-english-v3' }, // Converse API doesn't support\r\n // 'Cohere - Embed Multilingual': { alias: 'cohere.embed-multilingual-v3' }, // Converse API doesn't support\r\n //#endregion Cohere Models\r\n\r\n //#region Meta Models\r\n\r\n // 'Meta - Llama 2 Chat 13B' : { alias: 'meta.llama2-13b-chat-v1' } // Don't have access to the model\r\n // 'Meta - Llama 2 Chat 70B' : { alias: 'meta.llama2-70b-chat-v1' } // Don't have access to the model\r\n 'us.meta.llama3-2-1b-instruct-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Meta - Llama 3.2 1B Instruct',\r\n tokens: 200000,\r\n completionTokens: 2048,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n tags: ['new'],\r\n },\r\n 'us.meta.llama3-2-3b-instruct-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Meta - Llama 3.2 3B Instruct',\r\n tokens: 200000,\r\n completionTokens: 2048,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n tags: ['new'],\r\n },\r\n 'meta.llama3-8b-instruct-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Meta - Llama 3 8B Instruct',\r\n tokens: 8192,\r\n completionTokens: 2048,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'meta.llama3-70b-instruct-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Meta - Llama 3 70B Instruct',\r\n tokens: 8192,\r\n completionTokens: 2048,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n // 'Meta - Llama 3.1 8B Instruct': { alias: 'meta.llama3-1-8b-instruct-v1:0' }, // The provided model identifier is invalid.\r\n // 'Meta - Llama 3.1 70B Instruct': { alias: 'meta.llama3-1-70b-instruct-v1:0' }, // The provided model identifier is invalid.\r\n // 'Meta - Llama 3.1 405B Instruct': { alias: 'meta.llama3-1-405b-instruct-v1:0' }, // The provided model identifier is invalid.\r\n\r\n //#endregion Meta Models\r\n\r\n //#region Mistral Models\r\n 'mistral.mistral-7b-instruct-v0:2': {\r\n llm: 'Bedrock',\r\n label: 'Mistral AI - Mistral 7B Instruct',\r\n tokens: 32000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'mistral.mixtral-8x7b-instruct-v0:1': {\r\n llm: 'Bedrock',\r\n label: 'Mistral AI - Mixtral 8X7B Instruct',\r\n tokens: 32000,\r\n completionTokens: 4096,\r\n supportsSystemPrompt: false,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'mistral.mistral-large-2402-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Mistral AI - Mistral Large',\r\n tokens: 32000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n // 'Mistral AI - Mistral Large 2 (24.07)' : { alias: 'mistral.mistral-large-2407-v1:0' } // The provided model identifier is invalid.\r\n 'mistral.mistral-small-2402-v1:0': {\r\n llm: 'Bedrock',\r\n label: 'Mistral AI - Mistral Small',\r\n tokens: 32000,\r\n completionTokens: 8192,\r\n supportsSystemPrompt: true,\r\n supportsStreamingToolUse: false,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n //#endregion Mistral Models\r\n\r\n //#region Stability Models\r\n // 'Stability AI - Stable Diffusion XL 0.x' : { alias: 'stability.stable-diffusion-xl-v0' } // Converse API doesn't support\r\n // 'Stability AI - Stable Diffusion XL 1.x' : { alias: 'stability.stable-diffusion-xl-v1' } // Converse API doesn't support\r\n //#endregion Stability Models\r\n\r\n /**************************************************\r\n * Vertex AI Models\r\n **************************************************/\r\n\r\n /*\r\n Context token information sourced from :\r\n Vertex AI documentation - https://cloud.google.com/vertex-ai/generative-ai/docs/learn/models\r\n Anthropic - https://docs.anthropic.com/en/docs/about-claude/models\r\n \r\n Completion token information sourced from:\r\n Vertex AI Text Playground - https://console.cloud.google.com/vertex-ai/generative/language/create/text?model=text-bison@001&authuser=1&project=opt-smythos-vertexia-432522\r\n */\r\n\r\n 'gemini-1.5-flash': {\r\n llm: 'VertexAI',\r\n label: 'Gemini 1.5 Flash',\r\n supportsSystemPrompt: true,\r\n tokens: 1048576,\r\n completionTokens: 8192,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'gemini-1.5-pro': {\r\n llm: 'VertexAI',\r\n label: 'Gemini 1.5 Pro',\r\n supportsSystemPrompt: true,\r\n tokens: 2097152,\r\n completionTokens: 8192,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'gemini-1.0-pro': {\r\n llm: 'VertexAI',\r\n label: 'Gemini 1.0 Pro',\r\n supportsSystemPrompt: true,\r\n tokens: 32760,\r\n completionTokens: 8192,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-5-haiku': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3.5 Haiku',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n tags: ['new'],\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-5-sonnet-v2': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3.5 Sonnet',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n tags: ['v2', 'new'],\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-5-sonnet': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3.5 Sonnet',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 8192,\r\n tags: ['v1'],\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-sonnet': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3 Sonnet',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-opus': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3 Opus',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'claude-3-haiku': {\r\n llm: 'VertexAI',\r\n label: 'Claude 3 Haiku',\r\n supportsSystemPrompt: true,\r\n tokens: 200000,\r\n completionTokens: 4096,\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n gemma2: {\r\n llm: 'VertexAI',\r\n label: 'Gemma 2',\r\n supportsSystemPrompt: true,\r\n tokens: 8192, // @Ref https://huggingface.co/blog/gemma2\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/gemma2?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n gemma: {\r\n llm: 'VertexAI',\r\n label: 'Gemma',\r\n supportsSystemPrompt: true,\r\n tokens: 8192, // @Ref https://huggingface.co/blog/gemma2\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/gemma?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n codegemma: {\r\n llm: 'VertexAI',\r\n label: 'CodeGemma',\r\n supportsSystemPrompt: true,\r\n tokens: 8192, // @Ref - https://huggingface.co/google/gemma-7b-it/discussions/73\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/google/model-garden/codegemma?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'llama3-405b-instruct-maas': {\r\n llm: 'VertexAI',\r\n label: 'Llama 3.1 API Service',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // @Ref - https://docs.together.ai/docs/chat-models\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama3-405b-instruct-maas?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n llama3_1: {\r\n llm: 'VertexAI',\r\n label: 'Llama 3.1',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // by querying with Gemini - https://gemini.google.com/\r\n completionTokens: 4096, // by querying with Gemini - https://gemini.google.com/\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'llama-guard': {\r\n llm: 'VertexAI',\r\n label: 'Llama Guard',\r\n supportsSystemPrompt: true,\r\n tokens: 8192, // @Ref - by querying with Gemini - https://gemini.google.com/\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama-guard?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n llama3: {\r\n llm: 'VertexAI',\r\n label: 'Llama 3',\r\n supportsSystemPrompt: true,\r\n tokens: 8192, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama3?_ga=2.79473366.358158393.1724662649-247251619.1697981116&authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama3?_ga=2.79473366.358158393.1724662649-247251619.1697981116&authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n llama2: {\r\n llm: 'VertexAI',\r\n label: 'Llama 2',\r\n value: 'llama2',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama2?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/meta/model-garden/llama2?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'mistral-large': {\r\n llm: 'VertexAI',\r\n label: 'Mistral Large (2407)',\r\n supportsSystemPrompt: true,\r\n tokens: 128000, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/mistralai/model-garden/mistral-large?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 8192, // Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'mistral-nemo': {\r\n llm: 'VertexAI',\r\n label: 'Mistral Nemo',\r\n supportsSystemPrompt: true,\r\n tokens: 128000, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/mistralai/model-garden/mistral-nemo?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 8192, // Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n codestral: {\r\n llm: 'VertexAI',\r\n label: 'Codestral',\r\n supportsSystemPrompt: true,\r\n tokens: 32000, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/mistralai/model-garden/codestral?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 4096, // Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n mixtral: {\r\n llm: 'VertexAI',\r\n label: 'Mixtral',\r\n supportsSystemPrompt: true,\r\n tokens: 32000, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/mistral-ai/model-garden/mixtral?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 4096, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/mistral-ai/model-garden/mixtral?authuser=1&project=opt-smythos-vertexia-432522\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'chat-bison': {\r\n llm: 'VertexAI',\r\n label: 'PaLM 2 Chat Bison',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // @Ref - by querying with Gemini - https://gemini.google.com/\r\n completionTokens: 2048, // @Ref - https://console.cloud.google.com/vertex-ai/generative/language/create/chat?model=chat-bison@002&authuser=1&project=opt-smythos-vertexia-432522 [Playground]\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'text-bison': {\r\n llm: 'VertexAI',\r\n label: 'PaLM 2 Text Bison',\r\n supportsSystemPrompt: true,\r\n tokens: 32768, // by querying with Gemini - https://gemini.google.com/\r\n completionTokens: 2048, // @Ref - https://console.cloud.google.com/vertex-ai/generative/language/create/text?model=text-bison@001&authuser=1&project=opt-smythos-vertexia-432522 [Playground]\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n phi3: {\r\n llm: 'VertexAI',\r\n label: 'Phi-3',\r\n supportsSystemPrompt: true,\r\n tokens: 128000, // @Ref - https://console.cloud.google.com/vertex-ai/publishers/microsoft/model-garden/phi3?authuser=1&project=opt-smythos-vertexia-432522\r\n completionTokens: 8192, // Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n qwen2: {\r\n llm: 'VertexAI',\r\n label: 'Qwen2',\r\n supportsSystemPrompt: true,\r\n tokens: 131072, // @Ref - https://huggingface.co/Qwen/Qwen2-72B-Instruct\r\n completionTokens: 8192, // Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n mammut: {\r\n llm: 'VertexAI',\r\n label: 'MaMMUT',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // @Ref - by querying with Gemini - https://gemini.google.com/\r\n completionTokens: 2048, // @Ref - by querying with Gemini - https://gemini.google.com/\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'lmsys-vicuna-7b': {\r\n llm: 'VertexAI',\r\n label: 'Vicuna',\r\n supportsSystemPrompt: true,\r\n tokens: 4096, // @Ref - https://docs.together.ai/docs/chat-models\r\n completionTokens: 2048, // @Ref - Guessing from the context window (tokens)\r\n components: ['PromptGenerator', 'LLMAssistant', 'GenAILLM'],\r\n },\r\n 'bio-gpt': {\r\n llm: 'VertexAI',\r\n label: 'BioGPT',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'microsoft-biomedclip': {\r\n llm: 'VertexAI',\r\n label: 'BiomedCLIP',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n mistral: {\r\n llm: 'VertexAI',\r\n label: 'Mistral Self-host (7B & Nemo)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n nllb: {\r\n llm: 'VertexAI',\r\n label: 'NLLB',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'codellama-7b-hf': {\r\n llm: 'VertexAI',\r\n label: 'Code Llama',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'palmyra-med': {\r\n llm: 'VertexAI',\r\n label: 'Palmyra Med (Writer)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'llama-2-quantized': {\r\n llm: 'VertexAI',\r\n label: 'Llama 2 (Quantized)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'bert-base-uncased': {\r\n llm: 'VertexAI',\r\n label: 'BERT (PEFT)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'falcon-instruct-7b-peft': {\r\n llm: 'VertexAI',\r\n label: 'Falcon-instruct (PEFT)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n openllama: {\r\n llm: 'VertexAI',\r\n label: 'OpenLLaMA (PEFT)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'roberta-large': {\r\n llm: 'VertexAI',\r\n label: 'RoBERTa-large (PEFT)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'xlm-roberta-large': {\r\n llm: 'VertexAI',\r\n label: 'XLM-RoBERTa-large (PEFT)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'bart-large-cnn': {\r\n llm: 'VertexAI',\r\n label: 'Bart-large-cnn',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'dolly-v2': {\r\n llm: 'VertexAI',\r\n label: 'Dolly-v2',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n imagetext: {\r\n llm: 'VertexAI',\r\n label: 'Imagen for Captioning & VQA',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'codechat-bison': {\r\n llm: 'VertexAI',\r\n label: 'Codey for Code Chat',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'code-bison': {\r\n llm: 'VertexAI',\r\n label: 'Codey for Code Generation',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'code-gecko': {\r\n llm: 'VertexAI',\r\n label: 'Codey for Code Completion',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'text-unicorn': {\r\n llm: 'VertexAI',\r\n label: 'PaLM 2 Text Unicorn',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'textembedding-gecko': {\r\n llm: 'VertexAI',\r\n label: 'Embeddings for Text',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 't5-flan': {\r\n llm: 'VertexAI',\r\n label: 'T5-FLAN',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 't5-1.1': {\r\n llm: 'VertexAI',\r\n label: 'T5-1.1',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'blip2-opt-2.7-b': {\r\n llm: 'VertexAI',\r\n label: 'BLIP2',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'instruct-pix2pix': {\r\n llm: 'VertexAI',\r\n label: 'InstructPix2Pix',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'bert-base': {\r\n llm: 'VertexAI',\r\n label: 'BERT',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'mediapipe-mobile-bert-classifier': {\r\n llm: 'VertexAI',\r\n label: 'MobileBERT Classifier (MediaPipe)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'mediapipe-average-word-embedding-classifier': {\r\n llm: 'VertexAI',\r\n label: 'Average Word Embedding Classifier (MediaPipe)',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n pic2word: {\r\n llm: 'VertexAI',\r\n label: 'Pic2Word Composed Image Retrieval',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'text-translation': {\r\n llm: 'VertexAI',\r\n label: 'Text Translation',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'language-v1-moderate-text': {\r\n llm: 'VertexAI',\r\n label: 'Text Moderation',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'language-v1-analyze-syntax': {\r\n llm: 'VertexAI',\r\n label: 'Syntax analysis',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'language-v1-analyze-entity-sentiment': {\r\n llm: 'VertexAI',\r\n label: 'Entity sentiment analysis',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'language-v1-analyze-sentiment': {\r\n llm: 'VertexAI',\r\n label: 'Sentiment analysis',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'language-v1-classify-text-v1': {\r\n llm: 'VertexAI',\r\n label: 'Content classification',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n 'pt-test': {\r\n llm: 'VertexAI',\r\n label: 'Entity analysis',\r\n supportsSystemPrompt: false,\r\n tokens: 4096, // Guessed value, no reference\r\n completionTokens: 4096, // Guessed value, no reference\r\n components: ['PromptGenerator', 'GenAILLM'],\r\n },\r\n};\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport { TCustomLLMModel, TLLMCredentials, TLLMModel, TLLMModelsList, TLLMProvider } from '@sre/types/LLM.types';\r\nimport { customModels } from '../custom-models';\r\nimport { LocalCache } from '@sre/helpers/LocalCache.helper';\r\n\r\nexport interface IModelsProviderRequest {\r\n getModels(): Promise<any>;\r\n getMaxContextTokens(model: string, hasAPIKey?: boolean): Promise<number>;\r\n addModels(models: TLLMModelsList): Promise<void>;\r\n getModelInfo(model: string | TLLMModel | TCustomLLMModel, hasAPIKey?: boolean): Promise<TLLMModel>;\r\n getModelId(model: string | TLLMModel | TCustomLLMModel): Promise<string>;\r\n getProvider(model: string | TLLMModel | TCustomLLMModel): Promise<string>;\r\n isStandardLLM(model: string | TLLMModel | TCustomLLMModel): Promise<boolean>;\r\n adjustMaxCompletionTokens(model: string | TLLMModel | TCustomLLMModel, maxCompletionTokens: number, hasAPIKey?: boolean): Promise<number>;\r\n getMaxContextTokens(model: string | TLLMModel | TCustomLLMModel, hasAPIKey?: boolean): Promise<number>;\r\n getMaxCompletionTokens(model: string | TLLMModel | TCustomLLMModel, hasAPIKey?: boolean): Promise<number>;\r\n validateTokensLimit({\r\n model,\r\n promptTokens,\r\n completionTokens,\r\n hasAPIKey,\r\n }: {\r\n model: string | TLLMModel | TCustomLLMModel;\r\n promptTokens: number;\r\n completionTokens: number;\r\n hasAPIKey?: boolean;\r\n }): Promise<void>;\r\n}\r\n\r\nexport abstract class ModelsProviderConnector extends SecureConnector {\r\n protected static localCache = new LocalCache();\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n public abstract getModels(acRequest: AccessRequest): Promise<TLLMModelsList>;\r\n public abstract addModels(acRequest: AccessRequest, models: TLLMModelsList): Promise<void>;\r\n\r\n public requester(candidate: AccessCandidate): IModelsProviderRequest {\r\n const cacheKey = `ModelsProviderConnector:${candidate.toString()}`;\r\n if (ModelsProviderConnector.localCache.has(cacheKey)) {\r\n //update the TTL every time the requester is called\r\n return ModelsProviderConnector.localCache.get(cacheKey, 60 * 60 * 1000) as IModelsProviderRequest;\r\n }\r\n\r\n let teamModels = null;\r\n let customModels = null;\r\n\r\n const loadTeamModels = async () => {\r\n if (!teamModels) {\r\n try {\r\n const builtinmodels = await this.getModels(candidate.readRequest);\r\n customModels = await this.getCustomModels(candidate);\r\n teamModels = { ...builtinmodels, ...customModels };\r\n } catch (error) {\r\n return null;\r\n }\r\n }\r\n return teamModels;\r\n };\r\n loadTeamModels();\r\n\r\n const instance: IModelsProviderRequest = {\r\n getModels: async () => {\r\n return await loadTeamModels();\r\n },\r\n addModels: async (models: TLLMModelsList) => {\r\n return await this.addModels(candidate.readRequest, models);\r\n },\r\n getModelInfo: async (model: string | TLLMModel | TCustomLLMModel, hasAPIKey: boolean = false) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model, hasAPIKey);\r\n return modelInfo;\r\n },\r\n\r\n getModelId: async (model: string | TLLMModel | TCustomLLMModel) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n return this.getModelId(candidate.readRequest, teamModels, model);\r\n },\r\n getProvider: async (model: string | TLLMModel | TCustomLLMModel) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n return this.getProvider(candidate.readRequest, teamModels, model);\r\n },\r\n isStandardLLM: async (model: string | TLLMModel | TCustomLLMModel) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model);\r\n return !modelInfo.isCustomLLM;\r\n },\r\n adjustMaxCompletionTokens: async (\r\n model: string | TLLMModel | TCustomLLMModel,\r\n maxCompletionTokens: number,\r\n hasAPIKey: boolean = false,\r\n ) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model, hasAPIKey);\r\n return Math.min(maxCompletionTokens || 512, modelInfo?.completionTokens || modelInfo?.tokens || maxCompletionTokens || 512);\r\n },\r\n getMaxContextTokens: async (model: string | TLLMModel | TCustomLLMModel, hasAPIKey: boolean = false) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model, hasAPIKey);\r\n return modelInfo?.tokens || 1024;\r\n },\r\n getMaxCompletionTokens: async (model: string | TLLMModel | TCustomLLMModel, hasAPIKey: boolean = false) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model, hasAPIKey);\r\n return modelInfo?.completionTokens || modelInfo?.tokens || 512;\r\n },\r\n validateTokensLimit: async ({\r\n model,\r\n promptTokens,\r\n completionTokens,\r\n hasAPIKey,\r\n }: {\r\n model: string | TLLMModel | TCustomLLMModel;\r\n promptTokens: number;\r\n completionTokens: number;\r\n hasAPIKey: boolean;\r\n }) => {\r\n const teamModels = typeof model === 'string' ? await loadTeamModels() : {};\r\n const modelInfo = await this.getModelInfo(candidate.readRequest, teamModels, model, hasAPIKey);\r\n const allowedContextTokens = modelInfo?.tokens;\r\n const totalTokens = promptTokens + completionTokens;\r\n\r\n const teamAPIKeyExceededMessage = `This models' maximum content length is ${allowedContextTokens} tokens. (This is the sum of your prompt with all variables and the maximum output tokens you've set in Advanced Settings) However, you requested approx ${totalTokens} tokens (${promptTokens} in the prompt, ${completionTokens} in the output). Please reduce the length of either the input prompt or the Maximum output tokens.`;\r\n const noAPIKeyExceededMessage = `Input exceeds max tokens limit of ${allowedContextTokens}. Please add your API key and select Personal tagged models to unlock full length.`;\r\n\r\n if (totalTokens > allowedContextTokens) {\r\n throw new Error(hasAPIKey ? teamAPIKeyExceededMessage : noAPIKeyExceededMessage);\r\n }\r\n },\r\n };\r\n ModelsProviderConnector.localCache.set(cacheKey, instance, 60 * 60 * 1000); // cache for 1 hour\r\n return instance;\r\n }\r\n\r\n protected async getModelInfo(\r\n acRequest: AccessRequest,\r\n models: TLLMModelsList,\r\n model: string | TLLMModel | TCustomLLMModel,\r\n hasAPIKey: boolean = false,\r\n ): Promise<TLLMModel> {\r\n //model can be passed directly, in which case we do not need to look it up in the models list\r\n if (typeof model === 'object' && model.modelId) {\r\n return model;\r\n }\r\n\r\n //model can be passed as a string, in which case we need to look it up in the models list\r\n\r\n const modelId = await this.getModelId(acRequest, models, model);\r\n const alias = models?.[model as string]?.alias;\r\n const aliasModelInfo = models?.[alias];\r\n\r\n const modelInfo = models?.[model as string];\r\n\r\n const aliasKeyOptions = aliasModelInfo && hasAPIKey ? aliasModelInfo?.keyOptions : null;\r\n\r\n const modelKeyOptions = modelInfo?.keyOptions || aliasKeyOptions;\r\n\r\n return { ...aliasModelInfo, ...modelInfo, ...aliasKeyOptions, ...modelKeyOptions, modelId };\r\n }\r\n\r\n protected async getModelId(acRequest: AccessRequest, models: TLLMModelsList, model: string | TLLMModel | TCustomLLMModel): Promise<string> {\r\n //model can be passed directly, in which case we do not need to look it up in the models list\r\n if (typeof model === 'object' && model.modelId) {\r\n return model.modelId;\r\n }\r\n\r\n //model can be passed as a string, in which case we need to look it up in the models list\r\n const modelId = models?.[model as string]?.modelId || (model as string);\r\n const alias = models?.[model as string]?.alias;\r\n if (alias) {\r\n const aliasModelId = models?.[alias]?.modelId || alias || (model as string);\r\n return aliasModelId;\r\n }\r\n\r\n return modelId;\r\n }\r\n\r\n // public static async validateTokensLimit({\r\n // model,\r\n // promptTokens,\r\n // completionTokens,\r\n // hasAPIKey = false,\r\n // }: {\r\n // model: string;\r\n // promptTokens: number;\r\n // completionTokens: number;\r\n // hasAPIKey?: boolean;\r\n // }): Promise<void> {\r\n\r\n // const allowedContextTokens = this.getMaxContextTokens(model, hasAPIKey);\r\n // const totalTokens = promptTokens + completionTokens;\r\n\r\n // const teamAPIKeyExceededMessage = `This models' maximum content length is ${allowedContextTokens} tokens. (This is the sum of your prompt with all variables and the maximum output tokens you've set in Advanced Settings) However, you requested approx ${totalTokens} tokens (${promptTokens} in the prompt, ${completionTokens} in the output). Please reduce the length of either the input prompt or the Maximum output tokens.`;\r\n // const noAPIKeyExceededMessage = `Input exceeds max tokens limit of ${allowedContextTokens}. Please add your API key to unlock full length.`;\r\n\r\n // if (totalTokens > allowedContextTokens) {\r\n // throw new Error(hasAPIKey ? teamAPIKeyExceededMessage : noAPIKeyExceededMessage);\r\n // }\r\n // }\r\n\r\n protected async getProvider(acRequest: AccessRequest, models: TLLMModelsList, model: string | TLLMModel | TCustomLLMModel): Promise<string> {\r\n //model can be passed directly, in which case we do not need to look it up in the models list\r\n if (typeof model === 'object' && model.provider) {\r\n return model.provider;\r\n }\r\n\r\n //model can be passed as a string, in which case we need to look it up in the models list\r\n\r\n const modelId = await this.getModelId(acRequest, models, model);\r\n\r\n return models?.[modelId]?.provider || models?.[model as string]?.provider || models?.[modelId]?.llm || models?.[model as string]?.llm;\r\n }\r\n protected async getCustomModels(candidate: IAccessCandidate): Promise<Record<string, any>> {\r\n const models = {};\r\n const settingsKey = 'custom-llm';\r\n\r\n try {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const team = await accountConnector.requester(candidate as AccessCandidate).getTeam();\r\n\r\n const teamSettings = await accountConnector.team(team).getTeamSetting(settingsKey);\r\n const savedCustomModelsData = JSON.parse(teamSettings || '{}') as Record<string, any>;\r\n\r\n for (const [entryId, entry] of Object.entries(savedCustomModelsData)) {\r\n const foundationModel = entry.settings.foundationModel;\r\n const customModel = entry.settings.customModel;\r\n const supportsSystemPrompt = customModels[foundationModel]?.supportsSystemPrompt || entry.settings.supportsSystemPrompt;\r\n const customModelData = customModels[foundationModel] || {};\r\n\r\n let credentials = null;\r\n switch (entry.provider) {\r\n case TLLMProvider.Bedrock:\r\n credentials = TLLMCredentials.BedrockVault;\r\n break;\r\n case TLLMProvider.VertexAI:\r\n credentials = TLLMCredentials.VertexAIVault;\r\n break;\r\n default:\r\n credentials = TLLMCredentials.Internal;\r\n break;\r\n }\r\n models[entry.name] = {\r\n label: entry.name,\r\n modelId: customModel || foundationModel,\r\n provider: entry.provider,\r\n features: entry.features?.map((feature) => {\r\n switch (feature) {\r\n case 'text-completion':\r\n return 'text';\r\n case 'tool-use':\r\n return 'tools';\r\n default:\r\n return feature;\r\n }\r\n }),\r\n tags: Array.isArray(entry?.tags) ? ['Enterprise', ...entry?.tags] : ['Enterprise'],\r\n tokens: customModelData?.tokens ?? 100000,\r\n completionTokens: customModelData?.completionTokens ?? 4096,\r\n enabled: true,\r\n\r\n id: entryId,\r\n name: entry.name,\r\n alias: foundationModel,\r\n llm: entry.provider,\r\n components: customModelData?.components ?? [],\r\n isCustomLLM: true,\r\n supportsSystemPrompt,\r\n settings: entry.settings,\r\n credentials,\r\n };\r\n }\r\n\r\n return models;\r\n } catch (error) {\r\n return {};\r\n }\r\n }\r\n}\r\n","import { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { models } from '@sre/LLMManager/models';\r\nimport { ModelsProviderConnector } from '../ModelsProviderConnector';\r\nimport { IAccessCandidate } from '@sre/types/ACL.types';\r\nimport { TAccessLevel } from '@sre/types/ACL.types';\r\nimport { TAccessRole } from '@sre/types/ACL.types';\r\nimport { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { TLLMModel, TLLMModelsList } from '@sre/types/LLM.types';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { debounce } from '@sre/utils/general.utils';\r\nimport chokidar from 'chokidar';\r\nimport fs from 'fs/promises';\r\nimport path from 'path';\r\n\r\nconst console = Logger('SmythModelsProvider');\r\n\r\ntype SmythModelsProviderConfig = {\r\n /**\r\n * The models to be used.\r\n *\r\n * If a string is provided, it will be used as the directory name to load the models from.\r\n * If a TLLMModelsList is provided, it will be used as the models to be used.\r\n *\r\n */\r\n models?: string | TLLMModelsList;\r\n\r\n /**\r\n * The mode to be used.\r\n *\r\n * If 'append' is used, the models will be appended to the existing models.\r\n * If 'replace' is used, the existing models will be replaced with the new models.\r\n */\r\n mode?: 'merge' | 'replace';\r\n};\r\n\r\nexport class SmythModelsProvider extends ModelsProviderConnector {\r\n public name = 'SmythModelsProvider';\r\n\r\n private models: TLLMModelsList;\r\n\r\n constructor(protected _settings?: SmythModelsProviderConfig) {\r\n super(_settings);\r\n\r\n this.models = JSON.parse(JSON.stringify(models));\r\n if (typeof this._settings.models === 'string') {\r\n this.initDirWatcher(this._settings.models);\r\n } else if (typeof this._settings.models === 'object') {\r\n if (this._settings.mode === 'merge') this.models = { ...this.models, ...(this._settings.models as TLLMModelsList) };\r\n else this.models = this._settings.models as TLLMModelsList;\r\n this.started = true;\r\n } else {\r\n this.started = true;\r\n }\r\n }\r\n public async start() {\r\n super.start();\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async addModels(acRequest: AccessRequest, models: TLLMModelsList): Promise<void> {\r\n await this.ready();\r\n const validModels = (await this.getValidModels(models)) || {};\r\n if (Object.keys(validModels).length > 0) {\r\n this.models = { ...this.models, ...validModels };\r\n }\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n public async getModels(acRequest: AccessRequest): Promise<any> {\r\n await this.ready();\r\n\r\n return this.models;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n\r\n const acl = new ACL();\r\n //give read access to the candidate by default\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n\r\n return acl;\r\n }\r\n\r\n private async reindexModels(dir: string) {\r\n try {\r\n console.debug(`Reindexing models from directory: ${dir}`);\r\n\r\n // Scan directory for models and get them as an object\r\n const scannedModels = await this.scanDirectoryForModels(dir);\r\n\r\n // Apply models based on settings mode or default behavior\r\n if (this._settings?.mode === 'merge') {\r\n this.models = { ...this.models, ...scannedModels };\r\n } else {\r\n // Default behavior: reset to base models first, then add scanned models\r\n this.models = scannedModels;\r\n }\r\n\r\n SmythModelsProvider.localCache.clear();\r\n\r\n console.debug(`Successfully reindexed models. Total models: ${Object.keys(this.models).length}`);\r\n } catch (error) {\r\n console.error(`Error reindexing models from directory \"${dir}\":`, error);\r\n }\r\n }\r\n\r\n private async scanDirectoryForModels(dir: string): Promise<TLLMModelsList> {\r\n const scannedModels: TLLMModelsList = {};\r\n\r\n try {\r\n const entries = await fs.readdir(dir, { withFileTypes: true });\r\n\r\n for (const entry of entries) {\r\n const fullPath = path.join(dir, entry.name);\r\n\r\n if (entry.isDirectory()) {\r\n // Recursively scan subdirectories and merge results\r\n const subDirModels = await this.scanDirectoryForModels(fullPath);\r\n Object.assign(scannedModels, subDirModels);\r\n } else if (entry.isFile() && entry.name.endsWith('.json')) {\r\n // Process JSON files and merge results\r\n const fileContent = await fs.readFile(fullPath, 'utf-8');\r\n const modelData = JSON.parse(fileContent);\r\n const validModels = await this.getValidModels(modelData);\r\n Object.assign(scannedModels, validModels);\r\n }\r\n }\r\n } catch (error) {\r\n console.warn(`Error scanning directory \"${dir}\":`, error);\r\n }\r\n\r\n return scannedModels;\r\n }\r\n\r\n private async getValidModels(modelData: any): Promise<TLLMModelsList> {\r\n const validModels: TLLMModelsList = {};\r\n\r\n try {\r\n // Check if it's a single model or an object of models\r\n if (modelData.modelId) {\r\n // Single model case\r\n if (this.isValidSingleModel(modelData)) {\r\n validModels[modelData.modelId] = modelData as TLLMModel;\r\n console.debug(`Loaded model: ${modelData.modelId}`);\r\n } else {\r\n console.warn(`Invalid model format`, modelData);\r\n }\r\n } else if (typeof modelData === 'object' && !Array.isArray(modelData)) {\r\n // Object of models case\r\n for (const [modelId, model] of Object.entries(modelData)) {\r\n try {\r\n if (this.isValidSingleModel(model)) {\r\n validModels[modelId] = model as TLLMModel;\r\n console.debug(`Loaded model: ${modelId}`);\r\n } else {\r\n console.warn(`Invalid model format for model \"${modelId}\"`);\r\n }\r\n } catch (error) {\r\n console.warn(`Error processing model \"${modelId}\":`, error);\r\n // Continue processing other models instead of failing the whole file\r\n }\r\n }\r\n } else {\r\n console.warn(`Invalid format (not a model or object of models)`);\r\n }\r\n } catch (error) {\r\n console.warn(`Error loading model:`, error);\r\n }\r\n\r\n return validModels;\r\n }\r\n\r\n private isValidSingleModel(data: any): boolean {\r\n // Basic validation for single model structure\r\n return (\r\n data && typeof data === 'object' && typeof data.modelId === 'string' && (data.provider === undefined || typeof data.provider === 'string')\r\n );\r\n }\r\n\r\n private isValidModel(data: any): boolean {\r\n // Keep for backward compatibility, but delegate to simpler function\r\n return this.isValidSingleModel(data);\r\n }\r\n\r\n private async initDirWatcher(dir) {\r\n if (!(await fs.stat(dir)).isDirectory()) {\r\n console.warn(`Directory \"${dir}\" does not exist`);\r\n return;\r\n }\r\n\r\n const debouncedReindex = debounce(this.reindexModels.bind(this, dir), 1000, {\r\n leading: false,\r\n trailing: true,\r\n maxWait: 5000,\r\n });\r\n\r\n const watcher = chokidar.watch(dir, {\r\n ignored: /(^|[\\/\\\\])\\../, // ignore dotfiles\r\n persistent: true,\r\n ignoreInitial: true, // Don't fire events for files that already exist\r\n awaitWriteFinish: {\r\n stabilityThreshold: 2000,\r\n pollInterval: 100,\r\n },\r\n });\r\n\r\n watcher\r\n .on('add', (path) => {\r\n console.debug(`File ${path} has been added`);\r\n debouncedReindex();\r\n })\r\n .on('change', (path) => {\r\n console.debug(`File ${path} has been changed`);\r\n debouncedReindex();\r\n })\r\n .on('unlink', (path) => {\r\n console.debug(`File ${path} has been removed`);\r\n debouncedReindex();\r\n })\r\n .on('ready', () => {\r\n console.debug(`Watcher ready. Performing initial scan of ${dir}`);\r\n // Do initial scan once when watcher is ready\r\n this.reindexModels(dir);\r\n });\r\n }\r\n}\r\n","//==[ SRE: ModelsProvider ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { SmythModelsProvider } from './connectors/SmythModelsProvider.class';\r\n\r\nexport class ModelsProviderService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.ModelsProvider, 'SmythModelsProvider', SmythModelsProvider);\r\n }\r\n}\r\n","import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { IAccessCandidate, IACL } from '@sre/types/ACL.types';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\n\r\nexport interface CodeInput {\r\n code: string; // Main code to execute\r\n dependencies?: string; // Dependencies/imports/packages\r\n files?: Record<string, string>; // Additional files (filename -> content)\r\n inputs?: Record<string, any>; // Runtime input parameters\r\n}\r\n\r\nexport interface CodeConfig {\r\n runtime: string; // 'nodejs', 'python', 'java', etc.\r\n timeout?: number; // Execution timeout in milliseconds\r\n memoryLimit?: number; // Memory allocation in MB\r\n environment?: Record<string, string>; // Environment variables\r\n\r\n // Platform-specific settings\r\n platformConfig?: Record<string, any>;\r\n}\r\n\r\nexport interface CodeExecutionResult {\r\n output: any; // The execution result/return value\r\n executionTime: number; // Execution time in milliseconds\r\n logs?: string[]; // Execution logs\r\n errors?: string[]; // Error messages\r\n success: boolean; // Whether execution succeeded\r\n}\r\n\r\nexport interface CodePreparationResult {\r\n prepared: boolean; // Whether preparation succeeded\r\n errors?: string[]; // Preparation errors\r\n warnings?: string[]; // Preparation warnings\r\n metadata?: Record<string, any>; // Platform-specific preparation data\r\n}\r\n\r\nexport interface CodeDeployment {\r\n id: string; // Deployment identifier\r\n status: 'deploying' | 'ready' | 'failed';\r\n runtime: string;\r\n createdAt: Date;\r\n lastUsed?: Date;\r\n}\r\n\r\nexport interface ICodeRequest {\r\n // Core workflow\r\n prepare(input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;\r\n deploy(deploymentId: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;\r\n execute(input: CodeInput, config: CodeConfig): Promise<CodeExecutionResult>;\r\n\r\n // Execute with existing deployment (for platforms that support it)\r\n executeDeployment(deploymentId: string, inputs: Record<string, any>): Promise<CodeExecutionResult>;\r\n\r\n // Deployment management\r\n listDeployments(): Promise<CodeDeployment[]>;\r\n getDeployment(deploymentId: string): Promise<CodeDeployment | null>;\r\n deleteDeployment(deploymentId: string): Promise<void>;\r\n}\r\n\r\nexport abstract class CodeConnector extends SecureConnector {\r\n public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;\r\n\r\n // Abstract methods that concrete connectors must implement\r\n protected abstract prepare(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;\r\n protected abstract deploy(acRequest: AccessRequest, deploymentId: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;\r\n protected abstract execute(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodeExecutionResult>;\r\n protected abstract executeDeployment(acRequest: AccessRequest, deploymentId: string, inputs: Record<string, any>): Promise<CodeExecutionResult>;\r\n protected abstract listDeployments(acRequest: AccessRequest): Promise<CodeDeployment[]>;\r\n protected abstract getDeployment(acRequest: AccessRequest, deploymentId: string): Promise<CodeDeployment | null>;\r\n protected abstract deleteDeployment(acRequest: AccessRequest, deploymentId: string): Promise<void>;\r\n\r\n public requester(candidate: AccessCandidate): ICodeRequest {\r\n return {\r\n prepare: async (input: CodeInput, config: CodeConfig) => {\r\n return await this.prepare(candidate.readRequest, input, config);\r\n },\r\n deploy: async (deploymentId: string, input: CodeInput, config: CodeConfig) => {\r\n return await this.deploy(candidate.writeRequest, deploymentId, input, config);\r\n },\r\n execute: async (input: CodeInput, config: CodeConfig) => {\r\n return await this.execute(candidate.readRequest, input, config);\r\n },\r\n executeDeployment: async (deploymentId: string, inputs: Record<string, any>) => {\r\n return await this.executeDeployment(candidate.readRequest, deploymentId, inputs);\r\n },\r\n listDeployments: async () => {\r\n return await this.listDeployments(candidate.readRequest);\r\n },\r\n getDeployment: async (deploymentId: string) => {\r\n return await this.getDeployment(candidate.readRequest, deploymentId);\r\n },\r\n deleteDeployment: async (deploymentId: string) => {\r\n await this.deleteDeployment(candidate.writeRequest, deploymentId);\r\n },\r\n } as ICodeRequest;\r\n }\r\n}\r\n","import { IAccessCandidate, TAccessLevel } from '@sre/types/ACL.types';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { CodeConfig, CodePreparationResult, CodeConnector, CodeInput, CodeDeployment, CodeExecutionResult } from '../CodeConnector';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\n\r\nexport class AWSLambdaCode extends CodeConnector {\r\n public name = 'AWSLambdaCode';\r\n\r\n public async prepare(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodePreparationResult> {\r\n return {\r\n prepared: true,\r\n errors: [],\r\n warnings: [],\r\n };\r\n }\r\n\r\n public async deploy(acRequest: AccessRequest, deploymentId: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment> {\r\n return {\r\n id: deploymentId,\r\n runtime: config.runtime,\r\n createdAt: new Date(),\r\n status: 'deploying',\r\n };\r\n }\r\n\r\n public async execute(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodeExecutionResult> {\r\n return {\r\n output: {},\r\n executionTime: 0,\r\n success: true,\r\n };\r\n }\r\n\r\n public async executeDeployment(acRequest: AccessRequest, deploymentId: string, inputs: Record<string, any>): Promise<CodeExecutionResult> {\r\n return {\r\n output: {},\r\n executionTime: 0,\r\n success: true,\r\n };\r\n }\r\n\r\n public async listDeployments(acRequest: AccessRequest): Promise<CodeDeployment[]> {\r\n return [];\r\n }\r\n\r\n public async getDeployment(acRequest: AccessRequest, deploymentId: string): Promise<CodeDeployment | null> {\r\n return null;\r\n }\r\n\r\n public async deleteDeployment(acRequest: AccessRequest, deploymentId: string): Promise<void> {\r\n return;\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL> {\r\n const acl = new ACL();\r\n\r\n //give Read access everytime\r\n //FIXME: !!!!!! IMPORTANT !!!!!! this implementation have to be changed in order to reflect the security model of AWS Lambda\r\n acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);\r\n\r\n return acl;\r\n }\r\n}\r\n","//==[ SRE: Storage ]======================\r\n\r\nimport { ConnectorService, ConnectorServiceProvider } from '@sre/Core/ConnectorsService';\r\nimport { TConnectorService } from '@sre/types/SRE.types';\r\nimport { AWSLambdaCode } from './connectors/AWSLambdaCode.class';\r\n\r\nexport class CodeService extends ConnectorServiceProvider {\r\n public register() {\r\n ConnectorService.register(TConnectorService.Code, 'AWSLambda', AWSLambdaCode);\r\n }\r\n}\r\n","import { StorageService } from '@sre/IO/Storage.service';\r\nimport { LLMService } from '@sre/LLMManager/LLM.service';\r\nimport { SystemEvents } from './SystemEvents';\r\nimport { CacheService } from '@sre/MemoryManager/Cache.service';\r\nimport { Logger } from '../helpers/Log.helper';\r\nimport { TServiceRegistry } from '@sre/types/SRE.types';\r\nimport { VaultService } from '@sre/Security/Vault.service';\r\nimport { AccountService } from '@sre/Security/Account.service';\r\nimport { AgentDataService } from '@sre/AgentManager/AgentData.service';\r\nimport { VectorDBService } from '@sre/IO/VectorDB.service';\r\nimport { CLIService } from '@sre/IO/CLI.service';\r\nimport { NKVService } from '@sre/IO/NKV.service';\r\nimport { RouterService } from '@sre/IO/Router.service';\r\nimport { ManagedVaultService } from '@sre/Security/ManagedVault.service';\r\nimport { LogService } from '@sre/IO/Log.service';\r\nimport { ComponentService } from '@sre/AgentManager/Component.service';\r\nimport { ModelsProviderService } from '@sre/LLMManager/ModelsProvider.service';\r\nimport { CodeService } from '@sre/ComputeManager/Code.service';\r\nconst console = Logger('Boot');\r\nlet _booted = false;\r\nexport function boot() {\r\n if (_booted) {\r\n console.warn('SRE already booted');\r\n return;\r\n }\r\n _booted = true;\r\n console.debug('SRE Boot sequence started');\r\n const service: TServiceRegistry = {};\r\n service.NKV = new NKVService();\r\n service.Account = new AccountService();\r\n service.Vault = new VaultService();\r\n service.ManagedVault = new ManagedVaultService();\r\n service.Cache = new CacheService();\r\n service.Storage = new StorageService();\r\n service.ModelsProvider = new ModelsProviderService();\r\n service.LLM = new LLMService();\r\n service.AgentData = new AgentDataService();\r\n service.CLI = new CLIService();\r\n service.VectorDB = new VectorDBService();\r\n service.Router = new RouterService();\r\n service.Log = new LogService();\r\n service.Component = new ComponentService();\r\n service.Code = new CodeService();\r\n\r\n SystemEvents.on('SRE:Initialized', () => {\r\n console.debug('SRE Initialized');\r\n for (let key in service) {\r\n service[key].init();\r\n }\r\n\r\n SystemEvents.emit('SRE:Booted', service);\r\n\r\n console.debug('SRE Boot sequence completed');\r\n });\r\n}\r\n","import { boot } from './boot';\r\n\r\nimport { SREConfig, TConnectorService } from '@sre/types/SRE.types';\r\nimport { ConnectorService } from './ConnectorsService';\r\nimport { SystemEvents } from './SystemEvents';\r\nimport { Logger } from '../helpers/Log.helper';\r\nimport path from 'path';\r\nimport fs from 'fs';\r\nimport os from 'os';\r\nimport { fileURLToPath } from 'url';\r\nimport { dirname } from 'path';\r\n\r\nconst logger = Logger('SRE');\r\n\r\nexport class SmythRuntime {\r\n public started = false;\r\n\r\n private _smythDir: string;\r\n public get smythDir() {\r\n return this._smythDir;\r\n }\r\n private _readyPromise: Promise<boolean>;\r\n private _readyResolve: (value: boolean) => void;\r\n\r\n private defaultConfig: SREConfig = {\r\n Vault: {\r\n Connector: 'JSONFileVault',\r\n },\r\n Account: {\r\n Connector: 'DummyAccount',\r\n },\r\n Cache: {\r\n Connector: 'RAM',\r\n },\r\n Storage: {\r\n Connector: 'LocalStorage',\r\n },\r\n Code: {\r\n Connector: 'DummyConnector',\r\n },\r\n //NKV should be loaded before VectorDB\r\n NKV: {\r\n Connector: 'RAM',\r\n },\r\n VectorDB: {\r\n Connector: 'RAMVec',\r\n },\r\n ModelsProvider: {\r\n Connector: 'SmythModelsProvider',\r\n },\r\n AgentData: {\r\n Connector: 'NullAgentData',\r\n },\r\n Component: {\r\n Connector: 'LocalComponent',\r\n },\r\n ManagedVault: {\r\n Connector: 'NullManagedVault',\r\n },\r\n Log: {\r\n Connector: 'ConsoleLog',\r\n },\r\n Router: {\r\n Connector: 'NullRouter',\r\n },\r\n };\r\n\r\n protected constructor() {\r\n this.started = true;\r\n this._readyPromise = new Promise((resolve) => {\r\n this._readyResolve = resolve;\r\n });\r\n }\r\n\r\n protected static instance?: SmythRuntime;\r\n public static get Instance(): SmythRuntime {\r\n if (!SmythRuntime.instance) {\r\n SmythRuntime.instance = new SmythRuntime();\r\n }\r\n return SmythRuntime.instance;\r\n }\r\n\r\n private _initializing = false;\r\n\r\n public get initializing() {\r\n return this._initializing;\r\n }\r\n\r\n private _initialized = false;\r\n\r\n public init(_config?: SREConfig): SmythRuntime {\r\n if (!_config || JSON.stringify(_config) === '{}') {\r\n this._smythDir = findSmythDir();\r\n logger.info('.smyth directory found in:', this._smythDir);\r\n }\r\n\r\n if (this._initializing) {\r\n console.warn('You tried to initialize SRE while it is already initializing ... skipping');\r\n return;\r\n }\r\n if (this._initialized) {\r\n throw new Error('SRE already initialized');\r\n }\r\n this._initializing = true;\r\n SystemEvents.on('SRE:Booted', () => {\r\n this._readyResolve(true);\r\n });\r\n boot();\r\n\r\n const config = this.autoConf(_config);\r\n\r\n for (let connectorType in config) {\r\n for (let configEntry of config[connectorType]) {\r\n ConnectorService.init(\r\n connectorType as TConnectorService,\r\n configEntry.Connector,\r\n configEntry.Id,\r\n configEntry.Settings,\r\n configEntry.Default\r\n );\r\n }\r\n }\r\n\r\n this._initialized = true;\r\n SystemEvents.emit('SRE:Initialized');\r\n\r\n return SmythRuntime.Instance as SmythRuntime;\r\n }\r\n\r\n /**\r\n * This function tries to auto configure, or fixes the provided configuration\r\n *\r\n * FIXME: The current version does not actually auto configure SRE, it just fixes the provided configuration for now\r\n * TODO: Implement auto configuration based on present environment variables and auto-detected configs\r\n * @param config\r\n */\r\n private autoConf(config: SREConfig = {}) {\r\n // default config for missing connectors\r\n const defaultConfig = JSON.parse(JSON.stringify(this.defaultConfig));\r\n\r\n // for (let connectorType in defaultConfig) {\r\n // if (!config[connectorType]) {\r\n // config[connectorType] = defaultConfig[connectorType];\r\n // }\r\n // }\r\n\r\n const keys = Object.keys({ ...defaultConfig, ...config });\r\n\r\n const newConfig: SREConfig = {};\r\n for (let connectorType of keys) {\r\n newConfig[connectorType] = [];\r\n\r\n let entry = config[connectorType] || defaultConfig[connectorType];\r\n if (!Array.isArray(entry)) {\r\n entry = [entry];\r\n }\r\n\r\n let hasDefault = false;\r\n for (let connector of entry) {\r\n if (!connector.Connector) {\r\n logger.warn(`Missing Connector Name in ${connectorType} entry ... it will be ignored`);\r\n continue;\r\n }\r\n if (connector.Default) {\r\n if (hasDefault) {\r\n logger.warn(`Entry ${connectorType} has more than one default Connector ... only the first one will be used`);\r\n }\r\n hasDefault = true;\r\n }\r\n newConfig[connectorType].push(connector);\r\n }\r\n\r\n if (!hasDefault && newConfig[connectorType].length > 0) {\r\n newConfig[connectorType][0].Default = true;\r\n }\r\n }\r\n\r\n return newConfig;\r\n }\r\n\r\n public ready(): Promise<boolean> {\r\n return this._readyPromise;\r\n }\r\n\r\n private _stopping = false;\r\n public async _stop() {\r\n if (this._stopping) {\r\n return;\r\n }\r\n this._stopping = true;\r\n logger.info('Sending Shutdown Signals To All Subsystems...');\r\n await ConnectorService._stop();\r\n SmythRuntime.instance = undefined;\r\n this.started = false;\r\n }\r\n}\r\n\r\nexport const SRE = SmythRuntime.Instance;\r\nlet shuttingDown = false;\r\n\r\nfunction findSmythDir() {\r\n // 1. Try to find in local directory (the directory from which the program was run)\r\n const localDir = path.resolve(process.cwd(), '.smyth');\r\n if (fs.existsSync(localDir)) {\r\n return localDir;\r\n }\r\n\r\n // 2. Try to find from main script's directory (entry point)\r\n const mainScriptPath = process.argv[1];\r\n const mainScriptDir = path.dirname(path.resolve(mainScriptPath));\r\n if (mainScriptPath) {\r\n const mainScriptSmythDir = path.resolve(mainScriptDir, '.smyth');\r\n if (fs.existsSync(mainScriptSmythDir)) {\r\n return mainScriptSmythDir;\r\n }\r\n }\r\n\r\n // 3. Try to find it in current package root directory (where package.json is)\r\n let packageRootDir = findPackageRoot();\r\n if (packageRootDir) {\r\n const packageSmythDir = path.resolve(packageRootDir, '.smyth');\r\n if (fs.existsSync(packageSmythDir)) {\r\n return packageSmythDir;\r\n }\r\n }\r\n\r\n // 4. Try to find it in current package root directory from main script's directory\r\n packageRootDir = findPackageRoot(mainScriptDir);\r\n if (packageRootDir) {\r\n const packageSmythDir = path.resolve(packageRootDir, '.smyth');\r\n if (fs.existsSync(packageSmythDir)) {\r\n return packageSmythDir;\r\n }\r\n }\r\n\r\n // 5. Try to find it in user home directory\r\n const homeDir = path.resolve(os.homedir(), '.smyth');\r\n if (fs.existsSync(homeDir)) {\r\n return homeDir;\r\n }\r\n\r\n // Default: return path in current working directory (will be created if needed)\r\n return localDir;\r\n}\r\n\r\nfunction findPackageRoot(startDir = process.cwd()) {\r\n let currentDir = startDir;\r\n\r\n while (currentDir !== path.dirname(currentDir)) {\r\n const packageJsonPath = path.resolve(currentDir, 'package.json');\r\n if (fs.existsSync(packageJsonPath)) {\r\n return currentDir;\r\n }\r\n currentDir = path.dirname(currentDir);\r\n }\r\n\r\n return null;\r\n}\r\n\r\nasync function shutdown(reason) {\r\n if (!SmythRuntime.Instance.started) return;\r\n if (shuttingDown) return;\r\n shuttingDown = true;\r\n\r\n logger.info(`Caught ${reason} ... Attempting graceful shutdown`);\r\n if (SmythRuntime.Instance) {\r\n try {\r\n await SmythRuntime.Instance._stop();\r\n } catch (err) {\r\n logger.error('Shutdown error:', err);\r\n }\r\n }\r\n}\r\n\r\n['SIGINT', 'SIGTERM'].forEach((signal) => {\r\n process.on(signal, async () => {\r\n await shutdown(signal);\r\n process.exit(0); // Required after async\r\n });\r\n});\r\n\r\nprocess.on('beforeExit', (code) => {\r\n shutdown('beforeExit');\r\n});\r\n\r\nprocess.on('exit', (code) => {\r\n logger.info(`Goodbye!`);\r\n});\r\n\r\n// process.on('uncaughtException', (err) => {\r\n\r\n// });\r\n","export class SmythURI {\r\n static agent(id: string): string {\r\n return `smyth:agent:${id}`;\r\n }\r\n}\r\n","import { ConnectorService } from '@sre/Core/ConnectorsService';\r\nimport { Logger } from '@sre/helpers/Log.helper';\r\nimport { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';\r\nimport { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';\r\nimport { ACL } from '@sre/Security/AccessControl/ACL.class';\r\nimport { SecureConnector } from '@sre/Security/SecureConnector.class';\r\nimport { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.types';\r\nimport { IVaultRequest, VaultConnector } from '../VaultConnector';\r\n\r\nconst console = Logger('HashicorpVault');\r\nexport class HashicorpVault extends VaultConnector {\r\n public name: string = 'HashicorpVault';\r\n\r\n constructor(protected _settings: any) {\r\n super(_settings);\r\n //hashicorp client/api\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async get(acRequest: AccessRequest, keyId: string) {\r\n return null;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async exists(acRequest: AccessRequest, keyId: string) {\r\n return false;\r\n }\r\n\r\n @SecureConnector.AccessControl\r\n protected async listKeys(acRequest: AccessRequest) {\r\n return [];\r\n }\r\n\r\n public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {\r\n //FIXME : this is for dev, it always give full access, we must update the logic\r\n const accountConnector = ConnectorService.getAccountConnector();\r\n const teamId = await accountConnector.getCandidateTeam(candidate);\r\n const acl = new ACL();\r\n\r\n acl.addAccess(TAccessRole.Team, teamId, TAccessLevel.Owner)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Read)\r\n .addAccess(TAccessRole.Team, teamId, TAccessLevel.Write);\r\n\r\n return acl;\r\n }\r\n}\r\n"],"names":["dotenv","config","LOG_LEVEL","process","env","LOG_FILTER","NODE_ENV","REQUEST_METHODS","REQUEST_CONTENT_TYPES","none","urlEncodedFormData","multipartFormData","json","text","xml","binary","EMBODIMENT_TYPES","ERR_MSG_INVALID_IMAGE_SOURCE","ERR_MSG_INVALID_BINARY","ERR_MSG_MAX_DEPTH","ERR_MSG_MAX_ARRAY_SIZE","ERR_MSG_MAX_OBJECT_SIZE","MAX_DEPTH","MAX_OBJECT_SIZE","MAX_ARRAY_SIZE","MAX_FILE_SIZE","MAX_FILE_COUNT","DEFAULT_MAX_TOKENS_FOR_LLM","S3_DAILY_PURGE_LIFECYCLE_TAG","S3_WEEKLY_PURGE_LIFECYCLE_TAG","S3_MONTHLY_PURGE_LIFECYCLE_TAG","TOOL_USE_DEFAULT_MODEL","COMP_NAMES","apiCall","code","llmPrompt","visionLLM","JSON_RESPONSE_INSTRUCTION","SUPPORTED_MIME_TYPES_MAP","OpenAI","image","imageGen","document","TogetherAI","Anthropic","GoogleAI","video","audio","Groq","DEFAULT_SMYTHOS_LLM_PROVIDERS_SETTINGS","openai","enabled","anthropic","googleai","togetherai","groq","xai","BUILT_IN_MODEL_PREFIX","TConnectorService","uid","Date","now","Math","random","toString","replace","toUpperCase","async","processWithConcurrencyLimit","tasks","maxConcurrentTasks","limit","pLimit","limitedTasks","map","task","Promise","allSettled","flatMap","result","status","value","filter","Boolean","isJSONString","str","JSON","parse","ControlledPromise","constructor","executor","internalResolve","internalReject","_isSettled","super","resolve","reject","reason","__publicField","this","isSettled","debounce","func","wait","options","timeout","lastCall","args","clearTimeout","leading","apply","maxWait","setTimeout","getFormattedStackTrace","skip","stack","Error","relevantLines","split","slice","formattedCalls","length","min","i","line","trim","match","functionName","filePath","lineNum","fileName","pop","cleanFunctionName","includes","push","cleanLine","printStackTrace","logger","stackTrace","debug","forEach","call","index","delay","ms","r","isValidString","convertStringToRespectiveType","data","toLowerCase","num","parseFloat","isNaN","Number","MAX_SAFE_INTEGER","MIN_SAFE_INTEGER","isValidNumber","Array","isArray","item","Object","fromEntries","entries","key","kebabToCapitalize","input","word","charAt","join","chunkText","chunkSize","chunkOverlap","RecursiveTextSplitter","splitText","TextSplitter","separators","keepSeparator","_splitText","finalChunks","newSeparators","separator","s","splits","splitOnSeparator","goodSplits","_separator","lengthFunction","mergedText","mergeSplits","otherInfo","regexEscapedSeparator","RegExp","joinDocs","docs","currentDoc","total","d","_len","console","warn","doc","shift","isBase64FileUrl","url","base64Data","isBase64","getMimetypeFromBase64Data","_cleanUpBase64Data","imageBuffer","Buffer","from","type","fileTypeFromBuffer","mime","error","cleanBase64","isBase64DataUrl","test","cleanedBase64Data","identifyMimeTypeFromBase64DataUrl","matches","mimetype","parseBase64DataUrl","buffer","message","streamToBuffer","stream","chunks","chunk","concat","binaryMimeTypes","dataToBuffer","bufferData","ArrayBuffer","Uint8Array","isView","DataView","byteOffset","byteLength","isBuffer","isPlainObject","prototype","isUrl","isSmythFsUrl","isSmythFileObject","getMimeType","mimeTypeGetters","blob","fileType","response","axios","get","headers","smythFile","base64DataUrl","base64","cleanedData","identifyMimetypeFromBase64","string","trimmedInput","startsWith","endsWith","lines","firstLine","hasCommas","hasSemicolons","hasTabs","delimiter","firstLineFields","csvLikeLines","fieldsCount","identifyMimetypeFromString","typeChecks","Blob","matchedType","find","formatDataForDebug","dataForDebug","name","jsonData","getJsonData","size","base64String","padding","floor","getBase64FileSize","parseCLIArgs","argList","argv","mainArg","mainArgIndex","indexOf","values","keyValuePairs","valParts","val","isDigits","isSafeNumber","validateCharacterSet","parts","part","winston","addColors","info","logLevelMap","full","logLevel","namespaces","namespaceFilter","format","some","ns","module","ArrayTransport","Transport","opts","logs","log","callback","setImmediate","emit","level","LogHelper","EventEmitter","_logger","labels","output","elapsedTime","startTime","formatLogMessage","verbose","close","clear","printf","timestamp","colorize","MAX_LOG_MESSAGE_LENGTH","createBaseLogger","memoryStore","createLogger","combine","logMessage","sensitiveWords","sensitiveWord","regex","redactLogMessage","errors","splat","transports","Console","substring","stderrLevels","add","arg","stringify","String","Logger","withMemoryStore","defaultMeta","createLabeledLogger","DummyConnector","Proxy","target","prop","receiver","argsString","LocalCache","defaultTTL","cache","Map","expiryMap","timeouts","set","ttlMs","expiry","delete","unref","updateTTL","has","keys","DEFAULT_TEAM_ID","TAccessLevel","TAccessRole","RoleMap","user","agent","team","public","LevelMap","owner","read","write","ReverseRoleMap","k","v","ReverseLevelMap","TAccessResult","ACLAccessDeniedError","AccessRequest","object","id","every","candidate","acReq","resourceId","clone","request","setLevel","addLevel","resource","setCandidate","AccessCandidate","role","Public","readRequest","Read","writeRequest","Write","ownerRequest","Owner","teamId","Team","agentId","Agent","userId","User","_Connector","_settings","settings","interactionHandler","_interactionHandler","valid","setInteraction","handler","instance","configHash","createHash","update","digest","lCache","isValid","connector","start","started","stop","ready","_readyPromise","interval","setInterval","clearInterval","requester","Connector","SystemEvents","ServiceRegistry","_ready","on","services","_ConnectorService","service","register","connectorType","connectorName","connectorConstructor","subClass","superClass","getPrototypeOf","depth","isSubclassOf","Connectors","init","connectorId","isDefault","ConnectorInstances","entry","default","_stop","allConnectors","self","getInstance","getStorageConnector","Storage","getCacheConnector","Cache","getVectorDBConnector","VectorDB","getNKVConnector","NKV","getLLMConnector","LLM","getVaultConnector","Vault","getManagedVaultConnector","ManagedVault","getAccountConnector","Account","getAgentDataConnector","AgentData","getCLIConnector","CLI","getLogConnector","Log","getComponentConnector","Component","getModelsProviderConnector","ModelsProvider","hasInstance","getRouterConnector","Router","ConnectorService","ConnectorServiceProvider","VaultHelper","getTeamKey","vaultConnector","getUserKey","accountConnector","getCandidateTeam","getAgentKey","Match","doubleCurly","singleCurly","doubleCurlyForSingleMatch","templateVariables","prefix","suffix","prefSuf","fn","TPLProcessor","vaultTeam","token","componentTemplateVar","templateSettings","label","o","TemplateStringHelper","templateString","_current","_promiseQueue","asyncResult","all","create","escapeJsonField","parseRaw","parseTeamKeysAsync","parseComponentTemplateVarsAsync","processor","tokens","prosessorPromises","exec","_processor","then","clean","replaceWith","escapeString","TemplateString","LogTransaction","trId","storage","getCallId","_callId","logData","queue","_lastPush","processQueue","formatData","maxLength","substr","getDataFilePath","date","getFullYear","getMonth","padStart","getDate","getDayFormattedDate","prepareData","firstData","sourceId","componentId","preview","action","__action","__status","domain","inputTimestamp","outputTimestamp","sessionID","sourceData","components","componentData","sourceCptName","componentCptName","sourceName","displayName","componentName","curStepOrder","step","agentRuntime","curStep","inputTokensObj","encode","outputTokensObj","inputTokens","outputTokens","tags","raw_error","_error","workflowID","processID","raw_input","raw_output","raw_result","storeLogData","content","body","storagePath","path","posix","metadata","teamid","agentid","ContentType","logConnector","_isProcessing","resultObj","errorObj","logResult","bind","canDelete","_AgentLogger","cleanup","trIds","transactions","logTask","usingTestDomain","AgentLogger","RuntimeContext","runtime","_cacheConnector","reqId","xDebugId","reqTag","ctxFile","jobID","resolved","initRuntimeContext","serialize","sessionResult","sessionResults","deserialize","reset","_runtimeFileReady","endpointDBGCall","method","agentRequest","endpoint","endpoints","ctxData","connections","cptId","ctx","active","cpt","sync","sessionClosed","exists","incStep","updateComponent","component","resetComponent","runtimeData","getComponentData","LLMCache","cacheId","ttl","_cacheId","_ttl","_candidate","obj","e","AgentRuntimeUnavailable","_AgentRuntime","header","isNestedProcess","xDebugStop","xDebugRun","xDebugInject","xDebugRead","reqTagOwner","xDebugPendingInject","xMockDataInject","sessionId","workflowReqId","tagsData","processResults","errorResults","agentContext","alwaysActiveComponents","exclusiveComponents","ComponentInstances","alwaysActive","getRuntimeData","saveRuntimeComponentData","exclusive","_debugActive","xCacheId","llmCache","circularLimitReached","destroy","incTag","getWaitingComponents","c","getExclusiveActiveComponents","readState","stateId","deltaOnly","dbgAllComponents","dbgActiveComponents","_job_components","state","dbgComponent","dbgSession","remainingActiveComponents","activeAsyncComponents","checkCircularLimit","circularLimit","delta","runCycle","dbgActiveWaitingComponents","dbgActiveReadyComponents","expiredDbgSession","promises","injectInput","callComponent","dbgResults","flat","_missing_inputs","_ChildLoopData","finalResult","Infinity","reduce","acc","current","seen","_exclude","injectDebugOutput","allEmpty","updateRuntimeData","AgentRuntime","OSResourceMonitor","mem","totalMemory","os","totalmem","freeMemory","freemem","usedMemory","toFixed","memoryUsagePercentage","getMemoryUsage","cpu","cpus","nice","sys","idle","irq","times","load","getCpuUsage","AgentSSE","res","monitorId","Symbol","iterator","send","_type","_data","connection","finished","remove","connectionId","end","getConnectionCount","agentData","agentSettings","version","agentVersion","debugSessionEnabled","agentVariables","variables","apiBasePath","sourceComponent","targetComponent","targetId","sourceIndex","outputs","findIndex","targetIndex","inputs","next","prev","tagAsyncComponents","setRequest","sse","getAll","customComponents","_componentInstance","_componentInstancesLoader","modelsProvider","addSSE","sseSource","dateTime","getHours","getMinutes","getSeconds","getCurrentFormattedDate","sessionTags","sessionTag","callerSessionId","dummy","setCallback","kill","_kill","isKilled","parseVariables","endpointPath","eventId","logId","toISOString","dbgResult","postProcess","catch","endTime","duration","qosLatency","planInfo","maxLatency","circularLimitData","updateTasksCount","_error_handled","_result","_debug","_debug_time","_componentData","_component","postProcessResult","hasLoopAncestor","inputEntry","prevId","prevComponentData","clearChildLoopRuntimeComponentData","getComponentMissingInputs","_input","missingInputs","readablePredecessors","findReadablePredecessors","readableInputNames","pred","allInputIndexes","allInputs","optional","predComponentData","hasOutput","sourceComponentData","hasReadOutput","updateStep","title","prepareComponentInput","query","validationResult","validateConfig","Response","_in_progress","results","callNextComponents","_LoopData","branches","_is_leaf","parentId","resultsCopy","loopIndex","loopLength","JSONExpression","propertyString","properties","currentProperty","property","waitingComponents","waitingComponentIds","alwaysActiveIds","alwaysActiveConnections","prevComponent","outputEndpoint","readOutput","targetComponents","targetComponentData","_isErrorHandler","nextInput","inputEndpoint","outputExpression","expression","outputParts","defaultOutputs","combinedInput","_mergeInputs","sourceRuntimeData","rData","rDataInput","defaultVal","getConnectionSource","getConnectionTarget","recursiveTagAsyncComponents","connected","con","AsyncComponents","AsyncComponent","existing","newValue","AgentRequest","req","params","lowerCaseHeaders","URL","pathname","searchParams","files","_agent_authinfo","EmbodimentSettings","agentDataConnector","_embodiments","getAgentEmbodiments","embodimentType","_embodiment","embodiment","AgentSettings","embodiments","getAgentSettings","AgentProcess","initAgent","jsonRegex","idRegex","getAgentData","_loadPromise","itv","run","reqConfig","parseReqConfig","pathMatches","parseCLI","cli","usedMethod","session","cwd","basename","fs","existsSync","fileBuffer","readFileSync","ext","fileObj","fieldname","originalname","getType","FileType","post","readDebugState","ACLHashAlgo","source","xxh3","h64","xxhash","ACL","acl","deserializeACL","hashAlgorithm","migrated","serializedACL","serializeACL","checkExactAccess","acRequest","entryId","access","addPublicAccess","ownerId","hashedOwner","curLevel","removePublicAccess","l","addAccess","_level","removeAccess","tacl","compressed","roleShort","entriesArray","hashedOwnerKey","accessLevels","accessLevelsShort","entriesObj","short","SecureConnector","hasAccess","aclHelper","getResourceACL","publicRequest","teamRequest","teamOwnerRequest","getAccessTicket","sysAcRequest","Granted","Denied","AccessControl","propertyKey","descriptor","originalMethod","StorageConnector","getMetadata","setMetadata","getACL","setACL","expire","CacheConnector","getTTL","JSONContentHelper","dataString","tryParse","strInput","repairedJson","jsonrepair","extractJsonFromString","tryFullParse","JSONContent","_SmythFS","hash","generateInstanceHash","storageName","cacheName","instanceProps","crypto","Instance","storageProvider","cacheProvider","instances","router","Function","serveTempContent","serveResource","getBaseUri","uri","smythURI","URIParser","defaultCandidate","isTeamMember","toBuffer","genTempUrl","ttlSeconds","resourceMetadata","randomUUID","tempUserCandidate","accessCandidate","contentType","baseUrl","destroyTempUrl","delResource","tempPath","cacheVal","writeHead","contentBuffer","genResourceUrl","getExtension","getAgentConfig","agentStageDomain","destroyResourceUrl","file_id","extention","parsed","CaseSensitiveURL","tld","hostname","smyth","basePath","urlString","afterProtocol","hostnameEnd","originalHostnamePart","originalHostname","originalPort","protocol","port","search","href","origin","host","Readable","err","SmythFS","BinaryInput","_name","_source","finally","responseType","urlPath","extension","base64FileInfo","cleanData","getBase64FileInfo","getSizeFromBinary","arrayBuffer","getUrlInfo","contentLength","upload","_uploading","readData","getName","getBuffer","getReadStream","TLLMCredentials","BuiltinLLMProviders","Echo","DeepSeek","Bedrock","VertexAI","xAI","Perplexity","TLLMProvider","TLLMMessageRole","APIKeySource","TLLMEvent","isAgent","LLMInference$1","LLMInference","model","getTeam","llmInference","modelProviderReq","llmProvider","getProvider","llmConnector","prompt","contextWindow","messages","enhancePrompt","finishReason","promptStream","streamRequest","dummyEmitter","nextTick","imageGenRequest","imageEditRequest","multimodalStreamRequest","fileSources","_fileSources","file","binaryInput","userMessage","multimodalStreamRequestLegacy","_files","getContextWindow","systemPrompt","_messages","maxTokens","maxOutputTokens","modelInfo","getModelInfo","maxModelContext","maxModelOutputTokens","completionTokens","maxInputContext","maxOutputContext","systemMessage","smythContextWindow","tokensCount","encodeChat","curMessage","countTokens","messageBlock","toolsData","tool","unshift","modelContextWindow","internal_message","transformToolMessageBlocks","getConsistentMessages","_stringifiedContent","LLMContext","_systemPrompt","llmContextStore","_llmCache","_llmContextStore","save","addUserMessage","message_id","lastMessage","__smyth_data__","addAssistantMessage","addToolMessage","dereferenceSchema","schema","root","$ref","ref","segment","OpenAPIParser","mapReqMethods","paths","methods","pathData","operationId","mapEndpoints","operationIds","yamlToJson","yamlData","yaml","getJson","parsedData","innerError","getJsonFromUrl","isValidOpenAPI","openapi","servers","hooks","HookService","hookName","trigger","hook","hookAsync","hookAsyncWithContext","contextFn","additionalContext","Conversation","_model","_specSource","_lastError","maxContextSize","_maxContextSize","_maxOutputTokens","userDefinedSystemPrompt","toolChoice","store","_agentVersion","loadSpecFromSource","spec","_status","_spec","_agentId","assignTeamIdFromAgentId","updateModel","_context","context","specSource","_currentWaitPromise","waitTime","toolHeaders","concurrentToolCalls","abortSignal","streamPrompt","addEventListener","passThroughtContinueMessage","_content","reqMethods","_reqMethods","toolsConfig","_toolsConfig","_endpoints","_baseUrl","_teamId","eventEmitter","toolsStrategy","experimentalCache","removeAllListeners","Thinking","thinking","Content","internal","toolsPromise","hasTools","hasError","passThroughContent","ToolInfo","thinkingBlocks","llmMessage","tool_calls","block","function","arguments","_agentCallback","toolProcessingTasks","ToolCall","_llmRequest","toolArgs","agentCallback","functionResponse","useTool","ToolResult","processedToolsData","End","usage_data","_finishReason","Usage","toolsContent","Interrupted","resolveToolEndpoint","templateParams","parameters","p","in","parsedEndpoint","append","toolHandler","_customToolsHandlers","signal","requiresRemoteCall","agentProcess","monitUrl","eventSource","EventSource","fetch","event","maxTime","addTool","toolFunction","openApiArgs","extractArgsAsOpenAPI","_arguments","required","description","argsObj","requiredFields","items","toolDefinition","_customToolsDeclarations","formatToolsConfig","toolDefinitions","tools","functionDeclarations","getFunctionDeclarations","patchSpec","behavior","loadSpecFromAgent","assistantName","defaultBaseUrl","isDeployed","templateInfo","getOpenAPIJSON","declarations","requestBody","declaration","summary","acorn","ecmaVersion","counter","param","left","argument","__decorateClass","inputErrMsg","InferenceStrategies","any","inferStringType","number","floatVal","integer","intVal","parseInt","boolean","lowerCaseValue","array","errMsg","dayjs","locale","unix","inferBinaryType","performTypeInference","inputConfig","_inputs","_inputConfig","_createBinaryInput","extractSmythFsAgentId","segments","binarySource","normalizedValue","extractedUrls","parsedValue","urls","Set","_extractUrls","createComponentLogger","configuration","configSchema","_templateVars","tplVar","Joi","validate","enable","disable","AgentPlugin","max","openAiModel","descForModel","allow","desc","logoUrl","subAgentId","Prompt","isSubAgentDeployed","conv","isEmpty","isTemplateVar","isKeyTemplateVar","parseKey","APIEndpoint","pattern","ai_exposed","advancedModeEnabled","endpointLabel","_authInfo","inputsWithDefaultValue","bodyInputNames","queryInputNames","outputName","inputName","_inputWithDefaultValue","inputValue","isFile","binaryInputs","validResults","APIOutput","Output","rawOutput","agentVar","ForkedAgent","parent","componentID","clonedComponents","clonedConnections","cloneRecursively","rootComponentData","APIEndpointData","incomingConnections","conn","epInput","epOutput","fork","JobID","currentID","newIDMap","componentToClone","clonedComponent","newComponent","cloneComponent","clonedConnection","_Async","forked","forkedAgent","cleanJobIDBranch","JOBS","reloadCtxData","jobIDOutputIndex","removeOrphanedBranches","toDelete","removeComponent","Async","_Await","jobs_count","max_time","Results","jobs","Jobs","WAITS","promise","done","completed","Await","Classifier","Input","escapeJSONString","unescapeJSONString","inputCopy","categories","modelId","getModelId","excludedKeys","outputKeys","details","ComponentHost","componentConnector","DataSourceIndexer","namespace","custom","debugOutput","_config","namespaceId","vectorDbConnector","namespaceExists","createNamespace","inputSchema","validateInput","providedId","indexRes","dsId","genDsId","Source","addDSFromText","Success","dataSource","unknown","createDatasource","addDSFromUrl","DataSourceCleaner","validateConfigData","deleteDatasource","DataSourceLookup","topK","helpers","numValue","fieldName","_flags","postprocess","strict","includeMetadata","Query","parseMetadata","FEncDec","Data","encoding","FHash","algorithm","hashAlgo","Hash","FileStore","binaryData","fileData","customFileName","s3StorageConnector","getFileName","s3Key","smythFSUrl","Url","mimeType","customName","btoa","fromCharCode","getRandomValues","ForEach","Result","_temp_result","Loop","inputObject","inputArray","_ForEachData","cleanupResult","FSign","signingKey","Key","signMethod","dataTransform","hashType","RSA_padding","RSA_saltLength","querystring","Signature","signData","algo","sign","createSign","sign_options","constants","saltLength","hmac","createHmac","FSleep","FTimestamp","Timestamp","GenAILLM","temperature","maxThinkingTokens","stopSequences","allowEmpty","topP","frequencyPenalty","presencePenalty","responseFormat","passthrough","useSystemPrompt","useContextWindow","maxContextWindowLength","Attachment","Reply","useWebSearch","webSearchContextSize","webSearchCity","webSearchCountry","webSearchRegion","webSearchTimezone","useReasoning","passThrough","mediaTypes","inputFiles","parseFiles","isMultimodalRequest","provider","isEcho","supportedFileTypes","features","fileTypes","validFiles","requestFeature","_prompt","cachedMessages","messagesJSON","convMessages","contentPromise","GPTPlugin","specUrl","validateAndParseJson","parsedJson","HuggingFace","accessToken","modelName","modelTask","disableCache","hf","HfInference","hfFunc","group","kebabToCamel","formatRequest","hfParams","_hfParams","binaryFile","structuredInputs","formatRequestPattern","trimmedPattern","shouldNestInputs","inputsLog","modelCallWithRetry","retryCount","retryLimit","retryDelay","ImageSettingsConfig","positivePrompt","negativePrompt","width","multiple","height","outputFormat","outputQuality","numberResults","steps","backgroundColor","when","is","otherwise","strength","upscaleFactor","confidence","maxDetections","maskPadding","maskBlur","preProcessorType","ipAdapters","guideImage","weight","getCredentials","credentialsRequest","vaultProvider","keyName","vaultRequester","credentials","mapping","mappedCredentials","IMAGE_GEN_COST_MAP","standard","hd","ImageGenerator","sizeDalle2","sizeDalle3","quality","style","isRawInputPrompt","modelFamily","isGPTModel","isRunwareModel","isDallEModel","getModelFamily","imageGenerator","gpt","isValidImageFile","usage","reportTokenUsage","modelEntryName","keySource","Smyth","b64_json","_finalPrompt","cost","numberOfImages","n","revised_prompt","reportUsage","runware","apiKey","Runware","ensureConnection","seedImage","inputImage","normalizeImageInput","imageRequestArgs","outputType","includeCost","firstImage","requestImages","imageURL","disconnect","usageData","input_tokens_txt","input_tokens_details","text_tokens","input_tokens_img","image_tokens","output_tokens","input_tokens_cache_read","prompt_tokens_details","cached_tokens","PromptGenerator","parseHeaders","template","jsonHeaders","AxiosHeaders","parseUrl","parseSmythFsUrl","urlObj","publicUrls","pubUrl","destroyPublicUrls","parseData","handleJson","handleUrlEncoded","handleMultipartFormData","handleBinary","handleText","handleNone","URLSearchParams","formData","FormData","_body","bufferStream","filename","getHeaders","parseProxy","proxy","decodeURIComponent","proxyList","randomIdx","proxyUrl","proxyConfig","proxyUrlString","username","password","SocksProxyAgent","auth","mimeTypeCategories","contentHandlers","parseText","parseBinary","parseArrayBufferResponse","cleanContentType","handlerType","isBinaryFileSync","isBinaryData","managedVault","AccessTokenManager","clientId","clientSecret","secondaryToken","tokenUrl","expires_in","primaryToken","keyId","getAccessToken","currentTime","getTime","refreshAccessToken","client_id","client_secret","refresh_token","grant_type","newAccessToken","access_token","expiresInMilliseconds","expirationTimestamp","primary","extractAdditionalParamsForOAuth1","additionalParams","buildOAuth1Header","oauth1Credentials","oauth","OAuth","consumer","consumerKey","secret","consumerSecret","signature_method","hash_function","base_string","requestData","signedRequest","authorize","tokenSecret","toHeader","retrieveOAuthTokens","tokenKey","tokensData","secondary","oauthService","responseData","tokenURL","clientID","expiresIn","handleOAuthHeaders","rootUrl","oauthTokens","oAuthConfigString","oAuthConfig","logAndThrowError","oauth_info","oauth_keys_prefix","getClientCredentialToken","oauthHeader","accessTokenManager","APICall","Headers","_templateSettings","scope","authorizationURL","oauth2CallbackURL","callbackURL","requestTokenURL","accessTokenURL","userAuthorizationURL","oauth1CallbackURL","authenticate","isSecureEndpoint","oauthHeaders","generateOAuthHeaders","parsedRes","JSONFilter","fields","fieldList","field","filterObject","filterFields","LogicAND","cfgInput","Verified","Unverified","LogicOR","LogicXOR","trueCount","LogicAtLeast","minSetInputs","LogicAtMost","maxSetInputs","cacheConnector","LLMAssistant","userInput","UserInput","UserId","conversationId","ConversationId","isStandardLLM","hasKey","getMaxCompletionTokens","conv_uid","sessionData","filteredMessages","messageTokens","readMessagesFromSession","round","System","saveMessagesToSession","ScrapflyWebScrape","antiScrapingProtection","javascriptRendering","autoScroll","scrapeUrls","extractUrls","scrapeResults","scrapeURL","success","FailedURLs","totalCredits","urlsScraped","encodeURIComponent","cost_budget","asp","render_js","auto_scroll","hasOwnProperty","inputItem","isValidUrl","commaSeparatedUrls","credits","TavilyWebSearch","SearchQuery","includeImages","sourcesLimit","searchTopic","includeQAs","timeRange","includeRawContent","excludeDomains","searchQuery","api_key","topic","exclude_domains","max_results","time_range","include_images","include_answer","include_raw_content","Images","images","Answer","answer","MCPClient","mcpUrl","transport","SSEClientTransport","client","Client","connect","listTools","propName","propDetails","callTool","Note","LLMPrompt","WebSearch","WebScrape","generateLifecycleRules","rules","ID","Filter","Tag","Value","Status","Expiration","Days","generateExpiryMetadata","expiryDays","metadataValue","ceil","getNonExistingRules","existingRules","newRules","rule","existingRule","ttlToExpiryDays","checkAndInstallLifecycleRules","bucketName","s3Client","getLifecycleCommand","GetBucketLifecycleConfigurationCommand","Bucket","Rules","nonExistingNewRules","LifecycleConfiguration","putLifecycleCommand","PutBucketLifecycleConfigurationCommand","lifecycleRules","defineProperty","global","arr","randomBytes","S3Storage","bucket","clientConfig","region","accessKeyId","secretAccessKey","S3Client","initialize","isInitialized","s3HeadCommand","HeadObjectCommand","s3HeadData","expirationHeader","expirationDateMatch","expirationDate","s3DeleteCommand","DeleteObjectCommand","command","GetObjectCommand","Body","getS3Metadata","s3Metadata","setS3Metadata","PutObjectCommand","Metadata","serializeS3Metadata","expiryMetadata","s3PutObjectTaggingCommand","PutObjectTaggingCommand","Tagging","TagSet","migrateMetadata","userid","convertibleItems","newMetadata","amzMetadata","deserializeS3Metadata","s3RawMetadata","getObjectCommand","objectData","bufferBody","putObjectCommand","LocalStorage","folder","homedir","getStorageFilePath","metadataFilePath","getMetadataFilePath","deserializeMetadata","fileMetadata","serializedMetadata","serializeMetadata","writeFileSync","unlinkSync","metadataObject","storageFolderPath","storagePrefix","mkdirSync","recursive","metadataFolderPath","metadataPrefix","candidateId","createFoldersIfNotExists","fullPath","dirname","updatedMetadata","deserializedMetadata","StorageService","getLLMCredentials","credentialsList","None","credentialsMode","Internal","getStandardLLMCredentials","BedrockVault","getBedrockCredentials","VertexAIVault","getVertexAICredentials","llm","isUserKey","keyIdName","keyIDName","secretKeyName","sessionKeyName","sessionToken","jsonCredentialsName","jsonCredentials","LLMStream","dataQueue","isReading","_read","enqueueData","endStream","LLMConnector","preparedParams","prepareParams","hasFiles","requestParams","capabilities","webSearchRequest","newPrompt","clonedParams","_params","formatParamValues","getTeamId","modelProviderCandidate","baseURL","adjustMaxCompletionTokens","reasoning","imageGeneration","reqBodyAdapter","_value","EchoConnector","emitter","m","isLastChunk","LLMHelper","hasSystemMessage","separateSystemMessages","otherMessages","countVisionPromptTokens","textObj","textTokens","imageTokens","imageUrl","image_url","getImageDimensions","countImageTokens","dimensions","imageSize","detailMode","maxDimension","minDimension","scaledMinDimension","tiles","removeDuplicateUserMessages","MODELS_WITH_JSON_RESPONSE","costForNormalModels","low","medium","high","costForMiniModels","SEARCH_TOOL","OpenAIConnector","getClient","promptTokens","validateTokenLimit","max_completion_tokens","chat","completions","choices","finish_reason","reportedUsage","stream_options","include_usage","toolCall","_reported","responses","deltaMsg","searchTool","search_context_size","completion_tokens","prompt_tokens","total_tokens","generate","edit","processImageData","validSources","getValidImageFiles","getImageData","getValidDocumentFiles","validDocumentMimeTypes","processDocumentData","getDocumentData","prepareBodyForWebSearchRequest","prepareBodyForImageEditRequest","prepareBodyForImageGenRequest","prepareBody","input_tokens","input_tokens_cache_write","tool_choice","messageBlocks","transformedMessageBlock","transformedToolsData","toolData","tool_call_id","Tool","_message","textContent","textBlock","validImageMimeTypes","imageData","documentData","file_data","getWebSearchTool","searchCity","searchCountry","searchRegion","searchTimezone","location","city","country","timezone","user_location","validateTokensLimit","hasAPIKey","max_output_tokens","response_format","toFile","prepareMessages","top_p","frequency_penalty","presence_penalty","validImageFiles","validDocumentFiles","promptData","MODELS_SUPPORT_SYSTEM_INSTRUCTION","MODELS_SUPPORT_JSON_RESPONSE","VALID_MIME_TYPES","GoogleAIConnector","GoogleGenerativeAI","$model","getGenerativeModel","generateContent","candidates","usageMetadata","toolCalls","functionCall","Assistant","generateContentStream","responseMimeType","systemInstruction","generationConfig","tier","tierThresholds","textInputTokens","detail","modality","tokenCount","promptTokenCount","audioInputTokens","modelWithTier","candidatesTokenCount","input_tokens_audio","cachedContentTokenCount","reasoning_tokens","thoughtsTokenCount","sanitizeFunctionName","functionCalls","Model","prepareMessagesWithFiles","prepareMessagesWithTools","prepareMessagesWithTextQuery","getValidFiles","fileUploadingTasks","uploadFile","uploadedFiles","getFileData","formattedMessages","separateMessages","systemMessageContent","toolsPrompt","contents","toolConfig","functionCallingConfig","mode","sanitized","tempDir","tmpdir","tempFilePath","writeFile","fileManager","GoogleAIFileManager","uploadResponse","uploadedFile","getFile","FileState","PROCESSING","stdout","FAILED","unlink","validMimeTypes","fileUri","LEGACY_THINKING_MODELS","AnthropicConnector","stopReason","stop_reason","toolUseContentBlocks","toolUseBlock","finalMessage","shouldUseThinkingMode","prepareBodyForThinkingRequest","cache_creation_input_tokens","cache_read_input_tokens","input_schema","calls","toolResultsContent","tool_use_id","toolBlocks","max_tokens","system","prepareSystemPrompt","top_k","stop_sequences","budget_tokens","thinkingBody","media_type","GroqConnector","BedrockConnector","BedrockRuntimeClient","bedrock","ConverseCommand","toolUse","toolUseId","_deserializeToolName","ConverseStreamCommand","currentMessage","currentToolCall","currentToolInput","messageStart","contentBlockDelta","contentBlockStart","contentBlockStop","messageStop","typedError","customModelInfo","customModel","foundationModel","cacheWriteInputTokenCount","cacheReadInputTokenCount","toolSpec","_serializeToolName","toolResult","VertexAIConnector","projectId","project","googleAuthOptions","generativeModel","PerplexityConnector","Authorization","perplexity","respose","LLMService","RedisCache","sentinels","hosts","REDIS_HOSTS","hostName","redis","IORedis","REDIS_MASTER_NAME","REDIS_PASSWORD","_prefix","mdPrefix","_mdPrefix","setMetadataWithTTL","del","deserializeRedisMetadata","serializeRedisMetadata","_metadata","redisMetadata","strMetadata","quit","S3Cache","cachePrefix","headData","s3GetCommand","transformToString","s3PutCommandConfig","s3PutCommand","deleteCommand","s3HeadObjectResponse","currentDate","timeDifference","getObjectTaggingCommand","GetObjectTaggingCommand","objectTagging","copyObjectCommand","CopyObjectCommand","CopySource","MetadataDirective","tag","LocalStorageCache","cacheFolderPath","expiresAt","createDirectories","returnBasePath","folders","currentPath","RAMCache","cleanupInterval","cleanupExpiredEntries","getFullKey","getFullMetadataKey","fullKey","fullMetadataKey","remaining","CacheService","VaultConnector","listKeys","JSONFileVault","sharedVault","shared","vaultFile","findVaultFile","vaultData","fileKey","privateKey","encryptedVault","decryptedBuffer","privateDecrypt","RSA_PKCS1_OAEP_PADDING","encrypted","getMasterKeyInteractive","_vaultFile","masterKey","readlineSync","question","hideEchoBack","mask","SecretsManager","secretsManager","SecretsManagerClient","awsAccessKeyId","awsSecretAccessKey","secretName","getSecretByName","SecretString","secrets","nextToken","listResponse","ListSecretsCommand","NextToken","Filters","Values","SecretList","Name","ARN","CreatedDate","formattedSecrets","$promises","getSpecificSecret","secretString","GetSecretValueCommand","SecretId","parsedSecret","NullVault","VaultService","AccountConnector","getAllUserSettings","getUserSetting","settingKey","getAllTeamSettings","getTeamSetting","getAgentSetting","DummyAccount","users","agents","FAKE_AGENT_ID","accountId","AWSAccount","pool","mysql","createPool","database","connectionLimit","rows","execute","row","JSONFileAccount","loadData","fileContent","saveData","teamData","typedTeamData","AccountService","openapiTemplate","schemas","openapiEndpointTemplate","AgentDataConnector","server_url","aiOnly","shortDescription","_version","openAPITpl","model_name","model_description","openAPIObj","openAPIEntry","parameter","getOpenAPIInputSchema","explode","getOpenAPIParameterStyle","requiredProps","input_type","additionalProperties","CLIAgentDataConnector","__dirname","realpathSync","getAgentIdByDomain","listTeamAgents","deployedOnly","LocalAgentDataConnector","dev","prod","devDir","prodDir","indexDir","dir","readdirSync","agentsData","indexAgentsData","devAgentsData","devAgentSettings","prodAgentsData","prodAgentSettings","NullAgentData","AgentDataService","VectorDBConnector","datasource","datasourceId","listDatasources","getDatasource","deleteNamespace","constructNsName","joinedName","BaseEmbedding","stripNewLines","chunkArr","sizePerChunk","elem","chunkIndex","processTexts","texts","t","detectSourceType","transformSource","sourceType","embedTexts","vectors","dummyVector","fill","OpenAIEmbeds","maxConcurrency","dangerouslyAllowBrowser","canSpecifyDimensions","batches","batchRequests","batch","embed","batchResponses","embeddings","batchResponse","j","embedding","embedText","maxRetries","OpenAIClient","statusCode","APIError","errKey","createOpenAIError","supportedProviders","embedder","models","EmbeddingsFactory","PineconeVectorDB","indexName","Pinecone","nkvConnector","preparedNs","nsData","Index","upsert","isSkeletonVector","stats","describeIndexStats","deleteAll","deleteACL","pineconeIndex","_vector","vector","includeValues","insert","sourceWrapper","preparedSource","_ids","deleteMany","formattedNs","chunkedText","ids","_","_vIds","dsData","candidateRole","vectorIds","ds","list","ac","aclRes","MilvusVectorDB","address","MilvusClient","SCHEMA_DEFINITION","data_type","DataType","VarChar","is_primary_key","max_length","USER_METADATA_KEY","FloatVector","dim","INDEX_PARAMS","index_type","metric_type","field_name","createCollection","collection_name","index_params","hasCollection","error_code","ErrorCode","SUCCESS","dropCollection","output_fields","_record","score","user_metadata","datasourceLabel","deleteTarget","deleteEntities","expr","queryIterator","batchSize","datasourceMap","record","referenceRecord","allIds","RAMVectorDB","acls","storageType","datasources","getNamespace","listNamespaces","queryVector","namespaceData","similarity","cosineSimilarity","sort","a","b","sources","insertedIds","vectorData","existingIndex","splitTextIntoChunks","chunkId","totalChunks","storageDataSource","namespaceDatasources","vecA","vecB","dotProduct","normA","normB","sqrt","overlap","VectorDBService","CLIConnector","_keys","argsList","getMainArgs","CLIService","NKVConnector","_NKVRedis","redisCacheConnector","mdKey","setKey","fetchKeysByPrefix","pipeline","cursor","scan","NamespaceAccessControl","isNamespaceSearch","finalKey","Validate","NKVRedis","_NKVRAM","storageKey","nsKey","actualKey","keysToDelete","getKeysByPrefix","clearAll","getStats","totalKeys","totalNamespaces","NKVRAM","NKVService","RouterConnector","ExpressRouter","handlers","put","useFn","use","getRouter","NullRouter","RouterService","ManagedVaultConnector","SecretManagerManagedVault","PutSecretValueCommand","CreateSecretCommand","Tags","DeleteSecretCommand","NullManagedVault","ManagedVaultService","LogConnector","callId","isUsingTestDomain","ConsoleLog","LogService","ComponentConnector","componentInstance","LocalComponentConnector","ComponentService","keyOptions","alias","searchContextTokens","o3","hidden","o1","maxReasoningTokens","grok","customModels","supportsSystemPrompt","supportsStreamingToolUse","gemma2","gemma","codegemma","llama3_1","llama3","llama2","codestral","mixtral","phi3","qwen2","mammut","mistral","nllb","openllama","imagetext","pic2word","_ModelsProviderConnector","cacheKey","localCache","teamModels","loadTeamModels","builtinmodels","getModels","getCustomModels","addModels","isCustomLLM","maxCompletionTokens","getMaxContextTokens","allowedContextTokens","totalTokens","aliasModelInfo","aliasKeyOptions","modelKeyOptions","teamSettings","savedCustomModelsData","customModelData","feature","ModelsProviderConnector","_SmythModelsProvider","initDirWatcher","validModels","getValidModels","reindexModels","scannedModels","scanDirectoryForModels","readdir","withFileTypes","isDirectory","subDirModels","assign","readFile","modelData","isValidSingleModel","isValidModel","stat","debouncedReindex","chokidar","watch","ignored","persistent","ignoreInitial","awaitWriteFinish","stabilityThreshold","pollInterval","SmythModelsProvider","ModelsProviderService","CodeConnector","prepare","deploy","deploymentId","executeDeployment","listDeployments","getDeployment","deleteDeployment","AWSLambdaCode","prepared","warnings","createdAt","executionTime","CodeService","Code","_booted","boot","_SmythRuntime","_readyResolve","smythDir","_smythDir","initializing","_initializing","localDir","mainScriptPath","mainScriptDir","mainScriptSmythDir","packageRootDir","findPackageRoot","packageSmythDir","homeDir","findSmythDir","_initialized","autoConf","configEntry","Id","Settings","Default","defaultConfig","newConfig","hasDefault","_stopping","SmythRuntime","SRE","shuttingDown","startDir","currentDir","packageJsonPath","shutdown","exit","SmythURI","HashicorpVault"],"mappings":"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"}