@aj-archipelago/cortex 1.4.0 โ 1.4.2
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/config.js +25 -4
- package/helper-apps/cortex-autogen2/agents.py +19 -6
- package/helper-apps/cortex-autogen2/services/azure_ai_search.py +115 -0
- package/helper-apps/cortex-autogen2/services/run_analyzer.py +594 -0
- package/helper-apps/cortex-autogen2/task_processor.py +98 -2
- package/lib/crypto.js +1 -0
- package/lib/entityConstants.js +12 -35
- package/lib/keyValueStorageClient.js +53 -1
- package/lib/util.js +33 -6
- package/package.json +2 -1
- package/pathways/system/entity/memory/sys_memory_manager.js +1 -0
- package/pathways/system/entity/memory/sys_memory_process.js +4 -3
- package/pathways/system/entity/memory/sys_memory_update.js +4 -3
- package/pathways/system/entity/memory/sys_read_memory.js +12 -4
- package/pathways/system/entity/memory/sys_save_memory.js +16 -9
- package/pathways/system/entity/memory/sys_search_memory.js +5 -4
- package/pathways/system/entity/sys_entity_agent.js +2 -1
- package/pathways/system/entity/tools/sys_tool_bing_search.js +2 -2
- package/pathways/system/entity/tools/sys_tool_bing_search_afagent.js +1 -2
- package/pathways/system/entity/tools/sys_tool_callmodel.js +2 -1
- package/pathways/system/entity/tools/sys_tool_coding.js +1 -2
- package/pathways/system/entity/tools/sys_tool_grok_x_search.js +1 -1
- package/pathways/system/entity/tools/sys_tool_image.js +2 -1
- package/pathways/system/entity/tools/sys_tool_image_gemini.js +3 -3
- package/pathways/system/entity/tools/sys_tool_mermaid.js +187 -38
- package/pathways/system/entity/tools/sys_tool_reasoning.js +2 -0
- package/pathways/system/entity/tools/sys_tool_verify.js +1 -1
- package/pathways/transcribe_gemini.js +3 -2
- package/server/graphql.js +1 -1
- package/server/pathwayResolver.js +8 -7
- package/server/plugins/veoVideoPlugin.js +29 -1
- package/testrun.log +35371 -0
- package/tests/integration/graphql/async/stream/vendors/openai_streaming.test.js +1 -3
- package/tests/unit/core/crypto.test.js +65 -0
- package/tests/unit/core/doubleEncryptionStorageClient.test.js +262 -0
|
@@ -52,7 +52,6 @@ test('OpenAI vendor streaming over subscriptions emits OAI-style deltas', async
|
|
|
52
52
|
|
|
53
53
|
t.true(events.length > 0);
|
|
54
54
|
|
|
55
|
-
// Ensure streamed chunks (when they include model) use gpt-4.1 (not mini)
|
|
56
55
|
const models = events
|
|
57
56
|
.map(e => {
|
|
58
57
|
try {
|
|
@@ -64,8 +63,7 @@ test('OpenAI vendor streaming over subscriptions emits OAI-style deltas', async
|
|
|
64
63
|
.filter(Boolean);
|
|
65
64
|
|
|
66
65
|
if (models.length > 0) {
|
|
67
|
-
t.truthy(models.find(m => /gpt-
|
|
68
|
-
t.falsy(models.find(m => /gpt-4\.1-mini/.test(m)));
|
|
66
|
+
t.truthy(models.find(m => /gpt-5-chat/.test(m)));
|
|
69
67
|
}
|
|
70
68
|
});
|
|
71
69
|
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// crypto.test.js
|
|
2
|
+
// Tests for encryption and decryption functions in cortex/lib/crypto.js
|
|
3
|
+
|
|
4
|
+
import test from 'ava';
|
|
5
|
+
import { encrypt, decrypt } from '../../../lib/crypto.js';
|
|
6
|
+
|
|
7
|
+
// Test data
|
|
8
|
+
const testData = 'Hello, this is test data!';
|
|
9
|
+
const systemKey = '1234567890123456789012345678901234567890123456789012345678901234'; // 64 hex chars
|
|
10
|
+
const userKey = 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'; // 64 hex chars
|
|
11
|
+
const wrongUserKey = '0000000000000000000000000000000000000000000000000000000000000000'; // 64 hex chars
|
|
12
|
+
const wrongSystemKey = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'; // 64 hex chars
|
|
13
|
+
|
|
14
|
+
// Basic encryption/decryption tests
|
|
15
|
+
test('encrypt should encrypt data with valid key', t => {
|
|
16
|
+
const encrypted = encrypt(testData, systemKey);
|
|
17
|
+
t.truthy(encrypted);
|
|
18
|
+
t.not(encrypted, testData);
|
|
19
|
+
t.true(encrypted.includes(':'));
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
test('decrypt should decrypt data with correct key', t => {
|
|
23
|
+
const encrypted = encrypt(testData, systemKey);
|
|
24
|
+
const decrypted = decrypt(encrypted, systemKey);
|
|
25
|
+
t.is(decrypted, testData);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
test('encrypt should return original data when no key provided', t => {
|
|
29
|
+
const result = encrypt(testData, null);
|
|
30
|
+
t.is(result, testData);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
test('decrypt should return original data when no key provided', t => {
|
|
34
|
+
const result = decrypt(testData, null);
|
|
35
|
+
t.is(result, testData);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
// Edge cases and error handling
|
|
39
|
+
test('encrypt should handle empty string', t => {
|
|
40
|
+
const encrypted = encrypt('', systemKey);
|
|
41
|
+
t.truthy(encrypted);
|
|
42
|
+
const decrypted = decrypt(encrypted, systemKey);
|
|
43
|
+
t.is(decrypted, '');
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
test('encrypt should handle special characters', t => {
|
|
47
|
+
const specialData = 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?';
|
|
48
|
+
const encrypted = encrypt(specialData, systemKey);
|
|
49
|
+
const decrypted = decrypt(encrypted, systemKey);
|
|
50
|
+
t.is(decrypted, specialData);
|
|
51
|
+
});
|
|
52
|
+
|
|
53
|
+
test('encrypt should handle unicode characters', t => {
|
|
54
|
+
const unicodeData = 'Unicode: ๐ ๐ รฑรกรฉรญรณรบ ไธญๆ ุงูุนุฑุจูุฉ';
|
|
55
|
+
const encrypted = encrypt(unicodeData, systemKey);
|
|
56
|
+
const decrypted = decrypt(encrypted, systemKey);
|
|
57
|
+
t.is(decrypted, unicodeData);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
test('encrypt should handle JSON data', t => {
|
|
61
|
+
const jsonData = JSON.stringify({ message: 'test', number: 42, array: [1, 2, 3] });
|
|
62
|
+
const encrypted = encrypt(jsonData, systemKey);
|
|
63
|
+
const decrypted = decrypt(encrypted, systemKey);
|
|
64
|
+
t.is(decrypted, jsonData);
|
|
65
|
+
});
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
// doubleEncryptionStorageClient.test.js
|
|
2
|
+
// Tests for context key encryption integration in keyValueStorageClient
|
|
3
|
+
|
|
4
|
+
import test from 'ava';
|
|
5
|
+
import { setvWithDoubleEncryption, getvWithDoubleDecryption, setv, getv } from '../../../lib/keyValueStorageClient.js';
|
|
6
|
+
import { encrypt, decrypt } from '../../../lib/crypto.js';
|
|
7
|
+
|
|
8
|
+
// Test data
|
|
9
|
+
const testData = { message: 'Hello, this is test data!', number: 42, array: [1, 2, 3] };
|
|
10
|
+
const systemKey = '1234567890123456789012345678901234567890123456789012345678901234'; // 64 hex chars
|
|
11
|
+
const userKey = 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890'; // 64 hex chars
|
|
12
|
+
|
|
13
|
+
// Mock the config to provide test keys
|
|
14
|
+
import { config } from '../../../config.js';
|
|
15
|
+
const originalGet = config.get;
|
|
16
|
+
const mockGet = (key) => {
|
|
17
|
+
switch (key) {
|
|
18
|
+
case 'storageConnectionString':
|
|
19
|
+
return 'redis://localhost:6379'; // Use in-memory Redis for tests
|
|
20
|
+
case 'cortexId':
|
|
21
|
+
return 'test-cortex';
|
|
22
|
+
case 'redisEncryptionKey':
|
|
23
|
+
return systemKey;
|
|
24
|
+
default:
|
|
25
|
+
return originalGet(key);
|
|
26
|
+
}
|
|
27
|
+
};
|
|
28
|
+
config.get = mockGet;
|
|
29
|
+
|
|
30
|
+
// Helper function to clear storage between tests
|
|
31
|
+
async function clearStorage() {
|
|
32
|
+
// Clear any existing test data
|
|
33
|
+
try {
|
|
34
|
+
await setvWithDoubleEncryption('test-key', null, userKey);
|
|
35
|
+
await setv('test-key', null);
|
|
36
|
+
} catch (error) {
|
|
37
|
+
// Ignore errors when clearing
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
test.beforeEach(async t => {
|
|
42
|
+
await clearStorage();
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
// Test 1: Double encryption/decryption with both contextKey and redisEncryptionKey
|
|
46
|
+
test('should store and retrieve data with double encryption when both keys provided', async t => {
|
|
47
|
+
const key = 'test-double-encryption';
|
|
48
|
+
|
|
49
|
+
// Store with double encryption
|
|
50
|
+
await setvWithDoubleEncryption(key, testData, userKey);
|
|
51
|
+
|
|
52
|
+
// Retrieve with double decryption
|
|
53
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
54
|
+
|
|
55
|
+
t.deepEqual(retrieved, testData);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// Test 2: Double encryption/decryption with only redisEncryptionKey (no contextKey)
|
|
59
|
+
test('should store and retrieve data with single encryption when no contextKey provided', async t => {
|
|
60
|
+
const key = 'test-single-encryption';
|
|
61
|
+
|
|
62
|
+
// Store with single encryption (no contextKey)
|
|
63
|
+
await setvWithDoubleEncryption(key, testData, null);
|
|
64
|
+
|
|
65
|
+
// Retrieve with single decryption
|
|
66
|
+
const retrieved = await getvWithDoubleDecryption(key, null);
|
|
67
|
+
|
|
68
|
+
t.deepEqual(retrieved, testData);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
// Test 3: Reading single-encrypted data (from keyValueStorageClient) with doubleDecryption
|
|
72
|
+
test('should read single-encrypted data from keyValueStorageClient with doubleDecryption', async t => {
|
|
73
|
+
const key = 'test-single-to-double';
|
|
74
|
+
|
|
75
|
+
// Store using keyValueStorageClient (single encryption)
|
|
76
|
+
await setv(key, testData);
|
|
77
|
+
|
|
78
|
+
// Read using doubleEncryptionStorageClient (should handle single-encrypted data)
|
|
79
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
80
|
+
|
|
81
|
+
t.deepEqual(retrieved, testData);
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
// Test 4: Reading single-encrypted data without contextKey
|
|
85
|
+
test('should read single-encrypted data from keyValueStorageClient without contextKey', async t => {
|
|
86
|
+
const key = 'test-single-to-double-no-context';
|
|
87
|
+
|
|
88
|
+
// Store using keyValueStorageClient (single encryption)
|
|
89
|
+
await setv(key, testData);
|
|
90
|
+
|
|
91
|
+
// Read using doubleEncryptionStorageClient without contextKey
|
|
92
|
+
const retrieved = await getvWithDoubleDecryption(key, null);
|
|
93
|
+
|
|
94
|
+
t.deepEqual(retrieved, testData);
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
// Test 5: Reading unencrypted data with doubleDecryption
|
|
98
|
+
test('should read unencrypted data with doubleDecryption', async t => {
|
|
99
|
+
const key = 'test-unencrypted';
|
|
100
|
+
|
|
101
|
+
// Store unencrypted data using keyValueStorageClient with no encryption key
|
|
102
|
+
const originalRedisKey = config.get('redisEncryptionKey');
|
|
103
|
+
config.get = (key) => {
|
|
104
|
+
switch (key) {
|
|
105
|
+
case 'storageConnectionString':
|
|
106
|
+
return 'redis://localhost:6379';
|
|
107
|
+
case 'cortexId':
|
|
108
|
+
return 'test-cortex';
|
|
109
|
+
case 'redisEncryptionKey':
|
|
110
|
+
return null; // No encryption
|
|
111
|
+
default:
|
|
112
|
+
return originalGet(key);
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
|
|
116
|
+
// Store unencrypted data
|
|
117
|
+
await setv(key, testData);
|
|
118
|
+
|
|
119
|
+
// Restore mock config
|
|
120
|
+
config.get = mockGet;
|
|
121
|
+
|
|
122
|
+
// Read using doubleEncryptionStorageClient (should handle unencrypted data)
|
|
123
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
124
|
+
|
|
125
|
+
t.deepEqual(retrieved, testData);
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// Test 6: Reading unencrypted data without contextKey
|
|
129
|
+
test('should read unencrypted data without contextKey', async t => {
|
|
130
|
+
const key = 'test-unencrypted-no-context';
|
|
131
|
+
|
|
132
|
+
// Store unencrypted data using keyValueStorageClient with no encryption key
|
|
133
|
+
const originalRedisKey = config.get('redisEncryptionKey');
|
|
134
|
+
config.get = (key) => {
|
|
135
|
+
switch (key) {
|
|
136
|
+
case 'storageConnectionString':
|
|
137
|
+
return 'redis://localhost:6379';
|
|
138
|
+
case 'cortexId':
|
|
139
|
+
return 'test-cortex';
|
|
140
|
+
case 'redisEncryptionKey':
|
|
141
|
+
return null; // No encryption
|
|
142
|
+
default:
|
|
143
|
+
return originalGet(key);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
|
|
147
|
+
// Store unencrypted data
|
|
148
|
+
await setv(key, testData);
|
|
149
|
+
|
|
150
|
+
// Restore mock config
|
|
151
|
+
config.get = mockGet;
|
|
152
|
+
|
|
153
|
+
// Read using doubleEncryptionStorageClient without contextKey
|
|
154
|
+
const retrieved = await getvWithDoubleDecryption(key, null);
|
|
155
|
+
|
|
156
|
+
t.deepEqual(retrieved, testData);
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Test 7: Mixed data types - some double-encrypted, some single-encrypted
|
|
160
|
+
test('should handle mixed encryption states in storage', async t => {
|
|
161
|
+
const doubleKey = 'test-mixed-double';
|
|
162
|
+
const singleKey = 'test-mixed-single';
|
|
163
|
+
|
|
164
|
+
// Store with different encryption methods
|
|
165
|
+
await setvWithDoubleEncryption(doubleKey, testData, userKey); // Double encrypted
|
|
166
|
+
await setv(singleKey, testData); // Single encrypted
|
|
167
|
+
|
|
168
|
+
// Both should be readable with doubleDecryption
|
|
169
|
+
const doubleRetrieved = await getvWithDoubleDecryption(doubleKey, userKey);
|
|
170
|
+
const singleRetrieved = await getvWithDoubleDecryption(singleKey, userKey);
|
|
171
|
+
|
|
172
|
+
t.deepEqual(doubleRetrieved, testData, 'Double-encrypted data should be readable');
|
|
173
|
+
t.deepEqual(singleRetrieved, testData, 'Single-encrypted data should be readable');
|
|
174
|
+
});
|
|
175
|
+
|
|
176
|
+
// Test 8: Edge case - null/undefined data handling
|
|
177
|
+
test('should handle null and undefined data gracefully', async t => {
|
|
178
|
+
const key1 = 'test-null-data';
|
|
179
|
+
const key2 = 'test-undefined-data';
|
|
180
|
+
|
|
181
|
+
// Store null data
|
|
182
|
+
await setvWithDoubleEncryption(key1, null, userKey);
|
|
183
|
+
const retrieved1 = await getvWithDoubleDecryption(key1, userKey);
|
|
184
|
+
t.is(retrieved1, null);
|
|
185
|
+
|
|
186
|
+
// Store undefined data
|
|
187
|
+
await setvWithDoubleEncryption(key2, undefined, userKey);
|
|
188
|
+
const retrieved2 = await getvWithDoubleDecryption(key2, userKey);
|
|
189
|
+
t.is(retrieved2, undefined);
|
|
190
|
+
});
|
|
191
|
+
|
|
192
|
+
// Test 9: Edge case - empty object handling
|
|
193
|
+
test('should handle empty objects', async t => {
|
|
194
|
+
const key = 'test-empty-object';
|
|
195
|
+
const emptyData = {};
|
|
196
|
+
|
|
197
|
+
await setvWithDoubleEncryption(key, emptyData, userKey);
|
|
198
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
199
|
+
|
|
200
|
+
t.deepEqual(retrieved, emptyData);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
// Test 10: Context key changes between operations
|
|
204
|
+
test('should handle context key changes between operations', async t => {
|
|
205
|
+
const key1 = 'test-context-change-1';
|
|
206
|
+
const key2 = 'test-context-change-2';
|
|
207
|
+
const newUserKey = '1111111111111111111111111111111111111111111111111111111111111111';
|
|
208
|
+
|
|
209
|
+
// Store with first context key
|
|
210
|
+
await setvWithDoubleEncryption(key1, testData, userKey);
|
|
211
|
+
|
|
212
|
+
// Retrieve with same context key
|
|
213
|
+
const retrieved1 = await getvWithDoubleDecryption(key1, userKey);
|
|
214
|
+
t.deepEqual(retrieved1, testData);
|
|
215
|
+
|
|
216
|
+
// Store with different context key (different key to avoid conflicts)
|
|
217
|
+
await setvWithDoubleEncryption(key2, testData, newUserKey);
|
|
218
|
+
|
|
219
|
+
// Retrieve with new context key
|
|
220
|
+
const retrieved2 = await getvWithDoubleDecryption(key2, newUserKey);
|
|
221
|
+
t.deepEqual(retrieved2, testData);
|
|
222
|
+
|
|
223
|
+
// Verify that data encrypted with one key cannot be decrypted with another
|
|
224
|
+
const wrongKeyRetrieved = await getvWithDoubleDecryption(key1, newUserKey);
|
|
225
|
+
t.notDeepEqual(wrongKeyRetrieved, testData, 'Data encrypted with one key should not be readable with different key');
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
// Test 11: Large data handling
|
|
229
|
+
test('should handle large data objects', async t => {
|
|
230
|
+
const key = 'test-large-data';
|
|
231
|
+
const largeData = {
|
|
232
|
+
message: 'Large data test',
|
|
233
|
+
array: Array(1000).fill(0).map((_, i) => i),
|
|
234
|
+
nested: {
|
|
235
|
+
level1: {
|
|
236
|
+
level2: {
|
|
237
|
+
level3: Array(100).fill('test')
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
await setvWithDoubleEncryption(key, largeData, userKey);
|
|
244
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
245
|
+
|
|
246
|
+
t.deepEqual(retrieved, largeData);
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// Test 12: Special characters and unicode
|
|
250
|
+
test('should handle special characters and unicode', async t => {
|
|
251
|
+
const key = 'test-special-chars';
|
|
252
|
+
const specialData = {
|
|
253
|
+
message: 'Special chars: !@#$%^&*()_+-=[]{}|;:,.<>?',
|
|
254
|
+
unicode: 'Unicode: ๐ ๐ รฑรกรฉรญรณรบ ไธญๆ ุงูุนุฑุจูุฉ',
|
|
255
|
+
emoji: '๐๐๐๐คฃ๐๐๐
๐๐๐'
|
|
256
|
+
};
|
|
257
|
+
|
|
258
|
+
await setvWithDoubleEncryption(key, specialData, userKey);
|
|
259
|
+
const retrieved = await getvWithDoubleDecryption(key, userKey);
|
|
260
|
+
|
|
261
|
+
t.deepEqual(retrieved, specialData);
|
|
262
|
+
});
|