@smythos/sre 1.7.41 → 1.8.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.
- package/CHANGELOG +136 -64
- package/dist/index.js +65 -50
- package/dist/index.js.map +1 -1
- package/dist/types/Components/Async.class.d.ts +11 -5
- package/dist/types/index.d.ts +2 -0
- package/dist/types/subsystems/AgentManager/AgentData.service/connectors/SQLiteAgentDataConnector.class.d.ts +45 -0
- package/dist/types/subsystems/LLMManager/LLM.helper.d.ts +32 -1
- package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +25 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +27 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Groq.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Ollama.class.d.ts +22 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.d.ts +3 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.d.ts +23 -3
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.d.ts +2 -2
- package/dist/types/subsystems/LLMManager/LLM.service/connectors/xAI.class.d.ts +3 -3
- package/dist/types/subsystems/MemoryManager/LLMContext.d.ts +10 -3
- package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.d.ts +24 -0
- package/dist/types/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.redaction.helper.d.ts +49 -0
- package/dist/types/types/LLM.types.d.ts +30 -1
- package/package.json +4 -3
- package/src/Components/APICall/OAuth.helper.ts +16 -1
- package/src/Components/APIEndpoint.class.ts +11 -4
- package/src/Components/Async.class.ts +38 -5
- package/src/Components/GenAILLM.class.ts +13 -7
- package/src/Components/LLMAssistant.class.ts +3 -1
- package/src/Components/LogicAND.class.ts +13 -0
- package/src/Components/LogicAtLeast.class.ts +18 -0
- package/src/Components/LogicAtMost.class.ts +19 -0
- package/src/Components/LogicOR.class.ts +12 -2
- package/src/Components/LogicXOR.class.ts +11 -0
- package/src/constants.ts +1 -1
- package/src/helpers/Conversation.helper.ts +10 -8
- package/src/index.ts +2 -0
- package/src/index.ts.bak +2 -0
- package/src/subsystems/AgentManager/AgentData.service/connectors/SQLiteAgentDataConnector.class.ts +190 -0
- package/src/subsystems/AgentManager/AgentData.service/index.ts +2 -0
- package/src/subsystems/LLMManager/LLM.helper.ts +117 -1
- package/src/subsystems/LLMManager/LLM.inference.ts +136 -67
- package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +13 -6
- package/src/subsystems/LLMManager/LLM.service/connectors/Anthropic.class.ts +157 -33
- package/src/subsystems/LLMManager/LLM.service/connectors/Bedrock.class.ts +9 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +121 -83
- package/src/subsystems/LLMManager/LLM.service/connectors/Groq.class.ts +125 -62
- package/src/subsystems/LLMManager/LLM.service/connectors/Ollama.class.ts +168 -76
- package/src/subsystems/LLMManager/LLM.service/connectors/Perplexity.class.ts +18 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/VertexAI.class.ts +8 -4
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/OpenAIConnector.class.ts +50 -8
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ChatCompletionsApiInterface.ts +30 -16
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/OpenAIApiInterface.ts +2 -2
- package/src/subsystems/LLMManager/LLM.service/connectors/openai/apiInterfaces/ResponsesApiInterface.ts +29 -15
- package/src/subsystems/LLMManager/LLM.service/connectors/xAI.class.ts +10 -8
- package/src/subsystems/MemoryManager/LLMContext.ts +27 -8
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +467 -120
- package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.redaction.helper.ts +203 -0
- package/src/types/LLM.types.ts +31 -1
- package/src/types/node-sqlite.d.ts +45 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OTel Redaction Helper
|
|
3
|
+
*
|
|
4
|
+
* Provides sensitive data redaction functions for OpenTelemetry logs and traces.
|
|
5
|
+
* Adapted from Log.helper.ts redactLogMessage() function with enhancements for OTel.
|
|
6
|
+
*
|
|
7
|
+
* Key features:
|
|
8
|
+
* - JSON-aware redaction: handles "key":"value" patterns
|
|
9
|
+
* - Escaped JSON redaction: handles \"key\":\"value\" patterns in embedded strings
|
|
10
|
+
* - Truncated value support: handles preview strings without closing quotes
|
|
11
|
+
* - Key-based redaction: redacts values based on sensitive key names
|
|
12
|
+
* - JWT token redaction: full token redaction
|
|
13
|
+
* - Header redaction: full redaction for auth headers
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Sensitive words for content-based redaction
|
|
18
|
+
* Used to identify sensitive data in both key names and value content
|
|
19
|
+
*/
|
|
20
|
+
export const SENSITIVE_WORDS = [
|
|
21
|
+
// Common sensitive field names
|
|
22
|
+
'password',
|
|
23
|
+
'eyJ', // JWT token prefix (also caught by JWT regex, but catches partial matches)
|
|
24
|
+
'token',
|
|
25
|
+
'email',
|
|
26
|
+
'secret',
|
|
27
|
+
'key',
|
|
28
|
+
'apikey',
|
|
29
|
+
'api_key',
|
|
30
|
+
'auth',
|
|
31
|
+
'credential',
|
|
32
|
+
// Additional patterns
|
|
33
|
+
'bearer',
|
|
34
|
+
'private',
|
|
35
|
+
'AKIA', // AWS access key ID prefix
|
|
36
|
+
'authorization',
|
|
37
|
+
// API key prefixes
|
|
38
|
+
'sk-', // OpenAI secret keys
|
|
39
|
+
'sk_', // Stripe secret keys
|
|
40
|
+
'pk_', // Stripe publishable keys
|
|
41
|
+
'xox', // Slack tokens (xoxb-, xoxp-, xoxa-, xoxr-)
|
|
42
|
+
'ghp_', // GitHub personal access tokens
|
|
43
|
+
'gho_', // GitHub OAuth tokens
|
|
44
|
+
'npm_', // npm tokens
|
|
45
|
+
];
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Sensitive header names that should have their values fully redacted
|
|
49
|
+
*/
|
|
50
|
+
export const SENSITIVE_HEADERS = ['authorization', 'x-api-key', 'api-key', 'x-auth-token', 'x-access-token', 'cookie', 'set-cookie'];
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Redact sensitive data from a string value
|
|
54
|
+
* Applies multiple regex patterns to catch sensitive data in various formats.
|
|
55
|
+
*
|
|
56
|
+
* @param value - The string to redact
|
|
57
|
+
* @returns The redacted string with sensitive data replaced by [REDACTED]
|
|
58
|
+
*/
|
|
59
|
+
export function redactSensitiveString(value: string): string {
|
|
60
|
+
if (typeof value !== 'string' || value.length === 0) {
|
|
61
|
+
return value;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
let redacted = value;
|
|
65
|
+
|
|
66
|
+
// 1. Full JWT token redaction (entire token, not just 30 chars)
|
|
67
|
+
// JWT format: header.payload.signature (all base64url encoded)
|
|
68
|
+
const jwtPattern = /eyJ[A-Za-z0-9_-]+\.eyJ[A-Za-z0-9_-]+\.[A-Za-z0-9_-]+/g;
|
|
69
|
+
redacted = redacted.replace(jwtPattern, '[REDACTED]');
|
|
70
|
+
|
|
71
|
+
// 2. JSON-aware redaction: "key":"value" or "key": "value" patterns
|
|
72
|
+
// This handles JSON objects where sensitive keys have string values
|
|
73
|
+
for (const sensitiveWord of SENSITIVE_WORDS) {
|
|
74
|
+
// Match "sensitiveWord" (with quotes) followed by : and a quoted value
|
|
75
|
+
const jsonKeyPattern = new RegExp(`("${sensitiveWord}"\\s*:\\s*)"([^"]*)"`, 'gmi');
|
|
76
|
+
redacted = redacted.replace(jsonKeyPattern, '$1"[REDACTED]"');
|
|
77
|
+
|
|
78
|
+
// Match "sensitiveWord" (with quotes) followed by : and a non-quoted value until comma or }
|
|
79
|
+
// Exclude whitespace to avoid matching spaces after already-redacted quoted values
|
|
80
|
+
const jsonKeyUnquotedPattern = new RegExp(`("${sensitiveWord}"\\s*:\\s*)([^",}\\]\\s]+)`, 'gmi');
|
|
81
|
+
redacted = redacted.replace(jsonKeyUnquotedPattern, '$1[REDACTED]');
|
|
82
|
+
|
|
83
|
+
// Handle truncated values where the closing quote is missing (common in previews)
|
|
84
|
+
// Pattern: "key": "value (no closing quote, matches base64/API-key-like strings)
|
|
85
|
+
const jsonTruncatedPattern = new RegExp(`("${sensitiveWord}"\\s*:\\s*)"([A-Za-z0-9+/=_-]{8,})`, 'gmi');
|
|
86
|
+
redacted = redacted.replace(jsonTruncatedPattern, '$1"[REDACTED]');
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 3. Escaped JSON redaction: \"key\":\"value\" patterns (JSON embedded in strings)
|
|
90
|
+
// This handles nested JSON where quotes are escaped
|
|
91
|
+
for (const sensitiveWord of SENSITIVE_WORDS) {
|
|
92
|
+
// Match \"sensitiveWord\" (escaped quotes) followed by : and escaped quoted value
|
|
93
|
+
// Pattern: \"key\": \"value\" or \"key\":\"value\"
|
|
94
|
+
const escapedJsonPattern = new RegExp(`(\\\\"${sensitiveWord}\\\\"\\s*:\\s*)\\\\"([^\\\\]*?)\\\\"`, 'gmi');
|
|
95
|
+
redacted = redacted.replace(escapedJsonPattern, '$1\\"[REDACTED]\\"');
|
|
96
|
+
|
|
97
|
+
// Also handle truncated values where the closing quote is missing (common in previews)
|
|
98
|
+
// Pattern: \"key\": \"value (no closing quote, matches to end of string or next key)
|
|
99
|
+
const escapedJsonTruncatedPattern = new RegExp(`(\\\\"${sensitiveWord}\\\\"\\s*:\\s*)\\\\"([A-Za-z0-9+/=_-]{8,})`, 'gmi');
|
|
100
|
+
redacted = redacted.replace(escapedJsonTruncatedPattern, '$1\\"[REDACTED]');
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// 4. Word-based redaction for non-JSON text (more conservative - limit to 50 chars)
|
|
104
|
+
// Only applies to patterns not already caught by JSON patterns
|
|
105
|
+
for (const sensitiveWord of SENSITIVE_WORDS) {
|
|
106
|
+
// Match sensitive word followed by separator and up to 50 chars, stopping at common delimiters
|
|
107
|
+
const regex = new RegExp(`(${sensitiveWord})(\\s*[=:]\\s*)([^\\s,;\\n"'\\]\\}]{1,50})`, 'gmi');
|
|
108
|
+
redacted = redacted.replace(regex, '$1$2[REDACTED]');
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
return redacted;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Redact sensitive HTTP headers
|
|
116
|
+
* Full value redaction for known auth headers, string redaction for others.
|
|
117
|
+
*
|
|
118
|
+
* @param headers - The headers object or string to redact
|
|
119
|
+
* @returns The redacted headers with sensitive values replaced
|
|
120
|
+
*/
|
|
121
|
+
export function redactHeaders(headers: Record<string, unknown> | string | undefined | null): Record<string, unknown> | string | undefined | null {
|
|
122
|
+
if (headers === null || headers === undefined) {
|
|
123
|
+
return headers;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// If headers is already a string, apply string redaction
|
|
127
|
+
if (typeof headers === 'string') {
|
|
128
|
+
return redactSensitiveString(headers);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// If not an object, return as-is
|
|
132
|
+
if (typeof headers !== 'object') {
|
|
133
|
+
return headers;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
const redacted: Record<string, unknown> = {};
|
|
137
|
+
|
|
138
|
+
for (const [headerName, headerValue] of Object.entries(headers)) {
|
|
139
|
+
const lowerName = headerName.toLowerCase();
|
|
140
|
+
|
|
141
|
+
// Check if this is a sensitive header that needs full redaction
|
|
142
|
+
const isSensitiveHeader = SENSITIVE_HEADERS.some((h) => lowerName.includes(h));
|
|
143
|
+
|
|
144
|
+
if (isSensitiveHeader) {
|
|
145
|
+
// Full value redaction for auth headers
|
|
146
|
+
redacted[headerName] = '[REDACTED]';
|
|
147
|
+
} else if (typeof headerValue === 'string') {
|
|
148
|
+
// Apply string redaction to other header values
|
|
149
|
+
redacted[headerName] = redactSensitiveString(headerValue);
|
|
150
|
+
} else {
|
|
151
|
+
// Keep non-string values as-is
|
|
152
|
+
redacted[headerName] = headerValue;
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
return redacted;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Universal data redaction - handles any data type
|
|
161
|
+
* Recursively applies redaction to strings within objects/arrays.
|
|
162
|
+
* Also checks key names against sensitive words and redacts entire values.
|
|
163
|
+
* Preserves the input type structure for OTel compatibility.
|
|
164
|
+
*
|
|
165
|
+
* @param data - The data to redact (any type)
|
|
166
|
+
* @returns The redacted data with the same type structure
|
|
167
|
+
*/
|
|
168
|
+
export function redactData<T>(data: T): T {
|
|
169
|
+
if (data === null || data === undefined) {
|
|
170
|
+
return data;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// String: apply string redaction
|
|
174
|
+
if (typeof data === 'string') {
|
|
175
|
+
return redactSensitiveString(data) as T;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
// Array: recursively redact each element
|
|
179
|
+
if (Array.isArray(data)) {
|
|
180
|
+
return data.map((item) => redactData(item)) as T;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Object: recursively redact each value, also check key names
|
|
184
|
+
if (typeof data === 'object') {
|
|
185
|
+
const redacted: Record<string, unknown> = {};
|
|
186
|
+
for (const [key, value] of Object.entries(data)) {
|
|
187
|
+
// Check if the key name matches any sensitive word
|
|
188
|
+
const keyMatchesSensitive = SENSITIVE_WORDS.some((word) => key.toLowerCase().includes(word.toLowerCase()));
|
|
189
|
+
|
|
190
|
+
if (keyMatchesSensitive) {
|
|
191
|
+
// Redact the entire value if the key is sensitive
|
|
192
|
+
redacted[key] = '[REDACTED]';
|
|
193
|
+
} else {
|
|
194
|
+
// Otherwise, recursively process the value
|
|
195
|
+
redacted[key] = redactData(value);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
return redacted as T;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// Other types (numbers, booleans, etc.): return as-is
|
|
202
|
+
return data;
|
|
203
|
+
}
|
package/src/types/LLM.types.ts
CHANGED
|
@@ -204,6 +204,8 @@ export type TLLMPreparedParams = TLLMParams & {
|
|
|
204
204
|
imageEditing?: boolean;
|
|
205
205
|
};
|
|
206
206
|
toolsInfo?: TToolsInfo;
|
|
207
|
+
outputs?: any[]; // all outputs including default and system-specific (_debug, _error etc.)
|
|
208
|
+
structuredOutputs?: any[]; // custom outputs for structured response
|
|
207
209
|
};
|
|
208
210
|
|
|
209
211
|
export type TLLMConnectorParams = Omit<TLLMParams, 'model'> & {
|
|
@@ -513,6 +515,8 @@ export enum TLLMEvent {
|
|
|
513
515
|
Thinking = 'thinking',
|
|
514
516
|
/** End of the response */
|
|
515
517
|
End = 'end',
|
|
518
|
+
/** Request aborted */
|
|
519
|
+
Abort = 'abort',
|
|
516
520
|
/** Error */
|
|
517
521
|
Error = 'error',
|
|
518
522
|
/** Tool information : emitted by the LLM determines the next tool call */
|
|
@@ -547,15 +551,41 @@ export interface ILLMRequestFuncParams<TBody = any> {
|
|
|
547
551
|
acRequest: AccessRequest;
|
|
548
552
|
body: TBody;
|
|
549
553
|
context: ILLMRequestContext;
|
|
554
|
+
abortSignal?: AbortSignal;
|
|
550
555
|
}
|
|
551
556
|
|
|
552
557
|
// For future providers, you can add similar types:
|
|
553
558
|
// export type TAnthropicRequestBody = Anthropic.MessageCreateParams | Anthropic.MessageStreamParams;
|
|
554
559
|
// export type IAnthropicRequestFuncParams = ILLMRequestFuncParams<TAnthropicRequestBody>;
|
|
555
560
|
|
|
561
|
+
/**
|
|
562
|
+
* Standardized finish reasons for LLM responses across all providers.
|
|
563
|
+
*
|
|
564
|
+
* This enum normalizes provider-specific finish reasons (e.g., 'end_turn' from Anthropic,
|
|
565
|
+
* 'max_tokens' from Google AI) into a consistent set of values.
|
|
566
|
+
*/
|
|
567
|
+
export enum TLLMFinishReason {
|
|
568
|
+
/** Response completed normally (reached natural stopping point or stop sequence) */
|
|
569
|
+
Stop = 'stop',
|
|
570
|
+
/** Response was truncated due to maximum token limit or context window */
|
|
571
|
+
Length = 'length',
|
|
572
|
+
/** Response was truncated due to context window limit */
|
|
573
|
+
ContextWindowLength = 'context_window_length',
|
|
574
|
+
/** Response was filtered by content moderation policies */
|
|
575
|
+
ContentFilter = 'content_filter',
|
|
576
|
+
/** Response ended because the model called a tool/function */
|
|
577
|
+
ToolCalls = 'tool_calls',
|
|
578
|
+
/** Request was aborted by user or system */
|
|
579
|
+
Abort = 'abort',
|
|
580
|
+
/** Request ended due to an error */
|
|
581
|
+
Error = 'error',
|
|
582
|
+
/** Unknown or unmapped finish reason from provider */
|
|
583
|
+
Unknown = 'unknown',
|
|
584
|
+
}
|
|
585
|
+
|
|
556
586
|
export type TLLMChatResponse = {
|
|
557
587
|
content: string;
|
|
558
|
-
finishReason:
|
|
588
|
+
finishReason: TLLMFinishReason;
|
|
559
589
|
thinkingContent?: string;
|
|
560
590
|
usage?: any;
|
|
561
591
|
useTool?: boolean;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
declare module 'node:sqlite' {
|
|
2
|
+
export type SQLiteRunResult = {
|
|
3
|
+
changes?: number;
|
|
4
|
+
lastInsertRowid?: number | bigint;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export class StatementSync {
|
|
8
|
+
all<T = any>(...params: any[]): T[];
|
|
9
|
+
get<T = any>(...params: any[]): T | undefined;
|
|
10
|
+
run(...params: any[]): SQLiteRunResult;
|
|
11
|
+
iterate<T = any>(...params: any[]): IterableIterator<T>;
|
|
12
|
+
columns(): Array<{ name: string }>;
|
|
13
|
+
setAllowBareNamedParameters(allow: boolean): void;
|
|
14
|
+
setAllowUnknownNamedParameters(allow: boolean): void;
|
|
15
|
+
setReadBigInts(readBigInts: boolean): void;
|
|
16
|
+
setReturnArrays(returnArrays: boolean): void;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class DatabaseSync {
|
|
20
|
+
constructor(filename: string);
|
|
21
|
+
open(filename: string): void;
|
|
22
|
+
close(): void;
|
|
23
|
+
exec(sql: string): void;
|
|
24
|
+
prepare(sql: string): StatementSync;
|
|
25
|
+
function(name: string, options: any, func: (...args: any[]) => any): void;
|
|
26
|
+
aggregate(name: string, options: any): void;
|
|
27
|
+
createSession(): any;
|
|
28
|
+
applyChangeset(changeSet: Buffer): void;
|
|
29
|
+
enableLoadExtension(enabled: boolean): void;
|
|
30
|
+
loadExtension(fileName: string, entryPoint?: string): void;
|
|
31
|
+
location(filename: string): void;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function backup(sourceFilename: string, destinationFilename: string): void;
|
|
35
|
+
|
|
36
|
+
export const constants: Record<string, number>;
|
|
37
|
+
|
|
38
|
+
const _default: {
|
|
39
|
+
DatabaseSync: typeof DatabaseSync;
|
|
40
|
+
StatementSync: typeof StatementSync;
|
|
41
|
+
backup: typeof backup;
|
|
42
|
+
constants: typeof constants;
|
|
43
|
+
};
|
|
44
|
+
export default _default;
|
|
45
|
+
}
|