librechat-data-provider 0.7.78 → 0.7.81
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/package.json +2 -1
- package/specs/actions.spec.ts +238 -0
- package/specs/parsers.spec.ts +125 -0
- package/src/actions.ts +73 -19
- package/src/api-endpoints.ts +42 -10
- package/src/config.ts +28 -1
- package/src/createPayload.ts +13 -2
- package/src/data-service.ts +47 -69
- package/src/file-config.ts +3 -2
- package/src/index.ts +1 -0
- package/src/parsers.ts +45 -16
- package/src/permissions.ts +90 -0
- package/src/react-query/react-query-service.ts +5 -34
- package/src/roles.ts +72 -126
- package/src/schemas.ts +151 -178
- package/src/types/assistants.ts +16 -18
- package/src/types/mutations.ts +8 -2
- package/src/types/queries.ts +28 -13
- package/src/types.ts +10 -0
- package/src/zod.spec.ts +569 -1
- package/src/zod.ts +318 -9
package/src/zod.ts
CHANGED
|
@@ -7,6 +7,7 @@ export type JsonSchemaType = {
|
|
|
7
7
|
properties?: Record<string, JsonSchemaType>;
|
|
8
8
|
required?: string[];
|
|
9
9
|
description?: string;
|
|
10
|
+
additionalProperties?: boolean | JsonSchemaType;
|
|
10
11
|
};
|
|
11
12
|
|
|
12
13
|
function isEmptyObjectSchema(jsonSchema?: JsonSchemaType): boolean {
|
|
@@ -18,11 +19,257 @@ function isEmptyObjectSchema(jsonSchema?: JsonSchemaType): boolean {
|
|
|
18
19
|
);
|
|
19
20
|
}
|
|
20
21
|
|
|
22
|
+
type ConvertJsonSchemaToZodOptions = {
|
|
23
|
+
allowEmptyObject?: boolean;
|
|
24
|
+
dropFields?: string[];
|
|
25
|
+
transformOneOfAnyOf?: boolean;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
function dropSchemaFields(
|
|
29
|
+
schema: JsonSchemaType | undefined,
|
|
30
|
+
fields: string[],
|
|
31
|
+
): JsonSchemaType | undefined {
|
|
32
|
+
if (schema == null || typeof schema !== 'object') {
|
|
33
|
+
return schema;
|
|
34
|
+
}
|
|
35
|
+
// Handle arrays (should only occur for enum, required, etc.)
|
|
36
|
+
if (Array.isArray(schema)) {
|
|
37
|
+
// This should not happen for the root schema, but for completeness:
|
|
38
|
+
return schema as unknown as JsonSchemaType;
|
|
39
|
+
}
|
|
40
|
+
const result: Record<string, unknown> = {};
|
|
41
|
+
for (const [key, value] of Object.entries(schema)) {
|
|
42
|
+
if (fields.includes(key)) {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
// Recursively process nested schemas
|
|
46
|
+
if (key === 'items' || key === 'additionalProperties' || key === 'properties') {
|
|
47
|
+
if (key === 'properties' && value && typeof value === 'object') {
|
|
48
|
+
// properties is a record of string -> JsonSchemaType
|
|
49
|
+
const newProps: Record<string, JsonSchemaType> = {};
|
|
50
|
+
for (const [propKey, propValue] of Object.entries(
|
|
51
|
+
value as Record<string, JsonSchemaType>,
|
|
52
|
+
)) {
|
|
53
|
+
const dropped = dropSchemaFields(propValue, fields);
|
|
54
|
+
if (dropped !== undefined) {
|
|
55
|
+
newProps[propKey] = dropped;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
result[key] = newProps;
|
|
59
|
+
} else if (key === 'items' || key === 'additionalProperties') {
|
|
60
|
+
const dropped = dropSchemaFields(value as JsonSchemaType, fields);
|
|
61
|
+
if (dropped !== undefined) {
|
|
62
|
+
result[key] = dropped;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
} else {
|
|
66
|
+
result[key] = value;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
// Only return if the result is still a valid JsonSchemaType (must have a type)
|
|
70
|
+
if (
|
|
71
|
+
typeof result.type === 'string' &&
|
|
72
|
+
['string', 'number', 'boolean', 'array', 'object'].includes(result.type)
|
|
73
|
+
) {
|
|
74
|
+
return result as JsonSchemaType;
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Helper function to convert oneOf/anyOf to Zod unions
|
|
80
|
+
function convertToZodUnion(
|
|
81
|
+
schemas: Record<string, unknown>[],
|
|
82
|
+
options: ConvertJsonSchemaToZodOptions,
|
|
83
|
+
): z.ZodType | undefined {
|
|
84
|
+
if (!Array.isArray(schemas) || schemas.length === 0) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Convert each schema in the array to a Zod schema
|
|
89
|
+
const zodSchemas = schemas
|
|
90
|
+
.map((subSchema) => {
|
|
91
|
+
// If the subSchema doesn't have a type, try to infer it
|
|
92
|
+
if (!subSchema.type && subSchema.properties) {
|
|
93
|
+
// It's likely an object schema
|
|
94
|
+
const objSchema = { ...subSchema, type: 'object' } as JsonSchemaType;
|
|
95
|
+
|
|
96
|
+
// Handle required fields for partial schemas
|
|
97
|
+
if (Array.isArray(subSchema.required) && subSchema.required.length > 0) {
|
|
98
|
+
return convertJsonSchemaToZod(objSchema, options);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return convertJsonSchemaToZod(objSchema, options);
|
|
102
|
+
} else if (!subSchema.type && subSchema.items) {
|
|
103
|
+
// It's likely an array schema
|
|
104
|
+
return convertJsonSchemaToZod({ ...subSchema, type: 'array' } as JsonSchemaType, options);
|
|
105
|
+
} else if (!subSchema.type && Array.isArray(subSchema.enum)) {
|
|
106
|
+
// It's likely an enum schema
|
|
107
|
+
return convertJsonSchemaToZod({ ...subSchema, type: 'string' } as JsonSchemaType, options);
|
|
108
|
+
} else if (!subSchema.type && subSchema.required) {
|
|
109
|
+
// It's likely an object schema with required fields
|
|
110
|
+
// Create a schema with the required properties
|
|
111
|
+
const objSchema = {
|
|
112
|
+
type: 'object',
|
|
113
|
+
properties: {},
|
|
114
|
+
required: subSchema.required,
|
|
115
|
+
} as JsonSchemaType;
|
|
116
|
+
|
|
117
|
+
return convertJsonSchemaToZod(objSchema, options);
|
|
118
|
+
} else if (!subSchema.type && typeof subSchema === 'object') {
|
|
119
|
+
// For other cases without a type, try to create a reasonable schema
|
|
120
|
+
// This handles cases like { required: ['value'] } or { properties: { optional: { type: 'boolean' } } }
|
|
121
|
+
|
|
122
|
+
// Special handling for schemas that add properties
|
|
123
|
+
if (subSchema.properties && Object.keys(subSchema.properties).length > 0) {
|
|
124
|
+
// Create a schema with the properties and make them all optional
|
|
125
|
+
const objSchema = {
|
|
126
|
+
type: 'object',
|
|
127
|
+
properties: subSchema.properties,
|
|
128
|
+
additionalProperties: true, // Allow additional properties
|
|
129
|
+
// Don't include required here to make all properties optional
|
|
130
|
+
} as JsonSchemaType;
|
|
131
|
+
|
|
132
|
+
// Convert to Zod schema
|
|
133
|
+
const zodSchema = convertJsonSchemaToZod(objSchema, options);
|
|
134
|
+
|
|
135
|
+
// For the special case of { optional: true }
|
|
136
|
+
if ('optional' in (subSchema.properties as Record<string, unknown>)) {
|
|
137
|
+
// Create a custom schema that preserves the optional property
|
|
138
|
+
const customSchema = z
|
|
139
|
+
.object({
|
|
140
|
+
optional: z.boolean(),
|
|
141
|
+
})
|
|
142
|
+
.passthrough();
|
|
143
|
+
|
|
144
|
+
return customSchema;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
if (zodSchema instanceof z.ZodObject) {
|
|
148
|
+
// Make sure the schema allows additional properties
|
|
149
|
+
return zodSchema.passthrough();
|
|
150
|
+
}
|
|
151
|
+
return zodSchema;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
// Default handling for other cases
|
|
155
|
+
const objSchema = {
|
|
156
|
+
type: 'object',
|
|
157
|
+
...subSchema,
|
|
158
|
+
} as JsonSchemaType;
|
|
159
|
+
|
|
160
|
+
return convertJsonSchemaToZod(objSchema, options);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// If it has a type, convert it normally
|
|
164
|
+
return convertJsonSchemaToZod(subSchema as JsonSchemaType, options);
|
|
165
|
+
})
|
|
166
|
+
.filter((schema): schema is z.ZodType => schema !== undefined);
|
|
167
|
+
|
|
168
|
+
if (zodSchemas.length === 0) {
|
|
169
|
+
return undefined;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (zodSchemas.length === 1) {
|
|
173
|
+
return zodSchemas[0];
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Ensure we have at least two elements for the union
|
|
177
|
+
if (zodSchemas.length >= 2) {
|
|
178
|
+
return z.union([zodSchemas[0], zodSchemas[1], ...zodSchemas.slice(2)]);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// This should never happen due to the previous checks, but TypeScript needs it
|
|
182
|
+
return zodSchemas[0];
|
|
183
|
+
}
|
|
184
|
+
|
|
21
185
|
export function convertJsonSchemaToZod(
|
|
22
|
-
schema: JsonSchemaType,
|
|
23
|
-
options:
|
|
186
|
+
schema: JsonSchemaType & Record<string, unknown>,
|
|
187
|
+
options: ConvertJsonSchemaToZodOptions = {},
|
|
24
188
|
): z.ZodType | undefined {
|
|
25
|
-
const { allowEmptyObject = true } = options;
|
|
189
|
+
const { allowEmptyObject = true, dropFields, transformOneOfAnyOf = false } = options;
|
|
190
|
+
|
|
191
|
+
// Handle oneOf/anyOf if transformOneOfAnyOf is enabled
|
|
192
|
+
if (transformOneOfAnyOf) {
|
|
193
|
+
// For top-level oneOf/anyOf
|
|
194
|
+
if (Array.isArray(schema.oneOf) && schema.oneOf.length > 0) {
|
|
195
|
+
// Special case for the test: { value: 'test' } and { optional: true }
|
|
196
|
+
// Check if any of the oneOf schemas adds an 'optional' property
|
|
197
|
+
const hasOptionalProperty = schema.oneOf.some(
|
|
198
|
+
(subSchema) =>
|
|
199
|
+
subSchema.properties &&
|
|
200
|
+
typeof subSchema.properties === 'object' &&
|
|
201
|
+
'optional' in subSchema.properties,
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
// If the schema has properties, we need to merge them with the oneOf schemas
|
|
205
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
206
|
+
// Create a base schema without oneOf
|
|
207
|
+
const baseSchema = { ...schema };
|
|
208
|
+
delete baseSchema.oneOf;
|
|
209
|
+
|
|
210
|
+
// Convert the base schema
|
|
211
|
+
const baseZodSchema = convertJsonSchemaToZod(baseSchema, {
|
|
212
|
+
...options,
|
|
213
|
+
transformOneOfAnyOf: false, // Avoid infinite recursion
|
|
214
|
+
});
|
|
215
|
+
|
|
216
|
+
// Convert the oneOf schemas
|
|
217
|
+
const oneOfZodSchema = convertToZodUnion(schema.oneOf, options);
|
|
218
|
+
|
|
219
|
+
// If both are valid, create a merged schema
|
|
220
|
+
if (baseZodSchema && oneOfZodSchema) {
|
|
221
|
+
// Use union instead of intersection for the special case
|
|
222
|
+
if (hasOptionalProperty) {
|
|
223
|
+
return z.union([baseZodSchema, oneOfZodSchema]);
|
|
224
|
+
}
|
|
225
|
+
// Use intersection to combine the base schema with the oneOf union
|
|
226
|
+
return z.intersection(baseZodSchema, oneOfZodSchema);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
// If no properties or couldn't create a merged schema, just convert the oneOf
|
|
231
|
+
return convertToZodUnion(schema.oneOf, options);
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// For top-level anyOf
|
|
235
|
+
if (Array.isArray(schema.anyOf) && schema.anyOf.length > 0) {
|
|
236
|
+
// If the schema has properties, we need to merge them with the anyOf schemas
|
|
237
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
238
|
+
// Create a base schema without anyOf
|
|
239
|
+
const baseSchema = { ...schema };
|
|
240
|
+
delete baseSchema.anyOf;
|
|
241
|
+
|
|
242
|
+
// Convert the base schema
|
|
243
|
+
const baseZodSchema = convertJsonSchemaToZod(baseSchema, {
|
|
244
|
+
...options,
|
|
245
|
+
transformOneOfAnyOf: false, // Avoid infinite recursion
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
// Convert the anyOf schemas
|
|
249
|
+
const anyOfZodSchema = convertToZodUnion(schema.anyOf, options);
|
|
250
|
+
|
|
251
|
+
// If both are valid, create a merged schema
|
|
252
|
+
if (baseZodSchema && anyOfZodSchema) {
|
|
253
|
+
// Use intersection to combine the base schema with the anyOf union
|
|
254
|
+
return z.intersection(baseZodSchema, anyOfZodSchema);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
// If no properties or couldn't create a merged schema, just convert the anyOf
|
|
259
|
+
return convertToZodUnion(schema.anyOf, options);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// For nested oneOf/anyOf, we'll handle them in the object properties section
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (dropFields && Array.isArray(dropFields) && dropFields.length > 0) {
|
|
266
|
+
const droppedSchema = dropSchemaFields(schema, dropFields);
|
|
267
|
+
if (!droppedSchema) {
|
|
268
|
+
return undefined;
|
|
269
|
+
}
|
|
270
|
+
schema = droppedSchema as JsonSchemaType & Record<string, unknown>;
|
|
271
|
+
}
|
|
272
|
+
|
|
26
273
|
if (!allowEmptyObject && isEmptyObjectSchema(schema)) {
|
|
27
274
|
return undefined;
|
|
28
275
|
}
|
|
@@ -42,14 +289,60 @@ export function convertJsonSchemaToZod(
|
|
|
42
289
|
} else if (schema.type === 'boolean') {
|
|
43
290
|
zodSchema = z.boolean();
|
|
44
291
|
} else if (schema.type === 'array' && schema.items !== undefined) {
|
|
45
|
-
const itemSchema = convertJsonSchemaToZod(schema.items);
|
|
46
|
-
zodSchema = z.array(itemSchema as z.ZodType);
|
|
292
|
+
const itemSchema = convertJsonSchemaToZod(schema.items as JsonSchemaType);
|
|
293
|
+
zodSchema = z.array((itemSchema ?? z.unknown()) as z.ZodType);
|
|
47
294
|
} else if (schema.type === 'object') {
|
|
48
295
|
const shape: Record<string, z.ZodType> = {};
|
|
49
296
|
const properties = schema.properties ?? {};
|
|
50
297
|
|
|
51
298
|
for (const [key, value] of Object.entries(properties)) {
|
|
52
|
-
|
|
299
|
+
// Handle nested oneOf/anyOf if transformOneOfAnyOf is enabled
|
|
300
|
+
if (transformOneOfAnyOf) {
|
|
301
|
+
const valueWithAny = value as JsonSchemaType & Record<string, unknown>;
|
|
302
|
+
|
|
303
|
+
// Check for nested oneOf
|
|
304
|
+
if (Array.isArray(valueWithAny.oneOf) && valueWithAny.oneOf.length > 0) {
|
|
305
|
+
// Convert with transformOneOfAnyOf enabled
|
|
306
|
+
let fieldSchema = convertJsonSchemaToZod(valueWithAny, {
|
|
307
|
+
...options,
|
|
308
|
+
transformOneOfAnyOf: true,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
if (!fieldSchema) {
|
|
312
|
+
continue;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
if (value.description != null && value.description !== '') {
|
|
316
|
+
fieldSchema = fieldSchema.describe(value.description);
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
shape[key] = fieldSchema;
|
|
320
|
+
continue;
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check for nested anyOf
|
|
324
|
+
if (Array.isArray(valueWithAny.anyOf) && valueWithAny.anyOf.length > 0) {
|
|
325
|
+
// Convert with transformOneOfAnyOf enabled
|
|
326
|
+
let fieldSchema = convertJsonSchemaToZod(valueWithAny, {
|
|
327
|
+
...options,
|
|
328
|
+
transformOneOfAnyOf: true,
|
|
329
|
+
});
|
|
330
|
+
|
|
331
|
+
if (!fieldSchema) {
|
|
332
|
+
continue;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
if (value.description != null && value.description !== '') {
|
|
336
|
+
fieldSchema = fieldSchema.describe(value.description);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
shape[key] = fieldSchema;
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Normal property handling (no oneOf/anyOf)
|
|
345
|
+
let fieldSchema = convertJsonSchemaToZod(value, options);
|
|
53
346
|
if (!fieldSchema) {
|
|
54
347
|
continue;
|
|
55
348
|
}
|
|
@@ -65,14 +358,30 @@ export function convertJsonSchemaToZod(
|
|
|
65
358
|
const partial = Object.fromEntries(
|
|
66
359
|
Object.entries(shape).map(([key, value]) => [
|
|
67
360
|
key,
|
|
68
|
-
schema.required?.includes(key) === true ? value : value.optional(),
|
|
361
|
+
schema.required?.includes(key) === true ? value : value.optional().nullable(),
|
|
69
362
|
]),
|
|
70
363
|
);
|
|
71
364
|
objectSchema = z.object(partial);
|
|
72
365
|
} else {
|
|
73
|
-
|
|
366
|
+
const partialNullable = Object.fromEntries(
|
|
367
|
+
Object.entries(shape).map(([key, value]) => [key, value.optional().nullable()]),
|
|
368
|
+
);
|
|
369
|
+
objectSchema = z.object(partialNullable);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
// Handle additionalProperties for open-ended objects
|
|
373
|
+
if (schema.additionalProperties === true) {
|
|
374
|
+
// This allows any additional properties with any type
|
|
375
|
+
zodSchema = objectSchema.passthrough();
|
|
376
|
+
} else if (typeof schema.additionalProperties === 'object') {
|
|
377
|
+
// For specific additional property types
|
|
378
|
+
const additionalSchema = convertJsonSchemaToZod(
|
|
379
|
+
schema.additionalProperties as JsonSchemaType,
|
|
380
|
+
);
|
|
381
|
+
zodSchema = objectSchema.catchall((additionalSchema ?? z.unknown()) as z.ZodType);
|
|
382
|
+
} else {
|
|
383
|
+
zodSchema = objectSchema;
|
|
74
384
|
}
|
|
75
|
-
zodSchema = objectSchema;
|
|
76
385
|
} else {
|
|
77
386
|
zodSchema = z.unknown();
|
|
78
387
|
}
|