@smythos/sre 1.7.18 → 1.7.20

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 (23) hide show
  1. package/dist/index.js +21 -21
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/Components/RAG/DataSourceCleaner.class.d.ts +37 -0
  4. package/dist/types/Components/RAG/DataSourceComponent.class.d.ts +30 -0
  5. package/dist/types/Components/RAG/DataSourceIndexer.class.d.ts +14 -0
  6. package/dist/types/Components/RAG/DataSourceLookup.class.d.ts +36 -0
  7. package/dist/types/helpers/Conversation.helper.d.ts +3 -0
  8. package/dist/types/subsystems/LLMManager/LLM.inference.d.ts +10 -3
  9. package/dist/types/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.d.ts +4 -2
  10. package/dist/types/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.d.ts +10 -0
  11. package/dist/types/subsystems/Security/Vault.service/connectors/SecretsManager.class.d.ts +5 -0
  12. package/dist/types/types/LLM.types.d.ts +2 -0
  13. package/dist/types/utils/array.utils.d.ts +4 -0
  14. package/package.json +1 -1
  15. package/src/helpers/AWSLambdaCode.helper.ts +40 -45
  16. package/src/helpers/Conversation.helper.ts +14 -10
  17. package/src/subsystems/LLMManager/LLM.inference.ts +63 -47
  18. package/src/subsystems/LLMManager/LLM.service/connectors/GoogleAI.class.ts +92 -19
  19. package/src/subsystems/LLMManager/ModelsProvider.service/connectors/JSONModelsProvider.class.ts +34 -27
  20. package/src/subsystems/ObservabilityManager/Telemetry.service/connectors/OTel/OTel.class.ts +6 -0
  21. package/src/subsystems/Security/ManagedVault.service/connectors/SecretManagerManagedVault.ts +111 -48
  22. package/src/subsystems/Security/Vault.service/connectors/SecretsManager.class.ts +92 -62
  23. package/src/types/LLM.types.ts +5 -0
@@ -337,6 +337,12 @@ export class OTel extends TelemetryConnector {
337
337
 
338
338
  const convSpan = tracer.startSpan('Agent.Conv', {
339
339
  attributes: {
340
+ // OTel standard attributes
341
+ 'gen_ai.operation.name': 'chat',
342
+ 'gen_ai.provider.name': conversation?.llmInference?.llmProviderName || 'unknown',
343
+ 'gen_ai.conversation.id': processId,
344
+ 'gen_ai.request.model': modelId || 'unknown',
345
+ ////////////////////////////////
340
346
  'agent.id': agentId,
341
347
  'conv.id': processId,
342
348
  'llm.model': modelId || 'unknown',
@@ -1,6 +1,5 @@
1
1
  import { ConnectorService } from '@sre/Core/ConnectorsService';
2
2
  import { Logger } from '@sre/helpers/Log.helper';
3
- //import { SmythRuntime } from '@sre/Core/SmythRuntime.class';
4
3
  import { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';
5
4
  import { ACL } from '@sre/Security/AccessControl/ACL.class';
6
5
  import { SecureConnector } from '@sre/Security/SecureConnector.class';
@@ -9,16 +8,19 @@ import { IAccessCandidate, TAccessLevel, TAccessRole } from '@sre/types/ACL.type
9
8
  import {
10
9
  CreateSecretCommand,
11
10
  DeleteSecretCommand,
11
+ DescribeSecretCommand,
12
+ DescribeSecretCommandOutput,
12
13
  GetSecretValueCommand,
13
14
  GetSecretValueCommandOutput,
14
15
  ListSecretsCommand,
15
16
  ListSecretsCommandOutput,
16
17
  PutSecretValueCommand,
18
+ RestoreSecretCommand,
17
19
  SecretsManagerClient,
18
20
  } from '@aws-sdk/client-secrets-manager';
19
- import { randomUUID } from 'crypto';
20
21
  import { ManagedVaultConnector } from '../ManagedVaultConnector';
21
22
  import { SecretsManagerConfig } from '../../Vault.service/connectors/SecretsManager.class';
23
+ const DELETION_MARKER_ERROR_MESSAGE = "You can't create this secret because a secret with this name is already scheduled for deletion."
22
24
 
23
25
  const console = Logger('SecretManagerManagedVault');
24
26
 
@@ -26,49 +28,87 @@ export class SecretManagerManagedVault extends ManagedVaultConnector {
26
28
  public name: string = 'SecretManagerManagedVault';
27
29
  public scope: string = 'smyth-managed-vault';
28
30
  private secretsManager: SecretsManagerClient;
31
+ private prefix: string;
29
32
 
30
- constructor(protected _settings: SecretsManagerConfig & { vaultName: string }) {
33
+ constructor(protected _settings: SecretsManagerConfig & { vaultName: string, prefix: string }) {
31
34
  super(_settings);
32
- //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');
33
35
 
36
+ this.prefix = _settings.prefix || '';
34
37
  this.secretsManager = new SecretsManagerClient({
35
38
  region: _settings.region,
36
39
  ...(_settings.awsAccessKeyId && _settings.awsSecretAccessKey
37
40
  ? {
38
- accessKeyId: _settings.awsAccessKeyId,
39
- secretAccessKey: _settings.awsSecretAccessKey,
40
- }
41
+ accessKeyId: _settings.awsAccessKeyId,
42
+ secretAccessKey: _settings.awsSecretAccessKey,
43
+ }
41
44
  : {}),
42
45
  });
43
46
  }
44
47
 
45
48
  @SecureConnector.AccessControl
46
49
  protected async get(acRequest: AccessRequest, secretName: string) {
47
- const secret = await this.getSecretByName(secretName);
48
- return secret?.SecretString;
50
+ try {
51
+ const secret = await this.getSecretByName(acRequest, secretName);
52
+ return secret?.value;
53
+ } catch (error) {
54
+ console.error(error);
55
+ return null;
56
+ }
49
57
  }
50
58
 
51
59
  @SecureConnector.AccessControl
52
60
  protected async set(acRequest: AccessRequest, secretName: string, value: string) {
53
- const secret = await this.getSecretByName(secretName);
61
+ const accountConnector = ConnectorService.getAccountConnector();
62
+ const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
63
+ const secret = await this.getSecretByName(acRequest, secretName);
54
64
  if (secret) {
55
- await this.secretsManager.send(new PutSecretValueCommand({ SecretId: secret.ARN, SecretString: value }));
65
+ await this.secretsManager.send(new PutSecretValueCommand({ SecretId: secret.secretId, SecretString: value }));
56
66
  } else {
57
- await this.secretsManager.send(
58
- new CreateSecretCommand({
59
- Name: `smyth/${randomUUID()}`,
60
- SecretString: JSON.stringify({ [secretName]: value }),
61
- Tags: [{ Key: this.scope, Value: 'true' }],
62
- })
63
- );
67
+ const vaultKey = this.getVaultKey(secretName, teamId);
68
+ try {
69
+ await this.secretsManager.send(
70
+ new CreateSecretCommand({
71
+ Name: vaultKey,
72
+ Description: `Smyth Managed Vault Secret`,
73
+ SecretString: JSON.stringify({ [secretName]: value }),
74
+ Tags: [{ Key: this.scope, Value: 'true' }],
75
+ })
76
+ );
77
+ } catch (error) {
78
+ console.warn(error.message);
79
+ if (error.message === DELETION_MARKER_ERROR_MESSAGE) {
80
+ // The secret already exists — check if it's pending deletion
81
+ const secretDesc: DescribeSecretCommandOutput = await this.secretsManager.send(new DescribeSecretCommand({ SecretId: vaultKey }));
82
+
83
+ if (secretDesc.DeletedDate) {
84
+ console.debug(`Secret ${vaultKey} is pending deletion, restoring...`);
85
+ await this.secretsManager.send(new RestoreSecretCommand({ SecretId: vaultKey }));
86
+ } else {
87
+ console.debug(`Secret ${vaultKey} already exists, updating value...`);
88
+ }
89
+
90
+ // Update or re-put the secret value
91
+ await this.secretsManager.send(
92
+ new PutSecretValueCommand({
93
+ SecretId: vaultKey,
94
+ SecretString: JSON.stringify({
95
+ [secretName]: value,
96
+ }),
97
+ })
98
+ );
99
+
100
+ } else {
101
+ throw error;
102
+ }
103
+ }
64
104
  }
65
105
  }
66
106
 
67
107
  @SecureConnector.AccessControl
68
108
  protected async delete(acRequest: AccessRequest, secretName: string) {
69
- const secret = await this.getSecretByName(secretName);
109
+ const secret = await this.getSecretByName(acRequest, secretName);
70
110
  if (secret) {
71
- await this.secretsManager.send(new DeleteSecretCommand({ SecretId: secret.ARN }));
111
+ await this.secretsManager.send(new DeleteSecretCommand({ SecretId: secret.secretId, RecoveryWindowInDays: 7 }));
72
112
  }
73
113
  }
74
114
 
@@ -91,13 +131,35 @@ export class SecretManagerManagedVault extends ManagedVaultConnector {
91
131
  return acl;
92
132
  }
93
133
 
94
- private async getSecretByName(secretName: string) {
134
+ private async getSecretByName(acRequest: AccessRequest, secretName: string) {
95
135
  try {
136
+
137
+ const accountConnector = ConnectorService.getAccountConnector();
138
+ const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
139
+ const vaultKey = this.getVaultKey(secretName, teamId);
140
+ let secret: GetSecretValueCommandOutput | null = null;
141
+ try {
142
+ const describeSecret: DescribeSecretCommandOutput = await this.secretsManager.send(new DescribeSecretCommand({ SecretId: vaultKey }));
143
+ if (describeSecret.DeletedDate) {
144
+ secret = null;
145
+ } else {
146
+ secret = await this.secretsManager.send(new GetSecretValueCommand({ SecretId: vaultKey }));
147
+ }
148
+ } catch (error) {
149
+ secret = null;
150
+ console.warn('Secret not found by Id, trying to get it by name');
151
+ }
152
+ if (secret) {
153
+ return this.getFormattedSecret(secret);
154
+ }
155
+
156
+ // if not found by Id, try to get it by name
96
157
  const secrets = [];
97
158
  let nextToken: string | undefined;
159
+ let listingVaultKey = this.getVaultKey('', teamId);
98
160
  do {
99
161
  const listResponse: ListSecretsCommandOutput = await this.secretsManager.send(
100
- new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: [this.scope] }] })
162
+ new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: [this.scope] }, { Key: 'name', Values: [listingVaultKey] }] })
101
163
  );
102
164
  if (listResponse.SecretList) {
103
165
  for (const secret of listResponse.SecretList) {
@@ -105,7 +167,6 @@ export class SecretManagerManagedVault extends ManagedVaultConnector {
105
167
  secrets.push({
106
168
  ARN: secret.ARN,
107
169
  Name: secret.Name,
108
- CreatedDate: secret.CreatedDate,
109
170
  });
110
171
  }
111
172
  }
@@ -113,42 +174,44 @@ export class SecretManagerManagedVault extends ManagedVaultConnector {
113
174
  nextToken = listResponse.NextToken;
114
175
  } while (nextToken);
115
176
 
116
- const formattedSecrets = [];
117
177
  const $promises = [];
118
178
  for (const secret of secrets) {
119
179
  $promises.push(getSpecificSecret(secret, this.secretsManager));
120
180
  }
121
181
  const results = await Promise.all($promises);
122
- for (const result of results) {
123
- formattedSecrets.push(result);
124
- }
125
- const secret = formattedSecrets.find((s) => s.Name === secretName);
126
- return secret;
182
+ const secretData = results.find((s) => s.key === secretName);
183
+ return secretData;
127
184
  } catch (error) {
128
185
  console.error(error);
129
186
  }
130
187
 
131
188
  async function getSpecificSecret(secret, secretsManager: SecretsManagerClient) {
132
189
  const data: GetSecretValueCommandOutput = await secretsManager.send(new GetSecretValueCommand({ SecretId: secret.ARN }));
133
- let secretString = data.SecretString;
134
- let secretName = secret.Name;
135
-
136
- if (secretString) {
137
- try {
138
- let parsedSecret = JSON.parse(secretString);
139
- if (Object.keys(parsedSecret).length === 1) {
140
- secretName = Object.keys(parsedSecret)[0];
141
- secretString = parsedSecret[secretName];
142
- }
143
- } catch (error) {}
144
- }
145
- return {
146
- Name: secretName,
147
- ARN: secret.ARN,
148
- CreatedDate: secret.CreatedDate,
149
- SecretId: secret.Name,
150
- SecretString: secretString,
151
- };
190
+ return this.getFormattedSecret(data);
191
+ }
192
+ }
193
+
194
+ getVaultKey(secretName: string, teamId: string) {
195
+ return `${this.prefix.length ? `${this.prefix}/` : ''}${teamId}/${secretName}`;
196
+ }
197
+
198
+ getFormattedSecret(secret: GetSecretValueCommandOutput) {
199
+ let secretString = secret.SecretString;
200
+ let secretName = secret.Name;
201
+
202
+ if (secretString) {
203
+ try {
204
+ let parsedSecret = JSON.parse(secretString);
205
+ if (Object.keys(parsedSecret).length === 1) {
206
+ secretName = Object.keys(parsedSecret)[0];
207
+ secretString = parsedSecret[secretName];
208
+ }
209
+ } catch (error) { }
152
210
  }
211
+ return {
212
+ secretId: secret.Name,
213
+ key: secretName,
214
+ value: secretString,
215
+ };
153
216
  }
154
217
  }
@@ -1,7 +1,5 @@
1
1
  import { ConnectorService } from '@sre/Core/ConnectorsService';
2
2
  import { Logger } from '@sre/helpers/Log.helper';
3
- //import { SmythRuntime } from '@sre/Core/SmythRuntime.class';
4
- import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
5
3
  import { AccessRequest } from '@sre/Security/AccessControl/AccessRequest.class';
6
4
  import { ACL } from '@sre/Security/AccessControl/ACL.class';
7
5
  import { SecureConnector } from '@sre/Security/SecureConnector.class';
@@ -21,22 +19,24 @@ export type SecretsManagerConfig = {
21
19
  region: string;
22
20
  awsAccessKeyId?: string;
23
21
  awsSecretAccessKey?: string;
22
+ prefix?: string;
24
23
  };
25
24
  export class SecretsManager extends VaultConnector {
26
25
  public name: string = 'SecretsManager';
27
26
  private secretsManager: SecretsManagerClient;
27
+ private prefix: string;
28
28
 
29
29
  constructor(protected _settings: SecretsManagerConfig) {
30
30
  super(_settings);
31
31
  //if (!SmythRuntime.Instance) throw new Error('SRE not initialized');
32
-
32
+ this.prefix = _settings.prefix || '';
33
33
  this.secretsManager = new SecretsManagerClient({
34
34
  region: _settings.region,
35
35
  ...(_settings.awsAccessKeyId && _settings.awsSecretAccessKey
36
36
  ? {
37
- accessKeyId: _settings.awsAccessKeyId,
38
- secretAccessKey: _settings.awsSecretAccessKey,
39
- }
37
+ accessKeyId: _settings.awsAccessKeyId,
38
+ secretAccessKey: _settings.awsSecretAccessKey,
39
+ }
40
40
  : {}),
41
41
  });
42
42
  }
@@ -44,8 +44,14 @@ export class SecretsManager extends VaultConnector {
44
44
  @SecureConnector.AccessControl
45
45
  protected async get(acRequest: AccessRequest, secretName: string) {
46
46
  try {
47
- const secret = await this.getSecretByName(secretName);
48
- return secret?.SecretString;
47
+ const accountConnector = ConnectorService.getAccountConnector();
48
+ const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
49
+ // try fetchting by Id, if not found, try fetching by name
50
+ let secret = await this.getSecretById(teamId, secretName);
51
+ if (!secret) {
52
+ secret = await this.getSecretByName(acRequest, secretName);
53
+ }
54
+ return secret;
49
55
  } catch (error) {
50
56
  console.error(error);
51
57
  throw error;
@@ -60,8 +66,58 @@ export class SecretsManager extends VaultConnector {
60
66
 
61
67
  @SecureConnector.AccessControl
62
68
  protected async listKeys(acRequest: AccessRequest) {
63
- console.warn('SecretsManager.listKeys is not implemented');
64
- return [];
69
+ const accountConnector = ConnectorService.getAccountConnector();
70
+ const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
71
+ const secrets = [];
72
+ let nextToken: string | undefined;
73
+
74
+ do {
75
+ const listResponse: ListSecretsCommandOutput = await this.secretsManager.send(
76
+ new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: ['smyth-vault'] }, { Key: 'name', Values: [this.getVaultKey(teamId, '')] }] })
77
+ );
78
+ if (listResponse.SecretList) {
79
+ for (const secret of listResponse.SecretList) {
80
+ if (secret.Name) {
81
+ secrets.push({
82
+ ARN: secret.ARN,
83
+ Name: secret.Name,
84
+ CreatedDate: secret.CreatedDate,
85
+ });
86
+ }
87
+ }
88
+ }
89
+ nextToken = listResponse.NextToken;
90
+ } while (nextToken);
91
+
92
+ const $promises = [];
93
+ for (const secret of secrets) {
94
+ $promises.push(getSpecificSecret(secret, this.secretsManager));
95
+ }
96
+ const formattedSecrets = await Promise.all($promises);
97
+ return formattedSecrets;
98
+
99
+ async function getSpecificSecret(secret, secretsManager: SecretsManagerClient) {
100
+ const data: GetSecretValueCommandOutput = await secretsManager.send(new GetSecretValueCommand({ SecretId: secret.ARN }));
101
+ let secretString = data.SecretString;
102
+
103
+ if (secretString) {
104
+ try {
105
+ let parsedSecret = JSON.parse(secretString);
106
+ const secretId = secret.Name?.split('/').pop();
107
+ const key = parsedSecret.key;
108
+ const value = parsedSecret.value;
109
+ const metadata = parsedSecret.metadata;
110
+ return {
111
+ id: secretId,
112
+ key,
113
+ value,
114
+ metadata,
115
+ };
116
+ } catch (error) {
117
+ }
118
+ }
119
+ return null;
120
+ }
65
121
  }
66
122
 
67
123
  public async getResourceACL(resourceId: string, candidate: IAccessCandidate) {
@@ -77,64 +133,38 @@ export class SecretsManager extends VaultConnector {
77
133
  return acl;
78
134
  }
79
135
 
80
- private async getSecretByName(secretName: string) {
136
+ private async getSecretByName(acRequest: AccessRequest, secretName: string) {
81
137
  try {
82
- const secrets = [];
83
- let nextToken: string | undefined;
84
- do {
85
- const listResponse: ListSecretsCommandOutput = await this.secretsManager.send(
86
- new ListSecretsCommand({ NextToken: nextToken, Filters: [{ Key: 'tag-key', Values: ['smyth-vault'] }] })
87
- );
88
- if (listResponse.SecretList) {
89
- for (const secret of listResponse.SecretList) {
90
- if (secret.Name) {
91
- secrets.push({
92
- ARN: secret.ARN,
93
- Name: secret.Name,
94
- CreatedDate: secret.CreatedDate,
95
- });
96
- }
97
- }
98
- }
99
- nextToken = listResponse.NextToken;
100
- } while (nextToken);
138
+ const secrets = await this.listKeys(acRequest);
139
+ const secret = secrets.find((s) => s.key === secretName);
140
+ return secret?.value;
141
+ } catch (error) {
142
+ console.error(error);
143
+ return null;
144
+ }
145
+ }
101
146
 
102
- const formattedSecrets = [];
103
- const $promises = [];
104
- for (const secret of secrets) {
105
- $promises.push(getSpecificSecret(secret, this.secretsManager));
106
- }
107
- const results = await Promise.all($promises);
108
- for (const result of results) {
109
- formattedSecrets.push(result);
110
- }
111
- const secret = formattedSecrets.find((s) => s.Name === secretName);
112
- return secret;
147
+ private getVaultKey(teamId: string, secretName: string) {
148
+ return `${this.prefix.length ? `${this.prefix}/` : ''}${teamId}/${secretName}`;
149
+ }
150
+
151
+ private async getSecretById(teamId: string, secretId: string) {
152
+ try {
153
+ const secret: GetSecretValueCommandOutput = await this.secretsManager.send(new GetSecretValueCommand({ SecretId: this.getVaultKey(teamId, secretId) }));
154
+ return this.getSecretValue(secret);
113
155
  } catch (error) {
114
156
  console.error(error);
157
+ return null;
115
158
  }
159
+ }
116
160
 
117
- async function getSpecificSecret(secret, secretsManager: SecretsManagerClient) {
118
- const data: GetSecretValueCommandOutput = await secretsManager.send(new GetSecretValueCommand({ SecretId: secret.ARN }));
119
- let secretString = data.SecretString;
120
- let secretName = secret.Name;
121
-
122
- if (secretString) {
123
- try {
124
- let parsedSecret = JSON.parse(secretString);
125
- if (Object.keys(parsedSecret).length === 1) {
126
- secretName = Object.keys(parsedSecret)[0];
127
- secretString = parsedSecret[secretName];
128
- }
129
- } catch (error) {}
130
- }
131
- return {
132
- Name: secretName,
133
- ARN: secret.ARN,
134
- CreatedDate: secret.CreatedDate,
135
- SecretId: secret.Name,
136
- SecretString: secretString,
137
- };
161
+ private getSecretValue(secret: GetSecretValueCommandOutput) {
162
+ try {
163
+ const parsedSecret = typeof secret.SecretString === 'string' ? JSON.parse(secret.SecretString) : secret.SecretString;
164
+ return parsedSecret.value;
165
+ } catch (error) {
166
+ return null;
138
167
  }
168
+
139
169
  }
140
170
  }
@@ -80,6 +80,7 @@ export type TxAIToolsInfo = {
80
80
  };
81
81
  };
82
82
 
83
+ // #region TLLMParams
83
84
  export type TToolsInfo = {
84
85
  openai: TOpenAIToolsInfo;
85
86
  xai: TxAIToolsInfo;
@@ -189,6 +190,8 @@ type TLLMImageGenConfig = {
189
190
 
190
191
  export type TLLMParams = TLLMTextGenConfig & TLLMSearchConfig & TLLMImageGenConfig & TLLMMiscConfig & TLLMRuntimeContext;
191
192
 
193
+ // #endregion TLLMParams
194
+
192
195
  export type TLLMPreparedParams = TLLMParams & {
193
196
  body: any;
194
197
  modelEntryName?: string; // for usage reporting
@@ -344,6 +347,7 @@ export type ToolData = {
344
347
  function?: any;
345
348
  error?: string; // for Bedrock
346
349
  callId?: string; // for OpenAI Responses API call ID mapping
350
+ thoughtSignature?: string; // for Google AI - required to maintain reasoning context
347
351
  };
348
352
 
349
353
  /**
@@ -571,6 +575,7 @@ export interface TGoogleAIRequestBody {
571
575
  topK?: number;
572
576
  stopSequences?: string[];
573
577
  responseMimeType?: string;
578
+ media_resolution?: 'low' | 'medium' | 'high';
574
579
  };
575
580
  tools?: any;
576
581
  toolConfig?: any;