librechat-data-provider 0.8.400 → 0.8.402

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.8.400",
3
+ "version": "0.8.402",
4
4
  "description": "data services for librechat apps",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.es.js",
package/src/config.ts CHANGED
@@ -205,6 +205,8 @@ export const baseEndpointSchema = z.object({
205
205
  .optional(),
206
206
  titleEndpoint: z.string().optional(),
207
207
  titlePromptTemplate: z.string().optional(),
208
+ /** Maximum characters allowed in a single tool result before truncation. */
209
+ maxToolResultChars: z.number().positive().optional(),
208
210
  });
209
211
 
210
212
  export type TBaseEndpoint = z.infer<typeof baseEndpointSchema>;
@@ -781,7 +783,6 @@ export type TStartupConfig = {
781
783
  sharedLinksEnabled: boolean;
782
784
  publicSharedLinksEnabled: boolean;
783
785
  analyticsGtmId?: string;
784
- instanceProjectId: string;
785
786
  bundlerURL?: string;
786
787
  staticBundlerURL?: string;
787
788
  sharePointFilePickerEnabled?: boolean;
@@ -949,6 +950,34 @@ export const memorySchema = z.object({
949
950
 
950
951
  export type TMemoryConfig = DeepPartial<z.infer<typeof memorySchema>>;
951
952
 
953
+ export const summarizationTriggerSchema = z.object({
954
+ type: z.enum(['token_count']),
955
+ value: z.number().positive(),
956
+ });
957
+
958
+ export const contextPruningSchema = z.object({
959
+ enabled: z.boolean().optional(),
960
+ keepLastAssistants: z.number().min(0).max(10).optional(),
961
+ softTrimRatio: z.number().min(0).max(1).optional(),
962
+ hardClearRatio: z.number().min(0).max(1).optional(),
963
+ minPrunableToolChars: z.number().min(0).optional(),
964
+ });
965
+
966
+ export const summarizationConfigSchema = z.object({
967
+ enabled: z.boolean().optional(),
968
+ provider: z.string().optional(),
969
+ model: z.string().optional(),
970
+ parameters: z.record(z.union([z.string(), z.number(), z.boolean(), z.null()])).optional(),
971
+ trigger: summarizationTriggerSchema.optional(),
972
+ prompt: z.string().optional(),
973
+ updatePrompt: z.string().optional(),
974
+ reserveRatio: z.number().min(0).max(1).optional(),
975
+ maxSummaryTokens: z.number().positive().optional(),
976
+ contextPruning: contextPruningSchema.optional(),
977
+ });
978
+
979
+ export type SummarizationConfig = z.infer<typeof summarizationConfigSchema>;
980
+
952
981
  const customEndpointsSchema = z.array(endpointSchema.partial()).optional();
953
982
 
954
983
  export const configSchema = z.object({
@@ -957,6 +986,7 @@ export const configSchema = z.object({
957
986
  ocr: ocrSchema.optional(),
958
987
  webSearch: webSearchSchema.optional(),
959
988
  memory: memorySchema.optional(),
989
+ summarization: summarizationConfigSchema.optional(),
960
990
  secureImageLinks: z.boolean().optional(),
961
991
  imageOutputType: z.nativeEnum(EImageOutputType).default(EImageOutputType.PNG),
962
992
  includedTools: z.array(z.string()).optional(),
@@ -1616,6 +1646,10 @@ export enum ErrorTypes {
1616
1646
  * Model refused to respond (content policy violation)
1617
1647
  */
1618
1648
  REFUSAL = 'refusal',
1649
+ /**
1650
+ * SSE stream 404 — job completed, expired, or was deleted before the subscriber connected
1651
+ */
1652
+ STREAM_EXPIRED = 'stream_expired',
1619
1653
  }
1620
1654
 
1621
1655
  /**
@@ -1740,7 +1774,7 @@ export enum TTSProviders {
1740
1774
  /** Enum for app-wide constants */
1741
1775
  export enum Constants {
1742
1776
  /** Key for the app's version. */
1743
- VERSION = 'v0.8.4-rc1',
1777
+ VERSION = 'v0.8.4',
1744
1778
  /** Key for the Custom Config's version (librechat.yaml). */
1745
1779
  CONFIG_VERSION = '1.3.6',
1746
1780
  /** Standard value for the first message's `parentMessageId` value, to indicate no parent exists. */
@@ -1767,8 +1801,6 @@ export enum Constants {
1767
1801
  SAVED_TAG = 'Saved',
1768
1802
  /** Max number of Conversation starters for Agents/Assistants */
1769
1803
  MAX_CONVO_STARTERS = 4,
1770
- /** Global/instance Project Name */
1771
- GLOBAL_PROJECT_NAME = 'instance',
1772
1804
  /** Delimiter for MCP tools */
1773
1805
  mcp_delimiter = '_mcp_',
1774
1806
  /** Prefix for MCP plugins */
@@ -31,6 +31,7 @@ describe('inferMimeType', () => {
31
31
  expect(inferMimeType('test.py', '')).toBe('text/x-python');
32
32
  expect(inferMimeType('code.js', '')).toBe('text/javascript');
33
33
  expect(inferMimeType('photo.heic', '')).toBe('image/heic');
34
+ expect(inferMimeType('Main.java', '')).toBe('text/x-java');
34
35
  });
35
36
 
36
37
  it('should return empty string for unknown extension with no browser type', () => {
@@ -141,12 +142,12 @@ describe('documentParserMimeTypes', () => {
141
142
  'application/x-msexcel',
142
143
  'application/x-ms-excel',
143
144
  'application/vnd.oasis.opendocument.spreadsheet',
145
+ 'application/vnd.oasis.opendocument.text',
144
146
  ])('matches natively parseable type: %s', (mimeType) => {
145
147
  expect(check(mimeType)).toBe(true);
146
148
  });
147
149
 
148
150
  it.each([
149
- 'application/vnd.oasis.opendocument.text',
150
151
  'application/vnd.oasis.opendocument.presentation',
151
152
  'application/vnd.oasis.opendocument.graphics',
152
153
  'text/plain',
@@ -202,12 +202,13 @@ export const defaultOCRMimeTypes = [
202
202
  /^application\/vnd\.oasis\.opendocument\.(text|spreadsheet|presentation|graphics)$/,
203
203
  ];
204
204
 
205
- /** MIME types handled by the built-in document parser (pdf, docx, excel variants, ods) */
205
+ /** MIME types handled by the built-in document parser (pdf, docx, excel variants, ods/odt) */
206
206
  export const documentParserMimeTypes = [
207
207
  excelMimeTypes,
208
208
  /^application\/pdf$/,
209
209
  /^application\/vnd\.openxmlformats-officedocument\.wordprocessingml\.document$/,
210
210
  /^application\/vnd\.oasis\.opendocument\.spreadsheet$/,
211
+ /^application\/vnd\.oasis\.opendocument\.text$/,
211
212
  ];
212
213
 
213
214
  export const defaultTextMimeTypes = [/^[\w.-]+\/[\w.-]+$/];
@@ -242,6 +243,7 @@ export const codeTypeMapping: { [key: string]: string } = {
242
243
  py: 'text/x-python', // .py - Python source
243
244
  rb: 'text/x-ruby', // .rb - Ruby source
244
245
  tex: 'text/x-tex', // .tex - LaTeX source
246
+ java: 'text/x-java', // .java - Java source
245
247
  js: 'text/javascript', // .js - JavaScript source
246
248
  sh: 'application/x-sh', // .sh - Shell script
247
249
  ts: 'application/typescript', // .ts - TypeScript source
@@ -0,0 +1,132 @@
1
+ import { Permissions, PermissionTypes, permissionsSchema } from './permissions';
2
+ import { SystemRoles, roleDefaults } from './roles';
3
+
4
+ const RESOURCE_MANAGEMENT_FIELDS: Permissions[] = [
5
+ Permissions.CREATE,
6
+ Permissions.SHARE,
7
+ Permissions.SHARE_PUBLIC,
8
+ ];
9
+
10
+ /**
11
+ * Permission types where CREATE/SHARE/SHARE_PUBLIC must default to false for USER.
12
+ * MEMORIES is excluded: its CREATE/READ/UPDATE apply to the user's own private data.
13
+ * AGENTS/PROMPTS are excluded: CREATE=true is intentional (users own their agents/prompts).
14
+ * Add new types here if they gate shared/multi-user resources.
15
+ */
16
+ const RESOURCE_PERMISSION_TYPES: PermissionTypes[] = [
17
+ PermissionTypes.MCP_SERVERS,
18
+ PermissionTypes.REMOTE_AGENTS,
19
+ ];
20
+
21
+ describe('roleDefaults', () => {
22
+ describe('USER role', () => {
23
+ const userPerms = roleDefaults[SystemRoles.USER].permissions;
24
+
25
+ it('should have explicit values for every field in every multi-field permission type', () => {
26
+ const schemaShape = permissionsSchema.shape;
27
+
28
+ for (const [permType, subSchema] of Object.entries(schemaShape)) {
29
+ const fieldNames = Object.keys(subSchema.shape);
30
+ if (fieldNames.length <= 1) {
31
+ continue;
32
+ }
33
+
34
+ const userValues =
35
+ userPerms[permType as PermissionTypes] as Record<string, boolean>;
36
+
37
+ for (const field of fieldNames) {
38
+ expect({
39
+ permType,
40
+ field,
41
+ value: userValues[field],
42
+ }).toEqual(
43
+ expect.objectContaining({
44
+ permType,
45
+ field,
46
+ value: expect.any(Boolean),
47
+ }),
48
+ );
49
+ }
50
+ }
51
+ });
52
+
53
+ it('should never grant CREATE, SHARE, or SHARE_PUBLIC by default for resource-management types', () => {
54
+ for (const permType of RESOURCE_PERMISSION_TYPES) {
55
+ const permissions = userPerms[permType] as Record<string, boolean>;
56
+ for (const field of RESOURCE_MANAGEMENT_FIELDS) {
57
+ if (permissions[field] === undefined) {
58
+ continue;
59
+ }
60
+ expect({
61
+ permType,
62
+ field,
63
+ value: permissions[field],
64
+ }).toEqual(
65
+ expect.objectContaining({
66
+ permType,
67
+ field,
68
+ value: false,
69
+ }),
70
+ );
71
+ }
72
+ }
73
+ });
74
+
75
+ it('should cover every permission type that has CREATE, SHARE, or SHARE_PUBLIC fields', () => {
76
+ const schemaShape = permissionsSchema.shape;
77
+ const restrictedSet = new Set<string>(RESOURCE_PERMISSION_TYPES);
78
+
79
+ for (const [permType, subSchema] of Object.entries(schemaShape)) {
80
+ const fieldNames = Object.keys(subSchema.shape);
81
+ const hasResourceFields = fieldNames.some((f) => RESOURCE_MANAGEMENT_FIELDS.includes(f as Permissions));
82
+ if (!hasResourceFields) {
83
+ continue;
84
+ }
85
+
86
+ const isTracked =
87
+ restrictedSet.has(permType) ||
88
+ permType === PermissionTypes.MEMORIES ||
89
+ permType === PermissionTypes.PROMPTS ||
90
+ permType === PermissionTypes.AGENTS;
91
+
92
+ expect({
93
+ permType,
94
+ tracked: isTracked,
95
+ }).toEqual(
96
+ expect.objectContaining({
97
+ permType,
98
+ tracked: true,
99
+ }),
100
+ );
101
+ }
102
+ });
103
+ });
104
+
105
+ describe('ADMIN role', () => {
106
+ const adminPerms = roleDefaults[SystemRoles.ADMIN].permissions;
107
+
108
+ it('should have explicit values for every field in every permission type', () => {
109
+ const schemaShape = permissionsSchema.shape;
110
+
111
+ for (const [permType, subSchema] of Object.entries(schemaShape)) {
112
+ const fieldNames = Object.keys(subSchema.shape);
113
+ const adminValues =
114
+ adminPerms[permType as PermissionTypes] as Record<string, boolean>;
115
+
116
+ for (const field of fieldNames) {
117
+ expect({
118
+ permType,
119
+ field,
120
+ value: adminValues[field],
121
+ }).toEqual(
122
+ expect.objectContaining({
123
+ permType,
124
+ field,
125
+ value: expect.any(Boolean),
126
+ }),
127
+ );
128
+ }
129
+ }
130
+ });
131
+ });
132
+ });
package/src/roles.ts CHANGED
@@ -180,10 +180,20 @@ export const roleDefaults = defaultRolesSchema.parse({
180
180
  [SystemRoles.USER]: {
181
181
  name: SystemRoles.USER,
182
182
  permissions: {
183
- [PermissionTypes.PROMPTS]: {},
183
+ [PermissionTypes.PROMPTS]: {
184
+ [Permissions.USE]: true,
185
+ [Permissions.CREATE]: true,
186
+ [Permissions.SHARE]: false,
187
+ [Permissions.SHARE_PUBLIC]: false,
188
+ },
184
189
  [PermissionTypes.BOOKMARKS]: {},
185
190
  [PermissionTypes.MEMORIES]: {},
186
- [PermissionTypes.AGENTS]: {},
191
+ [PermissionTypes.AGENTS]: {
192
+ [Permissions.USE]: true,
193
+ [Permissions.CREATE]: true,
194
+ [Permissions.SHARE]: false,
195
+ [Permissions.SHARE_PUBLIC]: false,
196
+ },
187
197
  [PermissionTypes.MULTI_CONVO]: {},
188
198
  [PermissionTypes.TEMPORARY_CHAT]: {},
189
199
  [PermissionTypes.RUN_CODE]: {},
@@ -198,8 +208,18 @@ export const roleDefaults = defaultRolesSchema.parse({
198
208
  },
199
209
  [PermissionTypes.FILE_SEARCH]: {},
200
210
  [PermissionTypes.FILE_CITATIONS]: {},
201
- [PermissionTypes.MCP_SERVERS]: {},
202
- [PermissionTypes.REMOTE_AGENTS]: {},
211
+ [PermissionTypes.MCP_SERVERS]: {
212
+ [Permissions.USE]: true,
213
+ [Permissions.CREATE]: false,
214
+ [Permissions.SHARE]: false,
215
+ [Permissions.SHARE_PUBLIC]: false,
216
+ },
217
+ [PermissionTypes.REMOTE_AGENTS]: {
218
+ [Permissions.USE]: false,
219
+ [Permissions.CREATE]: false,
220
+ [Permissions.SHARE]: false,
221
+ [Permissions.SHARE_PUBLIC]: false,
222
+ },
203
223
  },
204
224
  },
205
225
  });
package/src/schemas.ts CHANGED
@@ -258,11 +258,8 @@ export const defaultAgentFormValues = {
258
258
  tools: [],
259
259
  tool_options: {},
260
260
  provider: {},
261
- projectIds: [],
262
261
  edges: [],
263
262
  artifacts: '',
264
- /** @deprecated Use ACL permissions instead */
265
- isCollaborative: false,
266
263
  recursion_limit: undefined,
267
264
  [Tools.execute_code]: false,
268
265
  [Tools.file_search]: false,
@@ -633,6 +630,18 @@ export const tMessageSchema = z.object({
633
630
  feedback: feedbackSchema.optional(),
634
631
  /** metadata */
635
632
  metadata: z.record(z.unknown()).optional(),
633
+ contextMeta: z
634
+ .object({
635
+ calibrationRatio: z
636
+ .number()
637
+ .optional()
638
+ .describe('EMA ratio of provider-reported vs local token estimates; seeds the pruner on subsequent runs'),
639
+ encoding: z
640
+ .string()
641
+ .optional()
642
+ .describe('Tokenizer encoding used when this ratio was computed (e.g. "claude", "o200k_base")'),
643
+ })
644
+ .optional(),
636
645
  });
637
646
 
638
647
  export type MemoryArtifact = {
@@ -1,7 +1,7 @@
1
1
  /* eslint-disable @typescript-eslint/no-namespace */
2
2
  import { StepTypes, ContentTypes, ToolCallTypes } from './runs';
3
+ import type { FunctionToolCall, SummaryContentPart } from './assistants';
3
4
  import type { TAttachment, TPlugin } from 'src/schemas';
4
- import type { FunctionToolCall } from './assistants';
5
5
 
6
6
  export namespace Agents {
7
7
  export type MessageType = 'human' | 'ai' | 'generic' | 'system' | 'function' | 'tool' | 'remove';
@@ -53,6 +53,8 @@ export namespace Agents {
53
53
  | MessageContentImageUrl
54
54
  | MessageContentVideoUrl
55
55
  | MessageContentInputAudio
56
+ | SummaryContentPart
57
+ | ToolCallContent
56
58
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
57
59
  | (Record<string, any> & { type?: ContentTypes | string })
58
60
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -187,6 +189,7 @@ export namespace Agents {
187
189
  /** Group ID for parallel content - parts with same groupId are displayed in columns */
188
190
  groupId?: number; // #new
189
191
  stepDetails: StepDetails;
192
+ summary?: SummaryContentPart;
190
193
  usage: null | object;
191
194
  };
192
195
 
@@ -313,6 +316,28 @@ export namespace Agents {
313
316
  | ContentTypes.VIDEO_URL
314
317
  | ContentTypes.INPUT_AUDIO
315
318
  | string;
319
+
320
+ export interface SummarizeStartEvent {
321
+ agentId: string;
322
+ provider: string;
323
+ model?: string;
324
+ messagesToRefineCount: number;
325
+ summaryVersion: number;
326
+ }
327
+
328
+ export interface SummarizeDeltaEvent {
329
+ id: string;
330
+ delta: {
331
+ summary: SummaryContentPart;
332
+ };
333
+ }
334
+
335
+ export interface SummarizeCompleteEvent {
336
+ id: string;
337
+ agentId: string;
338
+ summary?: SummaryContentPart;
339
+ error?: string;
340
+ }
316
341
  }
317
342
 
318
343
  export type ToolCallResult = {
@@ -252,15 +252,12 @@ export type Agent = {
252
252
  instructions?: string | null;
253
253
  additional_instructions?: string | null;
254
254
  tools?: string[];
255
- projectIds?: string[];
256
255
  tool_kwargs?: Record<string, unknown>;
257
256
  metadata?: Record<string, unknown>;
258
257
  provider: AgentProvider;
259
258
  model: string | null;
260
259
  model_parameters: AgentModelParameters;
261
260
  conversation_starters?: string[];
262
- /** @deprecated Use ACL permissions instead */
263
- isCollaborative?: boolean;
264
261
  tool_resources?: AgentToolResources;
265
262
  /** @deprecated Use edges instead */
266
263
  agent_ids?: string[];
@@ -313,9 +310,6 @@ export type AgentUpdateParams = {
313
310
  provider?: AgentProvider;
314
311
  model?: string | null;
315
312
  model_parameters?: AgentModelParameters;
316
- projectIds?: string[];
317
- removeProjectIds?: string[];
318
- isCollaborative?: boolean;
319
313
  } & Pick<
320
314
  Agent,
321
315
  | 'agent_ids'
@@ -527,6 +521,21 @@ export type ContentPart = (
527
521
 
528
522
  export type TextData = (Text & PartMetadata) | undefined;
529
523
 
524
+ export type SummaryContentPart = {
525
+ type: ContentTypes.SUMMARY;
526
+ content?: Array<{ type: ContentTypes.TEXT; text: string }>;
527
+ tokenCount?: number;
528
+ summarizing?: boolean;
529
+ summaryVersion?: number;
530
+ model?: string;
531
+ provider?: string;
532
+ createdAt?: string;
533
+ boundary?: {
534
+ messageId: string;
535
+ contentIndex: number;
536
+ };
537
+ };
538
+
530
539
  export type TMessageContentParts =
531
540
  | ({
532
541
  type: ContentTypes.ERROR;
@@ -551,6 +560,7 @@ export type TMessageContentParts =
551
560
  PartMetadata;
552
561
  } & ContentMetadata)
553
562
  | ({ type: ContentTypes.IMAGE_FILE; image_file: ImageFile & PartMetadata } & ContentMetadata)
563
+ | (SummaryContentPart & ContentMetadata)
554
564
  | (Agents.AgentUpdate & ContentMetadata)
555
565
  | (Agents.MessageContentImageUrl & ContentMetadata)
556
566
  | (Agents.MessageContentVideoUrl & ContentMetadata)
package/src/types/runs.ts CHANGED
@@ -8,6 +8,7 @@ export enum ContentTypes {
8
8
  VIDEO_URL = 'video_url',
9
9
  INPUT_AUDIO = 'input_audio',
10
10
  AGENT_UPDATE = 'agent_update',
11
+ SUMMARY = 'summary',
11
12
  ERROR = 'error',
12
13
  }
13
14
 
@@ -24,3 +25,16 @@ export enum ToolCallTypes {
24
25
  /* Agents Tool Call */
25
26
  TOOL_CALL = 'tool_call',
26
27
  }
28
+
29
+ /** Event names dispatched by the agent graph and consumed by step handlers. */
30
+ export enum StepEvents {
31
+ ON_RUN_STEP = 'on_run_step',
32
+ ON_AGENT_UPDATE = 'on_agent_update',
33
+ ON_MESSAGE_DELTA = 'on_message_delta',
34
+ ON_REASONING_DELTA = 'on_reasoning_delta',
35
+ ON_RUN_STEP_DELTA = 'on_run_step_delta',
36
+ ON_RUN_STEP_COMPLETED = 'on_run_step_completed',
37
+ ON_SUMMARIZE_START = 'on_summarize_start',
38
+ ON_SUMMARIZE_DELTA = 'on_summarize_delta',
39
+ ON_SUMMARIZE_COMPLETE = 'on_summarize_complete',
40
+ }
package/src/types.ts CHANGED
@@ -534,7 +534,6 @@ export type TPromptGroup = {
534
534
  command?: string;
535
535
  oneliner?: string;
536
536
  category?: string;
537
- projectIds?: string[];
538
537
  productionId?: string | null;
539
538
  productionPrompt?: Pick<TPrompt, 'prompt'> | null;
540
539
  author: string;
@@ -587,9 +586,7 @@ export type TCreatePromptResponse = {
587
586
  group?: TPromptGroup;
588
587
  };
589
588
 
590
- export type TUpdatePromptGroupPayload = Partial<TPromptGroup> & {
591
- removeProjectIds?: string[];
592
- };
589
+ export type TUpdatePromptGroupPayload = Partial<TPromptGroup>;
593
590
 
594
591
  export type TUpdatePromptGroupVariables = {
595
592
  id: string;