librechat-data-provider 0.7.82 → 0.7.83

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "librechat-data-provider",
3
- "version": "0.7.82",
3
+ "version": "0.7.83",
4
4
  "description": "data services for librechat apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
package/specs/mcp.spec.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { StdioOptionsSchema, processMCPEnv, MCPOptions } from '../src/mcp';
1
+ import { StdioOptionsSchema, StreamableHTTPOptionsSchema, processMCPEnv, MCPOptions } from '../src/mcp';
2
2
 
3
3
  describe('Environment Variable Extraction (MCP)', () => {
4
4
  const originalEnv = process.env;
@@ -50,6 +50,74 @@ describe('Environment Variable Extraction (MCP)', () => {
50
50
  });
51
51
  });
52
52
 
53
+ describe('StreamableHTTPOptionsSchema', () => {
54
+ it('should validate a valid streamable-http configuration', () => {
55
+ const options = {
56
+ type: 'streamable-http',
57
+ url: 'https://example.com/api',
58
+ headers: {
59
+ Authorization: 'Bearer token',
60
+ 'Content-Type': 'application/json',
61
+ },
62
+ };
63
+
64
+ const result = StreamableHTTPOptionsSchema.parse(options);
65
+
66
+ expect(result).toEqual(options);
67
+ });
68
+
69
+ it('should reject websocket URLs', () => {
70
+ const options = {
71
+ type: 'streamable-http',
72
+ url: 'ws://example.com/socket',
73
+ };
74
+
75
+ expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
76
+ });
77
+
78
+ it('should reject secure websocket URLs', () => {
79
+ const options = {
80
+ type: 'streamable-http',
81
+ url: 'wss://example.com/socket',
82
+ };
83
+
84
+ expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
85
+ });
86
+
87
+ it('should require type field to be set explicitly', () => {
88
+ const options = {
89
+ url: 'https://example.com/api',
90
+ };
91
+
92
+ // Type is now required, so parsing should fail
93
+ expect(() => StreamableHTTPOptionsSchema.parse(options)).toThrow();
94
+
95
+ // With type provided, it should pass
96
+ const validOptions = {
97
+ type: 'streamable-http' as const,
98
+ url: 'https://example.com/api',
99
+ };
100
+
101
+ const result = StreamableHTTPOptionsSchema.parse(validOptions);
102
+ expect(result.type).toBe('streamable-http');
103
+ });
104
+
105
+ it('should validate headers as record of strings', () => {
106
+ const options = {
107
+ type: 'streamable-http',
108
+ url: 'https://example.com/api',
109
+ headers: {
110
+ 'X-API-Key': '123456',
111
+ 'User-Agent': 'MCP Client',
112
+ },
113
+ };
114
+
115
+ const result = StreamableHTTPOptionsSchema.parse(options);
116
+
117
+ expect(result.headers).toEqual(options.headers);
118
+ });
119
+ });
120
+
53
121
  describe('processMCPEnv', () => {
54
122
  it('should create a deep clone of the input object', () => {
55
123
  const originalObj: MCPOptions = {
@@ -173,5 +241,37 @@ describe('Environment Variable Extraction (MCP)', () => {
173
241
  // Second user's config should be unchanged
174
242
  expect('headers' in resultUser2 && resultUser2.headers?.['User-Id']).toBe(user2Id);
175
243
  });
244
+
245
+ it('should process headers in streamable-http options', () => {
246
+ const userId = 'test-user-123';
247
+ const obj: MCPOptions = {
248
+ type: 'streamable-http',
249
+ url: 'https://example.com',
250
+ headers: {
251
+ Authorization: '${TEST_API_KEY}',
252
+ 'User-Id': '{{LIBRECHAT_USER_ID}}',
253
+ 'Content-Type': 'application/json',
254
+ },
255
+ };
256
+
257
+ const result = processMCPEnv(obj, userId);
258
+
259
+ expect('headers' in result && result.headers).toEqual({
260
+ Authorization: 'test-api-key-value',
261
+ 'User-Id': 'test-user-123',
262
+ 'Content-Type': 'application/json',
263
+ });
264
+ });
265
+
266
+ it('should maintain streamable-http type in processed options', () => {
267
+ const obj: MCPOptions = {
268
+ type: 'streamable-http',
269
+ url: 'https://example.com/api',
270
+ };
271
+
272
+ const result = processMCPEnv(obj);
273
+
274
+ expect(result.type).toBe('streamable-http');
275
+ });
176
276
  });
177
277
  });
package/src/config.ts CHANGED
@@ -52,6 +52,7 @@ export const excludedKeys = new Set([
52
52
  'model',
53
53
  'files',
54
54
  'spec',
55
+ 'disableParams',
55
56
  ]);
56
57
 
57
58
  export enum SettingsViews {
@@ -505,10 +506,28 @@ export const intefaceSchema = z
505
506
  export type TInterfaceConfig = z.infer<typeof intefaceSchema>;
506
507
  export type TBalanceConfig = z.infer<typeof balanceSchema>;
507
508
 
509
+ export const turnstileOptionsSchema = z
510
+ .object({
511
+ language: z.string().default('auto'),
512
+ size: z.enum(['normal', 'compact', 'flexible', 'invisible']).default('normal'),
513
+ })
514
+ .default({
515
+ language: 'auto',
516
+ size: 'normal',
517
+ });
518
+
519
+ export const turnstileSchema = z.object({
520
+ siteKey: z.string(),
521
+ options: turnstileOptionsSchema.optional(),
522
+ });
523
+
524
+ export type TTurnstileConfig = z.infer<typeof turnstileSchema>;
525
+
508
526
  export type TStartupConfig = {
509
527
  appTitle: string;
510
528
  socialLogins?: string[];
511
529
  interface?: TInterfaceConfig;
530
+ turnstile?: TTurnstileConfig;
512
531
  balance?: TBalanceConfig;
513
532
  discordLoginEnabled: boolean;
514
533
  facebookLoginEnabled: boolean;
@@ -578,6 +597,7 @@ export const configSchema = z.object({
578
597
  filteredTools: z.array(z.string()).optional(),
579
598
  mcpServers: MCPServersSchema.optional(),
580
599
  interface: intefaceSchema,
600
+ turnstile: turnstileSchema.optional(),
581
601
  fileStrategy: fileSourceSchema.default(FileSources.local),
582
602
  actions: z
583
603
  .object({
package/src/generate.ts CHANGED
@@ -358,7 +358,7 @@ export function validateSettingDefinitions(settings: SettingsConfiguration): voi
358
358
  // continue;
359
359
  }
360
360
  setting.includeInput =
361
- setting.type === SettingTypes.Number ? setting.includeInput ?? true : false; // Default to true if type is number
361
+ setting.type === SettingTypes.Number ? (setting.includeInput ?? true) : false; // Default to true if type is number
362
362
  }
363
363
 
364
364
  if (setting.component === ComponentTypes.Slider && setting.type === SettingTypes.Number) {
@@ -445,7 +445,8 @@ export function validateSettingDefinitions(settings: SettingsConfiguration): voi
445
445
 
446
446
  // Validate optionType and conversation schema
447
447
  if (setting.optionType !== OptionTypes.Custom) {
448
- const conversationSchema = tConversationSchema.shape[setting.key as keyof TConversation];
448
+ const conversationSchema =
449
+ tConversationSchema.shape[setting.key as keyof Omit<TConversation, 'disableParams'>];
449
450
  if (!conversationSchema) {
450
451
  errors.push({
451
452
  code: ZodIssueCode.custom,
package/src/mcp.ts CHANGED
@@ -82,10 +82,28 @@ export const SSEOptionsSchema = BaseOptionsSchema.extend({
82
82
  ),
83
83
  });
84
84
 
85
+ export const StreamableHTTPOptionsSchema = BaseOptionsSchema.extend({
86
+ type: z.literal('streamable-http'),
87
+ headers: z.record(z.string(), z.string()).optional(),
88
+ url: z
89
+ .string()
90
+ .url()
91
+ .refine(
92
+ (val) => {
93
+ const protocol = new URL(val).protocol;
94
+ return protocol !== 'ws:' && protocol !== 'wss:';
95
+ },
96
+ {
97
+ message: 'Streamable HTTP URL must not start with ws:// or wss://',
98
+ },
99
+ ),
100
+ });
101
+
85
102
  export const MCPOptionsSchema = z.union([
86
103
  StdioOptionsSchema,
87
104
  WebSocketOptionsSchema,
88
105
  SSEOptionsSchema,
106
+ StreamableHTTPOptionsSchema,
89
107
  ]);
90
108
 
91
109
  export const MCPServersSchema = z.record(z.string(), MCPOptionsSchema);
package/src/schemas.ts CHANGED
@@ -745,6 +745,7 @@ export type TSetOption = (
745
745
 
746
746
  export type TConversation = z.infer<typeof tConversationSchema> & {
747
747
  presetOverride?: Partial<TPreset>;
748
+ disableParams?: boolean;
748
749
  };
749
750
 
750
751
  export const tSharedLinkSchema = z.object({