@smythos/sre 1.5.12 → 1.5.13
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/dist/index.js +7 -7
- package/dist/index.js.map +1 -1
- package/dist/types/helpers/Conversation.helper.d.ts +2 -2
- package/dist/types/subsystems/IO/Storage.service/connectors/LocalStorage.class.d.ts +1 -1
- package/dist/types/subsystems/Security/Vault.service/connectors/JSONFileVault.class.d.ts +2 -2
- package/dist/types/utils/data.utils.d.ts +1 -0
- package/package.json +1 -1
- package/src/Core/SmythRuntime.class.ts +3 -0
- package/src/helpers/BinaryInput.helper.ts +9 -2
- package/src/helpers/Conversation.helper.ts +7 -2
- package/src/subsystems/IO/Storage.service/connectors/LocalStorage.class.ts +3 -3
- package/src/subsystems/LLMManager/LLM.helper.ts +1 -1
- package/src/subsystems/Security/AccessControl/AccessCandidate.class.ts +1 -1
- package/src/subsystems/Security/Vault.service/connectors/JSONFileVault.class.ts +8 -8
- package/src/utils/data.utils.ts +58 -0
|
@@ -46,8 +46,8 @@ export declare class Conversation extends EventEmitter {
|
|
|
46
46
|
agentVersion?: string;
|
|
47
47
|
});
|
|
48
48
|
get ready(): any;
|
|
49
|
-
prompt(message?: string, toolHeaders?: {}, concurrentToolCalls?: number, abortSignal?: AbortSignal): Promise<any>;
|
|
50
|
-
streamPrompt(message?: string, toolHeaders?: {}, concurrentToolCalls?: number, abortSignal?: AbortSignal): Promise<any>;
|
|
49
|
+
prompt(message?: string | any, toolHeaders?: {}, concurrentToolCalls?: number, abortSignal?: AbortSignal): Promise<any>;
|
|
50
|
+
streamPrompt(message?: string | any, toolHeaders?: {}, concurrentToolCalls?: number, abortSignal?: AbortSignal): Promise<any>;
|
|
51
51
|
private resolveToolEndpoint;
|
|
52
52
|
private useTool;
|
|
53
53
|
addTool(tool: {
|
|
@@ -27,7 +27,7 @@ export declare class LocalStorage extends StorageConnector {
|
|
|
27
27
|
* @param {string} resourceId - The key of the object to be read.
|
|
28
28
|
* @returns {Promise<any>} - A promise that resolves with the object data.
|
|
29
29
|
*/
|
|
30
|
-
read(acRequest: AccessRequest, resourceId: string): Promise<
|
|
30
|
+
read(acRequest: AccessRequest, resourceId: string): Promise<NonSharedBuffer>;
|
|
31
31
|
getMetadata(acRequest: AccessRequest, resourceId: string): Promise<StorageMetadata | undefined>;
|
|
32
32
|
setMetadata(acRequest: AccessRequest, resourceId: string, metadata: StorageMetadata): Promise<void>;
|
|
33
33
|
/**
|
|
@@ -5,14 +5,14 @@ import { VaultConnector } from '../VaultConnector';
|
|
|
5
5
|
export type JSONFileVaultConfig = {
|
|
6
6
|
file?: string;
|
|
7
7
|
fileKey?: string;
|
|
8
|
-
shared?:
|
|
8
|
+
shared?: string;
|
|
9
9
|
};
|
|
10
10
|
export declare class JSONFileVault extends VaultConnector {
|
|
11
11
|
protected _settings: JSONFileVaultConfig;
|
|
12
12
|
name: string;
|
|
13
13
|
private vaultData;
|
|
14
14
|
private index;
|
|
15
|
-
private
|
|
15
|
+
private shared;
|
|
16
16
|
constructor(_settings: JSONFileVaultConfig);
|
|
17
17
|
private findVaultFile;
|
|
18
18
|
private getMasterKeyInteractive;
|
|
@@ -8,6 +8,7 @@ export declare const isBuffer: (data: any) => boolean;
|
|
|
8
8
|
export declare const isBinaryMimeType: (mimetype: any) => boolean;
|
|
9
9
|
export declare const isBinaryData: (data: any) => boolean;
|
|
10
10
|
export declare function isUrl(str: string): boolean;
|
|
11
|
+
export declare function isFile(str: string): boolean;
|
|
11
12
|
export declare function isSmythFsUrl(str: string): boolean;
|
|
12
13
|
export declare const isSmythFileObject: (data: any) => boolean;
|
|
13
14
|
export declare const isBufferObject: (data: Record<string, any>) => boolean;
|
package/package.json
CHANGED
|
@@ -21,6 +21,9 @@ export class SmythRuntime {
|
|
|
21
21
|
private defaultConfig: SREConfig = {
|
|
22
22
|
Vault: {
|
|
23
23
|
Connector: 'JSONFileVault',
|
|
24
|
+
Settings: {
|
|
25
|
+
shared: 'default', //default team shares its secrets with all other teams
|
|
26
|
+
},
|
|
24
27
|
},
|
|
25
28
|
Account: {
|
|
26
29
|
Connector: 'DummyAccount',
|
|
@@ -135,7 +135,7 @@ export class BinaryInput {
|
|
|
135
135
|
extension = extension || mime.getExtension(this.mimetype);
|
|
136
136
|
if (!this._name.endsWith(`.${extension}`)) this._name += `.${extension}`;
|
|
137
137
|
} catch (error) {
|
|
138
|
-
console.error('Error loading binary data from url:', data.url);
|
|
138
|
+
console.error('Error loading binary data from url:', data.url, error);
|
|
139
139
|
}
|
|
140
140
|
|
|
141
141
|
//this._source = data.url;
|
|
@@ -194,15 +194,19 @@ export class BinaryInput {
|
|
|
194
194
|
}
|
|
195
195
|
const ext = mime.getExtension(this.mimetype);
|
|
196
196
|
if (!this._name.endsWith(`.${ext}`)) this._name += `.${ext}`;
|
|
197
|
+
this._ready = true;
|
|
198
|
+
return;
|
|
197
199
|
}
|
|
198
200
|
|
|
199
201
|
if (data instanceof Blob) {
|
|
200
202
|
this._source = Buffer.from(await data.arrayBuffer());
|
|
201
203
|
this.size = data.size;
|
|
202
204
|
this.mimetype = data.type;
|
|
205
|
+
this._ready = true;
|
|
206
|
+
return;
|
|
203
207
|
}
|
|
204
208
|
|
|
205
|
-
|
|
209
|
+
|
|
206
210
|
}
|
|
207
211
|
|
|
208
212
|
private async getUrlInfo(url) {
|
|
@@ -236,6 +240,9 @@ export class BinaryInput {
|
|
|
236
240
|
await SmythFS.Instance.write(this.url, this._source, candidate, undefined, ttl);
|
|
237
241
|
this._uploading = false;
|
|
238
242
|
}
|
|
243
|
+
else {
|
|
244
|
+
this._uploading = false;
|
|
245
|
+
}
|
|
239
246
|
} catch (error) {
|
|
240
247
|
console.error('Error uploading binary data:', error);
|
|
241
248
|
this._uploading = false;
|
|
@@ -217,7 +217,7 @@ export class Conversation extends EventEmitter {
|
|
|
217
217
|
model: instance._model,
|
|
218
218
|
};
|
|
219
219
|
})
|
|
220
|
-
public async prompt(message?: string, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
|
|
220
|
+
public async prompt(message?: string|any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
|
|
221
221
|
const result = await this.streamPrompt(message, toolHeaders, concurrentToolCalls, abortSignal);
|
|
222
222
|
return result;
|
|
223
223
|
}
|
|
@@ -232,7 +232,11 @@ export class Conversation extends EventEmitter {
|
|
|
232
232
|
model: instance._model,
|
|
233
233
|
};
|
|
234
234
|
})
|
|
235
|
-
public async streamPrompt(message?: string, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
|
|
235
|
+
public async streamPrompt(message?: string|any, toolHeaders = {}, concurrentToolCalls = 4, abortSignal?: AbortSignal) {
|
|
236
|
+
let options = typeof message === 'object' ? message : {message};
|
|
237
|
+
message = options?.message;
|
|
238
|
+
const files = options?.files;
|
|
239
|
+
|
|
236
240
|
if (message) {
|
|
237
241
|
//initial call, reset stop flag
|
|
238
242
|
|
|
@@ -287,6 +291,7 @@ export class Conversation extends EventEmitter {
|
|
|
287
291
|
const eventEmitter: any = await llmInference
|
|
288
292
|
.promptStream({
|
|
289
293
|
contextWindow,
|
|
294
|
+
files,
|
|
290
295
|
params: {
|
|
291
296
|
model: this.model,
|
|
292
297
|
toolsConfig: this._settings?.toolsStrategy ? this._settings.toolsStrategy(toolsConfig) : toolsConfig,
|
|
@@ -82,7 +82,7 @@ export class LocalStorage extends StorageConnector {
|
|
|
82
82
|
try {
|
|
83
83
|
const filePath = this.getStorageFilePath(acRequest.candidate.id, resourceId);
|
|
84
84
|
if (!fs.existsSync(filePath)) return undefined;
|
|
85
|
-
const data = fs.readFileSync(filePath,
|
|
85
|
+
const data = fs.readFileSync(filePath, null);
|
|
86
86
|
return data;
|
|
87
87
|
} catch (error) {
|
|
88
88
|
console.error(`Error reading object from local storage`, error.name, error.message);
|
|
@@ -143,10 +143,10 @@ export class LocalStorage extends StorageConnector {
|
|
|
143
143
|
}
|
|
144
144
|
const accessCandidate = acRequest.candidate;
|
|
145
145
|
|
|
146
|
-
let
|
|
146
|
+
let localACL = ACL.from(acl).addAccess(accessCandidate.role, accessCandidate.id, TAccessLevel.Owner).ACL;
|
|
147
147
|
let fileMetadata = {
|
|
148
148
|
...metadata,
|
|
149
|
-
acl:
|
|
149
|
+
acl: localACL,
|
|
150
150
|
};
|
|
151
151
|
|
|
152
152
|
//now we can write the file
|
|
@@ -14,7 +14,7 @@ export class AccessCandidate implements IAccessCandidate {
|
|
|
14
14
|
|
|
15
15
|
private _validateId(id: string) {
|
|
16
16
|
if (/[^a-zA-Z0-9-]/.test(id))
|
|
17
|
-
throw new Error(
|
|
17
|
+
throw new Error(`Access Candidate ID can only contain alphanumeric characters and hyphens, invalid id: ${id}`);
|
|
18
18
|
return id;
|
|
19
19
|
}
|
|
20
20
|
|
|
@@ -20,20 +20,20 @@ const console = Logger('JSONFileVault');
|
|
|
20
20
|
export type JSONFileVaultConfig = {
|
|
21
21
|
file?: string;
|
|
22
22
|
fileKey?: string;
|
|
23
|
-
shared?:
|
|
23
|
+
shared?: string;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
export class JSONFileVault extends VaultConnector {
|
|
26
|
+
export class JSONFileVault extends VaultConnector {
|
|
27
27
|
public name: string = 'JSONFileVault';
|
|
28
28
|
private vaultData: any;
|
|
29
29
|
private index: any;
|
|
30
|
-
private
|
|
30
|
+
private shared: string;
|
|
31
31
|
|
|
32
32
|
constructor(protected _settings: JSONFileVaultConfig) {
|
|
33
33
|
super(_settings);
|
|
34
34
|
//if (!SmythRuntime.Instance) throw new Error('SRE not initialized');
|
|
35
35
|
|
|
36
|
-
this.
|
|
36
|
+
this.shared = _settings.shared || ''; //if config.shared, all keys are accessible to all teams, and they are set under the 'shared' teamId
|
|
37
37
|
|
|
38
38
|
let vaultFile = this.findVaultFile(_settings.file);
|
|
39
39
|
this.vaultData = {};
|
|
@@ -124,14 +124,14 @@ export class JSONFileVault extends VaultConnector {
|
|
|
124
124
|
const accountConnector = ConnectorService.getAccountConnector();
|
|
125
125
|
const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
|
|
126
126
|
|
|
127
|
-
return this.vaultData?.[teamId]?.[keyId] || this.vaultData?.[
|
|
127
|
+
return this.vaultData?.[teamId]?.[keyId] || this.vaultData?.[this.shared]?.[keyId];
|
|
128
128
|
}
|
|
129
129
|
|
|
130
130
|
@SecureConnector.AccessControl
|
|
131
131
|
protected async exists(acRequest: AccessRequest, keyId: string) {
|
|
132
132
|
const accountConnector = ConnectorService.getAccountConnector();
|
|
133
133
|
const teamId = await accountConnector.getCandidateTeam(acRequest.candidate);
|
|
134
|
-
return !!(this.vaultData?.[teamId]?.[keyId] || this.vaultData?.[
|
|
134
|
+
return !!(this.vaultData?.[teamId]?.[keyId] || this.vaultData?.[this.shared]?.[keyId]);
|
|
135
135
|
}
|
|
136
136
|
|
|
137
137
|
@SecureConnector.AccessControl
|
|
@@ -146,7 +146,7 @@ export class JSONFileVault extends VaultConnector {
|
|
|
146
146
|
const acl = new ACL();
|
|
147
147
|
|
|
148
148
|
if (resourceId && typeof this.vaultData?.[teamId]?.[resourceId] !== 'string') {
|
|
149
|
-
if (this.
|
|
149
|
+
if (this.shared && typeof this.vaultData?.[this.shared]?.[resourceId] === 'string') {
|
|
150
150
|
acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);
|
|
151
151
|
}
|
|
152
152
|
|
|
@@ -157,7 +157,7 @@ export class JSONFileVault extends VaultConnector {
|
|
|
157
157
|
.addAccess(TAccessRole.Team, teamId, TAccessLevel.Read)
|
|
158
158
|
.addAccess(TAccessRole.Team, teamId, TAccessLevel.Write);
|
|
159
159
|
|
|
160
|
-
if (this.
|
|
160
|
+
if (this.shared && typeof this.vaultData?.[this.shared]?.[resourceId] === 'string') {
|
|
161
161
|
acl.addAccess(candidate.role, candidate.id, TAccessLevel.Read);
|
|
162
162
|
}
|
|
163
163
|
|
package/src/utils/data.utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Readable } from 'stream';
|
|
2
2
|
import axios from 'axios';
|
|
3
|
+
import * as fs from 'fs';
|
|
3
4
|
|
|
4
5
|
import { identifyMimeTypeFromBase64DataUrl, isBase64FileUrl, isBase64, identifyMimetypeFromBase64, isBase64DataUrl } from './base64.utils';
|
|
5
6
|
import { isBinaryFileSync } from 'isbinaryfile';
|
|
@@ -123,6 +124,63 @@ export function isUrl(str: string): boolean {
|
|
|
123
124
|
return regex.test(str);
|
|
124
125
|
}
|
|
125
126
|
|
|
127
|
+
export function isFile(str: string): boolean {
|
|
128
|
+
// Check if string exists and length is within limit
|
|
129
|
+
if (!str || str.length >= 1000) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Validate path format for both Windows and Unix systems
|
|
134
|
+
if (!isValidPathFormat(str)) {
|
|
135
|
+
return false;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Check if file exists using fs.stat
|
|
139
|
+
try {
|
|
140
|
+
const stats = fs.statSync(str);
|
|
141
|
+
return stats.isFile();
|
|
142
|
+
} catch (error) {
|
|
143
|
+
// File doesn't exist or permission denied
|
|
144
|
+
return false;
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Validates if a string is in a valid file path format for both Windows and Unix systems
|
|
150
|
+
* Supports both absolute and relative paths
|
|
151
|
+
*/
|
|
152
|
+
function isValidPathFormat(path: string): boolean {
|
|
153
|
+
// Check for invalid characters that are not allowed in file paths
|
|
154
|
+
const invalidChars = /[\0<>"|?*]/;
|
|
155
|
+
if (invalidChars.test(path)) {
|
|
156
|
+
return false;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Windows path patterns
|
|
160
|
+
const windowsAbsolute = /^[a-zA-Z]:[\\\/]/; // C:\ or C:/
|
|
161
|
+
const windowsUNC = /^\\\\[^\\]+\\[^\\]+/; // \\server\share
|
|
162
|
+
const windowsRelative = /^\.{1,2}[\\\/]/; // .\ or ..\ or ./ or ../
|
|
163
|
+
|
|
164
|
+
// Unix path patterns
|
|
165
|
+
const unixAbsolute = /^\//; // /path/to/file
|
|
166
|
+
const unixHome = /^~[\/]/; // ~/path/to/file
|
|
167
|
+
const unixRelative = /^\.{1,2}\//; // ./ or ../
|
|
168
|
+
|
|
169
|
+
// Relative paths without leading ./ or .\
|
|
170
|
+
const genericRelative = /^[^\\\/]/; // path/to/file or path\to\file
|
|
171
|
+
|
|
172
|
+
// Check if path matches any valid pattern
|
|
173
|
+
return (
|
|
174
|
+
windowsAbsolute.test(path) ||
|
|
175
|
+
windowsUNC.test(path) ||
|
|
176
|
+
windowsRelative.test(path) ||
|
|
177
|
+
unixAbsolute.test(path) ||
|
|
178
|
+
unixHome.test(path) ||
|
|
179
|
+
unixRelative.test(path) ||
|
|
180
|
+
genericRelative.test(path)
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
|
|
126
184
|
export function isSmythFsUrl(str: string): boolean {
|
|
127
185
|
if (typeof str !== 'string') return false;
|
|
128
186
|
const regex = /^smythfs:\/\/([^\s.]+\.[^\s]{2,})(:[0-9]{1,5})?(\/[^\s]*)?(\?[^\s]*)?$/i;
|