@elizaos/core 1.5.4 → 1.5.5
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/README.md +0 -15
- package/dist/index.d.ts +4886 -3
- package/dist/index.js +5287 -4
- package/package.json +21 -39
- package/dist/browser/index.browser.js +0 -1109
- package/dist/browser/index.browser.js.map +0 -707
- package/dist/browser/index.d.ts +0 -3
- package/dist/node/index.d.ts +0 -3
- package/dist/node/index.node.js +0 -74530
- package/dist/node/index.node.js.map +0 -1027
- package/src/__tests__/action-chaining-simple.test.ts +0 -203
- package/src/__tests__/actions.test.ts +0 -218
- package/src/__tests__/buffer.test.ts +0 -337
- package/src/__tests__/character-validation.test.ts +0 -309
- package/src/__tests__/database.test.ts +0 -750
- package/src/__tests__/entities.test.ts +0 -727
- package/src/__tests__/env.test.ts +0 -23
- package/src/__tests__/environment.test.ts +0 -285
- package/src/__tests__/logger-browser-node.test.ts +0 -716
- package/src/__tests__/logger.test.ts +0 -403
- package/src/__tests__/messages.test.ts +0 -196
- package/src/__tests__/mockCharacter.ts +0 -544
- package/src/__tests__/parsing.test.ts +0 -58
- package/src/__tests__/prompts.test.ts +0 -159
- package/src/__tests__/roles.test.ts +0 -331
- package/src/__tests__/runtime-embedding.test.ts +0 -343
- package/src/__tests__/runtime.test.ts +0 -978
- package/src/__tests__/search.test.ts +0 -15
- package/src/__tests__/services-by-type.test.ts +0 -204
- package/src/__tests__/services.test.ts +0 -136
- package/src/__tests__/settings.test.ts +0 -810
- package/src/__tests__/utils.test.ts +0 -1105
- package/src/__tests__/uuid.test.ts +0 -94
- package/src/actions.ts +0 -122
- package/src/database.ts +0 -579
- package/src/entities.ts +0 -406
- package/src/index.browser.ts +0 -48
- package/src/index.node.ts +0 -39
- package/src/index.ts +0 -50
- package/src/logger.ts +0 -527
- package/src/prompts.ts +0 -243
- package/src/roles.ts +0 -85
- package/src/runtime.ts +0 -2514
- package/src/schemas/character.ts +0 -149
- package/src/search.ts +0 -1543
- package/src/sentry/instrument.browser.ts +0 -65
- package/src/sentry/instrument.node.ts +0 -57
- package/src/sentry/instrument.ts +0 -82
- package/src/services.ts +0 -105
- package/src/settings.ts +0 -409
- package/src/test_resources/constants.ts +0 -12
- package/src/test_resources/testSetup.ts +0 -21
- package/src/test_resources/types.ts +0 -22
- package/src/types/agent.ts +0 -112
- package/src/types/browser.ts +0 -145
- package/src/types/components.ts +0 -184
- package/src/types/database.ts +0 -348
- package/src/types/email.ts +0 -162
- package/src/types/environment.ts +0 -129
- package/src/types/events.ts +0 -249
- package/src/types/index.ts +0 -29
- package/src/types/knowledge.ts +0 -65
- package/src/types/lp.ts +0 -124
- package/src/types/memory.ts +0 -228
- package/src/types/message.ts +0 -233
- package/src/types/messaging.ts +0 -57
- package/src/types/model.ts +0 -359
- package/src/types/pdf.ts +0 -77
- package/src/types/plugin.ts +0 -78
- package/src/types/post.ts +0 -271
- package/src/types/primitives.ts +0 -97
- package/src/types/runtime.ts +0 -190
- package/src/types/service.ts +0 -198
- package/src/types/settings.ts +0 -30
- package/src/types/state.ts +0 -60
- package/src/types/task.ts +0 -72
- package/src/types/tee.ts +0 -107
- package/src/types/testing.ts +0 -30
- package/src/types/token.ts +0 -96
- package/src/types/transcription.ts +0 -133
- package/src/types/video.ts +0 -108
- package/src/types/wallet.ts +0 -56
- package/src/types/web-search.ts +0 -146
- package/src/utils/__tests__/buffer.test.ts +0 -80
- package/src/utils/__tests__/environment.test.ts +0 -58
- package/src/utils/__tests__/stringToUuid.test.ts +0 -88
- package/src/utils/buffer.ts +0 -312
- package/src/utils/environment.ts +0 -316
- package/src/utils/server-health.ts +0 -117
- package/src/utils.ts +0 -1076
|
@@ -1,810 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, beforeEach, afterEach } from 'bun:test';
|
|
2
|
-
import { mock, spyOn } from 'bun:test';
|
|
3
|
-
import {
|
|
4
|
-
createSettingFromConfig,
|
|
5
|
-
getSalt,
|
|
6
|
-
encryptStringValue,
|
|
7
|
-
decryptStringValue,
|
|
8
|
-
saltSettingValue,
|
|
9
|
-
unsaltSettingValue,
|
|
10
|
-
saltWorldSettings,
|
|
11
|
-
unsaltWorldSettings,
|
|
12
|
-
updateWorldSettings,
|
|
13
|
-
getWorldSettings,
|
|
14
|
-
initializeOnboarding,
|
|
15
|
-
encryptedCharacter,
|
|
16
|
-
decryptedCharacter,
|
|
17
|
-
encryptObjectValues,
|
|
18
|
-
decryptObjectValues,
|
|
19
|
-
decryptSecret,
|
|
20
|
-
} from '../settings';
|
|
21
|
-
import type {
|
|
22
|
-
IAgentRuntime,
|
|
23
|
-
Setting,
|
|
24
|
-
World,
|
|
25
|
-
WorldSettings,
|
|
26
|
-
OnboardingConfig,
|
|
27
|
-
Character,
|
|
28
|
-
UUID,
|
|
29
|
-
} from '../types';
|
|
30
|
-
|
|
31
|
-
import * as entities from '../entities';
|
|
32
|
-
import * as logger_module from '../logger';
|
|
33
|
-
import { getEnvironment } from '../utils/environment';
|
|
34
|
-
|
|
35
|
-
// Remove global module mocks - they interfere with other tests
|
|
36
|
-
|
|
37
|
-
describe('settings utilities', () => {
|
|
38
|
-
let mockRuntime: IAgentRuntime;
|
|
39
|
-
let mockWorld: World;
|
|
40
|
-
|
|
41
|
-
beforeEach(() => {
|
|
42
|
-
mock.restore();
|
|
43
|
-
|
|
44
|
-
// Set up scoped mocks for this test
|
|
45
|
-
spyOn(entities, 'createUniqueUuid').mockImplementation(
|
|
46
|
-
(_runtime, serverId) => `world-${serverId}` as UUID
|
|
47
|
-
);
|
|
48
|
-
|
|
49
|
-
// Mock logger if it doesn't have the methods
|
|
50
|
-
if (logger_module.logger) {
|
|
51
|
-
const methods = ['error', 'info', 'warn', 'debug'];
|
|
52
|
-
methods.forEach((method) => {
|
|
53
|
-
if (typeof logger_module.logger[method] === 'function') {
|
|
54
|
-
spyOn(logger_module.logger, method).mockImplementation(() => {});
|
|
55
|
-
} else {
|
|
56
|
-
logger_module.logger[method] = mock(() => {});
|
|
57
|
-
}
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
// Mock process.env
|
|
62
|
-
process.env.SECRET_SALT = 'test-salt-value';
|
|
63
|
-
// Clear environment cache after setting env var
|
|
64
|
-
getEnvironment().clearCache();
|
|
65
|
-
|
|
66
|
-
mockRuntime = {
|
|
67
|
-
agentId: 'agent-123' as any,
|
|
68
|
-
getWorld: mock(),
|
|
69
|
-
updateWorld: mock(),
|
|
70
|
-
} as unknown as IAgentRuntime;
|
|
71
|
-
|
|
72
|
-
mockWorld = {
|
|
73
|
-
id: 'world-123' as any,
|
|
74
|
-
name: 'Test World',
|
|
75
|
-
agentId: 'agent-123' as any,
|
|
76
|
-
serverId: 'server-123',
|
|
77
|
-
metadata: {},
|
|
78
|
-
};
|
|
79
|
-
});
|
|
80
|
-
|
|
81
|
-
afterEach(() => {
|
|
82
|
-
mock.restore();
|
|
83
|
-
delete process.env.SECRET_SALT;
|
|
84
|
-
getEnvironment().clearCache(); // Clear cache after cleanup
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
describe('createSettingFromConfig', () => {
|
|
88
|
-
it('should create setting with all required fields', () => {
|
|
89
|
-
const cfg = {
|
|
90
|
-
name: 'API_KEY',
|
|
91
|
-
description: 'API Key for service',
|
|
92
|
-
usageDescription: '',
|
|
93
|
-
required: true,
|
|
94
|
-
};
|
|
95
|
-
|
|
96
|
-
const setting = createSettingFromConfig(cfg);
|
|
97
|
-
|
|
98
|
-
expect(setting).toEqual({
|
|
99
|
-
name: 'API_KEY',
|
|
100
|
-
description: 'API Key for service',
|
|
101
|
-
usageDescription: '',
|
|
102
|
-
value: null,
|
|
103
|
-
required: true,
|
|
104
|
-
validation: undefined,
|
|
105
|
-
public: false,
|
|
106
|
-
secret: false,
|
|
107
|
-
dependsOn: [],
|
|
108
|
-
onSetAction: undefined,
|
|
109
|
-
visibleIf: undefined,
|
|
110
|
-
});
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
it('should create setting with optional fields', () => {
|
|
114
|
-
const validationFn = (value: any) => /^[A-Z0-9]+$/.test(value);
|
|
115
|
-
const onSetActionFn = (_value: any) => 'restart';
|
|
116
|
-
const cfg = {
|
|
117
|
-
name: 'API_KEY',
|
|
118
|
-
description: 'API Key for service',
|
|
119
|
-
usageDescription: 'Enter your API key',
|
|
120
|
-
required: false,
|
|
121
|
-
validation: validationFn,
|
|
122
|
-
public: true,
|
|
123
|
-
secret: true,
|
|
124
|
-
dependsOn: ['OTHER_SETTING'],
|
|
125
|
-
onSetAction: onSetActionFn,
|
|
126
|
-
visibleIf: (settings) => settings['OTHER_SETTING']?.value === 'enabled',
|
|
127
|
-
};
|
|
128
|
-
|
|
129
|
-
const setting = createSettingFromConfig(cfg);
|
|
130
|
-
|
|
131
|
-
expect(setting.usageDescription).toBe('Enter your API key');
|
|
132
|
-
expect(setting.validation).toBe(validationFn);
|
|
133
|
-
expect(setting.public).toBe(true);
|
|
134
|
-
expect(setting.secret).toBe(true);
|
|
135
|
-
expect(setting.dependsOn).toEqual(['OTHER_SETTING']);
|
|
136
|
-
expect(setting.onSetAction).toBe(onSetActionFn);
|
|
137
|
-
expect(setting.visibleIf).toBeInstanceOf(Function);
|
|
138
|
-
expect(
|
|
139
|
-
setting.visibleIf({
|
|
140
|
-
OTHER_SETTING: {
|
|
141
|
-
name: 'OTHER_SETTING',
|
|
142
|
-
description: 'Other setting',
|
|
143
|
-
usageDescription: 'Other setting description',
|
|
144
|
-
value: 'enabled',
|
|
145
|
-
required: true,
|
|
146
|
-
secret: false,
|
|
147
|
-
},
|
|
148
|
-
})
|
|
149
|
-
).toBe(true);
|
|
150
|
-
expect(
|
|
151
|
-
setting.visibleIf({
|
|
152
|
-
OTHER_SETTING: {
|
|
153
|
-
name: 'OTHER_SETTING',
|
|
154
|
-
description: 'Other setting',
|
|
155
|
-
usageDescription: 'Other setting description',
|
|
156
|
-
value: 'disabled',
|
|
157
|
-
required: true,
|
|
158
|
-
secret: false,
|
|
159
|
-
},
|
|
160
|
-
})
|
|
161
|
-
).toBe(false);
|
|
162
|
-
});
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
describe('getSalt', () => {
|
|
166
|
-
it('should return salt from environment variable', () => {
|
|
167
|
-
const salt = getSalt();
|
|
168
|
-
expect(salt).toBe('test-salt-value');
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
it('should use default salt when env variable is not set', () => {
|
|
172
|
-
delete process.env.SECRET_SALT;
|
|
173
|
-
getEnvironment().clearCache(); // Clear cache after deleting env var
|
|
174
|
-
const salt = getSalt();
|
|
175
|
-
expect(salt).toBe('secretsalt');
|
|
176
|
-
});
|
|
177
|
-
|
|
178
|
-
it('should handle import.meta.env in non-node environments', () => {
|
|
179
|
-
// This test is skipped as it's difficult to properly simulate non-node environment
|
|
180
|
-
// without breaking other tests. The getSalt function is tested in other scenarios.
|
|
181
|
-
expect(true).toBe(true);
|
|
182
|
-
});
|
|
183
|
-
});
|
|
184
|
-
|
|
185
|
-
describe('encryptStringValue', () => {
|
|
186
|
-
const salt = 'test-salt';
|
|
187
|
-
|
|
188
|
-
it('should encrypt a string value', () => {
|
|
189
|
-
const encrypted = encryptStringValue('secret-value', salt);
|
|
190
|
-
|
|
191
|
-
expect(encrypted).not.toBe('secret-value');
|
|
192
|
-
expect(encrypted).toContain(':'); // Should have iv:encrypted format
|
|
193
|
-
});
|
|
194
|
-
|
|
195
|
-
it('should return undefined/null values as is', () => {
|
|
196
|
-
expect(encryptStringValue(undefined as any, salt)).toBeUndefined();
|
|
197
|
-
expect(encryptStringValue(null as any, salt)).toBeNull();
|
|
198
|
-
});
|
|
199
|
-
|
|
200
|
-
it('should return boolean values as is', () => {
|
|
201
|
-
expect(encryptStringValue(true as any, salt)).toBe(true);
|
|
202
|
-
expect(encryptStringValue(false as any, salt)).toBe(false);
|
|
203
|
-
});
|
|
204
|
-
|
|
205
|
-
it('should return number values as is', () => {
|
|
206
|
-
expect(encryptStringValue(123 as any, salt)).toBe(123);
|
|
207
|
-
expect(encryptStringValue(0 as any, salt)).toBe(0);
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
it('should return non-string objects as is', () => {
|
|
211
|
-
const obj = { key: 'value' };
|
|
212
|
-
expect(encryptStringValue(obj as any, salt)).toBe(obj);
|
|
213
|
-
});
|
|
214
|
-
|
|
215
|
-
it('should not re-encrypt already encrypted values', () => {
|
|
216
|
-
const encrypted = encryptStringValue('secret', salt);
|
|
217
|
-
const doubleEncrypted = encryptStringValue(encrypted, salt);
|
|
218
|
-
|
|
219
|
-
expect(doubleEncrypted).toBe(encrypted);
|
|
220
|
-
});
|
|
221
|
-
|
|
222
|
-
it('should encrypt values that look like encrypted format but have invalid IV', () => {
|
|
223
|
-
const fakeEncrypted = 'invalid:value';
|
|
224
|
-
const encrypted = encryptStringValue(fakeEncrypted, salt);
|
|
225
|
-
|
|
226
|
-
expect(encrypted).not.toBe(fakeEncrypted);
|
|
227
|
-
expect(encrypted.split(':').length).toBe(2);
|
|
228
|
-
});
|
|
229
|
-
});
|
|
230
|
-
|
|
231
|
-
describe('decryptStringValue', () => {
|
|
232
|
-
const salt = 'test-salt';
|
|
233
|
-
|
|
234
|
-
it('should decrypt an encrypted value', () => {
|
|
235
|
-
const original = 'secret-value';
|
|
236
|
-
const encrypted = encryptStringValue(original, salt);
|
|
237
|
-
const decrypted = decryptStringValue(encrypted, salt);
|
|
238
|
-
|
|
239
|
-
expect(decrypted).toBe(original);
|
|
240
|
-
});
|
|
241
|
-
|
|
242
|
-
it('should return undefined/null values as is', () => {
|
|
243
|
-
expect(decryptStringValue(undefined as any, salt)).toBeUndefined();
|
|
244
|
-
expect(decryptStringValue(null as any, salt)).toBeNull();
|
|
245
|
-
});
|
|
246
|
-
|
|
247
|
-
it('should return boolean values as is', () => {
|
|
248
|
-
expect(decryptStringValue(true as any, salt)).toBe(true);
|
|
249
|
-
expect(decryptStringValue(false as any, salt)).toBe(false);
|
|
250
|
-
});
|
|
251
|
-
|
|
252
|
-
it('should return number values as is', () => {
|
|
253
|
-
expect(decryptStringValue(123 as any, salt)).toBe(123);
|
|
254
|
-
});
|
|
255
|
-
|
|
256
|
-
it('should return non-string objects as is', () => {
|
|
257
|
-
const obj = { key: 'value' };
|
|
258
|
-
expect(decryptStringValue(obj as any, salt)).toBe(obj);
|
|
259
|
-
});
|
|
260
|
-
|
|
261
|
-
it('should return original value if not in encrypted format', () => {
|
|
262
|
-
const plainValue = 'not-encrypted';
|
|
263
|
-
expect(decryptStringValue(plainValue, salt)).toBe(plainValue);
|
|
264
|
-
});
|
|
265
|
-
|
|
266
|
-
it('should return original value if IV length is invalid', () => {
|
|
267
|
-
const invalidFormat = 'shortiv:encrypted';
|
|
268
|
-
expect(decryptStringValue(invalidFormat, salt)).toBe(invalidFormat);
|
|
269
|
-
});
|
|
270
|
-
|
|
271
|
-
it('should return original value on decryption error', () => {
|
|
272
|
-
const invalidEncrypted = '0123456789abcdef0123456789abcdef:invalidhex';
|
|
273
|
-
const result = decryptStringValue(invalidEncrypted, salt);
|
|
274
|
-
expect(result).toBe(invalidEncrypted);
|
|
275
|
-
});
|
|
276
|
-
|
|
277
|
-
it('should handle empty IV gracefully', () => {
|
|
278
|
-
const emptyIv = ':encrypted';
|
|
279
|
-
expect(decryptStringValue(emptyIv, salt)).toBe(emptyIv);
|
|
280
|
-
});
|
|
281
|
-
});
|
|
282
|
-
|
|
283
|
-
describe('saltSettingValue', () => {
|
|
284
|
-
const salt = 'test-salt';
|
|
285
|
-
|
|
286
|
-
it('should encrypt secret string settings', () => {
|
|
287
|
-
const setting: Setting = {
|
|
288
|
-
name: 'API_KEY',
|
|
289
|
-
description: 'API Key',
|
|
290
|
-
usageDescription: 'Enter API key',
|
|
291
|
-
value: 'my-secret-key',
|
|
292
|
-
secret: true,
|
|
293
|
-
required: true,
|
|
294
|
-
};
|
|
295
|
-
|
|
296
|
-
const salted = saltSettingValue(setting, salt);
|
|
297
|
-
|
|
298
|
-
expect(salted.value).not.toBe('my-secret-key');
|
|
299
|
-
expect(salted.value).toContain(':');
|
|
300
|
-
});
|
|
301
|
-
|
|
302
|
-
it('should not encrypt non-secret settings', () => {
|
|
303
|
-
const setting: Setting = {
|
|
304
|
-
name: 'PUBLIC_URL',
|
|
305
|
-
description: 'Public URL',
|
|
306
|
-
usageDescription: 'Enter public URL',
|
|
307
|
-
value: 'https://example.com',
|
|
308
|
-
secret: false,
|
|
309
|
-
required: true,
|
|
310
|
-
};
|
|
311
|
-
|
|
312
|
-
const salted = saltSettingValue(setting, salt);
|
|
313
|
-
|
|
314
|
-
expect(salted.value).toBe('https://example.com');
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
it('should not encrypt non-string values', () => {
|
|
318
|
-
const setting: Setting = {
|
|
319
|
-
name: 'ENABLED',
|
|
320
|
-
description: 'Feature enabled',
|
|
321
|
-
usageDescription: 'Enable feature',
|
|
322
|
-
value: true,
|
|
323
|
-
secret: true,
|
|
324
|
-
required: true,
|
|
325
|
-
};
|
|
326
|
-
|
|
327
|
-
const salted = saltSettingValue(setting, salt);
|
|
328
|
-
|
|
329
|
-
expect(salted.value).toBe(true);
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
it('should not encrypt empty string values', () => {
|
|
333
|
-
const setting: Setting = {
|
|
334
|
-
name: 'API_KEY',
|
|
335
|
-
description: 'API Key',
|
|
336
|
-
usageDescription: 'Enter API key',
|
|
337
|
-
value: '',
|
|
338
|
-
secret: true,
|
|
339
|
-
required: false,
|
|
340
|
-
};
|
|
341
|
-
|
|
342
|
-
const salted = saltSettingValue(setting, salt);
|
|
343
|
-
|
|
344
|
-
expect(salted.value).toBe('');
|
|
345
|
-
});
|
|
346
|
-
});
|
|
347
|
-
|
|
348
|
-
describe('unsaltSettingValue', () => {
|
|
349
|
-
const salt = 'test-salt';
|
|
350
|
-
|
|
351
|
-
it('should decrypt secret string settings', () => {
|
|
352
|
-
const original = 'my-secret-key';
|
|
353
|
-
const encrypted = encryptStringValue(original, salt);
|
|
354
|
-
const setting: Setting = {
|
|
355
|
-
name: 'API_KEY',
|
|
356
|
-
description: 'API Key',
|
|
357
|
-
usageDescription: 'Enter API key',
|
|
358
|
-
value: encrypted,
|
|
359
|
-
secret: true,
|
|
360
|
-
required: true,
|
|
361
|
-
};
|
|
362
|
-
|
|
363
|
-
const unsalted = unsaltSettingValue(setting, salt);
|
|
364
|
-
|
|
365
|
-
expect(unsalted.value).toBe(original);
|
|
366
|
-
});
|
|
367
|
-
|
|
368
|
-
it('should not decrypt non-secret settings', () => {
|
|
369
|
-
const setting: Setting = {
|
|
370
|
-
name: 'PUBLIC_URL',
|
|
371
|
-
description: 'Public URL',
|
|
372
|
-
usageDescription: 'Enter public URL',
|
|
373
|
-
value: 'https://example.com',
|
|
374
|
-
secret: false,
|
|
375
|
-
required: true,
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
const unsalted = unsaltSettingValue(setting, salt);
|
|
379
|
-
|
|
380
|
-
expect(unsalted.value).toBe('https://example.com');
|
|
381
|
-
});
|
|
382
|
-
});
|
|
383
|
-
|
|
384
|
-
describe('saltWorldSettings', () => {
|
|
385
|
-
const salt = 'test-salt';
|
|
386
|
-
|
|
387
|
-
it('should salt all secret settings in world settings', () => {
|
|
388
|
-
const worldSettings: WorldSettings = {
|
|
389
|
-
API_KEY: {
|
|
390
|
-
name: 'API_KEY',
|
|
391
|
-
description: 'API Key',
|
|
392
|
-
usageDescription: 'Enter API key',
|
|
393
|
-
value: 'secret1',
|
|
394
|
-
secret: true,
|
|
395
|
-
required: true,
|
|
396
|
-
},
|
|
397
|
-
DB_PASSWORD: {
|
|
398
|
-
name: 'DB_PASSWORD',
|
|
399
|
-
description: 'Database Password',
|
|
400
|
-
usageDescription: 'Enter database password',
|
|
401
|
-
value: 'secret2',
|
|
402
|
-
secret: true,
|
|
403
|
-
required: true,
|
|
404
|
-
},
|
|
405
|
-
PUBLIC_URL: {
|
|
406
|
-
name: 'PUBLIC_URL',
|
|
407
|
-
description: 'Public URL',
|
|
408
|
-
usageDescription: 'Enter public URL',
|
|
409
|
-
value: 'https://example.com',
|
|
410
|
-
secret: false,
|
|
411
|
-
required: true,
|
|
412
|
-
},
|
|
413
|
-
};
|
|
414
|
-
|
|
415
|
-
const salted = saltWorldSettings(worldSettings, salt);
|
|
416
|
-
|
|
417
|
-
expect(salted.API_KEY.value).not.toBe('secret1');
|
|
418
|
-
expect(salted.API_KEY.value).toContain(':');
|
|
419
|
-
expect(salted.DB_PASSWORD.value).not.toBe('secret2');
|
|
420
|
-
expect(salted.DB_PASSWORD.value).toContain(':');
|
|
421
|
-
expect(salted.PUBLIC_URL.value).toBe('https://example.com');
|
|
422
|
-
});
|
|
423
|
-
});
|
|
424
|
-
|
|
425
|
-
describe('unsaltWorldSettings', () => {
|
|
426
|
-
const salt = 'test-salt';
|
|
427
|
-
|
|
428
|
-
it('should unsalt all secret settings in world settings', () => {
|
|
429
|
-
const encrypted1 = encryptStringValue('secret1', salt);
|
|
430
|
-
const encrypted2 = encryptStringValue('secret2', salt);
|
|
431
|
-
|
|
432
|
-
const worldSettings: WorldSettings = {
|
|
433
|
-
API_KEY: {
|
|
434
|
-
name: 'API_KEY',
|
|
435
|
-
description: 'API Key',
|
|
436
|
-
usageDescription: 'Enter your API key',
|
|
437
|
-
value: encrypted1,
|
|
438
|
-
secret: true,
|
|
439
|
-
required: true,
|
|
440
|
-
},
|
|
441
|
-
DB_PASSWORD: {
|
|
442
|
-
name: 'DB_PASSWORD',
|
|
443
|
-
description: 'Database Password',
|
|
444
|
-
usageDescription: 'Enter your database password',
|
|
445
|
-
value: encrypted2,
|
|
446
|
-
secret: true,
|
|
447
|
-
required: true,
|
|
448
|
-
},
|
|
449
|
-
};
|
|
450
|
-
|
|
451
|
-
const unsalted = unsaltWorldSettings(worldSettings, salt);
|
|
452
|
-
|
|
453
|
-
expect(unsalted.API_KEY.value).toBe('secret1');
|
|
454
|
-
expect(unsalted.DB_PASSWORD.value).toBe('secret2');
|
|
455
|
-
});
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
describe('updateWorldSettings', () => {
|
|
459
|
-
it('should update world settings successfully', async () => {
|
|
460
|
-
const worldSettings: WorldSettings = {
|
|
461
|
-
API_KEY: {
|
|
462
|
-
name: 'API_KEY',
|
|
463
|
-
description: 'API Key',
|
|
464
|
-
usageDescription: 'Enter your API key',
|
|
465
|
-
value: 'secret-key',
|
|
466
|
-
secret: true,
|
|
467
|
-
required: true,
|
|
468
|
-
},
|
|
469
|
-
};
|
|
470
|
-
|
|
471
|
-
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
472
|
-
(mockRuntime.updateWorld as any).mockResolvedValue(true);
|
|
473
|
-
|
|
474
|
-
const result = await updateWorldSettings(mockRuntime, 'server-123', worldSettings);
|
|
475
|
-
|
|
476
|
-
expect(result).toBe(true);
|
|
477
|
-
expect(mockRuntime.updateWorld).toHaveBeenCalledWith(
|
|
478
|
-
expect.objectContaining({
|
|
479
|
-
metadata: expect.objectContaining({
|
|
480
|
-
settings: expect.any(Object),
|
|
481
|
-
}),
|
|
482
|
-
})
|
|
483
|
-
);
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
it('should return false when world not found', async () => {
|
|
487
|
-
(mockRuntime.getWorld as any).mockResolvedValue(null);
|
|
488
|
-
|
|
489
|
-
const result = await updateWorldSettings(mockRuntime, 'server-123', {});
|
|
490
|
-
|
|
491
|
-
expect(result).toBe(false);
|
|
492
|
-
expect(mockRuntime.updateWorld).not.toHaveBeenCalled();
|
|
493
|
-
});
|
|
494
|
-
|
|
495
|
-
it('should initialize metadata if it does not exist', async () => {
|
|
496
|
-
const worldWithoutMetadata = { ...mockWorld, metadata: undefined };
|
|
497
|
-
(mockRuntime.getWorld as any).mockResolvedValue(worldWithoutMetadata);
|
|
498
|
-
(mockRuntime.updateWorld as any).mockResolvedValue(true);
|
|
499
|
-
|
|
500
|
-
const result = await updateWorldSettings(mockRuntime, 'server-123', {});
|
|
501
|
-
|
|
502
|
-
expect(result).toBe(true);
|
|
503
|
-
expect(mockRuntime.updateWorld).toHaveBeenCalledWith(
|
|
504
|
-
expect.objectContaining({
|
|
505
|
-
metadata: expect.objectContaining({
|
|
506
|
-
settings: {},
|
|
507
|
-
}),
|
|
508
|
-
})
|
|
509
|
-
);
|
|
510
|
-
});
|
|
511
|
-
});
|
|
512
|
-
|
|
513
|
-
describe('getWorldSettings', () => {
|
|
514
|
-
it('should get and unsalt world settings', async () => {
|
|
515
|
-
const salt = getSalt();
|
|
516
|
-
const encrypted = encryptStringValue('secret-value', salt);
|
|
517
|
-
|
|
518
|
-
mockWorld.metadata = {
|
|
519
|
-
settings: {
|
|
520
|
-
API_KEY: {
|
|
521
|
-
name: 'API_KEY',
|
|
522
|
-
description: 'API Key',
|
|
523
|
-
usageDescription: 'Enter your API key',
|
|
524
|
-
value: encrypted,
|
|
525
|
-
secret: true,
|
|
526
|
-
required: true,
|
|
527
|
-
},
|
|
528
|
-
},
|
|
529
|
-
};
|
|
530
|
-
|
|
531
|
-
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
532
|
-
|
|
533
|
-
const result = await getWorldSettings(mockRuntime, 'server-123');
|
|
534
|
-
|
|
535
|
-
expect(result).not.toBeNull();
|
|
536
|
-
expect(result!.API_KEY.value).toBe('secret-value');
|
|
537
|
-
});
|
|
538
|
-
|
|
539
|
-
it('should return null when world not found', async () => {
|
|
540
|
-
(mockRuntime.getWorld as any).mockResolvedValue(null);
|
|
541
|
-
|
|
542
|
-
const result = await getWorldSettings(mockRuntime, 'server-123');
|
|
543
|
-
|
|
544
|
-
expect(result).toBeNull();
|
|
545
|
-
});
|
|
546
|
-
|
|
547
|
-
it('should return null when world has no settings', async () => {
|
|
548
|
-
(mockRuntime.getWorld as any).mockResolvedValue(mockWorld);
|
|
549
|
-
|
|
550
|
-
const result = await getWorldSettings(mockRuntime, 'server-123');
|
|
551
|
-
|
|
552
|
-
expect(result).toBeNull();
|
|
553
|
-
});
|
|
554
|
-
});
|
|
555
|
-
|
|
556
|
-
describe('initializeOnboarding', () => {
|
|
557
|
-
it('should initialize settings from config', async () => {
|
|
558
|
-
const config: OnboardingConfig = {
|
|
559
|
-
settings: {
|
|
560
|
-
API_KEY: {
|
|
561
|
-
name: 'API_KEY',
|
|
562
|
-
description: 'API Key',
|
|
563
|
-
usageDescription: 'Enter your API key',
|
|
564
|
-
required: true,
|
|
565
|
-
secret: true,
|
|
566
|
-
},
|
|
567
|
-
PUBLIC_URL: {
|
|
568
|
-
name: 'PUBLIC_URL',
|
|
569
|
-
description: 'Public URL',
|
|
570
|
-
usageDescription: 'Enter your public URL',
|
|
571
|
-
required: false,
|
|
572
|
-
secret: false,
|
|
573
|
-
},
|
|
574
|
-
},
|
|
575
|
-
};
|
|
576
|
-
|
|
577
|
-
(mockRuntime.updateWorld as any).mockResolvedValue(true);
|
|
578
|
-
|
|
579
|
-
const result = await initializeOnboarding(mockRuntime, mockWorld, config);
|
|
580
|
-
|
|
581
|
-
expect(result).not.toBeNull();
|
|
582
|
-
expect(result!.API_KEY).toBeDefined();
|
|
583
|
-
expect(result!.API_KEY.value).toBeNull();
|
|
584
|
-
expect(result!.API_KEY.secret).toBe(true);
|
|
585
|
-
expect(result!.PUBLIC_URL).toBeDefined();
|
|
586
|
-
expect(result!.PUBLIC_URL.secret).toBe(false);
|
|
587
|
-
});
|
|
588
|
-
|
|
589
|
-
it('should return existing settings if already initialized', async () => {
|
|
590
|
-
const salt = getSalt();
|
|
591
|
-
const encrypted = encryptStringValue('existing-secret', salt);
|
|
592
|
-
|
|
593
|
-
mockWorld.metadata = {
|
|
594
|
-
settings: {
|
|
595
|
-
API_KEY: {
|
|
596
|
-
name: 'API_KEY',
|
|
597
|
-
description: 'API Key',
|
|
598
|
-
usageDescription: 'Enter your API key',
|
|
599
|
-
value: encrypted,
|
|
600
|
-
secret: true,
|
|
601
|
-
required: true,
|
|
602
|
-
},
|
|
603
|
-
},
|
|
604
|
-
};
|
|
605
|
-
|
|
606
|
-
const config: OnboardingConfig = {
|
|
607
|
-
settings: {
|
|
608
|
-
NEW_KEY: {
|
|
609
|
-
name: 'NEW_KEY',
|
|
610
|
-
description: 'New Key',
|
|
611
|
-
usageDescription: 'Enter new key',
|
|
612
|
-
required: true,
|
|
613
|
-
},
|
|
614
|
-
},
|
|
615
|
-
};
|
|
616
|
-
|
|
617
|
-
const result = await initializeOnboarding(mockRuntime, mockWorld, config);
|
|
618
|
-
|
|
619
|
-
expect(result).not.toBeNull();
|
|
620
|
-
expect(result!.API_KEY).toBeDefined();
|
|
621
|
-
expect(result!.API_KEY.value).toBe('existing-secret');
|
|
622
|
-
expect(result!.NEW_KEY).toBeUndefined(); // Should not add new settings
|
|
623
|
-
});
|
|
624
|
-
|
|
625
|
-
it('should handle config without settings', async () => {
|
|
626
|
-
const config: OnboardingConfig = { settings: {} };
|
|
627
|
-
|
|
628
|
-
(mockRuntime.updateWorld as any).mockResolvedValue(true);
|
|
629
|
-
|
|
630
|
-
const result = await initializeOnboarding(mockRuntime, mockWorld, config);
|
|
631
|
-
|
|
632
|
-
expect(result).toEqual({});
|
|
633
|
-
expect(mockRuntime.updateWorld).toHaveBeenCalled();
|
|
634
|
-
});
|
|
635
|
-
});
|
|
636
|
-
|
|
637
|
-
describe('encryptedCharacter', () => {
|
|
638
|
-
it('should encrypt character settings.secrets', () => {
|
|
639
|
-
const character: Character = {
|
|
640
|
-
id: 'char-123' as any,
|
|
641
|
-
name: 'Test Character',
|
|
642
|
-
bio: 'Test character bio',
|
|
643
|
-
settings: {
|
|
644
|
-
secrets: {
|
|
645
|
-
API_KEY: 'secret-api-key',
|
|
646
|
-
PASSWORD: 'secret-password',
|
|
647
|
-
},
|
|
648
|
-
},
|
|
649
|
-
};
|
|
650
|
-
|
|
651
|
-
const encrypted = encryptedCharacter(character);
|
|
652
|
-
|
|
653
|
-
expect(encrypted.settings?.secrets?.['API_KEY']).not.toBe('secret-api-key');
|
|
654
|
-
expect(encrypted.settings?.secrets?.['API_KEY']).toContain(':');
|
|
655
|
-
expect(encrypted.settings?.secrets?.['PASSWORD']).not.toBe('secret-password');
|
|
656
|
-
expect(encrypted.settings?.secrets?.['PASSWORD']).toContain(':');
|
|
657
|
-
});
|
|
658
|
-
|
|
659
|
-
it('should encrypt character.secrets', () => {
|
|
660
|
-
const character: Character = {
|
|
661
|
-
id: 'char-123' as any,
|
|
662
|
-
name: 'Test Character',
|
|
663
|
-
bio: 'Test character bio',
|
|
664
|
-
secrets: {
|
|
665
|
-
TOKEN: 'secret-token',
|
|
666
|
-
KEY: 'secret-key',
|
|
667
|
-
},
|
|
668
|
-
};
|
|
669
|
-
|
|
670
|
-
const encrypted = encryptedCharacter(character);
|
|
671
|
-
|
|
672
|
-
expect(encrypted.secrets?.TOKEN).not.toBe('secret-token');
|
|
673
|
-
expect(encrypted.secrets?.TOKEN).toContain(':');
|
|
674
|
-
expect(encrypted.secrets?.KEY).not.toBe('secret-key');
|
|
675
|
-
expect(encrypted.secrets?.KEY).toContain(':');
|
|
676
|
-
});
|
|
677
|
-
|
|
678
|
-
it('should handle character without secrets', () => {
|
|
679
|
-
const character: Character = {
|
|
680
|
-
id: 'char-123' as any,
|
|
681
|
-
name: 'Test Character',
|
|
682
|
-
bio: 'Test character bio',
|
|
683
|
-
};
|
|
684
|
-
|
|
685
|
-
const encrypted = encryptedCharacter(character);
|
|
686
|
-
|
|
687
|
-
expect(encrypted).toEqual(character);
|
|
688
|
-
});
|
|
689
|
-
|
|
690
|
-
it('should not modify original character', () => {
|
|
691
|
-
const character: Character = {
|
|
692
|
-
id: 'char-123' as any,
|
|
693
|
-
name: 'Test Character',
|
|
694
|
-
bio: 'Test character bio',
|
|
695
|
-
secrets: {
|
|
696
|
-
TOKEN: 'secret-token',
|
|
697
|
-
},
|
|
698
|
-
};
|
|
699
|
-
|
|
700
|
-
const encrypted = encryptedCharacter(character);
|
|
701
|
-
|
|
702
|
-
expect(character.secrets?.TOKEN).toBe('secret-token');
|
|
703
|
-
expect(encrypted.secrets?.TOKEN).not.toBe('secret-token');
|
|
704
|
-
});
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
describe('decryptedCharacter', () => {
|
|
708
|
-
it('should decrypt character settings.secrets', () => {
|
|
709
|
-
const salt = getSalt();
|
|
710
|
-
const character: Character = {
|
|
711
|
-
id: 'char-123' as any,
|
|
712
|
-
name: 'Test Character',
|
|
713
|
-
bio: 'Test character bio',
|
|
714
|
-
settings: {
|
|
715
|
-
secrets: {
|
|
716
|
-
API_KEY: encryptStringValue('secret-api-key', salt),
|
|
717
|
-
PASSWORD: encryptStringValue('secret-password', salt),
|
|
718
|
-
},
|
|
719
|
-
},
|
|
720
|
-
};
|
|
721
|
-
|
|
722
|
-
const decrypted = decryptedCharacter(character, mockRuntime);
|
|
723
|
-
|
|
724
|
-
expect(decrypted.settings?.secrets?.['API_KEY']).toBe('secret-api-key');
|
|
725
|
-
expect(decrypted.settings?.secrets?.['PASSWORD']).toBe('secret-password');
|
|
726
|
-
});
|
|
727
|
-
|
|
728
|
-
it('should decrypt character.secrets', () => {
|
|
729
|
-
const salt = getSalt();
|
|
730
|
-
const character: Character = {
|
|
731
|
-
id: 'char-123' as any,
|
|
732
|
-
name: 'Test Character',
|
|
733
|
-
bio: 'Test character bio',
|
|
734
|
-
secrets: {
|
|
735
|
-
TOKEN: encryptStringValue('secret-token', salt),
|
|
736
|
-
KEY: encryptStringValue('secret-key', salt),
|
|
737
|
-
},
|
|
738
|
-
};
|
|
739
|
-
|
|
740
|
-
const decrypted = decryptedCharacter(character, mockRuntime);
|
|
741
|
-
|
|
742
|
-
expect(decrypted.secrets?.TOKEN).toBe('secret-token');
|
|
743
|
-
expect(decrypted.secrets?.KEY).toBe('secret-key');
|
|
744
|
-
});
|
|
745
|
-
|
|
746
|
-
it('should handle character without secrets', () => {
|
|
747
|
-
const character: Character = {
|
|
748
|
-
id: 'char-123' as any,
|
|
749
|
-
name: 'Test Character',
|
|
750
|
-
bio: 'Test character bio',
|
|
751
|
-
};
|
|
752
|
-
|
|
753
|
-
const decrypted = decryptedCharacter(character, mockRuntime);
|
|
754
|
-
|
|
755
|
-
expect(decrypted).toEqual(character);
|
|
756
|
-
});
|
|
757
|
-
});
|
|
758
|
-
|
|
759
|
-
describe('encryptObjectValues', () => {
|
|
760
|
-
const salt = 'test-salt';
|
|
761
|
-
|
|
762
|
-
it('should encrypt all string values in object', () => {
|
|
763
|
-
const obj = {
|
|
764
|
-
key1: 'value1',
|
|
765
|
-
key2: 'value2',
|
|
766
|
-
key3: 123,
|
|
767
|
-
key4: true,
|
|
768
|
-
key5: null,
|
|
769
|
-
key6: '',
|
|
770
|
-
};
|
|
771
|
-
|
|
772
|
-
const encrypted = encryptObjectValues(obj, salt);
|
|
773
|
-
|
|
774
|
-
expect(encrypted.key1).not.toBe('value1');
|
|
775
|
-
expect(encrypted.key1).toContain(':');
|
|
776
|
-
expect(encrypted.key2).not.toBe('value2');
|
|
777
|
-
expect(encrypted.key2).toContain(':');
|
|
778
|
-
expect(encrypted.key3).toBe(123);
|
|
779
|
-
expect(encrypted.key4).toBe(true);
|
|
780
|
-
expect(encrypted.key5).toBeNull();
|
|
781
|
-
expect(encrypted.key6).toBe(''); // Empty strings are not encrypted
|
|
782
|
-
});
|
|
783
|
-
});
|
|
784
|
-
|
|
785
|
-
describe('decryptObjectValues', () => {
|
|
786
|
-
const salt = 'test-salt';
|
|
787
|
-
|
|
788
|
-
it('should decrypt all string values in object', () => {
|
|
789
|
-
const obj = {
|
|
790
|
-
key1: encryptStringValue('value1', salt),
|
|
791
|
-
key2: encryptStringValue('value2', salt),
|
|
792
|
-
key3: 123,
|
|
793
|
-
key4: true,
|
|
794
|
-
};
|
|
795
|
-
|
|
796
|
-
const decrypted = decryptObjectValues(obj, salt);
|
|
797
|
-
|
|
798
|
-
expect(decrypted.key1).toBe('value1');
|
|
799
|
-
expect(decrypted.key2).toBe('value2');
|
|
800
|
-
expect(decrypted.key3).toBe(123);
|
|
801
|
-
expect(decrypted.key4).toBe(true);
|
|
802
|
-
});
|
|
803
|
-
});
|
|
804
|
-
|
|
805
|
-
describe('decryptSecret alias', () => {
|
|
806
|
-
it('should be an alias for decryptStringValue', () => {
|
|
807
|
-
expect(decryptSecret).toBe(decryptStringValue);
|
|
808
|
-
});
|
|
809
|
-
});
|
|
810
|
-
});
|