@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.
- package/LICENSE +18 -0
- package/dist/index.js +22329 -4
- package/dist/index.js.map +1 -1
- package/dist/types/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.d.ts +2 -2
- package/dist/types/subsystems/IO/VectorDB.service/embed/BaseEmbedding.d.ts +11 -7
- package/dist/types/types/VectorDB.types.d.ts +13 -11
- package/package.json +102 -127
- package/src/Components/APICall/APICall.class.ts +155 -0
- package/src/Components/APICall/AccessTokenManager.ts +130 -0
- package/src/Components/APICall/ArrayBufferResponse.helper.ts +58 -0
- package/src/Components/APICall/OAuth.helper.ts +294 -0
- package/src/Components/APICall/mimeTypeCategories.ts +46 -0
- package/src/Components/APICall/parseData.ts +167 -0
- package/src/Components/APICall/parseHeaders.ts +41 -0
- package/src/Components/APICall/parseProxy.ts +68 -0
- package/src/Components/APICall/parseUrl.ts +91 -0
- package/src/Components/APIEndpoint.class.ts +234 -0
- package/src/Components/APIOutput.class.ts +58 -0
- package/src/Components/AgentPlugin.class.ts +102 -0
- package/src/Components/Async.class.ts +155 -0
- package/src/Components/Await.class.ts +90 -0
- package/src/Components/Classifier.class.ts +158 -0
- package/src/Components/Component.class.ts +94 -0
- package/src/Components/ComponentHost.class.ts +38 -0
- package/src/Components/DataSourceCleaner.class.ts +92 -0
- package/src/Components/DataSourceIndexer.class.ts +181 -0
- package/src/Components/DataSourceLookup.class.ts +141 -0
- package/src/Components/FEncDec.class.ts +29 -0
- package/src/Components/FHash.class.ts +33 -0
- package/src/Components/FSign.class.ts +80 -0
- package/src/Components/FSleep.class.ts +25 -0
- package/src/Components/FTimestamp.class.ts +25 -0
- package/src/Components/FileStore.class.ts +75 -0
- package/src/Components/ForEach.class.ts +97 -0
- package/src/Components/GPTPlugin.class.ts +70 -0
- package/src/Components/GenAILLM.class.ts +395 -0
- package/src/Components/HuggingFace.class.ts +314 -0
- package/src/Components/Image/imageSettings.config.ts +70 -0
- package/src/Components/ImageGenerator.class.ts +407 -0
- package/src/Components/JSONFilter.class.ts +54 -0
- package/src/Components/LLMAssistant.class.ts +213 -0
- package/src/Components/LogicAND.class.ts +28 -0
- package/src/Components/LogicAtLeast.class.ts +85 -0
- package/src/Components/LogicAtMost.class.ts +86 -0
- package/src/Components/LogicOR.class.ts +29 -0
- package/src/Components/LogicXOR.class.ts +34 -0
- package/src/Components/MCPClient.class.ts +112 -0
- package/src/Components/PromptGenerator.class.ts +122 -0
- package/src/Components/ScrapflyWebScrape.class.ts +159 -0
- package/src/Components/TavilyWebSearch.class.ts +98 -0
- package/src/Components/index.ts +77 -0
- package/src/Core/AgentProcess.helper.ts +240 -0
- package/src/Core/Connector.class.ts +123 -0
- package/src/Core/ConnectorsService.ts +192 -0
- package/src/Core/DummyConnector.ts +49 -0
- package/src/Core/HookService.ts +105 -0
- package/src/Core/SmythRuntime.class.ts +292 -0
- package/src/Core/SystemEvents.ts +15 -0
- package/src/Core/boot.ts +55 -0
- package/src/config.ts +15 -0
- package/src/constants.ts +125 -0
- package/src/data/hugging-face.params.json +580 -0
- package/src/helpers/BinaryInput.helper.ts +324 -0
- package/src/helpers/Conversation.helper.ts +1094 -0
- package/src/helpers/JsonContent.helper.ts +97 -0
- package/src/helpers/LocalCache.helper.ts +97 -0
- package/src/helpers/Log.helper.ts +234 -0
- package/src/helpers/OpenApiParser.helper.ts +150 -0
- package/src/helpers/S3Cache.helper.ts +129 -0
- package/src/helpers/SmythURI.helper.ts +5 -0
- package/src/helpers/TemplateString.helper.ts +243 -0
- package/src/helpers/TypeChecker.helper.ts +329 -0
- package/src/index.ts +179 -0
- package/src/index.ts.bak +179 -0
- package/src/subsystems/AgentManager/Agent.class.ts +1108 -0
- package/src/subsystems/AgentManager/Agent.helper.ts +3 -0
- package/src/subsystems/AgentManager/AgentData.service/AgentDataConnector.ts +230 -0
- package/src/subsystems/AgentManager/AgentData.service/connectors/CLIAgentDataConnector.class.ts +66 -0
- package/src/subsystems/AgentManager/AgentData.service/connectors/LocalAgentDataConnector.class.ts +142 -0
- package/src/subsystems/AgentManager/AgentData.service/connectors/NullAgentData.class.ts +39 -0
- package/src/subsystems/AgentManager/AgentData.service/index.ts +18 -0
- package/src/subsystems/AgentManager/AgentLogger.class.ts +297 -0
- package/src/subsystems/AgentManager/AgentRequest.class.ts +51 -0
- package/src/subsystems/AgentManager/AgentRuntime.class.ts +559 -0
- package/src/subsystems/AgentManager/AgentSSE.class.ts +101 -0
- package/src/subsystems/AgentManager/AgentSettings.class.ts +52 -0
- package/src/subsystems/AgentManager/Component.service/ComponentConnector.ts +32 -0
- package/src/subsystems/AgentManager/Component.service/connectors/LocalComponentConnector.class.ts +59 -0
- package/src/subsystems/AgentManager/Component.service/index.ts +11 -0
- package/src/subsystems/AgentManager/EmbodimentSettings.class.ts +47 -0
- package/src/subsystems/AgentManager/ForkedAgent.class.ts +153 -0
- package/src/subsystems/AgentManager/OSResourceMonitor.ts +77 -0
- package/src/subsystems/ComputeManager/Code.service/CodeConnector.ts +99 -0
- package/src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts +63 -0
- package/src/subsystems/ComputeManager/Code.service/index.ts +11 -0
- package/src/subsystems/IO/CLI.service/CLIConnector.ts +47 -0
- package/src/subsystems/IO/CLI.service/index.ts +9 -0
- package/src/subsystems/IO/Log.service/LogConnector.ts +32 -0
- package/src/subsystems/IO/Log.service/connectors/ConsoleLog.class.ts +28 -0
- package/src/subsystems/IO/Log.service/index.ts +13 -0
- package/src/subsystems/IO/NKV.service/NKVConnector.ts +41 -0
- package/src/subsystems/IO/NKV.service/connectors/NKVRAM.class.ts +204 -0
- package/src/subsystems/IO/NKV.service/connectors/NKVRedis.class.ts +182 -0
- package/src/subsystems/IO/NKV.service/index.ts +12 -0
- package/src/subsystems/IO/Router.service/RouterConnector.ts +21 -0
- package/src/subsystems/IO/Router.service/connectors/ExpressRouter.class.ts +48 -0
- package/src/subsystems/IO/Router.service/connectors/NullRouter.class.ts +40 -0
- package/src/subsystems/IO/Router.service/index.ts +11 -0
- package/src/subsystems/IO/Storage.service/SmythFS.class.ts +472 -0
- package/src/subsystems/IO/Storage.service/StorageConnector.ts +66 -0
- package/src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts +305 -0
- package/src/subsystems/IO/Storage.service/connectors/S3Storage.class.ts +418 -0
- package/src/subsystems/IO/Storage.service/index.ts +13 -0
- package/src/subsystems/IO/VectorDB.service/VectorDBConnector.ts +108 -0
- package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +454 -0
- package/src/subsystems/IO/VectorDB.service/connectors/PineconeVectorDB.class.ts +384 -0
- package/src/subsystems/IO/VectorDB.service/connectors/RAMVecrtorDB.class.ts +421 -0
- package/src/subsystems/IO/VectorDB.service/embed/BaseEmbedding.ts +107 -0
- package/src/subsystems/IO/VectorDB.service/embed/OpenAIEmbedding.ts +109 -0
- package/src/subsystems/IO/VectorDB.service/embed/index.ts +21 -0
- package/src/subsystems/IO/VectorDB.service/index.ts +14 -0
- package/src/subsystems/LLMManager/LLM.helper.ts +221 -0
- package/src/subsystems/LLMManager/LLM.inference.ts +335 -0
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +375 -0
- package/src/subsystems/LLMManager/LLM.service/LLMCredentials.helper.ts +145 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +632 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +405 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Echo.class.ts +81 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +689 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +257 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/OpenAI.class.ts +848 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +255 -0
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +193 -0
- package/src/subsystems/LLMManager/LLM.service/index.ts +43 -0
- package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +281 -0
- package/src/subsystems/LLMManager/ModelsProvider.service/connectors/SmythModelsProvider.class.ts +229 -0
- package/src/subsystems/LLMManager/ModelsProvider.service/index.ts +11 -0
- package/src/subsystems/LLMManager/custom-models.ts +854 -0
- package/src/subsystems/LLMManager/models.ts +2539 -0
- package/src/subsystems/LLMManager/paramMappings.ts +69 -0
- package/src/subsystems/MemoryManager/Cache.service/CacheConnector.ts +86 -0
- package/src/subsystems/MemoryManager/Cache.service/connectors/LocalStorageCache.class.ts +297 -0
- package/src/subsystems/MemoryManager/Cache.service/connectors/RAMCache.class.ts +201 -0
- package/src/subsystems/MemoryManager/Cache.service/connectors/RedisCache.class.ts +252 -0
- package/src/subsystems/MemoryManager/Cache.service/connectors/S3Cache.class.ts +373 -0
- package/src/subsystems/MemoryManager/Cache.service/index.ts +15 -0
- package/src/subsystems/MemoryManager/LLMCache.ts +72 -0
- package/src/subsystems/MemoryManager/LLMContext.ts +125 -0
- package/src/subsystems/MemoryManager/RuntimeContext.ts +249 -0
- package/src/subsystems/Security/AccessControl/ACL.class.ts +208 -0
- package/src/subsystems/Security/AccessControl/AccessCandidate.class.ts +76 -0
- package/src/subsystems/Security/AccessControl/AccessRequest.class.ts +52 -0
- package/src/subsystems/Security/Account.service/AccountConnector.ts +41 -0
- package/src/subsystems/Security/Account.service/connectors/AWSAccount.class.ts +76 -0
- package/src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts +130 -0
- package/src/subsystems/Security/Account.service/connectors/JSONFileAccount.class.ts +159 -0
- package/src/subsystems/Security/Account.service/index.ts +14 -0
- package/src/subsystems/Security/Credentials.helper.ts +62 -0
- package/src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts +34 -0
- package/src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts +57 -0
- package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +154 -0
- package/src/subsystems/Security/ManagedVault.service/index.ts +12 -0
- package/src/subsystems/Security/SecureConnector.class.ts +110 -0
- package/src/subsystems/Security/Vault.service/Vault.helper.ts +30 -0
- package/src/subsystems/Security/Vault.service/VaultConnector.ts +26 -0
- package/src/subsystems/Security/Vault.service/connectors/HashicorpVault.class.ts +46 -0
- package/src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts +166 -0
- package/src/subsystems/Security/Vault.service/connectors/NullVault.class.ts +54 -0
- package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +140 -0
- package/src/subsystems/Security/Vault.service/index.ts +12 -0
- package/src/types/ACL.types.ts +104 -0
- package/src/types/AWS.types.ts +9 -0
- package/src/types/Agent.types.ts +61 -0
- package/src/types/AgentLogger.types.ts +17 -0
- package/src/types/Cache.types.ts +1 -0
- package/src/types/Common.types.ts +3 -0
- package/src/types/LLM.types.ts +419 -0
- package/src/types/Redis.types.ts +8 -0
- package/src/types/SRE.types.ts +64 -0
- package/src/types/Security.types.ts +18 -0
- package/src/types/Storage.types.ts +5 -0
- package/src/types/VectorDB.types.ts +86 -0
- package/src/utils/base64.utils.ts +275 -0
- package/src/utils/cli.utils.ts +68 -0
- package/src/utils/data.utils.ts +263 -0
- package/src/utils/date-time.utils.ts +22 -0
- package/src/utils/general.utils.ts +238 -0
- package/src/utils/index.ts +12 -0
- package/src/utils/numbers.utils.ts +13 -0
- package/src/utils/oauth.utils.ts +35 -0
- package/src/utils/string.utils.ts +414 -0
- package/src/utils/url.utils.ts +19 -0
- 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
|
+
}
|