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.
- package/dist/index.es.js +1 -1
- package/dist/index.es.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/react-query/index.es.js +1 -1
- package/dist/react-query/index.es.js.map +1 -1
- package/dist/types/accessPermissions.d.ts +744 -0
- package/dist/types/actions.d.ts +118 -0
- package/dist/types/api-endpoints.d.ts +150 -0
- package/dist/types/artifacts.d.ts +97 -0
- package/dist/types/azure.d.ts +22 -0
- package/dist/types/bedrock.d.ts +1220 -0
- package/dist/types/config.d.ts +14849 -0
- package/dist/types/config.spec.d.ts +1 -0
- package/dist/types/createPayload.d.ts +5 -0
- package/dist/types/data-service.d.ts +287 -0
- package/dist/types/feedback.d.ts +36 -0
- package/dist/types/file-config.d.ts +263 -0
- package/dist/types/file-config.spec.d.ts +1 -0
- package/dist/types/generate.d.ts +597 -0
- package/dist/types/headers-helpers.d.ts +2 -0
- package/{src/index.ts → dist/types/index.d.ts} +0 -15
- package/dist/types/keys.d.ts +92 -0
- package/dist/types/mcp.d.ts +2760 -0
- package/dist/types/messages.d.ts +10 -0
- package/dist/types/models.d.ts +1547 -0
- package/dist/types/parameterSettings.d.ts +69 -0
- package/dist/types/parsers.d.ts +110 -0
- package/dist/types/permissions.d.ts +522 -0
- package/dist/types/react-query/react-query-service.d.ts +85 -0
- package/dist/types/request.d.ts +25 -0
- package/dist/types/roles.d.ts +554 -0
- package/dist/types/roles.spec.d.ts +1 -0
- package/dist/types/schemas.d.ts +5110 -0
- package/dist/types/schemas.spec.d.ts +1 -0
- package/dist/types/types/agents.d.ts +433 -0
- package/dist/types/types/assistants.d.ts +547 -0
- package/dist/types/types/files.d.ts +172 -0
- package/dist/types/types/graph.d.ts +135 -0
- package/{src/types/mcpServers.ts → dist/types/types/mcpServers.d.ts} +12 -18
- package/dist/types/types/mutations.d.ts +209 -0
- package/dist/types/types/queries.d.ts +169 -0
- package/dist/types/types/runs.d.ts +36 -0
- package/dist/types/types/web.d.ts +520 -0
- package/dist/types/types.d.ts +503 -0
- package/dist/types/utils.d.ts +12 -0
- package/package.json +5 -1
- package/babel.config.js +0 -4
- package/check_updates.sh +0 -52
- package/jest.config.js +0 -19
- package/react-query/package-lock.json +0 -292
- package/react-query/package.json +0 -10
- package/rollup.config.js +0 -74
- package/server-rollup.config.js +0 -40
- package/specs/actions.spec.ts +0 -2533
- package/specs/api-endpoints-subdir.spec.ts +0 -140
- package/specs/api-endpoints.spec.ts +0 -74
- package/specs/azure.spec.ts +0 -844
- package/specs/bedrock.spec.ts +0 -862
- package/specs/filetypes.spec.ts +0 -175
- package/specs/generate.spec.ts +0 -770
- package/specs/headers-helpers.spec.ts +0 -24
- package/specs/mcp.spec.ts +0 -147
- package/specs/openapiSpecs.ts +0 -524
- package/specs/parsers.spec.ts +0 -601
- package/specs/request-interceptor.spec.ts +0 -304
- package/specs/utils.spec.ts +0 -196
- package/src/accessPermissions.ts +0 -346
- package/src/actions.ts +0 -813
- package/src/api-endpoints.ts +0 -440
- package/src/artifacts.ts +0 -3104
- package/src/azure.ts +0 -328
- package/src/bedrock.ts +0 -425
- package/src/config.spec.ts +0 -315
- package/src/config.ts +0 -2006
- package/src/createPayload.ts +0 -46
- package/src/data-service.ts +0 -1087
- package/src/feedback.ts +0 -141
- package/src/file-config.spec.ts +0 -1248
- package/src/file-config.ts +0 -764
- package/src/generate.ts +0 -634
- package/src/headers-helpers.ts +0 -13
- package/src/keys.ts +0 -99
- package/src/mcp.ts +0 -271
- package/src/messages.ts +0 -50
- package/src/models.ts +0 -69
- package/src/parameterSettings.ts +0 -1111
- package/src/parsers.ts +0 -563
- package/src/permissions.ts +0 -188
- package/src/react-query/react-query-service.ts +0 -566
- package/src/request.ts +0 -171
- package/src/roles.spec.ts +0 -132
- package/src/roles.ts +0 -225
- package/src/schemas.spec.ts +0 -355
- package/src/schemas.ts +0 -1234
- package/src/types/agents.ts +0 -470
- package/src/types/assistants.ts +0 -654
- package/src/types/files.ts +0 -191
- package/src/types/graph.ts +0 -145
- package/src/types/mutations.ts +0 -422
- package/src/types/queries.ts +0 -208
- package/src/types/runs.ts +0 -40
- package/src/types/web.ts +0 -588
- package/src/types.ts +0 -676
- package/src/utils.ts +0 -85
- package/tsconfig.json +0 -28
- package/tsconfig.spec.json +0 -10
- /package/{src/react-query/index.ts → dist/types/react-query/index.d.ts} +0 -0
- /package/{src/types/index.ts → dist/types/types/index.d.ts} +0 -0
package/specs/generate.spec.ts
DELETED
|
@@ -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
|
-
});
|