@smythos/sre 1.5.1 → 1.5.4

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 (193) hide show
  1. package/LICENSE +18 -0
  2. package/dist/index.js +22329 -4
  3. package/dist/index.js.map +1 -1
  4. package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +2 -2
  5. package/dist/types/subsystems/IO/VectorDB.service/embed/BaseEmbedding.d.ts +11 -7
  6. package/dist/types/types/VectorDB.types.d.ts +13 -11
  7. package/package.json +102 -127
  8. package/src/Components/APICall/APICall.class.ts +155 -0
  9. package/src/Components/APICall/AccessTokenManager.ts +130 -0
  10. package/src/Components/APICall/ArrayBufferResponse.helper.ts +58 -0
  11. package/src/Components/APICall/OAuth.helper.ts +294 -0
  12. package/src/Components/APICall/mimeTypeCategories.ts +46 -0
  13. package/src/Components/APICall/parseData.ts +167 -0
  14. package/src/Components/APICall/parseHeaders.ts +41 -0
  15. package/src/Components/APICall/parseProxy.ts +68 -0
  16. package/src/Components/APICall/parseUrl.ts +91 -0
  17. package/src/Components/APIEndpoint.class.ts +234 -0
  18. package/src/Components/APIOutput.class.ts +58 -0
  19. package/src/Components/AgentPlugin.class.ts +102 -0
  20. package/src/Components/Async.class.ts +155 -0
  21. package/src/Components/Await.class.ts +90 -0
  22. package/src/Components/Classifier.class.ts +158 -0
  23. package/src/Components/Component.class.ts +94 -0
  24. package/src/Components/ComponentHost.class.ts +38 -0
  25. package/src/Components/DataSourceCleaner.class.ts +92 -0
  26. package/src/Components/DataSourceIndexer.class.ts +181 -0
  27. package/src/Components/DataSourceLookup.class.ts +141 -0
  28. package/src/Components/FEncDec.class.ts +29 -0
  29. package/src/Components/FHash.class.ts +33 -0
  30. package/src/Components/FSign.class.ts +80 -0
  31. package/src/Components/FSleep.class.ts +25 -0
  32. package/src/Components/FTimestamp.class.ts +25 -0
  33. package/src/Components/FileStore.class.ts +75 -0
  34. package/src/Components/ForEach.class.ts +97 -0
  35. package/src/Components/GPTPlugin.class.ts +70 -0
  36. package/src/Components/GenAILLM.class.ts +395 -0
  37. package/src/Components/HuggingFace.class.ts +314 -0
  38. package/src/Components/Image/imageSettings.config.ts +70 -0
  39. package/src/Components/ImageGenerator.class.ts +407 -0
  40. package/src/Components/JSONFilter.class.ts +54 -0
  41. package/src/Components/LLMAssistant.class.ts +213 -0
  42. package/src/Components/LogicAND.class.ts +28 -0
  43. package/src/Components/LogicAtLeast.class.ts +85 -0
  44. package/src/Components/LogicAtMost.class.ts +86 -0
  45. package/src/Components/LogicOR.class.ts +29 -0
  46. package/src/Components/LogicXOR.class.ts +34 -0
  47. package/src/Components/MCPClient.class.ts +112 -0
  48. package/src/Components/PromptGenerator.class.ts +122 -0
  49. package/src/Components/ScrapflyWebScrape.class.ts +159 -0
  50. package/src/Components/TavilyWebSearch.class.ts +98 -0
  51. package/src/Components/index.ts +77 -0
  52. package/src/Core/AgentProcess.helper.ts +240 -0
  53. package/src/Core/Connector.class.ts +123 -0
  54. package/src/Core/ConnectorsService.ts +192 -0
  55. package/src/Core/DummyConnector.ts +49 -0
  56. package/src/Core/HookService.ts +105 -0
  57. package/src/Core/SmythRuntime.class.ts +292 -0
  58. package/src/Core/SystemEvents.ts +15 -0
  59. package/src/Core/boot.ts +55 -0
  60. package/src/config.ts +15 -0
  61. package/src/constants.ts +125 -0
  62. package/src/data/hugging-face.params.json +580 -0
  63. package/src/helpers/BinaryInput.helper.ts +324 -0
  64. package/src/helpers/Conversation.helper.ts +1094 -0
  65. package/src/helpers/JsonContent.helper.ts +97 -0
  66. package/src/helpers/LocalCache.helper.ts +97 -0
  67. package/src/helpers/Log.helper.ts +234 -0
  68. package/src/helpers/OpenApiParser.helper.ts +150 -0
  69. package/src/helpers/S3Cache.helper.ts +129 -0
  70. package/src/helpers/SmythURI.helper.ts +5 -0
  71. package/src/helpers/TemplateString.helper.ts +243 -0
  72. package/src/helpers/TypeChecker.helper.ts +329 -0
  73. package/src/index.ts +179 -0
  74. package/src/index.ts.bak +179 -0
  75. package/src/subsystems/AgentManager/Agent.class.ts +1108 -0
  76. package/src/subsystems/AgentManager/Agent.helper.ts +3 -0
  77. package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +230 -0
  78. package/src/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.ts +66 -0
  79. package/src/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.ts +142 -0
  80. package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +39 -0
  81. package/src/subsystems/AgentManager/AgentData.service/index.ts +18 -0
  82. package/src/subsystems/AgentManager/AgentLogger.class.ts +297 -0
  83. package/src/subsystems/AgentManager/AgentRequest.class.ts +51 -0
  84. package/src/subsystems/AgentManager/AgentRuntime.class.ts +559 -0
  85. package/src/subsystems/AgentManager/AgentSSE.class.ts +101 -0
  86. package/src/subsystems/AgentManager/AgentSettings.class.ts +52 -0
  87. package/src/subsystems/AgentManager/Component.service/ComponentConnector.ts +32 -0
  88. package/src/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.ts +59 -0
  89. package/src/subsystems/AgentManager/Component.service/index.ts +11 -0
  90. package/src/subsystems/AgentManager/EmbodimentSettings.class.ts +47 -0
  91. package/src/subsystems/AgentManager/ForkedAgent.class.ts +153 -0
  92. package/src/subsystems/AgentManager/OSResourceMonitor.ts +77 -0
  93. package/src/subsystems/ComputeManager/Code.service/CodeConnector.ts +99 -0
  94. package/src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts +63 -0
  95. package/src/subsystems/ComputeManager/Code.service/index.ts +11 -0
  96. package/src/subsystems/IO/CLI.service/CLIConnector.ts +47 -0
  97. package/src/subsystems/IO/CLI.service/index.ts +9 -0
  98. package/src/subsystems/IO/Log.service/LogConnector.ts +32 -0
  99. package/src/subsystems/IO/Log.service/connectors/ConsoleLog.class.ts +28 -0
  100. package/src/subsystems/IO/Log.service/index.ts +13 -0
  101. package/src/subsystems/IO/NKV.service/NKVConnector.ts +41 -0
  102. package/src/subsystems/IO/NKV.service/connectors/NKVRAM.class.ts +204 -0
  103. package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +182 -0
  104. package/src/subsystems/IO/NKV.service/index.ts +12 -0
  105. package/src/subsystems/IO/Router.service/RouterConnector.ts +21 -0
  106. package/src/subsystems/IO/Router.service/connectors/ExpressRouter.class.ts +48 -0
  107. package/src/subsystems/IO/Router.service/connectors/NullRouter.class.ts +40 -0
  108. package/src/subsystems/IO/Router.service/index.ts +11 -0
  109. package/src/subsystems/IO/Storage.service/SmythFS.class.ts +472 -0
  110. package/src/subsystems/IO/Storage.service/StorageConnector.ts +66 -0
  111. package/src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts +305 -0
  112. package/src/subsystems/IO/Storage.service/connectors/S3Storage.class.ts +418 -0
  113. package/src/subsystems/IO/Storage.service/index.ts +13 -0
  114. package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +108 -0
  115. package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +454 -0
  116. package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +384 -0
  117. package/src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts +421 -0
  118. package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +107 -0
  119. package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +109 -0
  120. package/src/subsystems/IO/VectorDB.service/embed/index.ts +21 -0
  121. package/src/subsystems/IO/VectorDB.service/index.ts +14 -0
  122. package/src/subsystems/LLMManager/LLM.helper.ts +221 -0
  123. package/src/subsystems/LLMManager/LLM.inference.ts +335 -0
  124. package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +375 -0
  125. package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +145 -0
  126. package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +632 -0
  127. package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +405 -0
  128. package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +81 -0
  129. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +689 -0
  130. package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +257 -0
  131. package/src/subsystems/LLMManager/LLM.service/connectors/OpenAI.class.ts +848 -0
  132. package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +255 -0
  133. package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +193 -0
  134. package/src/subsystems/LLMManager/LLM.service/index.ts +43 -0
  135. package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +281 -0
  136. package/src/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.ts +229 -0
  137. package/src/subsystems/LLMManager/ModelsProvider.service/index.ts +11 -0
  138. package/src/subsystems/LLMManager/custom-models.ts +854 -0
  139. package/src/subsystems/LLMManager/models.ts +2539 -0
  140. package/src/subsystems/LLMManager/paramMappings.ts +69 -0
  141. package/src/subsystems/MemoryManager/Cache.service/CacheConnector.ts +86 -0
  142. package/src/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.ts +297 -0
  143. package/src/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.ts +201 -0
  144. package/src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts +252 -0
  145. package/src/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.ts +373 -0
  146. package/src/subsystems/MemoryManager/Cache.service/index.ts +15 -0
  147. package/src/subsystems/MemoryManager/LLMCache.ts +72 -0
  148. package/src/subsystems/MemoryManager/LLMContext.ts +125 -0
  149. package/src/subsystems/MemoryManager/RuntimeContext.ts +249 -0
  150. package/src/subsystems/Security/AccessControl/ACL.class.ts +208 -0
  151. package/src/subsystems/Security/AccessControl/AccessCandidate.class.ts +76 -0
  152. package/src/subsystems/Security/AccessControl/AccessRequest.class.ts +52 -0
  153. package/src/subsystems/Security/Account.service/AccountConnector.ts +41 -0
  154. package/src/subsystems/Security/Account.service/connectors/AWSAccount.class.ts +76 -0
  155. package/src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts +130 -0
  156. package/src/subsystems/Security/Account.service/connectors/JSONFileAccount.class.ts +159 -0
  157. package/src/subsystems/Security/Account.service/index.ts +14 -0
  158. package/src/subsystems/Security/Credentials.helper.ts +62 -0
  159. package/src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts +34 -0
  160. package/src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts +57 -0
  161. package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +154 -0
  162. package/src/subsystems/Security/ManagedVault.service/index.ts +12 -0
  163. package/src/subsystems/Security/SecureConnector.class.ts +110 -0
  164. package/src/subsystems/Security/Vault.service/Vault.helper.ts +30 -0
  165. package/src/subsystems/Security/Vault.service/VaultConnector.ts +26 -0
  166. package/src/subsystems/Security/Vault.service/connectors/HashicorpVault.class.ts +46 -0
  167. package/src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts +166 -0
  168. package/src/subsystems/Security/Vault.service/connectors/NullVault.class.ts +54 -0
  169. package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +140 -0
  170. package/src/subsystems/Security/Vault.service/index.ts +12 -0
  171. package/src/types/ACL.types.ts +104 -0
  172. package/src/types/AWS.types.ts +9 -0
  173. package/src/types/Agent.types.ts +61 -0
  174. package/src/types/AgentLogger.types.ts +17 -0
  175. package/src/types/Cache.types.ts +1 -0
  176. package/src/types/Common.types.ts +3 -0
  177. package/src/types/LLM.types.ts +419 -0
  178. package/src/types/Redis.types.ts +8 -0
  179. package/src/types/SRE.types.ts +64 -0
  180. package/src/types/Security.types.ts +18 -0
  181. package/src/types/Storage.types.ts +5 -0
  182. package/src/types/VectorDB.types.ts +86 -0
  183. package/src/utils/base64.utils.ts +275 -0
  184. package/src/utils/cli.utils.ts +68 -0
  185. package/src/utils/data.utils.ts +263 -0
  186. package/src/utils/date-time.utils.ts +22 -0
  187. package/src/utils/general.utils.ts +238 -0
  188. package/src/utils/index.ts +12 -0
  189. package/src/utils/numbers.utils.ts +13 -0
  190. package/src/utils/oauth.utils.ts +35 -0
  191. package/src/utils/string.utils.ts +414 -0
  192. package/src/utils/url.utils.ts +19 -0
  193. package/src/utils/validation.utils.ts +74 -0
@@ -0,0 +1,97 @@
1
+ import { jsonrepair } from 'jsonrepair';
2
+ import { isDigits, isSafeNumber, isValidString } from '@sre/utils';
3
+
4
+ export class JSONContentHelper {
5
+ private _current: string;
6
+
7
+ public get result() {
8
+ return this._current;
9
+ }
10
+ private constructor(private dataString: string) {
11
+ this._current = dataString;
12
+ }
13
+
14
+ public static create(dataString: string) {
15
+ return new JSONContentHelper(dataString);
16
+ }
17
+
18
+ /**
19
+ * 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.
20
+ * if the string is not a JSON representation, but contains a JSON object, it will extract and parse it.
21
+ * @returns
22
+ */
23
+ public tryParse() {
24
+ const strInput = this._current;
25
+
26
+ // is it an object ? a digit ? a safe number ?
27
+ if (!isValidString(strInput) || isDigits(strInput) || isSafeNumber(strInput)) return strInput;
28
+
29
+ let str = strInput.trim();
30
+
31
+ // the string seems to be a json object
32
+ if ((str.startsWith('{') && str.endsWith('}')) || (str.startsWith('[') && str.endsWith(']'))) {
33
+ try {
34
+ return JSON.parse(str);
35
+ } catch (e) {
36
+ try {
37
+ const repairedJson = jsonrepair(str);
38
+ return JSON.parse(repairedJson);
39
+ } catch (e: any) {}
40
+ }
41
+ }
42
+
43
+ // the string does not seem to be a json object, so we try to extract a json object from it
44
+ str = (this.extractJsonFromString(strInput) || strInput).trim();
45
+
46
+ if ((isDigits(str) && !isSafeNumber(str)) || (!str.startsWith('{') && !str.startsWith('['))) return str;
47
+
48
+ try {
49
+ return JSON.parse(str);
50
+ } catch (e) {
51
+ try {
52
+ const repairedJson = jsonrepair(str);
53
+ return JSON.parse(repairedJson);
54
+ } catch (e: any) {
55
+ //console.warn('Error on parseJson: ', e.toString());
56
+ //console.warn(' Tried to parse: ', str);
57
+ return strInput;
58
+ }
59
+ }
60
+ }
61
+
62
+ // Same as tryParse but it does not extract JSON from string
63
+ public tryFullParse() {
64
+ const str = this._current;
65
+ if (!str) return str;
66
+
67
+ if ((isDigits(str) && !isSafeNumber(str)) || (!str.startsWith('{') && !str.startsWith('['))) return str;
68
+
69
+ try {
70
+ return JSON.parse(str);
71
+ } catch (e) {
72
+ try {
73
+ return JSON.parse(jsonrepair(str));
74
+ } catch (e: any) {
75
+ console.warn('Error on parseJson: ', e.toString());
76
+ console.warn(' Tried to parse: ', str);
77
+ return { result: str, error: e.toString() };
78
+ }
79
+ }
80
+ }
81
+
82
+ private extractJsonFromString(str) {
83
+ try {
84
+ const regex = /(\{.*\})/s; // LLMs in smythOS are expected to generate json between curly brackets only
85
+
86
+ const match = str.match(regex);
87
+
88
+ return match?.[1];
89
+ } catch {
90
+ return null;
91
+ }
92
+ }
93
+ }
94
+
95
+ export function JSONContent(dataString: string) {
96
+ return JSONContentHelper.create(dataString);
97
+ }
@@ -0,0 +1,97 @@
1
+ interface CacheItem<T> {
2
+ value: T;
3
+ expiry: number;
4
+ }
5
+
6
+ export class LocalCache<K, V> {
7
+ private cache: Map<K, V>;
8
+ private expiryMap: Map<K, number>;
9
+ private timeouts: Map<K, NodeJS.Timeout>;
10
+ private defaultTTL: number = 60 * 60 * 1000;
11
+
12
+ constructor(defaultTTL: number = 60 * 60 * 1000) {
13
+ this.defaultTTL = defaultTTL;
14
+ this.cache = new Map<K, V>();
15
+ this.expiryMap = new Map<K, number>();
16
+ this.timeouts = new Map<K, NodeJS.Timeout>();
17
+ }
18
+
19
+ set(key: K, value: V, ttlMs: number = this.defaultTTL): void {
20
+ this.cache.set(key, value);
21
+ const expiry = Date.now() + ttlMs;
22
+ this.expiryMap.set(key, expiry);
23
+
24
+ // Clear any existing timeout for this key
25
+ this.clearTimeout(key);
26
+
27
+ // Set a new timeout to remove the item when it expires
28
+ const timeout = setTimeout(() => {
29
+ this.delete(key);
30
+ }, ttlMs);
31
+ this.timeouts.set(key, timeout);
32
+ timeout.unref(); //unblock the event loop
33
+ }
34
+
35
+ updateTTL(key: K, ttlMs: number = this.defaultTTL): void {
36
+ if (!this.has(key)) {
37
+ return;
38
+ }
39
+ const expiry = Date.now() + ttlMs;
40
+ this.expiryMap.set(key, expiry);
41
+
42
+ // Clear existing timeout and set a new one
43
+ this.clearTimeout(key);
44
+ const timeout = setTimeout(() => {
45
+ this.delete(key);
46
+ }, ttlMs);
47
+ this.timeouts.set(key, timeout);
48
+ timeout.unref(); //unblock the event loop
49
+ }
50
+
51
+ get(key: K, ttlMs?: number): V | undefined {
52
+ if (!this.has(key)) {
53
+ return undefined;
54
+ }
55
+ const value = this.cache.get(key);
56
+ if (value === undefined) {
57
+ return undefined;
58
+ }
59
+ this.updateTTL(key, ttlMs);
60
+ return value;
61
+ }
62
+
63
+ has(key: K): boolean {
64
+ if (!this.cache.has(key)) {
65
+ return false;
66
+ }
67
+ const expiry = this.expiryMap.get(key);
68
+ if (expiry && Date.now() > expiry) {
69
+ this.delete(key);
70
+ return false;
71
+ }
72
+ return true;
73
+ }
74
+
75
+ delete(key: K): boolean {
76
+ this.clearTimeout(key);
77
+ this.expiryMap.delete(key);
78
+ return this.cache.delete(key);
79
+ }
80
+
81
+ clear(): void {
82
+ for (const key of this.cache.keys()) {
83
+ this.clearTimeout(key);
84
+ }
85
+ this.cache.clear();
86
+ this.expiryMap.clear();
87
+ this.timeouts.clear();
88
+ }
89
+
90
+ private clearTimeout(key: K): void {
91
+ const timeout = this.timeouts.get(key);
92
+ if (timeout) {
93
+ clearTimeout(timeout);
94
+ this.timeouts.delete(key);
95
+ }
96
+ }
97
+ }
@@ -0,0 +1,234 @@
1
+ import 'dotenv/config';
2
+ import winston from 'winston';
3
+ import Transport from 'winston-transport';
4
+ import { getFormattedStackTrace, parseCLIArgs } from '../utils';
5
+ import config from '@sre/config';
6
+ import { EventEmitter } from 'events';
7
+ winston.addColors({
8
+ error: 'red',
9
+ warn: 'yellow',
10
+ info: 'green',
11
+ debug: 'blue',
12
+ });
13
+
14
+ const logLevelMap = {
15
+ min: 'info',
16
+ full: 'debug',
17
+ };
18
+
19
+ let logLevel = () => {
20
+ let val = parseCLIArgs('debug')?.debug || config?.env?.LOG_LEVEL || 'none';
21
+ if (logLevelMap[val]) val = logLevelMap[val];
22
+ return !['none', 'error', 'warn', 'info', 'debug'].includes(val) ? 'none' : val;
23
+ };
24
+
25
+ // Retrieve the DEBUG environment variable and split it into an array of namespaces
26
+ const namespaces = (config.env.LOG_FILTER || '').split(',');
27
+
28
+ // Create a Winston format that filters messages based on namespaces
29
+ const namespaceFilter = winston.format((info: any) => {
30
+ // If DEBUG is not set, log everything
31
+ if (!config.env.LOG_FILTER || namespaces.some((ns) => info.module?.includes(ns))) {
32
+ return info;
33
+ }
34
+ return false; // Filter out messages that do not match the namespace
35
+ })();
36
+
37
+ // Custom stream for your transport
38
+ class ArrayTransport extends Transport {
39
+ private logs: any[];
40
+ constructor(opts) {
41
+ super(opts);
42
+ // Configure your storage array
43
+ this.logs = opts.logs;
44
+ }
45
+
46
+ log(info, callback) {
47
+ setImmediate(() => {
48
+ this.emit('logged', info);
49
+ });
50
+
51
+ // Perform the writing to the array storage
52
+ this.logs.push(`${info.level}: ${info.message}`);
53
+
54
+ // Perform the writing to the remote service
55
+ callback();
56
+ }
57
+ }
58
+
59
+ export class LogHelper extends EventEmitter {
60
+ public startTime = Date.now();
61
+ public get output() {
62
+ return Array.isArray(this.data) ? this.data.join('\n') : undefined;
63
+ }
64
+ public get elapsedTime() {
65
+ return Date.now() - this.startTime;
66
+ }
67
+ constructor(
68
+ private _logger: winston.Logger,
69
+ public data,
70
+ private labels: { [key: string]: any },
71
+ ) {
72
+ super();
73
+ }
74
+
75
+ public log(...args) {
76
+ this._logger.log('info', formatLogMessage(...args), this.labels);
77
+ this.emit('logged', { level: 'info', message: formatLogMessage(...args) });
78
+ }
79
+ public warn(...args) {
80
+ this._logger.log('warn', formatLogMessage(...args), this.labels);
81
+ this.emit('logged', { level: 'warn', message: formatLogMessage(...args) });
82
+ }
83
+ public debug(...args) {
84
+ this._logger.log('debug', formatLogMessage(...args), this.labels);
85
+ this.emit('logged', { level: 'debug', message: formatLogMessage(...args) });
86
+ }
87
+ public info(...args) {
88
+ this._logger.log('info', formatLogMessage(...args), this.labels);
89
+ this.emit('logged', { level: 'info', message: formatLogMessage(...args) });
90
+ }
91
+ public verbose(...args) {
92
+ this._logger.log('verbose', formatLogMessage(...args), this.labels);
93
+ this.emit('logged', { level: 'verbose', message: formatLogMessage(...args) });
94
+ }
95
+
96
+ public error(...args) {
97
+ const stack = '\nCall Stack:\n' + getFormattedStackTrace(10).join('\n');
98
+
99
+ this._logger.log('error', formatLogMessage(...args), { ...this.labels, stack });
100
+
101
+ this.emit('logged', { level: 'error', message: formatLogMessage(...args) });
102
+ }
103
+
104
+ public close() {
105
+ this._logger.clear();
106
+ this._logger.close();
107
+ }
108
+ }
109
+
110
+ const colorizedFormat = winston.format.printf((info) => {
111
+ return `${info.timestamp} ${winston.format.colorize().colorize(info.level, `${info.level}: ${info.message}`)}`;
112
+ });
113
+
114
+ const MAX_LOG_MESSAGE_LENGTH = 500;
115
+
116
+ function redactLogMessage(logMessage: string) {
117
+ if (config.env.NODE_ENV !== 'PROD') return logMessage; //only redact logs in PROD
118
+ if (logMessage.length > 500) {
119
+ return logMessage;
120
+ }
121
+
122
+ const sensitiveWords = ['password', 'eyJ', 'token', 'email', 'secret', 'key', 'apikey', 'api_key', 'auth', 'credential'];
123
+ const obfuscatedString = ' [!! SmythOS::REDACTED_DATA !!] ';
124
+
125
+ // Iterate through the sensitive words list and replace sensitive data in the log message
126
+
127
+ for (const sensitiveWord of sensitiveWords) {
128
+ // Create a regular expression to find the sensitive word followed by any character (non-greedy) until a space, newline, or separator is found.
129
+ const regex = new RegExp(`(${sensitiveWord})((?:[^\\n]{0,29}(?=\\n))|(?:[^\\n]{30}\\S*))`, 'gmi');
130
+
131
+ // Replace sensitive data with the obfuscated string
132
+ logMessage = logMessage.replace(regex, `$1${obfuscatedString}`);
133
+ }
134
+
135
+ return logMessage;
136
+ }
137
+
138
+ function createBaseLogger(memoryStore?: any[]) {
139
+ const logger = winston.createLogger({
140
+ //level: 'info', // log level
141
+
142
+ format: winston.format.combine(
143
+ winston.format((info: any) => {
144
+ if (config.env.LOG_LEVEL == 'none' || logLevel() == 'none' || logLevel() == '') return false; // skip logging if log level is none
145
+
146
+ // Apply redaction to the log message
147
+ //info.message = redactSecrets(info.message, sensitiveOptions);
148
+
149
+ info.message = redactLogMessage(info.message);
150
+ return info;
151
+ })(),
152
+ winston.format.timestamp(),
153
+ winston.format.errors({
154
+ stack: true,
155
+ }),
156
+ winston.format.splat(),
157
+ winston.format.json(),
158
+ ),
159
+
160
+ transports: [
161
+ new winston.transports.Console({
162
+ level: 'error',
163
+ //handleExceptions: true,
164
+ format: winston.format.combine(
165
+ winston.format.printf((info: any) => {
166
+ let message = info.message;
167
+ message = message?.length > MAX_LOG_MESSAGE_LENGTH ? message.substring(0, MAX_LOG_MESSAGE_LENGTH) + '...' : message;
168
+ return `${info.level}:${info.module || ''} ${message} ${info.stack || ''}`;
169
+ }),
170
+ ),
171
+ stderrLevels: ['error'], // Define levels that should be logged to stderr
172
+ }),
173
+ new winston.transports.Console({
174
+ level: logLevel(),
175
+ format: winston.format.combine(
176
+ namespaceFilter,
177
+ winston.format.printf((info: any) => {
178
+ const module = info.module ? winston.format.colorize().colorize(info.level, ` [${info.module}]`) : '';
179
+ const ns = winston.format.colorize().colorize(info.level, `${info.level}${module}`);
180
+
181
+ let message = info.message;
182
+ message = message?.length > MAX_LOG_MESSAGE_LENGTH ? message.substring(0, MAX_LOG_MESSAGE_LENGTH) + '...' : message;
183
+
184
+ return `${ns} - ${message}`;
185
+ }),
186
+ ),
187
+
188
+ //handleExceptions: true,
189
+ }),
190
+ ],
191
+ });
192
+
193
+ if (Array.isArray(memoryStore)) {
194
+ logger.add(
195
+ new ArrayTransport({
196
+ level: 'debug',
197
+ logs: memoryStore,
198
+ }),
199
+ );
200
+ }
201
+
202
+ return logger;
203
+ }
204
+
205
+ function formatLogMessage(...args) {
206
+ return args
207
+ .map((arg) => {
208
+ // If the argument is an object (and not null), serialize it to JSON
209
+ if (typeof arg === 'object' && arg !== null && !(arg instanceof Error)) {
210
+ try {
211
+ return JSON.stringify(arg, null, 2); // set the space to 2 for better readability
212
+ } catch (error) {
213
+ return String(arg);
214
+ }
215
+ }
216
+ // Otherwise, just convert it to a string in case it's not
217
+ return String(arg);
218
+ })
219
+ .join(' '); // Concatenate all arguments with a space
220
+ }
221
+
222
+ function createLabeledLogger(labels: { [key: string]: any }, memoryStore?: any[]) {
223
+ const _logger = createBaseLogger(memoryStore);
224
+
225
+ _logger.defaultMeta = labels;
226
+
227
+ const logger = new LogHelper(_logger, memoryStore, labels);
228
+
229
+ return logger;
230
+ }
231
+
232
+ export function Logger(module: string, withMemoryStore = false) {
233
+ return createLabeledLogger({ module }, withMemoryStore ? [] : undefined);
234
+ }
@@ -0,0 +1,150 @@
1
+ import axios from 'axios';
2
+ import yaml from 'js-yaml';
3
+
4
+ import { REQUEST_METHODS } from '../constants';
5
+
6
+ // * We need a couple of packages to resolve references in the OpenAPI specification
7
+ //FIXME : YAML support temporarly disabled to allow executable packaging
8
+ //import SwaggerParser from '@apidevtools/swagger-parser';
9
+ //import $RefParser from '@apidevtools/json-schema-ref-parser';
10
+ //import { JSONSchema } from '@apidevtools/json-schema-ref-parser/dist/lib/types';
11
+
12
+ //const swaggerParser = new SwaggerParser();
13
+
14
+ type JSONSchema = Record<string, any>;
15
+
16
+ /**
17
+ * Utility function to resolve $ref values within a schema.
18
+ * @param schema The schema containing potential $ref values.
19
+ * @param root The root schema for reference resolution.
20
+ * @returns The dereferenced schema.
21
+ */
22
+ const dereferenceSchema = async (schema: any, root: any = schema): Promise<any> => {
23
+ if (typeof schema !== 'object' || schema === null) {
24
+ return schema;
25
+ }
26
+
27
+ if (schema.$ref) {
28
+ const ref = schema.$ref;
29
+ const path = ref.replace(/^#\//, '').split('/'); // Remove the initial '#/' and split the path
30
+ let resolved = root;
31
+ for (const segment of path) {
32
+ if (resolved[segment] === undefined) {
33
+ throw new Error(`Could not resolve $ref: ${ref}`);
34
+ }
35
+ resolved = resolved[segment];
36
+ }
37
+ return dereferenceSchema(resolved, root); // Recursively dereference
38
+ }
39
+
40
+ // Recursively resolve all properties and items
41
+ if (Array.isArray(schema)) {
42
+ return Promise.all(schema.map((item) => dereferenceSchema(item, root)));
43
+ }
44
+
45
+ const result: any = {};
46
+ for (const key of Object.keys(schema)) {
47
+ result[key] = await dereferenceSchema(schema[key], root);
48
+ }
49
+ return result;
50
+ };
51
+
52
+ export class OpenAPIParser {
53
+ static mapReqMethods(paths: Array<Record<string, any>>): Map<string, any> {
54
+ const methods = new Map();
55
+
56
+ for (const path in paths) {
57
+ const pathData = paths[path];
58
+
59
+ for (const method in pathData) {
60
+ const data = pathData[method];
61
+
62
+ if (REQUEST_METHODS.includes(method.toUpperCase())) {
63
+ methods.set(data?.operationId, method);
64
+ }
65
+ }
66
+ }
67
+
68
+ return methods;
69
+ }
70
+ static mapEndpoints(paths: Array<Record<string, any>>): Map<string, any> {
71
+ const operationIds = new Map();
72
+
73
+ for (const path in paths) {
74
+ const pathData = paths[path];
75
+
76
+ // it's possible we have multiple methods for a single path
77
+ for (const method in pathData) {
78
+ const data = pathData[method];
79
+
80
+ if (REQUEST_METHODS.includes(method.toUpperCase())) {
81
+ operationIds.set(data?.operationId, path);
82
+ }
83
+ }
84
+ }
85
+
86
+ return operationIds;
87
+ }
88
+
89
+ // static async yamlToJson(yamlData: string): Promise<JSONSchema> {
90
+ // const data = yaml.load(yamlData);
91
+ // //FIXME : YAML support temporarly disabled to allow executable packaging
92
+ // const schema = await $RefParser.dereference(data);
93
+ // //const schema: any = {};
94
+
95
+ // return schema;
96
+ // }
97
+
98
+ static async yamlToJson(yamlData: string): Promise<JSONSchema> {
99
+ const data = yaml.load(yamlData);
100
+ const schema = await dereferenceSchema(data);
101
+ return schema;
102
+ }
103
+
104
+ // static async getJson(data: string | Record<string, any>): Promise<Record<string, any>> {
105
+ // try {
106
+ // let _data = data;
107
+ // if (typeof data === 'string') {
108
+ // _data = JSON.parse(_data as string);
109
+ // }
110
+ // //FIXME : YAML support temporarly disabled to allow executable packaging
111
+ // const result = swaggerParser.dereference(_data as any);
112
+ // //const result: any = {};
113
+ // return result;
114
+ // } catch (error) {
115
+ // try {
116
+ // return OpenAPIParser.yamlToJson(data as string);
117
+ // } catch (error) {
118
+ // throw new Error('Invalid OpenAPI specification data format');
119
+ // }
120
+ // }
121
+ // }
122
+
123
+ static async getJson(data: string | Record<string, any>): Promise<Record<string, any>> {
124
+ try {
125
+ let parsedData = data;
126
+ if (typeof data === 'string') {
127
+ parsedData = JSON.parse(data);
128
+ }
129
+
130
+ return await dereferenceSchema(parsedData);
131
+ } catch (error) {
132
+ try {
133
+ // Fallback to handle YAML data
134
+ return await OpenAPIParser.yamlToJson(data as string);
135
+ } catch (innerError) {
136
+ throw new Error('Invalid OpenAPI specification or JSON data format');
137
+ }
138
+ }
139
+ }
140
+ static async getJsonFromUrl(url: string): Promise<Record<string, any>> {
141
+ const response = await axios.get(url);
142
+ const data = response.data;
143
+
144
+ return OpenAPIParser.getJson(data);
145
+ }
146
+
147
+ static isValidOpenAPI(data: Record<string, any>): boolean {
148
+ return data?.openapi && data?.paths && data?.servers;
149
+ }
150
+ }