librechat-data-provider 0.7.87 → 0.7.89

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/src/schemas.ts CHANGED
@@ -3,7 +3,6 @@ import { Tools } from './types/assistants';
3
3
  import type { TMessageContentParts, FunctionTool, FunctionToolCall } from './types/assistants';
4
4
  import { TFeedback, feedbackSchema } from './feedback';
5
5
  import type { SearchResultData } from './types/web';
6
- import type { TEphemeralAgent } from './types';
7
6
  import type { TFile } from './types/files';
8
7
 
9
8
  export const isUUID = z.string().uuid();
@@ -91,22 +90,6 @@ export const isAgentsEndpoint = (_endpoint?: EModelEndpoint.agents | null | stri
91
90
  return endpoint === EModelEndpoint.agents;
92
91
  };
93
92
 
94
- export const isEphemeralAgent = (
95
- endpoint?: EModelEndpoint.agents | null | string,
96
- ephemeralAgent?: TEphemeralAgent | null,
97
- ) => {
98
- if (!ephemeralAgent) {
99
- return false;
100
- }
101
- if (isAgentsEndpoint(endpoint)) {
102
- return false;
103
- }
104
- const hasMCPSelected = (ephemeralAgent?.mcp?.length ?? 0) > 0;
105
- const hasCodeSelected = (ephemeralAgent?.execute_code ?? false) === true;
106
- const hasSearchSelected = (ephemeralAgent?.web_search ?? false) === true;
107
- return hasMCPSelected || hasCodeSelected || hasSearchSelected;
108
- };
109
-
110
93
  export const isParamEndpoint = (
111
94
  endpoint: EModelEndpoint | string,
112
95
  endpointType?: EModelEndpoint | string,
@@ -272,6 +255,18 @@ export const googleSettings = {
272
255
  step: 1 as const,
273
256
  default: 40 as const,
274
257
  },
258
+ thinking: {
259
+ default: true as const,
260
+ },
261
+ thinkingBudget: {
262
+ min: -1 as const,
263
+ max: 32768 as const,
264
+ step: 1 as const,
265
+ /** `-1` = Dynamic Thinking, meaning the model will adjust
266
+ * the budget based on the complexity of the request.
267
+ */
268
+ default: -1 as const,
269
+ },
275
270
  };
276
271
 
277
272
  const ANTHROPIC_MAX_OUTPUT = 128000 as const;
@@ -417,7 +412,7 @@ export type TPluginAuthConfig = z.infer<typeof tPluginAuthConfigSchema>;
417
412
  export const tPluginSchema = z.object({
418
413
  name: z.string(),
419
414
  pluginKey: z.string(),
420
- description: z.string(),
415
+ description: z.string().optional(),
421
416
  icon: z.string().optional(),
422
417
  authConfig: z.array(tPluginAuthConfigSchema).optional(),
423
418
  authenticated: z.boolean().optional(),
@@ -802,6 +797,8 @@ export const googleBaseSchema = tConversationSchema.pick({
802
797
  artifacts: true,
803
798
  topP: true,
804
799
  topK: true,
800
+ thinking: true,
801
+ thinkingBudget: true,
805
802
  iconURL: true,
806
803
  greeting: true,
807
804
  spec: true,
@@ -827,6 +824,12 @@ export const googleGenConfigSchema = z
827
824
  presencePenalty: coerceNumber.optional(),
828
825
  frequencyPenalty: coerceNumber.optional(),
829
826
  stopSequences: z.array(z.string()).optional(),
827
+ thinkingConfig: z
828
+ .object({
829
+ includeThoughts: z.boolean().optional(),
830
+ thinkingBudget: coerceNumber.optional(),
831
+ })
832
+ .optional(),
830
833
  })
831
834
  .strip()
832
835
  .optional();
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-namespace */
2
2
  import { StepTypes, ContentTypes, ToolCallTypes } from './runs';
3
+ import type { TAttachment, TPlugin } from 'src/schemas';
3
4
  import type { FunctionToolCall } from './assistants';
4
- import type { TAttachment } from 'src/schemas';
5
5
 
6
6
  export namespace Agents {
7
7
  export type MessageType = 'human' | 'ai' | 'generic' | 'system' | 'function' | 'tool' | 'remove';
@@ -279,3 +279,79 @@ export type ToolCallResult = {
279
279
  conversationId: string;
280
280
  attachments?: TAttachment[];
281
281
  };
282
+
283
+ export enum AuthTypeEnum {
284
+ ServiceHttp = 'service_http',
285
+ OAuth = 'oauth',
286
+ None = 'none',
287
+ }
288
+
289
+ export enum AuthorizationTypeEnum {
290
+ Bearer = 'bearer',
291
+ Basic = 'basic',
292
+ Custom = 'custom',
293
+ }
294
+
295
+ export enum TokenExchangeMethodEnum {
296
+ DefaultPost = 'default_post',
297
+ BasicAuthHeader = 'basic_auth_header',
298
+ }
299
+
300
+ export type Action = {
301
+ action_id: string;
302
+ type?: string;
303
+ settings?: Record<string, unknown>;
304
+ metadata: ActionMetadata;
305
+ version: number | string;
306
+ } & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id: string });
307
+
308
+ export type ActionMetadata = {
309
+ api_key?: string;
310
+ auth?: ActionAuth;
311
+ domain?: string;
312
+ privacy_policy_url?: string;
313
+ raw_spec?: string;
314
+ oauth_client_id?: string;
315
+ oauth_client_secret?: string;
316
+ };
317
+
318
+ export type ActionAuth = {
319
+ authorization_type?: AuthorizationTypeEnum;
320
+ custom_auth_header?: string;
321
+ type?: AuthTypeEnum;
322
+ authorization_content_type?: string;
323
+ authorization_url?: string;
324
+ client_url?: string;
325
+ scope?: string;
326
+ token_exchange_method?: TokenExchangeMethodEnum;
327
+ };
328
+
329
+ export type ActionMetadataRuntime = ActionMetadata & {
330
+ oauth_access_token?: string;
331
+ oauth_refresh_token?: string;
332
+ oauth_token_expires_at?: Date;
333
+ };
334
+
335
+ export type MCP = {
336
+ mcp_id: string;
337
+ metadata: MCPMetadata;
338
+ } & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id: string });
339
+
340
+ export type MCPMetadata = Omit<ActionMetadata, 'auth'> & {
341
+ name?: string;
342
+ description?: string;
343
+ url?: string;
344
+ tools?: string[];
345
+ auth?: MCPAuth;
346
+ icon?: string;
347
+ trust?: boolean;
348
+ };
349
+
350
+ export type MCPAuth = ActionAuth;
351
+
352
+ export type AgentToolType = {
353
+ tool_id: string;
354
+ metadata: ToolMetadata;
355
+ } & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id: string });
356
+
357
+ export type ToolMetadata = TPlugin;
@@ -487,60 +487,6 @@ export const actionDomainSeparator = '---';
487
487
  export const hostImageIdSuffix = '_host_copy';
488
488
  export const hostImageNamePrefix = 'host_copy_';
489
489
 
490
- export enum AuthTypeEnum {
491
- ServiceHttp = 'service_http',
492
- OAuth = 'oauth',
493
- None = 'none',
494
- }
495
-
496
- export enum AuthorizationTypeEnum {
497
- Bearer = 'bearer',
498
- Basic = 'basic',
499
- Custom = 'custom',
500
- }
501
-
502
- export enum TokenExchangeMethodEnum {
503
- DefaultPost = 'default_post',
504
- BasicAuthHeader = 'basic_auth_header',
505
- }
506
-
507
- export type ActionAuth = {
508
- authorization_type?: AuthorizationTypeEnum;
509
- custom_auth_header?: string;
510
- type?: AuthTypeEnum;
511
- authorization_content_type?: string;
512
- authorization_url?: string;
513
- client_url?: string;
514
- scope?: string;
515
- token_exchange_method?: TokenExchangeMethodEnum;
516
- };
517
-
518
- export type ActionMetadata = {
519
- api_key?: string;
520
- auth?: ActionAuth;
521
- domain?: string;
522
- privacy_policy_url?: string;
523
- raw_spec?: string;
524
- oauth_client_id?: string;
525
- oauth_client_secret?: string;
526
- };
527
-
528
- export type ActionMetadataRuntime = ActionMetadata & {
529
- oauth_access_token?: string;
530
- oauth_refresh_token?: string;
531
- oauth_token_expires_at?: Date;
532
- };
533
-
534
- /* Assistant types */
535
-
536
- export type Action = {
537
- action_id: string;
538
- type?: string;
539
- settings?: Record<string, unknown>;
540
- metadata: ActionMetadata;
541
- version: number | string;
542
- } & ({ assistant_id: string; agent_id?: never } | { assistant_id?: never; agent_id: string });
543
-
544
490
  export type AssistantAvatar = {
545
491
  filepath: string;
546
492
  source: string;
@@ -10,6 +10,7 @@ export enum FileSources {
10
10
  vectordb = 'vectordb',
11
11
  execute_code = 'execute_code',
12
12
  mistral_ocr = 'mistral_ocr',
13
+ azure_mistral_ocr = 'azure_mistral_ocr',
13
14
  text = 'text',
14
15
  }
15
16
 
@@ -47,6 +48,12 @@ export type FileConfig = {
47
48
  };
48
49
  serverFileSizeLimit?: number;
49
50
  avatarSizeLimit?: number;
51
+ clientImageResize?: {
52
+ enabled?: boolean;
53
+ maxWidth?: number;
54
+ maxHeight?: number;
55
+ quality?: number;
56
+ };
50
57
  checkType?: (fileType: string, supportedTypes: RegExp[]) => boolean;
51
58
  };
52
59
 
@@ -6,14 +6,13 @@ import {
6
6
  Assistant,
7
7
  AssistantCreateParams,
8
8
  AssistantUpdateParams,
9
- ActionMetadata,
10
9
  FunctionTool,
11
10
  AssistantDocument,
12
- Action,
13
11
  Agent,
14
12
  AgentCreateParams,
15
13
  AgentUpdateParams,
16
14
  } from './assistants';
15
+ import { Action, ActionMetadata } from './agents';
17
16
 
18
17
  export type MutationOptions<
19
18
  Response,
package/src/types.ts CHANGED
@@ -98,6 +98,7 @@ export type TEndpointOption = Pick<
98
98
  export type TEphemeralAgent = {
99
99
  mcp?: string[];
100
100
  web_search?: boolean;
101
+ file_search?: boolean;
101
102
  execute_code?: boolean;
102
103
  };
103
104
 
@@ -133,7 +134,7 @@ export type EventSubmission = Omit<TSubmission, 'initialResponse'> & { initialRe
133
134
  export type TPluginAction = {
134
135
  pluginKey: string;
135
136
  action: 'install' | 'uninstall';
136
- auth?: Partial<Record<string, string>>;
137
+ auth?: Partial<Record<string, string>> | null;
137
138
  isEntityTool?: boolean;
138
139
  };
139
140
 
@@ -143,7 +144,7 @@ export type TUpdateUserPlugins = {
143
144
  isEntityTool?: boolean;
144
145
  pluginKey: string;
145
146
  action: string;
146
- auth?: Partial<Record<string, string | null>>;
147
+ auth?: Partial<Record<string, string | null>> | null;
147
148
  };
148
149
 
149
150
  // TODO `label` needs to be changed to the proper `TranslationKeys`
package/specs/mcp.spec.ts DELETED
@@ -1,277 +0,0 @@
1
- import { StdioOptionsSchema, StreamableHTTPOptionsSchema, processMCPEnv, MCPOptions } from '../src/mcp';
2
-
3
- describe('Environment Variable Extraction (MCP)', () => {
4
- const originalEnv = process.env;
5
-
6
- beforeEach(() => {
7
- process.env = {
8
- ...originalEnv,
9
- TEST_API_KEY: 'test-api-key-value',
10
- ANOTHER_SECRET: 'another-secret-value',
11
- };
12
- });
13
-
14
- afterEach(() => {
15
- process.env = originalEnv;
16
- });
17
-
18
- describe('StdioOptionsSchema', () => {
19
- it('should transform environment variables in the env field', () => {
20
- const options = {
21
- command: 'node',
22
- args: ['server.js'],
23
- env: {
24
- API_KEY: '${TEST_API_KEY}',
25
- ANOTHER_KEY: '${ANOTHER_SECRET}',
26
- PLAIN_VALUE: 'plain-value',
27
- NON_EXISTENT: '${NON_EXISTENT_VAR}',
28
- },
29
- };
30
-
31
- const result = StdioOptionsSchema.parse(options);
32
-
33
- expect(result.env).toEqual({
34
- API_KEY: 'test-api-key-value',
35
- ANOTHER_KEY: 'another-secret-value',
36
- PLAIN_VALUE: 'plain-value',
37
- NON_EXISTENT: '${NON_EXISTENT_VAR}',
38
- });
39
- });
40
-
41
- it('should handle undefined env field', () => {
42
- const options = {
43
- command: 'node',
44
- args: ['server.js'],
45
- };
46
-
47
- const result = StdioOptionsSchema.parse(options);
48
-
49
- expect(result.env).toBeUndefined();
50
- });
51
- });
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
-
121
- describe('processMCPEnv', () => {
122
- it('should create a deep clone of the input object', () => {
123
- const originalObj: MCPOptions = {
124
- command: 'node',
125
- args: ['server.js'],
126
- env: {
127
- API_KEY: '${TEST_API_KEY}',
128
- PLAIN_VALUE: 'plain-value',
129
- },
130
- };
131
-
132
- const result = processMCPEnv(originalObj);
133
-
134
- // Verify it's not the same object reference
135
- expect(result).not.toBe(originalObj);
136
-
137
- // Modify the result and ensure original is unchanged
138
- if ('env' in result && result.env) {
139
- result.env.API_KEY = 'modified-value';
140
- }
141
-
142
- expect(originalObj.env?.API_KEY).toBe('${TEST_API_KEY}');
143
- });
144
-
145
- it('should process environment variables in env field', () => {
146
- const obj: MCPOptions = {
147
- command: 'node',
148
- args: ['server.js'],
149
- env: {
150
- API_KEY: '${TEST_API_KEY}',
151
- ANOTHER_KEY: '${ANOTHER_SECRET}',
152
- PLAIN_VALUE: 'plain-value',
153
- NON_EXISTENT: '${NON_EXISTENT_VAR}',
154
- },
155
- };
156
-
157
- const result = processMCPEnv(obj);
158
-
159
- expect('env' in result && result.env).toEqual({
160
- API_KEY: 'test-api-key-value',
161
- ANOTHER_KEY: 'another-secret-value',
162
- PLAIN_VALUE: 'plain-value',
163
- NON_EXISTENT: '${NON_EXISTENT_VAR}',
164
- });
165
- });
166
-
167
- it('should process user ID in headers field', () => {
168
- const userId = 'test-user-123';
169
- const obj: MCPOptions = {
170
- type: 'sse',
171
- url: 'https://example.com',
172
- headers: {
173
- Authorization: '${TEST_API_KEY}',
174
- 'User-Id': '{{LIBRECHAT_USER_ID}}',
175
- 'Content-Type': 'application/json',
176
- },
177
- };
178
-
179
- const result = processMCPEnv(obj, userId);
180
-
181
- expect('headers' in result && result.headers).toEqual({
182
- Authorization: 'test-api-key-value',
183
- 'User-Id': 'test-user-123',
184
- 'Content-Type': 'application/json',
185
- });
186
- });
187
-
188
- it('should handle null or undefined input', () => {
189
- // @ts-ignore - Testing null/undefined handling
190
- expect(processMCPEnv(null)).toBeNull();
191
- // @ts-ignore - Testing null/undefined handling
192
- expect(processMCPEnv(undefined)).toBeUndefined();
193
- });
194
-
195
- it('should not modify objects without env or headers', () => {
196
- const obj: MCPOptions = {
197
- command: 'node',
198
- args: ['server.js'],
199
- timeout: 5000,
200
- };
201
-
202
- const result = processMCPEnv(obj);
203
-
204
- expect(result).toEqual(obj);
205
- expect(result).not.toBe(obj); // Still a different object (deep clone)
206
- });
207
-
208
- it('should ensure different users with same starting config get separate values', () => {
209
- // Create a single base configuration
210
- const baseConfig: MCPOptions = {
211
- type: 'sse',
212
- url: 'https://example.com',
213
- headers: {
214
- 'User-Id': '{{LIBRECHAT_USER_ID}}',
215
- 'API-Key': '${TEST_API_KEY}',
216
- },
217
- };
218
-
219
- // Process for two different users
220
- const user1Id = 'user-123';
221
- const user2Id = 'user-456';
222
-
223
- const resultUser1 = processMCPEnv(baseConfig, user1Id);
224
- const resultUser2 = processMCPEnv(baseConfig, user2Id);
225
-
226
- // Verify each has the correct user ID
227
- expect('headers' in resultUser1 && resultUser1.headers?.['User-Id']).toBe(user1Id);
228
- expect('headers' in resultUser2 && resultUser2.headers?.['User-Id']).toBe(user2Id);
229
-
230
- // Verify they're different objects
231
- expect(resultUser1).not.toBe(resultUser2);
232
-
233
- // Modify one result and ensure it doesn't affect the other
234
- if ('headers' in resultUser1 && resultUser1.headers) {
235
- resultUser1.headers['User-Id'] = 'modified-user';
236
- }
237
-
238
- // Original config should be unchanged
239
- expect(baseConfig.headers?.['User-Id']).toBe('{{LIBRECHAT_USER_ID}}');
240
-
241
- // Second user's config should be unchanged
242
- expect('headers' in resultUser2 && resultUser2.headers?.['User-Id']).toBe(user2Id);
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
- });
276
- });
277
- });