@smythos/sre 1.5.16 → 1.5.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 (48) hide show
  1. package/dist/index.js +68 -34
  2. package/dist/index.js.map +1 -1
  3. package/dist/types/Components/Component.class.d.ts +4 -0
  4. package/dist/types/Components/ServerlessCode.class.d.ts +13 -0
  5. package/dist/types/Components/index.d.ts +2 -0
  6. package/dist/types/Core/ConnectorsService.d.ts +1 -0
  7. package/dist/types/Core/SystemEvents.d.ts +2 -1
  8. package/dist/types/helpers/AWSLambdaCode.helper.d.ts +30 -0
  9. package/dist/types/index.d.ts +2 -0
  10. package/dist/types/subsystems/ComputeManager/Code.service/CodeConnector.d.ts +16 -15
  11. package/dist/types/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.d.ts +13 -7
  12. package/dist/types/subsystems/IO/NKV.service/connectors/NKVLocalStorage.class.d.ts +1 -0
  13. package/dist/types/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.d.ts +3 -3
  14. package/dist/types/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.d.ts +1 -0
  15. package/dist/types/subsystems/Security/Account.service/AccountConnector.d.ts +2 -0
  16. package/dist/types/subsystems/Security/ManagedVault.service/ManagedVaultConnector.d.ts +2 -0
  17. package/dist/types/subsystems/Security/Vault.service/VaultConnector.d.ts +2 -0
  18. package/dist/types/types/AWS.types.d.ts +1 -0
  19. package/dist/types/types/Security.types.d.ts +0 -3
  20. package/package.json +7 -3
  21. package/src/Components/Component.class.ts +40 -2
  22. package/src/Components/GenAILLM.class.ts +3 -2
  23. package/src/Components/ServerlessCode.class.ts +100 -0
  24. package/src/Components/index.ts +2 -0
  25. package/src/Core/ConnectorsService.ts +5 -0
  26. package/src/Core/SmythRuntime.class.ts +6 -3
  27. package/src/Core/SystemEvents.ts +2 -1
  28. package/src/Core/boot.ts +1 -0
  29. package/src/helpers/AWSLambdaCode.helper.ts +347 -0
  30. package/src/helpers/Conversation.helper.ts +15 -6
  31. package/src/helpers/Sysconfig.helper.ts +11 -1
  32. package/src/index.ts +2 -0
  33. package/src/index.ts.bak +2 -0
  34. package/src/subsystems/AgentManager/ForkedAgent.class.ts +1 -0
  35. package/src/subsystems/ComputeManager/Code.service/CodeConnector.ts +30 -31
  36. package/src/subsystems/ComputeManager/Code.service/connectors/AWSLambdaCode.class.ts +127 -24
  37. package/src/subsystems/IO/NKV.service/connectors/NKVLocalStorage.class.ts +25 -2
  38. package/src/subsystems/IO/VectorDB.service/connectors/MilvusVectorDB.class.ts +13 -13
  39. package/src/subsystems/LLMManager/LLM.service/LLMConnector.ts +5 -4
  40. package/src/subsystems/LLMManager/LLM.service/connectors/OpenAI.class.ts +1 -1
  41. package/src/subsystems/LLMManager/ModelsProvider.service/ModelsProviderConnector.ts +4 -0
  42. package/src/subsystems/Security/Account.service/AccountConnector.ts +3 -0
  43. package/src/subsystems/Security/Account.service/connectors/DummyAccount.class.ts +1 -1
  44. package/src/subsystems/Security/ManagedVault.service/ManagedVaultConnector.ts +4 -0
  45. package/src/subsystems/Security/ManagedVault.service/connectors/NullManagedVault.class.ts +1 -5
  46. package/src/subsystems/Security/Vault.service/VaultConnector.ts +3 -0
  47. package/src/types/AWS.types.ts +2 -0
  48. package/src/types/Security.types.ts +0 -4
@@ -0,0 +1,347 @@
1
+ import crypto from 'crypto';
2
+ import { ConnectorService } from '@sre/Core/ConnectorsService';
3
+ import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
4
+ import zl from 'zip-lib';
5
+ import { InvokeCommand, Runtime, LambdaClient, UpdateFunctionCodeCommand, CreateFunctionCommand, GetFunctionCommand, GetFunctionCommandOutput, InvokeCommandOutput } from '@aws-sdk/client-lambda';
6
+ import { GetRoleCommand, CreateRoleCommand, IAMClient, GetRoleCommandOutput, CreateRoleCommandOutput } from '@aws-sdk/client-iam';
7
+ import fs from 'fs';
8
+ import { AWSCredentials, AWSRegionConfig } from '@sre/types/AWS.types';
9
+ export const cachePrefix = 'serverless_code';
10
+ export const cacheTTL = 60 * 60 * 24 * 16; // 16 days
11
+
12
+ export function getLambdaFunctionName(agentId: string, componentId: string) {
13
+ return `${agentId}-${componentId}`;
14
+ }
15
+
16
+
17
+ export function generateCodeHash(code_body: string, code_imports: string, codeInputs: string[]) {
18
+ const importsHash = getSanitizeCodeHash(code_imports);
19
+ const bodyHash = getSanitizeCodeHash(code_body);
20
+ const inputsHash = getSanitizeCodeHash(JSON.stringify(codeInputs));
21
+ return `imports-${importsHash}__body-${bodyHash}__inputs-${inputsHash}`;
22
+ }
23
+
24
+ export function getSanitizeCodeHash(code: string) {
25
+ let output = '';
26
+ let isSingleQuote = false;
27
+ let isDoubleQuote = false;
28
+ let isTemplateLiteral = false;
29
+ let isRegex = false;
30
+ let isComment = false;
31
+ let prevChar = '';
32
+
33
+ for (let i = 0; i < code.length; i++) {
34
+ let char = code[i];
35
+ let nextChar = code[i + 1];
36
+
37
+ // Toggle string flags
38
+ if (char === "'" && !isDoubleQuote && !isTemplateLiteral && prevChar !== '\\') isSingleQuote = !isSingleQuote;
39
+ if (char === '"' && !isSingleQuote && !isTemplateLiteral && prevChar !== '\\') isDoubleQuote = !isDoubleQuote;
40
+ if (char === '`' && !isSingleQuote && !isDoubleQuote && prevChar !== '\\') isTemplateLiteral = !isTemplateLiteral;
41
+
42
+ // Handle regex cases
43
+ if (char === '/' && nextChar === '/' && !isSingleQuote && !isDoubleQuote && !isTemplateLiteral && !isRegex) {
44
+ isComment = true; // Single-line comment
45
+ }
46
+ if (char === '/' && nextChar === '*' && !isSingleQuote && !isDoubleQuote && !isTemplateLiteral) {
47
+ isComment = true; // Multi-line comment start
48
+ }
49
+ if (char === '*' && nextChar === '/' && isComment) {
50
+ isComment = false; // Multi-line comment end
51
+ i++; // Skip ending slash
52
+ continue;
53
+ }
54
+ if (char === '\n' && isComment) {
55
+ isComment = false; // End single-line comment
56
+ }
57
+
58
+ if (!isComment) {
59
+ output += char;
60
+ }
61
+ prevChar = char;
62
+ }
63
+
64
+ return crypto.createHash('md5').update(output.replace(/\s+/g, ' ').trim()).digest('hex');
65
+ }
66
+
67
+ export async function getDeployedCodeHash(agentId: string, componentId: string) {
68
+ const redisCache = ConnectorService.getCacheConnector();
69
+ const cachedCodeHash = await redisCache.user(AccessCandidate.agent(agentId)).get(`${cachePrefix}_${agentId}-${componentId}`);
70
+ return cachedCodeHash;
71
+ }
72
+
73
+ export async function setDeployedCodeHash(agentId: string, componentId: string, codeHash: string) {
74
+ const redisCache = ConnectorService.getCacheConnector();
75
+ await redisCache
76
+ .user(AccessCandidate.agent(agentId))
77
+ .set(`${cachePrefix}_${agentId}-${componentId}`, codeHash, null, null, cacheTTL);
78
+ }
79
+
80
+
81
+ export function extractNpmImports(code: string) {
82
+ const importRegex = /import\s+(?:[\w*\s{},]*\s+from\s+)?['"]([^'"]+)['"]/g;
83
+ const requireRegex = /require\(['"]([^'"]+)['"]\)/g;
84
+ const dynamicImportRegex = /import\(['"]([^'"]+)['"]\)/g;
85
+
86
+ let libraries = new Set();
87
+ let match;
88
+
89
+ // Function to extract the main package name
90
+ function extractPackageName(modulePath: string) {
91
+ if (modulePath.startsWith('@')) {
92
+ // Handle scoped packages (e.g., @babel/core)
93
+ return modulePath.split('/').slice(0, 2).join('/');
94
+ }
95
+ return modulePath.split('/')[0]; // Extract the first part (main package)
96
+ }
97
+ // Match static ESM imports
98
+ while ((match = importRegex.exec(code)) !== null) {
99
+ libraries.add(extractPackageName(match[1]));
100
+ }
101
+ // Match CommonJS require() calls
102
+ while ((match = requireRegex.exec(code)) !== null) {
103
+ libraries.add(extractPackageName(match[1]));
104
+ }
105
+ // Match dynamic import() calls
106
+ while ((match = dynamicImportRegex.exec(code)) !== null) {
107
+ libraries.add(extractPackageName(match[1]));
108
+ }
109
+
110
+ return Array.from(libraries);
111
+ }
112
+
113
+
114
+ export function generateLambdaCode(code_imports: string, code_body: string, input_variables: string[]) {
115
+ const lambdaCode = `${code_imports}\nexport const handler = async (event, context) => {
116
+ try {
117
+ context.callbackWaitsForEmptyEventLoop = false;
118
+ let startTime = Date.now();
119
+ const result = await (async () => {
120
+ ${input_variables && input_variables.length ? input_variables.map((variable) => `const ${variable} = event.${variable};`).join('\n') : ''}
121
+ ${code_body}
122
+ })();
123
+ let endTime = Date.now();
124
+ return {
125
+ result,
126
+ executionTime: endTime - startTime
127
+ }
128
+ } catch (e) {
129
+ throw e;
130
+ }
131
+ };`;
132
+ return lambdaCode;
133
+ }
134
+
135
+ export async function zipCode(directory: string) {
136
+ return new Promise((resolve, reject) => {
137
+ zl.archiveFolder(directory, `${directory}.zip`).then(
138
+ function () {
139
+ resolve(`${directory}.zip`);
140
+ },
141
+ function (err) {
142
+ reject(err);
143
+ },
144
+ );
145
+ });
146
+ }
147
+
148
+ export async function createOrUpdateLambdaFunction(functionName, zipFilePath, awsConfigs) {
149
+ const client = new LambdaClient({
150
+ region: awsConfigs.region,
151
+ credentials: {
152
+ accessKeyId: awsConfigs.accessKeyId,
153
+ secretAccessKey: awsConfigs.secretAccessKey,
154
+ },
155
+ });
156
+ const functionContent = fs.readFileSync(zipFilePath);
157
+
158
+ try {
159
+ // Check if the function exists
160
+ const exisitingFunction = await getDeployedFunction(functionName, awsConfigs);
161
+ if (exisitingFunction) {
162
+ if (exisitingFunction.status === 'InProgress') {
163
+ await verifyFunctionDeploymentStatus(functionName, client);
164
+ }
165
+ // Update function code if it exists
166
+ const updateCodeParams = {
167
+ FunctionName: functionName,
168
+ ZipFile: functionContent,
169
+ };
170
+ const updateFunctionCodeCommand = new UpdateFunctionCodeCommand(updateCodeParams);
171
+ await client.send(updateFunctionCodeCommand);
172
+ // Update function configuration to attach layer
173
+ await verifyFunctionDeploymentStatus(functionName, client);
174
+ // console.log('Lambda function code and configuration updated successfully!');
175
+ } else {
176
+ // Create function if it does not exist
177
+ let roleArn = '';
178
+ // check if the role exists
179
+ try {
180
+ const iamClient = new IAMClient({
181
+ region: awsConfigs.region,
182
+ credentials: { accessKeyId: awsConfigs.accessKeyId, secretAccessKey: awsConfigs.secretAccessKey },
183
+ });
184
+ const getRoleCommand = new GetRoleCommand({ RoleName: `smyth-${functionName}-role` });
185
+ const roleResponse: GetRoleCommandOutput = await iamClient.send(getRoleCommand);
186
+ roleArn = roleResponse.Role.Arn;
187
+ } catch (error) {
188
+ if (error.name === 'NoSuchEntityException') {
189
+ // create role
190
+ const iamClient = new IAMClient({
191
+ region: awsConfigs.region,
192
+ credentials: { accessKeyId: awsConfigs.accessKeyId, secretAccessKey: awsConfigs.secretAccessKey },
193
+ });
194
+ const createRoleCommand = new CreateRoleCommand({
195
+ RoleName: `smyth-${functionName}-role`,
196
+ AssumeRolePolicyDocument: getLambdaRolePolicy(),
197
+ });
198
+ const roleResponse: CreateRoleCommandOutput = await iamClient.send(createRoleCommand);
199
+ await waitForRoleDeploymentStatus(`smyth-${functionName}-role`, iamClient);
200
+ roleArn = roleResponse.Role.Arn;
201
+ } else {
202
+ throw error;
203
+ }
204
+ }
205
+
206
+ const functionParams = {
207
+ Code: { ZipFile: functionContent },
208
+ FunctionName: functionName,
209
+ Handler: 'index.handler',
210
+ Role: roleArn,
211
+ Runtime: Runtime.nodejs18x,
212
+ Layers: [],
213
+ Timeout: 900,
214
+ Tags: {
215
+ 'auto-delete': 'true',
216
+ },
217
+ MemorySize: 256,
218
+ };
219
+
220
+ const functionCreateCommand = new CreateFunctionCommand(functionParams);
221
+ const functionResponse = await client.send(functionCreateCommand);
222
+ // console.log('Function ARN:', functionResponse.FunctionArn);
223
+ await verifyFunctionDeploymentStatus(functionName, client);
224
+ }
225
+ } catch (error) {
226
+ throw error;
227
+ }
228
+ }
229
+
230
+ export async function waitForRoleDeploymentStatus(roleName, client): Promise<boolean> {
231
+ return new Promise((resolve, reject) => {
232
+ try {
233
+ let interval = setInterval(async () => {
234
+ const getRoleCommand = new GetRoleCommand({ RoleName: roleName });
235
+ const roleResponse = await client.send(getRoleCommand);
236
+ if (roleResponse.Role.AssumeRolePolicyDocument) {
237
+ clearInterval(interval);
238
+ return resolve(true);
239
+ }
240
+ }, 7000);
241
+ } catch (error) {
242
+ return false;
243
+ }
244
+ });
245
+ }
246
+
247
+ export async function verifyFunctionDeploymentStatus(functionName, client): Promise<boolean> {
248
+ return new Promise((resolve, reject) => {
249
+ try {
250
+ let interval = setInterval(async () => {
251
+ const getFunctionCommand = new GetFunctionCommand({ FunctionName: functionName });
252
+ const lambdaResponse = await client.send(getFunctionCommand);
253
+
254
+ if (lambdaResponse.Configuration.LastUpdateStatus === 'Successful') {
255
+ clearInterval(interval);
256
+ return resolve(true);
257
+ }
258
+ }, 5000);
259
+ } catch (error) {
260
+ return false;
261
+ }
262
+ });
263
+ }
264
+
265
+ export function getLambdaRolePolicy() {
266
+ return JSON.stringify({
267
+ Version: '2012-10-17',
268
+ Statement: [
269
+ {
270
+ Effect: 'Allow',
271
+ Principal: {
272
+ Service: 'lambda.amazonaws.com',
273
+ },
274
+ Action: 'sts:AssumeRole',
275
+ },
276
+ ],
277
+ });
278
+ }
279
+
280
+
281
+ export async function updateDeployedCodeTTL(agentId: string, componentId: string, ttl: number) {
282
+ const redisCache = ConnectorService.getCacheConnector();
283
+ await redisCache.user(AccessCandidate.agent(agentId)).updateTTL(`${cachePrefix}_${agentId}-${componentId}`, ttl);
284
+ }
285
+
286
+ export async function invokeLambdaFunction(
287
+ functionName: string,
288
+ inputs: { [key: string]: any },
289
+ awsCredentials: AWSCredentials & AWSRegionConfig,
290
+ ): Promise<any> {
291
+ try {
292
+ const client = new LambdaClient({
293
+ region: awsCredentials.region as string,
294
+ ...(awsCredentials.accessKeyId && {
295
+ credentials: {
296
+ accessKeyId: awsCredentials.accessKeyId as string,
297
+ secretAccessKey: awsCredentials.secretAccessKey as string,
298
+ },
299
+ }),
300
+ });
301
+
302
+ const invokeCommand = new InvokeCommand({
303
+ FunctionName: functionName,
304
+ Payload: new TextEncoder().encode(`${JSON.stringify(inputs)}`),
305
+ InvocationType: 'RequestResponse',
306
+ });
307
+
308
+ const response: InvokeCommandOutput = await client.send(invokeCommand);
309
+ if (response.FunctionError) {
310
+ throw new Error(new TextDecoder().decode(response.Payload));
311
+ }
312
+ return new TextDecoder().decode(response.Payload);
313
+ } catch (error) {
314
+ throw error;
315
+ }
316
+ }
317
+
318
+ export async function getDeployedFunction(functionName: string, awsConfigs: AWSCredentials & AWSRegionConfig) {
319
+ try {
320
+ const client = new LambdaClient({
321
+ region: awsConfigs.region as string,
322
+ credentials: {
323
+ accessKeyId: awsConfigs.accessKeyId as string,
324
+ secretAccessKey: awsConfigs.secretAccessKey as string,
325
+ },
326
+ });
327
+ const getFunctionCommand = new GetFunctionCommand({ FunctionName: functionName });
328
+ const lambdaResponse: GetFunctionCommandOutput = await client.send(getFunctionCommand);
329
+ return {
330
+ status: lambdaResponse.Configuration.LastUpdateStatus,
331
+ functionName: lambdaResponse.Configuration.FunctionName,
332
+ functionVersion: lambdaResponse.Configuration.Version,
333
+ updatedAt: lambdaResponse.Configuration.LastModified,
334
+ role: lambdaResponse.Configuration.Role,
335
+ runtime: lambdaResponse.Configuration.Runtime,
336
+ version: lambdaResponse.Configuration.Version,
337
+ };
338
+ } catch (error) {
339
+ return null;
340
+ }
341
+ }
342
+
343
+ export function extractKeyFromTemplateVar(input: string) {
344
+ const regex = /\{\{KEY\((.*?)\)\}\}/;
345
+ const match = input.match(regex);
346
+ return match ? match[1] : input;
347
+ }
@@ -13,10 +13,8 @@ import { JSONContent } from './JsonContent.helper';
13
13
  import { OpenAPIParser } from './OpenApiParser.helper';
14
14
  import { Match, TemplateString } from './TemplateString.helper';
15
15
  import { AccessCandidate } from '@sre/Security/AccessControl/AccessCandidate.class';
16
- import { delay } from '@sre/utils/date-time.utils';
17
16
  import { EventSource, FetchLike } from 'eventsource';
18
17
  import { hookAsyncWithContext } from '@sre/Core/HookService';
19
- import { DEFAULT_TEAM_ID } from '@sre/types/ACL.types';
20
18
  import { randomUUID } from 'crypto';
21
19
  import * as acorn from 'acorn';
22
20
 
@@ -159,7 +157,7 @@ export class Conversation extends EventEmitter {
159
157
  this._spec = spec;
160
158
 
161
159
  if (!this._agentId && _settings?.agentId) this._agentId = _settings.agentId;
162
- if (!this._agentId) this._agentId = 'FAKE_AGENT_ID'; //We use a fake agent ID to avoid ACL check errors
160
+ if (!this._agentId) this._agentId = 'FAKE-AGENT-ID'; //We use a fake agent ID to avoid ACL check errors
163
161
 
164
162
  // teamId is required to load custom LLMs, we must assign it before updateModel()
165
163
  await this.assignTeamIdFromAgentId(this._agentId);
@@ -217,8 +215,19 @@ export class Conversation extends EventEmitter {
217
215
  model: instance._model,
218
216
  };
219
217
  })
220
- public async prompt(message?: string|any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
218
+ public async prompt(message?: string | any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
219
+ // if an error occured while streaming, we need to propagate it so for this, we register a one time error listener
220
+ let error = null;
221
+ const errListener = (err) => (error = err);
222
+ this.once('error', errListener);
221
223
  const result = await this.streamPrompt(message, toolHeaders, concurrentToolCalls, abortSignal);
224
+
225
+ // if an error event occured, throw the error
226
+ if (error) {
227
+ throw error;
228
+ }
229
+
230
+ this.removeListener('error', errListener);
222
231
  return result;
223
232
  }
224
233
 
@@ -232,8 +241,8 @@ export class Conversation extends EventEmitter {
232
241
  model: instance._model,
233
242
  };
234
243
  })
235
- public async streamPrompt(message?: string|any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
236
- let options = typeof message === 'object' ? message : {message};
244
+ public async streamPrompt(message?: string | any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
245
+ let options = typeof message === 'object' ? message : { message };
237
246
  message = options?.message;
238
247
  const files = options?.files;
239
248
 
@@ -5,6 +5,12 @@ import os from 'os';
5
5
  export function findSmythPath(_path: string = '', callback?: (smythDir: string, success?: boolean, nextDir?: string) => void) {
6
6
  //TODO : also search for a local sre configuration file indicating .smyth folder explicitly
7
7
 
8
+ let _smythDir = '';
9
+
10
+ if (_path) {
11
+ _smythDir = findSmythPath('');
12
+ }
13
+
8
14
  const searchDirectories = [];
9
15
 
10
16
  // 1. Try to find in local directory (the directory from which the program was run)
@@ -49,7 +55,11 @@ export function findSmythPath(_path: string = '', callback?: (smythDir: string,
49
55
  return dir;
50
56
  }
51
57
 
52
- return localDir;
58
+ if (_smythDir && _path) {
59
+ return path.resolve(_smythDir, _path);
60
+ }
61
+
62
+ return homeDir;
53
63
  }
54
64
 
55
65
  function findPackageRoot(startDir = process.cwd()) {
package/src/index.ts CHANGED
@@ -40,6 +40,7 @@ export * from './Components/LogicXOR.class';
40
40
  export * from './Components/MCPClient.class';
41
41
  export * from './Components/PromptGenerator.class';
42
42
  export * from './Components/ScrapflyWebScrape.class';
43
+ export * from './Components/ServerlessCode.class';
43
44
  export * from './Components/TavilyWebSearch.class';
44
45
  export * from './Core/AgentProcess.helper';
45
46
  export * from './Core/boot';
@@ -49,6 +50,7 @@ export * from './Core/DummyConnector';
49
50
  export * from './Core/HookService';
50
51
  export * from './Core/SmythRuntime.class';
51
52
  export * from './Core/SystemEvents';
53
+ export * from './helpers/AWSLambdaCode.helper';
52
54
  export * from './helpers/BinaryInput.helper';
53
55
  export * from './helpers/Conversation.helper';
54
56
  export * from './helpers/JsonContent.helper';
package/src/index.ts.bak CHANGED
@@ -40,6 +40,7 @@ export * from './Components/LogicXOR.class';
40
40
  export * from './Components/MCPClient.class';
41
41
  export * from './Components/PromptGenerator.class';
42
42
  export * from './Components/ScrapflyWebScrape.class';
43
+ export * from './Components/ServerlessCode.class';
43
44
  export * from './Components/TavilyWebSearch.class';
44
45
  export * from './Core/AgentProcess.helper';
45
46
  export * from './Core/boot';
@@ -49,6 +50,7 @@ export * from './Core/DummyConnector';
49
50
  export * from './Core/HookService';
50
51
  export * from './Core/SmythRuntime.class';
51
52
  export * from './Core/SystemEvents';
53
+ export * from './helpers/AWSLambdaCode.helper';
52
54
  export * from './helpers/BinaryInput.helper';
53
55
  export * from './helpers/Conversation.helper';
54
56
  export * from './helpers/JsonContent.helper';
@@ -31,6 +31,7 @@ export class ForkedAgent {
31
31
  const data: any = fork(this.parent.data, componentId);
32
32
  data.variables = JSON.parse(JSON.stringify(this.parent?.data?.variables || {})); //copy parent Agent variables to forked agent
33
33
  data.teamId = this.parent.teamId;
34
+ data.planInfo = this.parent.data?.planInfo || {};
34
35
  //TODO : we need to create a default APIEndpoint bound to the root component if root component is not an APIEndpoint
35
36
  const content = { name: this.parent.name, data, teamId: this.parent.teamId, debugSessionEnabled: false, version: this.parent.version };
36
37
 
@@ -16,7 +16,6 @@ export interface CodeConfig {
16
16
  timeout?: number; // Execution timeout in milliseconds
17
17
  memoryLimit?: number; // Memory allocation in MB
18
18
  environment?: Record<string, string>; // Environment variables
19
-
20
19
  // Platform-specific settings
21
20
  platformConfig?: Record<string, any>;
22
21
  }
@@ -38,61 +37,61 @@ export interface CodePreparationResult {
38
37
 
39
38
  export interface CodeDeployment {
40
39
  id: string; // Deployment identifier
41
- status: 'deploying' | 'ready' | 'failed';
40
+ status: string;
42
41
  runtime: string;
43
42
  createdAt: Date;
44
43
  lastUsed?: Date;
44
+ lastUpdated?: Date;
45
45
  }
46
46
 
47
47
  export interface ICodeRequest {
48
48
  // Core workflow
49
- prepare(input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;
50
- deploy(deploymentId: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;
51
- execute(input: CodeInput, config: CodeConfig): Promise<CodeExecutionResult>;
49
+ prepare(codeUID: string, input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;
50
+ deploy(codeUID: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;
51
+ execute(codeUID: string, inputs: Record<string, any>, config: CodeConfig): Promise<CodeExecutionResult>;
52
52
 
53
53
  // Execute with existing deployment (for platforms that support it)
54
- executeDeployment(deploymentId: string, inputs: Record<string, any>): Promise<CodeExecutionResult>;
54
+ executeDeployment(codeUID: string, deploymentId: string, inputs: Record<string, any>, config: CodeConfig): Promise<CodeExecutionResult>;
55
55
 
56
56
  // Deployment management
57
- listDeployments(): Promise<CodeDeployment[]>;
58
- getDeployment(deploymentId: string): Promise<CodeDeployment | null>;
59
- deleteDeployment(deploymentId: string): Promise<void>;
57
+ listDeployments(codeUID: string, config: CodeConfig): Promise<CodeDeployment[]>;
58
+ getDeployment(codeUID: string, deploymentId: string, config: CodeConfig): Promise<CodeDeployment | null>;
59
+ deleteDeployment(codeUID: string, deploymentId: string, config: CodeConfig): Promise<void>;
60
60
  }
61
61
 
62
62
  export abstract class CodeConnector extends SecureConnector {
63
63
  public abstract getResourceACL(resourceId: string, candidate: IAccessCandidate): Promise<ACL>;
64
-
65
64
  // Abstract methods that concrete connectors must implement
66
- protected abstract prepare(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;
67
- protected abstract deploy(acRequest: AccessRequest, deploymentId: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;
68
- protected abstract execute(acRequest: AccessRequest, input: CodeInput, config: CodeConfig): Promise<CodeExecutionResult>;
69
- protected abstract executeDeployment(acRequest: AccessRequest, deploymentId: string, inputs: Record<string, any>): Promise<CodeExecutionResult>;
70
- protected abstract listDeployments(acRequest: AccessRequest): Promise<CodeDeployment[]>;
71
- protected abstract getDeployment(acRequest: AccessRequest, deploymentId: string): Promise<CodeDeployment | null>;
72
- protected abstract deleteDeployment(acRequest: AccessRequest, deploymentId: string): Promise<void>;
65
+ protected abstract prepare(acRequest: AccessRequest, codeUID: string, input: CodeInput, config: CodeConfig): Promise<CodePreparationResult>;
66
+ protected abstract deploy(acRequest: AccessRequest, codeUID: string, input: CodeInput, config: CodeConfig): Promise<CodeDeployment>;
67
+ protected abstract execute(acRequest: AccessRequest, codeUID: string, inputs: Record<string, any>, config: CodeConfig): Promise<CodeExecutionResult>;
68
+ protected abstract executeDeployment(acRequest: AccessRequest, codeUID: string, deploymentId: string, inputs: Record<string, any>, config: CodeConfig): Promise<CodeExecutionResult>;
69
+ protected abstract listDeployments(acRequest: AccessRequest, codeUID: string, config: CodeConfig): Promise<CodeDeployment[]>;
70
+ protected abstract getDeployment(acRequest: AccessRequest, codeUID: string, deploymentId: string, config: CodeConfig): Promise<CodeDeployment | null>;
71
+ protected abstract deleteDeployment(acRequest: AccessRequest, codeUID: string, deploymentId: string, config: CodeConfig): Promise<void>;
73
72
 
74
73
  public requester(candidate: AccessCandidate): ICodeRequest {
75
74
  return {
76
- prepare: async (input: CodeInput, config: CodeConfig) => {
77
- return await this.prepare(candidate.readRequest, input, config);
75
+ prepare: async (codeUID: string, input: CodeInput, config: CodeConfig) => {
76
+ return await this.prepare(candidate.readRequest, codeUID, input, config);
78
77
  },
79
- deploy: async (deploymentId: string, input: CodeInput, config: CodeConfig) => {
80
- return await this.deploy(candidate.writeRequest, deploymentId, input, config);
78
+ deploy: async (codeUID: string, input: CodeInput, config: CodeConfig) => {
79
+ return await this.deploy(candidate.writeRequest, codeUID, input, config);
81
80
  },
82
- execute: async (input: CodeInput, config: CodeConfig) => {
83
- return await this.execute(candidate.readRequest, input, config);
81
+ execute: async (codeUID: string, inputs: Record<string, any>, config: CodeConfig) => {
82
+ return await this.execute(candidate.readRequest, codeUID, inputs, config);
84
83
  },
85
- executeDeployment: async (deploymentId: string, inputs: Record<string, any>) => {
86
- return await this.executeDeployment(candidate.readRequest, deploymentId, inputs);
84
+ executeDeployment: async (codeUID: string, deploymentId: string, inputs: Record<string, any>, config: CodeConfig) => {
85
+ return await this.executeDeployment(candidate.readRequest, codeUID, deploymentId, inputs, config);
87
86
  },
88
- listDeployments: async () => {
89
- return await this.listDeployments(candidate.readRequest);
87
+ listDeployments: async (codeUID: string, config: CodeConfig) => {
88
+ return await this.listDeployments(candidate.readRequest, codeUID, config);
90
89
  },
91
- getDeployment: async (deploymentId: string) => {
92
- return await this.getDeployment(candidate.readRequest, deploymentId);
90
+ getDeployment: async (codeUID: string, deploymentId: string, config: CodeConfig) => {
91
+ return await this.getDeployment(candidate.readRequest, codeUID, deploymentId, config);
93
92
  },
94
- deleteDeployment: async (deploymentId: string) => {
95
- await this.deleteDeployment(candidate.writeRequest, deploymentId);
93
+ deleteDeployment: async (codeUID: string, deploymentId: string, config: CodeConfig) => {
94
+ await this.deleteDeployment(candidate.writeRequest, codeUID, deploymentId, config);
96
95
  },
97
96
  } as ICodeRequest;
98
97
  }