librechat-data-provider 0.8.402 → 0.8.404

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 (109) hide show
  1. package/dist/index.es.js +1 -1
  2. package/dist/index.es.js.map +1 -1
  3. package/dist/index.js +1 -1
  4. package/dist/index.js.map +1 -1
  5. package/dist/react-query/index.es.js +1 -1
  6. package/dist/react-query/index.es.js.map +1 -1
  7. package/dist/types/accessPermissions.d.ts +744 -0
  8. package/dist/types/actions.d.ts +118 -0
  9. package/dist/types/api-endpoints.d.ts +150 -0
  10. package/dist/types/artifacts.d.ts +97 -0
  11. package/dist/types/azure.d.ts +22 -0
  12. package/dist/types/bedrock.d.ts +1220 -0
  13. package/dist/types/config.d.ts +14849 -0
  14. package/dist/types/config.spec.d.ts +1 -0
  15. package/dist/types/createPayload.d.ts +5 -0
  16. package/dist/types/data-service.d.ts +287 -0
  17. package/dist/types/feedback.d.ts +36 -0
  18. package/dist/types/file-config.d.ts +263 -0
  19. package/dist/types/file-config.spec.d.ts +1 -0
  20. package/dist/types/generate.d.ts +597 -0
  21. package/dist/types/headers-helpers.d.ts +2 -0
  22. package/{src/index.ts → dist/types/index.d.ts} +0 -15
  23. package/dist/types/keys.d.ts +92 -0
  24. package/dist/types/mcp.d.ts +2760 -0
  25. package/dist/types/messages.d.ts +10 -0
  26. package/dist/types/models.d.ts +1547 -0
  27. package/dist/types/parameterSettings.d.ts +69 -0
  28. package/dist/types/parsers.d.ts +110 -0
  29. package/dist/types/permissions.d.ts +522 -0
  30. package/dist/types/react-query/react-query-service.d.ts +85 -0
  31. package/dist/types/request.d.ts +25 -0
  32. package/dist/types/roles.d.ts +554 -0
  33. package/dist/types/roles.spec.d.ts +1 -0
  34. package/dist/types/schemas.d.ts +5110 -0
  35. package/dist/types/schemas.spec.d.ts +1 -0
  36. package/dist/types/types/agents.d.ts +433 -0
  37. package/dist/types/types/assistants.d.ts +547 -0
  38. package/dist/types/types/files.d.ts +172 -0
  39. package/dist/types/types/graph.d.ts +135 -0
  40. package/{src/types/mcpServers.ts → dist/types/types/mcpServers.d.ts} +12 -18
  41. package/dist/types/types/mutations.d.ts +209 -0
  42. package/dist/types/types/queries.d.ts +169 -0
  43. package/dist/types/types/runs.d.ts +36 -0
  44. package/dist/types/types/web.d.ts +520 -0
  45. package/dist/types/types.d.ts +503 -0
  46. package/dist/types/utils.d.ts +12 -0
  47. package/package.json +5 -1
  48. package/babel.config.js +0 -4
  49. package/check_updates.sh +0 -52
  50. package/jest.config.js +0 -19
  51. package/react-query/package-lock.json +0 -292
  52. package/react-query/package.json +0 -10
  53. package/rollup.config.js +0 -74
  54. package/server-rollup.config.js +0 -40
  55. package/specs/actions.spec.ts +0 -2533
  56. package/specs/api-endpoints-subdir.spec.ts +0 -140
  57. package/specs/api-endpoints.spec.ts +0 -74
  58. package/specs/azure.spec.ts +0 -844
  59. package/specs/bedrock.spec.ts +0 -862
  60. package/specs/filetypes.spec.ts +0 -175
  61. package/specs/generate.spec.ts +0 -770
  62. package/specs/headers-helpers.spec.ts +0 -24
  63. package/specs/mcp.spec.ts +0 -147
  64. package/specs/openapiSpecs.ts +0 -524
  65. package/specs/parsers.spec.ts +0 -601
  66. package/specs/request-interceptor.spec.ts +0 -304
  67. package/specs/utils.spec.ts +0 -196
  68. package/src/accessPermissions.ts +0 -346
  69. package/src/actions.ts +0 -813
  70. package/src/api-endpoints.ts +0 -440
  71. package/src/artifacts.ts +0 -3104
  72. package/src/azure.ts +0 -328
  73. package/src/bedrock.ts +0 -425
  74. package/src/config.spec.ts +0 -315
  75. package/src/config.ts +0 -2006
  76. package/src/createPayload.ts +0 -46
  77. package/src/data-service.ts +0 -1087
  78. package/src/feedback.ts +0 -141
  79. package/src/file-config.spec.ts +0 -1248
  80. package/src/file-config.ts +0 -764
  81. package/src/generate.ts +0 -634
  82. package/src/headers-helpers.ts +0 -13
  83. package/src/keys.ts +0 -99
  84. package/src/mcp.ts +0 -271
  85. package/src/messages.ts +0 -50
  86. package/src/models.ts +0 -69
  87. package/src/parameterSettings.ts +0 -1111
  88. package/src/parsers.ts +0 -563
  89. package/src/permissions.ts +0 -188
  90. package/src/react-query/react-query-service.ts +0 -566
  91. package/src/request.ts +0 -171
  92. package/src/roles.spec.ts +0 -132
  93. package/src/roles.ts +0 -225
  94. package/src/schemas.spec.ts +0 -355
  95. package/src/schemas.ts +0 -1234
  96. package/src/types/agents.ts +0 -470
  97. package/src/types/assistants.ts +0 -654
  98. package/src/types/files.ts +0 -191
  99. package/src/types/graph.ts +0 -145
  100. package/src/types/mutations.ts +0 -422
  101. package/src/types/queries.ts +0 -208
  102. package/src/types/runs.ts +0 -40
  103. package/src/types/web.ts +0 -588
  104. package/src/types.ts +0 -676
  105. package/src/utils.ts +0 -85
  106. package/tsconfig.json +0 -28
  107. package/tsconfig.spec.json +0 -10
  108. /package/{src/react-query/index.ts → dist/types/react-query/index.d.ts} +0 -0
  109. /package/{src/types/index.ts → dist/types/types/index.d.ts} +0 -0
@@ -1,770 +0,0 @@
1
- import { ZodError, z } from 'zod';
2
- import { generateDynamicSchema, validateSettingDefinitions, OptionTypes } from '../src/generate';
3
- import type { SettingsConfiguration } from '../src/generate';
4
-
5
- describe('generateDynamicSchema', () => {
6
- it('should generate a schema for number settings with range', () => {
7
- const settings: SettingsConfiguration = [
8
- {
9
- key: 'testNumber',
10
- description: 'A test number setting',
11
- type: 'number',
12
- default: 5,
13
- range: { min: 1, max: 10, step: 1 },
14
- component: 'slider',
15
- optionType: 'conversation',
16
- columnSpan: 2,
17
- label: 'Test Number Slider',
18
- },
19
- ];
20
-
21
- const schema = generateDynamicSchema(settings);
22
- const result = schema.safeParse({ testNumber: 6 });
23
-
24
- expect(result.success).toBeTruthy();
25
- expect(result['data']).toEqual({ testNumber: 6 });
26
- });
27
-
28
- it('should generate a schema for boolean settings', () => {
29
- const settings: SettingsConfiguration = [
30
- {
31
- key: 'testBoolean',
32
- description: 'A test boolean setting',
33
- type: 'boolean',
34
- default: true,
35
- component: 'switch',
36
- optionType: 'model', // Only if relevant to your application's context
37
- columnSpan: 1,
38
- label: 'Test Boolean Switch',
39
- },
40
- ];
41
-
42
- const schema = generateDynamicSchema(settings);
43
- const result = schema.safeParse({ testBoolean: false });
44
-
45
- expect(result.success).toBeTruthy();
46
- expect(result['data']).toEqual({ testBoolean: false });
47
- });
48
-
49
- it('should generate a schema for string settings', () => {
50
- const settings: SettingsConfiguration = [
51
- {
52
- key: 'testString',
53
- description: 'A test string setting',
54
- type: 'string',
55
- default: 'default value',
56
- component: 'input',
57
- optionType: 'model', // Optional and only if relevant
58
- columnSpan: 3,
59
- label: 'Test String Input',
60
- placeholder: 'Enter text here...',
61
- minText: 0, // Optional
62
- maxText: 100, // Optional
63
- },
64
- ];
65
-
66
- const schema = generateDynamicSchema(settings);
67
- const result = schema.safeParse({ testString: 'custom value' });
68
-
69
- expect(result.success).toBeTruthy();
70
- expect(result['data']).toEqual({ testString: 'custom value' });
71
- });
72
-
73
- it('should generate a schema for enum settings', () => {
74
- const settings: SettingsConfiguration = [
75
- {
76
- key: 'testEnum',
77
- description: 'A test enum setting',
78
- type: 'enum',
79
- default: 'option1',
80
- options: ['option1', 'option2', 'option3'],
81
- enumMappings: {
82
- option1: 'First Option',
83
- option2: 'Second Option',
84
- option3: 'Third Option',
85
- },
86
- component: 'dropdown',
87
- columnSpan: 2,
88
- label: 'Test Enum Dropdown',
89
- },
90
- ];
91
-
92
- const schema = generateDynamicSchema(settings);
93
- const result = schema.safeParse({ testEnum: 'option2' });
94
-
95
- expect(result.success).toBeTruthy();
96
- expect(result['data']).toEqual({ testEnum: 'option2' });
97
- });
98
-
99
- it('should generate a schema for enum settings with empty string option', () => {
100
- const settings: SettingsConfiguration = [
101
- {
102
- key: 'testEnumWithEmpty',
103
- description: 'A test enum setting with empty string',
104
- type: 'enum',
105
- default: '',
106
- options: ['', 'option1', 'option2'],
107
- enumMappings: {
108
- '': 'None',
109
- option1: 'First Option',
110
- option2: 'Second Option',
111
- },
112
- component: 'slider',
113
- columnSpan: 2,
114
- label: 'Test Enum with Empty String',
115
- },
116
- ];
117
-
118
- const schema = generateDynamicSchema(settings);
119
- const result = schema.safeParse({ testEnumWithEmpty: '' });
120
-
121
- expect(result.success).toBeTruthy();
122
- expect(result['data']).toEqual({ testEnumWithEmpty: '' });
123
-
124
- // Test with non-empty option
125
- const result2 = schema.safeParse({ testEnumWithEmpty: 'option1' });
126
- expect(result2.success).toBeTruthy();
127
- expect(result2['data']).toEqual({ testEnumWithEmpty: 'option1' });
128
- });
129
-
130
- it('should fail for incorrect enum value', () => {
131
- const settings: SettingsConfiguration = [
132
- {
133
- key: 'testEnum',
134
- description: 'A test enum setting',
135
- type: 'enum',
136
- default: 'option1',
137
- options: ['option1', 'option2', 'option3'],
138
- component: 'dropdown',
139
- },
140
- ];
141
-
142
- const schema = generateDynamicSchema(settings);
143
- const result = schema.safeParse({ testEnum: 'option4' }); // This option does not exist
144
-
145
- expect(result.success).toBeFalsy();
146
- });
147
-
148
- it('should generate a schema for array settings', () => {
149
- const settings: SettingsConfiguration = [
150
- {
151
- key: 'testArray',
152
- description: 'A test array setting',
153
- type: 'array',
154
- default: ['default', 'values'],
155
- component: 'tags', // Assuming 'tags' imply an array of strings
156
- optionType: OptionTypes.Custom,
157
- columnSpan: 3,
158
- label: 'Test Array Tags',
159
- minTags: 1, // Minimum number of tags
160
- maxTags: 5, // Maximum number of tags
161
- },
162
- ];
163
-
164
- const schema = generateDynamicSchema(settings);
165
- // Testing with right number of tags
166
- let result = schema.safeParse({ testArray: ['value1', 'value2', 'value3'] });
167
-
168
- expect(result.success).toBeTruthy();
169
- expect(result?.['data']).toEqual({ testArray: ['value1', 'value2', 'value3'] });
170
-
171
- // Testing with too few tags (should fail)
172
- result = schema.safeParse({ testArray: [] }); // Assuming minTags is 1, empty array should fail
173
- expect(result.success).toBeFalsy();
174
- if (!result.success) {
175
- // Additional check to ensure the failure is because of the minTags condition
176
- const issues = result.error.issues.filter(
177
- (issue) => issue.path.includes('testArray') && issue.code === 'too_small',
178
- );
179
- expect(issues.length).toBeGreaterThan(0); // Ensure there is at least one issue related to 'testArray' being too small
180
- }
181
-
182
- // Testing with too many tags (should fail)
183
- result = schema.safeParse({
184
- testArray: ['value1', 'value2', 'value3', 'value4', 'value5', 'value6'],
185
- }); // Assuming maxTags is 5, this should fail
186
- expect(result.success).toBeFalsy();
187
- if (!result.success) {
188
- // Additional check to ensure the failure is because of the maxTags condition
189
- const issues = result.error.issues.filter(
190
- (issue) => issue.path.includes('testArray') && issue.code === 'too_big',
191
- );
192
- expect(issues.length).toBeGreaterThan(0); // Ensure there is at least one issue related to 'testArray' being too big
193
- }
194
- });
195
- });
196
-
197
- describe('validateSettingDefinitions', () => {
198
- test('should throw error for Conversation optionType', () => {
199
- const validSettings: SettingsConfiguration = [
200
- {
201
- key: 'themeColor',
202
- component: 'input',
203
- type: 'string',
204
- default: '#ffffff',
205
- label: 'Theme Color',
206
- columns: 2,
207
- columnSpan: 1,
208
- optionType: OptionTypes.Conversation,
209
- },
210
- ];
211
-
212
- expect(() => validateSettingDefinitions(validSettings)).toThrow();
213
- });
214
-
215
- test('should throw error for Model optionType', () => {
216
- const validSettings: SettingsConfiguration = [
217
- {
218
- key: 'themeColor',
219
- component: 'input',
220
- type: 'string',
221
- default: '#ffffff',
222
- label: 'Theme Color',
223
- columns: 2,
224
- columnSpan: 1,
225
- optionType: OptionTypes.Model,
226
- },
227
- ];
228
-
229
- expect(() => validateSettingDefinitions(validSettings)).toThrow();
230
- });
231
-
232
- test('should not throw error for valid settings', () => {
233
- const validSettings: SettingsConfiguration = [
234
- {
235
- key: 'themeColor',
236
- component: 'input',
237
- type: 'string',
238
- default: '#ffffff',
239
- label: 'Theme Color',
240
- columns: 2,
241
- columnSpan: 1,
242
- optionType: OptionTypes.Custom,
243
- },
244
- {
245
- key: 'fontSize',
246
- component: 'slider',
247
- type: 'number',
248
- range: { min: 8, max: 36 },
249
- default: 14,
250
- columnSpan: 2,
251
- optionType: OptionTypes.Custom,
252
- },
253
- ];
254
-
255
- expect(() => validateSettingDefinitions(validSettings)).not.toThrow();
256
- });
257
-
258
- // Test for incorrectly configured columns
259
- test('should throw error for invalid columns configuration', () => {
260
- const invalidSettings: SettingsConfiguration = [
261
- {
262
- key: 'themeColor',
263
- component: 'input',
264
- type: 'string',
265
- columns: 5,
266
- },
267
- ];
268
-
269
- expect(() => validateSettingDefinitions(invalidSettings)).toThrow(ZodError);
270
- });
271
-
272
- test('should correctly handle columnSpan defaulting based on columns', () => {
273
- const settingsWithColumnAdjustment: SettingsConfiguration = [
274
- {
275
- key: 'fontSize',
276
- component: 'slider',
277
- type: 'number',
278
- columns: 4,
279
- range: { min: 8, max: 14 },
280
- default: 11,
281
- optionType: OptionTypes.Custom,
282
- },
283
- ];
284
-
285
- expect(() => validateSettingDefinitions(settingsWithColumnAdjustment)).not.toThrow();
286
- });
287
-
288
- // Test for label defaulting to key if not provided
289
- test('label should default to key if not explicitly set', () => {
290
- const settingsWithDefaultLabel: SettingsConfiguration = [
291
- {
292
- key: 'fontWeight',
293
- component: 'dropdown',
294
- type: 'string',
295
- options: ['normal', 'bold'],
296
- optionType: OptionTypes.Custom,
297
- },
298
- ];
299
-
300
- expect(() => validateSettingDefinitions(settingsWithDefaultLabel)).not.toThrow();
301
- expect(settingsWithDefaultLabel[0].label).toBe('fontWeight');
302
- });
303
-
304
- // Test for minText and maxText in input/textarea component
305
- test('should throw error for negative minText or maxText', () => {
306
- const settingsWithNegativeTextLimits: SettingsConfiguration = [
307
- { key: 'biography', component: 'textarea', type: 'string', minText: -1 },
308
- ];
309
-
310
- expect(() => validateSettingDefinitions(settingsWithNegativeTextLimits)).toThrow(ZodError);
311
- });
312
-
313
- // Validate optionType with tConversationSchema
314
- test('should throw error for optionType "conversation" not matching schema', () => {
315
- const settingsWithInvalidConversationOptionType: SettingsConfiguration = [
316
- { key: 'userAge', component: 'input', type: 'number', optionType: 'conversation' },
317
- ];
318
-
319
- expect(() => validateSettingDefinitions(settingsWithInvalidConversationOptionType)).toThrow(
320
- ZodError,
321
- );
322
- });
323
-
324
- // Test for columnSpan defaulting and label defaulting to key
325
- test('columnSpan defaults based on columns and label defaults to key if not set', () => {
326
- const settings: SettingsConfiguration = [
327
- {
328
- key: 'textSize',
329
- type: 'number',
330
- component: 'slider',
331
- range: { min: 10, max: 20 },
332
- columns: 4,
333
- optionType: OptionTypes.Custom,
334
- },
335
- ];
336
-
337
- validateSettingDefinitions(settings); // Perform validation which also mutates settings with default values
338
-
339
- expect(settings[0].columnSpan).toBe(2); // Expects columnSpan to default based on columns
340
- expect(settings[0].label).toBe('textSize'); // Expects label to default to key
341
- });
342
-
343
- // Test for errors thrown due to invalid columns value
344
- test('throws error if columns value is out of range', () => {
345
- const settings: SettingsConfiguration = [
346
- {
347
- key: 'themeMode',
348
- type: 'string',
349
- component: 'dropdown',
350
- options: ['dark', 'light'],
351
- columns: 5,
352
- },
353
- ];
354
-
355
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
356
- });
357
-
358
- // Test range validation for slider component
359
- test('slider component range validation', () => {
360
- const settings: SettingsConfiguration = [
361
- { key: 'volume', type: 'number', component: 'slider' }, // Missing range
362
- ];
363
-
364
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
365
- });
366
-
367
- // Test options validation for enum type in slider component
368
- test('slider component with enum type requires at least 2 options', () => {
369
- const settings: SettingsConfiguration = [
370
- { key: 'color', type: 'enum', component: 'slider', options: ['red'] }, // Not enough options
371
- ];
372
-
373
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
374
- });
375
-
376
- // Test checkbox component options validation
377
- test('checkbox component must have 1-2 options if options are provided', () => {
378
- const settings: SettingsConfiguration = [
379
- {
380
- key: 'agreeToTerms',
381
- type: 'boolean',
382
- component: 'checkbox',
383
- options: ['Yes', 'No', 'Maybe'],
384
- }, // Too many options
385
- ];
386
-
387
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
388
- });
389
-
390
- // Test dropdown component options validation
391
- test('dropdown component requires at least 2 options', () => {
392
- const settings: SettingsConfiguration = [
393
- { key: 'country', type: 'enum', component: 'dropdown', options: ['USA'] }, // Not enough options
394
- ];
395
-
396
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
397
- });
398
-
399
- // Validate minText and maxText constraints in input and textarea
400
- test('validate minText and maxText constraints', () => {
401
- const settings: SettingsConfiguration = [
402
- { key: 'biography', type: 'string', component: 'textarea', minText: 10, maxText: 5 }, // Incorrect minText and maxText
403
- ];
404
-
405
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
406
- });
407
-
408
- // Validate optionType constraint with tConversationSchema
409
- test('validate optionType constraint with tConversationSchema', () => {
410
- const settings: SettingsConfiguration = [
411
- { key: 'userAge', type: 'number', component: 'input', optionType: 'conversation' }, // No corresponding schema in tConversationSchema
412
- ];
413
-
414
- expect(() => validateSettingDefinitions(settings)).toThrow(ZodError);
415
- });
416
-
417
- // Validate correct handling of boolean settings with default values
418
- test('correct handling of boolean settings with defaults', () => {
419
- const settings: SettingsConfiguration = [
420
- {
421
- key: 'enableFeatureX',
422
- type: 'boolean',
423
- component: 'switch',
424
- optionType: OptionTypes.Custom,
425
- }, // Missing default, should default to false
426
- ];
427
-
428
- validateSettingDefinitions(settings); // This would populate default values where missing
429
-
430
- expect(settings[0].default).toBe(false); // Expects default to be false for boolean without explicit default
431
- });
432
-
433
- // Validate that number slider without default uses middle of range
434
- test('number slider without default uses middle of range', () => {
435
- const settings: SettingsConfiguration = [
436
- {
437
- key: 'brightness',
438
- type: 'number',
439
- component: 'slider',
440
- range: { min: 0, max: 100 },
441
- optionType: OptionTypes.Custom,
442
- }, // Missing default
443
- ];
444
-
445
- validateSettingDefinitions(settings); // This would populate default values where missing
446
-
447
- expect(settings[0].default).toBe(50); // Expects default to be midpoint of range
448
- });
449
-
450
- // Test for validating minTags and maxTags constraints
451
- test('should validate minTags and maxTags constraints', () => {
452
- const settingsWithTagsConstraints: SettingsConfiguration = [
453
- {
454
- key: 'selectedTags',
455
- component: 'tags',
456
- type: 'array',
457
- default: ['tag1'], // Only one tag by default
458
- minTags: 2, // Requires at least 2 tags, which should cause validation to fail
459
- maxTags: 4,
460
- optionType: OptionTypes.Custom,
461
- },
462
- ];
463
-
464
- expect(() => validateSettingDefinitions(settingsWithTagsConstraints)).toThrow(ZodError);
465
- });
466
-
467
- // Test for ensuring default values for tags are arrays
468
- test('should ensure default values for tags are arrays', () => {
469
- const settingsWithInvalidDefaultForTags: SettingsConfiguration = [
470
- {
471
- key: 'favoriteTags',
472
- component: 'tags',
473
- type: 'array',
474
- default: 'notAnArray', // Incorrect default type
475
- optionType: OptionTypes.Custom,
476
- },
477
- ];
478
-
479
- expect(() => validateSettingDefinitions(settingsWithInvalidDefaultForTags)).toThrow(ZodError);
480
- });
481
-
482
- // Test for array settings without default values should not throw if constraints are satisfied
483
- test('array settings without defaults should not throw if constraints are met', () => {
484
- const settingsWithNoDefaultButValidTags: SettingsConfiguration = [
485
- {
486
- key: 'userTags',
487
- component: 'tags',
488
- type: 'array',
489
- minTags: 1, // Requires at least 1 tag
490
- maxTags: 5, // Allows up to 5 tags
491
- optionType: OptionTypes.Custom,
492
- },
493
- ];
494
-
495
- // No default is set, but since the constraints are potentially met (depends on user input), this should not throw
496
- expect(() => validateSettingDefinitions(settingsWithNoDefaultButValidTags)).not.toThrow();
497
- });
498
-
499
- // Test for ensuring maxTags is respected in default array values
500
- test('should ensure maxTags is respected for default array values', () => {
501
- const settingsExceedingMaxTags: SettingsConfiguration = [
502
- {
503
- key: 'interestTags',
504
- component: 'tags',
505
- type: 'array',
506
- default: ['music', 'movies', 'books', 'travel', 'cooking', 'sports'], // 6 tags
507
- maxTags: 5, // Exceeds the maxTags limit
508
- optionType: OptionTypes.Custom,
509
- },
510
- ];
511
-
512
- expect(() => validateSettingDefinitions(settingsExceedingMaxTags)).toThrow(ZodError);
513
- });
514
-
515
- // Test for incomplete enumMappings
516
- test('should throw error for incomplete enumMappings', () => {
517
- const settingsWithIncompleteEnumMappings: SettingsConfiguration = [
518
- {
519
- key: 'displayMode',
520
- type: 'enum',
521
- component: 'dropdown',
522
- options: ['light', 'dark', 'auto'],
523
- enumMappings: {
524
- light: 'Light Mode',
525
- dark: 'Dark Mode',
526
- // Missing mapping for 'auto'
527
- },
528
- optionType: OptionTypes.Custom,
529
- },
530
- ];
531
-
532
- expect(() => validateSettingDefinitions(settingsWithIncompleteEnumMappings)).toThrow(ZodError);
533
- });
534
-
535
- // Test for complete enumMappings including empty string
536
- test('should not throw error for complete enumMappings including empty string', () => {
537
- const settingsWithCompleteEnumMappings: SettingsConfiguration = [
538
- {
539
- key: 'selectionMode',
540
- type: 'enum',
541
- component: 'slider',
542
- options: ['', 'single', 'multiple'],
543
- enumMappings: {
544
- '': 'None',
545
- single: 'Single Selection',
546
- multiple: 'Multiple Selection',
547
- },
548
- default: '',
549
- optionType: OptionTypes.Custom,
550
- },
551
- ];
552
-
553
- expect(() => validateSettingDefinitions(settingsWithCompleteEnumMappings)).not.toThrow();
554
- });
555
- });
556
-
557
- const settingsConfiguration: SettingsConfiguration = [
558
- {
559
- key: 'temperature',
560
- description:
561
- 'Higher values = more random, while lower values = more focused and deterministic. We recommend altering this or Top P but not both.',
562
- type: 'number',
563
- default: 1,
564
- range: {
565
- min: 0,
566
- max: 2,
567
- step: 0.01,
568
- },
569
- component: 'slider',
570
- optionType: OptionTypes.Custom,
571
- },
572
- {
573
- key: 'top_p',
574
- description:
575
- 'An alternative to sampling with temperature, called nucleus sampling, where the model considers the results of the tokens with top_p probability mass. So 0.1 means only the tokens comprising the top 10% probability mass are considered. We recommend altering this or temperature but not both.',
576
- type: 'number',
577
- default: 1,
578
- range: {
579
- min: 0,
580
- max: 1,
581
- step: 0.01,
582
- },
583
- component: 'slider',
584
- optionType: OptionTypes.Custom,
585
- },
586
- {
587
- key: 'presence_penalty',
588
- description:
589
- "Number between -2.0 and 2.0. Positive values penalize new tokens based on whether they appear in the text so far, increasing the model's likelihood to talk about new topics.",
590
- type: 'number',
591
- default: 0,
592
- range: {
593
- min: -2,
594
- max: 2,
595
- step: 0.01,
596
- },
597
- component: 'slider',
598
- optionType: OptionTypes.Custom,
599
- },
600
- {
601
- key: 'frequency_penalty',
602
- description:
603
- "Number between -2.0 and 2.0. Positive values penalize new tokens based on their existing frequency in the text so far, decreasing the model's likelihood to repeat the same line verbatim.",
604
- type: 'number',
605
- default: 0,
606
- range: {
607
- min: -2,
608
- max: 2,
609
- step: 0.01,
610
- },
611
- component: 'slider',
612
- optionType: OptionTypes.Custom,
613
- },
614
- {
615
- key: 'resendFiles',
616
- description:
617
- 'Resend all previously attached files. Note: this will increase token cost and you may experience errors with many attachments.',
618
- type: 'boolean',
619
- default: true,
620
- component: 'switch',
621
- optionType: OptionTypes.Custom,
622
- },
623
- {
624
- key: 'imageDetail',
625
- description:
626
- 'The resolution for Vision requests. "Low" is cheaper and faster, "High" is more detailed and expensive, and "Auto" will automatically choose between the two based on the image resolution.',
627
- type: 'enum',
628
- default: 'auto',
629
- options: ['low', 'high', 'auto'],
630
- component: 'slider',
631
- optionType: OptionTypes.Custom,
632
- },
633
- {
634
- key: 'promptPrefix',
635
- type: 'string',
636
- default: '',
637
- component: 'input',
638
- optionType: OptionTypes.Custom,
639
- placeholder: 'Set custom instructions to include in System Message. Default: none',
640
- },
641
- {
642
- key: 'chatGptLabel',
643
- type: 'string',
644
- default: '',
645
- component: 'input',
646
- optionType: OptionTypes.Custom,
647
- placeholder: 'Set a custom name for your AI',
648
- },
649
- ];
650
-
651
- describe('Settings Validation and Schema Generation', () => {
652
- // Test 1: Validate settings definitions do not throw for valid configuration
653
- test('validateSettingDefinitions does not throw for valid configuration', () => {
654
- expect(() => validateSettingDefinitions(settingsConfiguration)).not.toThrow();
655
- });
656
-
657
- test('validateSettingDefinitions throws for invalid type in settings', () => {
658
- const settingsWithInvalidType = [
659
- ...settingsConfiguration,
660
- {
661
- key: 'newSetting',
662
- description: 'A setting with an unsupported type',
663
- type: 'unsupportedType', // Assuming 'unsupportedType' is not supported
664
- component: 'input',
665
- },
666
- ];
667
-
668
- expect(() =>
669
- validateSettingDefinitions(settingsWithInvalidType as SettingsConfiguration),
670
- ).toThrow();
671
- });
672
-
673
- test('validateSettingDefinitions throws for missing required fields', () => {
674
- const settingsMissingRequiredField = [
675
- ...settingsConfiguration,
676
- {
677
- key: 'incompleteSetting',
678
- type: 'number',
679
- // Missing 'component',
680
- },
681
- ];
682
-
683
- expect(() =>
684
- validateSettingDefinitions(settingsMissingRequiredField as SettingsConfiguration),
685
- ).toThrow();
686
- });
687
-
688
- test('validateSettingDefinitions throws for default value out of range', () => {
689
- const settingsOutOfRange = [
690
- ...settingsConfiguration,
691
- {
692
- key: 'rangeTestSetting',
693
- description: 'A setting with default value out of specified range',
694
- type: 'number',
695
- default: 5,
696
- range: {
697
- min: 0,
698
- max: 1,
699
- },
700
- component: 'slider',
701
- },
702
- ];
703
-
704
- expect(() => validateSettingDefinitions(settingsOutOfRange as SettingsConfiguration)).toThrow();
705
- });
706
-
707
- test('validateSettingDefinitions throws for enum setting with incorrect default', () => {
708
- const settingsWithIncorrectEnumDefault = [
709
- ...settingsConfiguration,
710
- {
711
- key: 'enumSetting',
712
- description: 'Enum setting with a default not in options',
713
- type: 'enum',
714
- default: 'unlistedOption',
715
- options: ['option1', 'option2'],
716
- component: 'dropdown',
717
- },
718
- ];
719
-
720
- expect(() =>
721
- validateSettingDefinitions(settingsWithIncorrectEnumDefault as SettingsConfiguration),
722
- ).toThrow();
723
- });
724
-
725
- // Test 2: Generate dynamic schema and validate correct input
726
- test('generateDynamicSchema generates a schema that validates correct input', () => {
727
- const schema = generateDynamicSchema(settingsConfiguration);
728
- const validInput = {
729
- temperature: 0.5,
730
- top_p: 0.8,
731
- presence_penalty: 1,
732
- frequency_penalty: -1,
733
- resendFiles: true,
734
- imageDetail: 'high',
735
- promptPrefix: 'Hello, AI.',
736
- chatGptLabel: 'My Custom AI',
737
- };
738
-
739
- expect(schema.parse(validInput)).toEqual(validInput);
740
- });
741
-
742
- // Test 3: Generate dynamic schema and catch invalid input
743
- test('generateDynamicSchema generates a schema that catches invalid input and provides detailed errors', async () => {
744
- const schema = generateDynamicSchema(settingsConfiguration);
745
- const invalidInput: z.infer<typeof schema> = {
746
- temperature: 2.5, // Out of range
747
- top_p: -0.5, // Out of range
748
- presence_penalty: 3, // Out of range
749
- frequency_penalty: -3, // Out of range
750
- resendFiles: 'yes', // Wrong type
751
- imageDetail: 'ultra', // Invalid option
752
- promptPrefix: 123, // Wrong type
753
- chatGptLabel: true, // Wrong type
754
- };
755
-
756
- const result = schema.safeParse(invalidInput);
757
- expect(result.success).toBeFalsy();
758
- if (!result.success) {
759
- const errorPaths = result.error.issues.map((issue) => issue.path.join('.'));
760
- expect(errorPaths).toContain('temperature');
761
- expect(errorPaths).toContain('top_p');
762
- expect(errorPaths).toContain('presence_penalty');
763
- expect(errorPaths).toContain('frequency_penalty');
764
- expect(errorPaths).toContain('resendFiles');
765
- expect(errorPaths).toContain('imageDetail');
766
- expect(errorPaths).toContain('promptPrefix');
767
- expect(errorPaths).toContain('chatGptLabel');
768
- }
769
- });
770
- });