librechat-data-provider 0.7.78 → 0.7.82

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.
@@ -1,4 +1,24 @@
1
1
  import type { AssistantsEndpoint } from './schemas';
2
+ import * as q from './types/queries';
3
+
4
+ // Testing this buildQuery function
5
+ const buildQuery = (params: Record<string, unknown>): string => {
6
+ const query = Object.entries(params)
7
+ .filter(([, value]) => {
8
+ if (Array.isArray(value)) {
9
+ return value.length > 0;
10
+ }
11
+ return value !== undefined && value !== null && value !== '';
12
+ })
13
+ .map(([key, value]) => {
14
+ if (Array.isArray(value)) {
15
+ return value.map((v) => `${key}=${encodeURIComponent(v)}`).join('&');
16
+ }
17
+ return `${key}=${encodeURIComponent(String(value))}`;
18
+ })
19
+ .join('&');
20
+ return query ? `?${query}` : '';
21
+ };
2
22
 
3
23
  export const health = () => '/health';
4
24
  export const user = () => '/api/user';
@@ -9,8 +29,19 @@ export const userPlugins = () => '/api/user/plugins';
9
29
 
10
30
  export const deleteUser = () => '/api/user/delete';
11
31
 
12
- export const messages = (conversationId: string, messageId?: string) =>
13
- `/api/messages/${conversationId}${messageId != null && messageId ? `/${messageId}` : ''}`;
32
+ export const messages = (params: q.MessagesListParams) => {
33
+ const { conversationId, messageId, ...rest } = params;
34
+
35
+ if (conversationId && messageId) {
36
+ return `/api/messages/${conversationId}/${messageId}`;
37
+ }
38
+
39
+ if (conversationId) {
40
+ return `/api/messages/${conversationId}`;
41
+ }
42
+
43
+ return `/api/messages${buildQuery(rest)}`;
44
+ };
14
45
 
15
46
  const shareRoot = '/api/share';
16
47
  export const shareMessages = (shareId: string) => `${shareRoot}/${shareId}`;
@@ -43,10 +74,9 @@ export const abortRequest = (endpoint: string) => `/api/ask/${endpoint}/abort`;
43
74
 
44
75
  export const conversationsRoot = '/api/convos';
45
76
 
46
- export const conversations = (pageNumber: string, isArchived?: boolean, tags?: string[]) =>
47
- `${conversationsRoot}?pageNumber=${pageNumber}${
48
- isArchived === true ? '&isArchived=true' : ''
49
- }${tags?.map((tag) => `&tags=${tag}`).join('')}`;
77
+ export const conversations = (params: q.ConversationListParams) => {
78
+ return `${conversationsRoot}${buildQuery(params)}`;
79
+ };
50
80
 
51
81
  export const conversationById = (id: string) => `${conversationsRoot}/${id}`;
52
82
 
@@ -54,7 +84,9 @@ export const genTitle = () => `${conversationsRoot}/gen_title`;
54
84
 
55
85
  export const updateConversation = () => `${conversationsRoot}/update`;
56
86
 
57
- export const deleteConversation = () => `${conversationsRoot}/clear`;
87
+ export const deleteConversation = () => `${conversationsRoot}`;
88
+
89
+ export const deleteAllConversation = () => `${conversationsRoot}/all`;
58
90
 
59
91
  export const importConversation = () => `${conversationsRoot}/import`;
60
92
 
@@ -62,8 +94,8 @@ export const forkConversation = () => `${conversationsRoot}/fork`;
62
94
 
63
95
  export const duplicateConversation = () => `${conversationsRoot}/duplicate`;
64
96
 
65
- export const search = (q: string, pageNumber: string) =>
66
- `/api/search?q=${q}&pageNumber=${pageNumber}`;
97
+ export const search = (q: string, cursor?: string | null) =>
98
+ `/api/search?q=${q}${cursor ? `&cursor=${cursor}` : ''}`;
67
99
 
68
100
  export const searchEnabled = () => '/api/search/enable';
69
101
 
@@ -244,4 +276,4 @@ export const verifyTwoFactor = () => '/api/auth/2fa/verify';
244
276
  export const confirmTwoFactor = () => '/api/auth/2fa/confirm';
245
277
  export const disableTwoFactor = () => '/api/auth/2fa/disable';
246
278
  export const regenerateBackupCodes = () => '/api/auth/2fa/backup/regenerate';
247
- export const verifyTwoFactorTemp = () => '/api/auth/2fa/verify-temp';
279
+ export const verifyTwoFactorTemp = () => '/api/auth/2fa/verify-temp';
package/src/config.ts CHANGED
@@ -541,6 +541,7 @@ export type TStartupConfig = {
541
541
  analyticsGtmId?: string;
542
542
  instanceProjectId: string;
543
543
  bundlerURL?: string;
544
+ staticBundlerURL?: string;
544
545
  };
545
546
 
546
547
  export enum OCRStrategy {
@@ -855,15 +856,21 @@ export const visionModels = [
855
856
  'gpt-4o',
856
857
  'gpt-4-turbo',
857
858
  'gpt-4-vision',
859
+ 'o4-mini',
860
+ 'o3',
858
861
  'o1',
862
+ 'gpt-4.1',
859
863
  'gpt-4.5',
860
864
  'llava',
861
865
  'llava-13b',
862
866
  'gemini-pro-vision',
863
867
  'claude-3',
868
+ 'gemma',
864
869
  'gemini-exp',
865
870
  'gemini-1.5',
866
871
  'gemini-2.0',
872
+ 'gemini-2.5',
873
+ 'gemini-3',
867
874
  'moondream',
868
875
  'llama3.2-vision',
869
876
  'llama-3.2-11b-vision',
@@ -1007,6 +1014,10 @@ export enum CacheKeys {
1007
1014
  * Key for in-progress flow states.
1008
1015
  */
1009
1016
  FLOWS = 'flows',
1017
+ /**
1018
+ * Key for pending chat requests (concurrency check)
1019
+ */
1020
+ PENDING_REQ = 'pending_req',
1010
1021
  /**
1011
1022
  * Key for s3 check intervals per user
1012
1023
  */
@@ -1217,13 +1228,15 @@ export enum TTSProviders {
1217
1228
  /** Enum for app-wide constants */
1218
1229
  export enum Constants {
1219
1230
  /** Key for the app's version. */
1220
- VERSION = 'v0.7.7',
1231
+ VERSION = 'v0.7.8',
1221
1232
  /** Key for the Custom Config's version (librechat.yaml). */
1222
- CONFIG_VERSION = '1.2.4',
1233
+ CONFIG_VERSION = '1.2.5',
1223
1234
  /** Standard value for the first message's `parentMessageId` value, to indicate no parent exists. */
1224
1235
  NO_PARENT = '00000000-0000-0000-0000-000000000000',
1225
1236
  /** Standard value for the initial conversationId before a request is sent */
1226
1237
  NEW_CONVO = 'new',
1238
+ /** Standard value for the temporary conversationId after a request is sent and before the server responds */
1239
+ PENDING_CONVO = 'PENDING',
1227
1240
  /** Standard value for the conversationId used for search queries */
1228
1241
  SEARCH = 'search',
1229
1242
  /** Fixed, encoded domain length for Azure OpenAI Assistants Function name parsing. */
@@ -1244,6 +1257,8 @@ export enum Constants {
1244
1257
  GLOBAL_PROJECT_NAME = 'instance',
1245
1258
  /** Delimiter for MCP tools */
1246
1259
  mcp_delimiter = '_mcp_',
1260
+ /** Placeholder Agent ID for Ephemeral Agents */
1261
+ EPHEMERAL_AGENT_ID = 'ephemeral',
1247
1262
  }
1248
1263
 
1249
1264
  export enum LocalStorageKeys {
@@ -1279,6 +1294,10 @@ export enum LocalStorageKeys {
1279
1294
  ENABLE_USER_MSG_MARKDOWN = 'enableUserMsgMarkdown',
1280
1295
  /** Key for displaying analysis tool code input */
1281
1296
  SHOW_ANALYSIS_CODE = 'showAnalysisCode',
1297
+ /** Last selected MCP values per conversation ID */
1298
+ LAST_MCP_ = 'LAST_MCP_',
1299
+ /** Last checked toggle for Code Interpreter API per conversation ID */
1300
+ LAST_CODE_TOGGLE_ = 'LAST_CODE_TOGGLE_',
1282
1301
  }
1283
1302
 
1284
1303
  export enum ForkOptions {
@@ -1331,3 +1350,12 @@ export const providerEndpointMap = {
1331
1350
  [EModelEndpoint.anthropic]: EModelEndpoint.anthropic,
1332
1351
  [EModelEndpoint.azureOpenAI]: EModelEndpoint.azureOpenAI,
1333
1352
  };
1353
+
1354
+ export const specialVariables = {
1355
+ current_date: true,
1356
+ current_user: true,
1357
+ iso_datetime: true,
1358
+ current_datetime: true,
1359
+ };
1360
+
1361
+ export type TSpecialVarLabel = `com_ui_special_var_${keyof typeof specialVariables}`;
@@ -3,8 +3,15 @@ import { EndpointURLs } from './config';
3
3
  import * as s from './schemas';
4
4
 
5
5
  export default function createPayload(submission: t.TSubmission) {
6
- const { conversation, userMessage, endpointOption, isEdited, isContinued, isTemporary } =
7
- submission;
6
+ const {
7
+ conversation,
8
+ userMessage,
9
+ endpointOption,
10
+ isEdited,
11
+ isContinued,
12
+ isTemporary,
13
+ ephemeralAgent,
14
+ } = submission;
8
15
  const { conversationId } = s.tConvoUpdateSchema.parse(conversation);
9
16
  const { endpoint, endpointType } = endpointOption as {
10
17
  endpoint: s.EModelEndpoint;
@@ -12,16 +19,20 @@ export default function createPayload(submission: t.TSubmission) {
12
19
  };
13
20
 
14
21
  let server = EndpointURLs[endpointType ?? endpoint];
22
+ const isEphemeral = s.isEphemeralAgent(endpoint, ephemeralAgent);
15
23
 
16
24
  if (isEdited && s.isAssistantsEndpoint(endpoint)) {
17
25
  server += '/modify';
18
26
  } else if (isEdited) {
19
27
  server = server.replace('/ask/', '/edit/');
28
+ } else if (isEphemeral) {
29
+ server = `${EndpointURLs[s.EModelEndpoint.agents]}/${endpoint}`;
20
30
  }
21
31
 
22
32
  const payload: t.TPayload = {
23
33
  ...userMessage,
24
34
  ...endpointOption,
35
+ ephemeralAgent: isEphemeral ? ephemeralAgent : undefined,
25
36
  isContinued: !!(isEdited && isContinued),
26
37
  conversationId,
27
38
  isTemporary,
@@ -30,13 +30,6 @@ export function deleteUser(): Promise<s.TPreset> {
30
30
  return request.delete(endpoints.deleteUser());
31
31
  }
32
32
 
33
- export function getMessagesByConvoId(conversationId: string): Promise<s.TMessage[]> {
34
- if (conversationId === 'new') {
35
- return Promise.resolve([]);
36
- }
37
- return request.get(endpoints.messages(conversationId));
38
- }
39
-
40
33
  export function getSharedMessages(shareId: string): Promise<t.TSharedMessagesResponse> {
41
34
  return request.get(endpoints.shareMessages(shareId));
42
35
  }
@@ -67,31 +60,6 @@ export function deleteSharedLink(shareId: string): Promise<m.TDeleteSharedLinkRe
67
60
  return request.delete(endpoints.shareMessages(shareId));
68
61
  }
69
62
 
70
- export function updateMessage(payload: t.TUpdateMessageRequest): Promise<unknown> {
71
- const { conversationId, messageId, text } = payload;
72
- if (!conversationId) {
73
- throw new Error('conversationId is required');
74
- }
75
-
76
- return request.put(endpoints.messages(conversationId, messageId), { text });
77
- }
78
-
79
- export const editArtifact = async ({
80
- messageId,
81
- ...params
82
- }: m.TEditArtifactRequest): Promise<m.TEditArtifactResponse> => {
83
- return request.post(`/api/messages/artifact/${messageId}`, params);
84
- };
85
-
86
- export function updateMessageContent(payload: t.TUpdateMessageContent): Promise<unknown> {
87
- const { conversationId, messageId, index, text } = payload;
88
- if (!conversationId) {
89
- throw new Error('conversationId is required');
90
- }
91
-
92
- return request.put(endpoints.messages(conversationId, messageId), { text, index });
93
- }
94
-
95
63
  export function updateUserKey(payload: t.TUpdateUserKeyRequest) {
96
64
  const { value } = payload;
97
65
  if (!value) {
@@ -589,46 +557,21 @@ export function forkConversation(payload: t.TForkConvoRequest): Promise<t.TForkC
589
557
  }
590
558
 
591
559
  export function deleteConversation(payload: t.TDeleteConversationRequest) {
592
- //todo: this should be a DELETE request
593
- return request.post(endpoints.deleteConversation(), { arg: payload });
560
+ return request.deleteWithOptions(endpoints.deleteConversation(), { data: { arg: payload } });
594
561
  }
595
562
 
596
563
  export function clearAllConversations(): Promise<unknown> {
597
- return request.post(endpoints.deleteConversation(), { arg: {} });
564
+ return request.delete(endpoints.deleteAllConversation());
598
565
  }
599
566
 
600
567
  export const listConversations = (
601
568
  params?: q.ConversationListParams,
602
569
  ): Promise<q.ConversationListResponse> => {
603
- // Assuming params has a pageNumber property
604
- const pageNumber = (params?.pageNumber ?? '1') || '1'; // Default to page 1 if not provided
605
- const isArchived = params?.isArchived ?? false; // Default to false if not provided
606
- const tags = params?.tags || []; // Default to an empty array if not provided
607
- return request.get(endpoints.conversations(pageNumber, isArchived, tags));
608
- };
609
-
610
- export const listConversationsByQuery = (
611
- params?: q.ConversationListParams & { searchQuery?: string },
612
- ): Promise<q.ConversationListResponse> => {
613
- const pageNumber = (params?.pageNumber ?? '1') || '1'; // Default to page 1 if not provided
614
- const searchQuery = params?.searchQuery ?? ''; // If no search query is provided, default to an empty string
615
- // Update the endpoint to handle a search query
616
- if (searchQuery !== '') {
617
- return request.get(endpoints.search(searchQuery, pageNumber));
618
- } else {
619
- return request.get(endpoints.conversations(pageNumber));
620
- }
570
+ return request.get(endpoints.conversations(params ?? {}));
621
571
  };
622
572
 
623
- export const searchConversations = async (
624
- q: string,
625
- pageNumber: string,
626
- ): Promise<t.TSearchResults> => {
627
- return request.get(endpoints.search(q, pageNumber));
628
- };
629
-
630
- export function getConversations(pageNumber: string): Promise<t.TGetConversationsResponse> {
631
- return request.get(endpoints.conversations(pageNumber));
573
+ export function getConversations(cursor: string): Promise<t.TGetConversationsResponse> {
574
+ return request.get(endpoints.conversations({ cursor }));
632
575
  }
633
576
 
634
577
  export function getConversationById(id: string): Promise<s.TConversation> {
@@ -651,6 +594,45 @@ export function genTitle(payload: m.TGenTitleRequest): Promise<m.TGenTitleRespon
651
594
  return request.post(endpoints.genTitle(), payload);
652
595
  }
653
596
 
597
+ export const listMessages = (params?: q.MessagesListParams): Promise<q.MessagesListResponse> => {
598
+ return request.get(endpoints.messages(params ?? {}));
599
+ };
600
+
601
+ export function updateMessage(payload: t.TUpdateMessageRequest): Promise<unknown> {
602
+ const { conversationId, messageId, text } = payload;
603
+ if (!conversationId) {
604
+ throw new Error('conversationId is required');
605
+ }
606
+
607
+ return request.put(endpoints.messages({ conversationId, messageId }), { text });
608
+ }
609
+
610
+ export function updateMessageContent(payload: t.TUpdateMessageContent): Promise<unknown> {
611
+ const { conversationId, messageId, index, text } = payload;
612
+ if (!conversationId) {
613
+ throw new Error('conversationId is required');
614
+ }
615
+
616
+ return request.put(endpoints.messages({ conversationId, messageId }), { text, index });
617
+ }
618
+
619
+ export const editArtifact = async ({
620
+ messageId,
621
+ ...params
622
+ }: m.TEditArtifactRequest): Promise<m.TEditArtifactResponse> => {
623
+ return request.post(`/api/messages/artifact/${messageId}`, params);
624
+ };
625
+
626
+ export function getMessagesByConvoId(conversationId: string): Promise<s.TMessage[]> {
627
+ if (
628
+ conversationId === config.Constants.NEW_CONVO ||
629
+ conversationId === config.Constants.PENDING_CONVO
630
+ ) {
631
+ return Promise.resolve([]);
632
+ }
633
+ return request.get(endpoints.messages({ conversationId }));
634
+ }
635
+
654
636
  export function getPrompt(id: string): Promise<{ prompt: t.TPrompt }> {
655
637
  return request.get(endpoints.getPrompt(id));
656
638
  }
@@ -779,15 +761,11 @@ export function enableTwoFactor(): Promise<t.TEnable2FAResponse> {
779
761
  return request.get(endpoints.enableTwoFactor());
780
762
  }
781
763
 
782
- export function verifyTwoFactor(
783
- payload: t.TVerify2FARequest,
784
- ): Promise<t.TVerify2FAResponse> {
764
+ export function verifyTwoFactor(payload: t.TVerify2FARequest): Promise<t.TVerify2FAResponse> {
785
765
  return request.post(endpoints.verifyTwoFactor(), payload);
786
766
  }
787
767
 
788
- export function confirmTwoFactor(
789
- payload: t.TVerify2FARequest,
790
- ): Promise<t.TVerify2FAResponse> {
768
+ export function confirmTwoFactor(payload: t.TVerify2FARequest): Promise<t.TVerify2FAResponse> {
791
769
  return request.post(endpoints.confirmTwoFactor(), payload);
792
770
  }
793
771
 
@@ -803,4 +781,4 @@ export function verifyTwoFactorTemp(
803
781
  payload: t.TVerify2FATempRequest,
804
782
  ): Promise<t.TVerify2FATempResponse> {
805
783
  return request.post(endpoints.verifyTwoFactorTemp(), payload);
806
- }
784
+ }
@@ -112,7 +112,7 @@ export const excelMimeTypes =
112
112
  /^application\/(vnd\.ms-excel|msexcel|x-msexcel|x-ms-excel|x-excel|x-dos_ms_excel|xls|x-xls|vnd\.openxmlformats-officedocument\.spreadsheetml\.sheet)$/;
113
113
 
114
114
  export const textMimeTypes =
115
- /^(text\/(x-c|x-csharp|x-c\+\+|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv))$/;
115
+ /^(text\/(x-c|x-csharp|tab-separated-values|x-c\+\+|x-java|html|markdown|x-php|x-python|x-script\.python|x-ruby|x-tex|plain|css|vtt|javascript|csv))$/;
116
116
 
117
117
  export const applicationMimeTypes =
118
118
  /^(application\/(epub\+zip|csv|json|pdf|x-tar|typescript|vnd\.openxmlformats-officedocument\.(wordprocessingml\.document|presentationml\.presentation|spreadsheetml\.sheet)|xml|zip))$/;
@@ -152,6 +152,7 @@ export const codeTypeMapping: { [key: string]: string } = {
152
152
  yml: 'application/x-yaml',
153
153
  yaml: 'application/x-yaml',
154
154
  log: 'text/plain',
155
+ tsv: 'text/tab-separated-values',
155
156
  };
156
157
 
157
158
  export const retrievalMimeTypes = [
@@ -230,7 +231,7 @@ export const convertStringsToRegex = (patterns: string[]): RegExp[] =>
230
231
  const regex = new RegExp(pattern);
231
232
  acc.push(regex);
232
233
  } catch (error) {
233
- console.error(`Invalid regex pattern "${pattern}" skipped.`);
234
+ console.error(`Invalid regex pattern "${pattern}" skipped.`, error);
234
235
  }
235
236
  return acc;
236
237
  }, []);
package/src/index.ts CHANGED
@@ -15,6 +15,7 @@ export * from './models';
15
15
  /* mcp */
16
16
  export * from './mcp';
17
17
  /* RBAC */
18
+ export * from './permissions';
18
19
  export * from './roles';
19
20
  /* types (exports schemas from `./types` as they contain needed in other defs) */
20
21
  export * from './types';
package/src/mcp.ts CHANGED
@@ -5,6 +5,8 @@ const BaseOptionsSchema = z.object({
5
5
  iconPath: z.string().optional(),
6
6
  timeout: z.number().optional(),
7
7
  initTimeout: z.number().optional(),
8
+ /** Controls visibility in chat dropdown menu (MCPSelect) */
9
+ chatMenu: z.boolean().optional(),
8
10
  });
9
11
 
10
12
  export const StdioOptionsSchema = BaseOptionsSchema.extend({
@@ -96,28 +98,30 @@ export type MCPOptions = z.infer<typeof MCPOptionsSchema>;
96
98
  * @param {string} [userId] - The user ID
97
99
  * @returns {MCPOptions} - The processed object with environment variables replaced
98
100
  */
99
- export function processMCPEnv(obj: MCPOptions, userId?: string): MCPOptions {
101
+ export function processMCPEnv(obj: Readonly<MCPOptions>, userId?: string): MCPOptions {
100
102
  if (obj === null || obj === undefined) {
101
103
  return obj;
102
104
  }
103
105
 
104
- if ('env' in obj && obj.env) {
106
+ const newObj: MCPOptions = structuredClone(obj);
107
+
108
+ if ('env' in newObj && newObj.env) {
105
109
  const processedEnv: Record<string, string> = {};
106
- for (const [key, value] of Object.entries(obj.env)) {
110
+ for (const [key, value] of Object.entries(newObj.env)) {
107
111
  processedEnv[key] = extractEnvVariable(value);
108
112
  }
109
- obj.env = processedEnv;
110
- } else if ('headers' in obj && obj.headers) {
113
+ newObj.env = processedEnv;
114
+ } else if ('headers' in newObj && newObj.headers) {
111
115
  const processedHeaders: Record<string, string> = {};
112
- for (const [key, value] of Object.entries(obj.headers)) {
116
+ for (const [key, value] of Object.entries(newObj.headers)) {
113
117
  if (value === '{{LIBRECHAT_USER_ID}}' && userId != null && userId) {
114
118
  processedHeaders[key] = userId;
115
119
  continue;
116
120
  }
117
121
  processedHeaders[key] = extractEnvVariable(value);
118
122
  }
119
- obj.headers = processedHeaders;
123
+ newObj.headers = processedHeaders;
120
124
  }
121
125
 
122
- return obj;
126
+ return newObj;
123
127
  }
package/src/parsers.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import dayjs from 'dayjs';
1
2
  import type { ZodIssue } from 'zod';
2
3
  import type * as a from './types/assistants';
3
4
  import type * as s from './schemas';
@@ -13,8 +14,6 @@ import {
13
14
  // agentsSchema,
14
15
  compactAgentsSchema,
15
16
  compactGoogleSchema,
16
- compactChatGPTSchema,
17
- chatGPTBrowserSchema,
18
17
  compactPluginsSchema,
19
18
  compactAssistantSchema,
20
19
  } from './schemas';
@@ -26,19 +25,19 @@ type EndpointSchema =
26
25
  | typeof openAISchema
27
26
  | typeof googleSchema
28
27
  | typeof anthropicSchema
29
- | typeof chatGPTBrowserSchema
30
28
  | typeof gptPluginsSchema
31
29
  | typeof assistantSchema
32
30
  | typeof compactAgentsSchema
33
31
  | typeof bedrockInputSchema;
34
32
 
35
- const endpointSchemas: Record<EModelEndpoint, EndpointSchema> = {
33
+ export type EndpointSchemaKey = Exclude<EModelEndpoint, EModelEndpoint.chatGPTBrowser>;
34
+
35
+ const endpointSchemas: Record<EndpointSchemaKey, EndpointSchema> = {
36
36
  [EModelEndpoint.openAI]: openAISchema,
37
37
  [EModelEndpoint.azureOpenAI]: openAISchema,
38
38
  [EModelEndpoint.custom]: openAISchema,
39
39
  [EModelEndpoint.google]: googleSchema,
40
40
  [EModelEndpoint.anthropic]: anthropicSchema,
41
- [EModelEndpoint.chatGPTBrowser]: chatGPTBrowserSchema,
42
41
  [EModelEndpoint.gptPlugins]: gptPluginsSchema,
43
42
  [EModelEndpoint.assistants]: assistantSchema,
44
43
  [EModelEndpoint.azureAssistants]: assistantSchema,
@@ -167,8 +166,8 @@ export const parseConvo = ({
167
166
  conversation,
168
167
  possibleValues,
169
168
  }: {
170
- endpoint: EModelEndpoint;
171
- endpointType?: EModelEndpoint | null;
169
+ endpoint: EndpointSchemaKey;
170
+ endpointType?: EndpointSchemaKey | null;
172
171
  conversation: Partial<s.TConversation | s.TPreset> | null;
173
172
  possibleValues?: TPossibleValues;
174
173
  // TODO: POC for default schema
@@ -252,8 +251,10 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
252
251
  return modelLabel;
253
252
  } else if (model && extractOmniVersion(model)) {
254
253
  return extractOmniVersion(model);
255
- } else if (model && model.includes('mistral')) {
254
+ } else if (model && (model.includes('mistral') || model.includes('codestral'))) {
256
255
  return 'Mistral';
256
+ } else if (model && model.includes('deepseek')) {
257
+ return 'Deepseek';
257
258
  } else if (model && model.includes('gpt-')) {
258
259
  const gptVersion = extractGPTVersion(model);
259
260
  return gptVersion || 'GPT';
@@ -274,6 +275,8 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
274
275
  return modelLabel;
275
276
  } else if (model && (model.includes('gemini') || model.includes('learnlm'))) {
276
277
  return 'Gemini';
278
+ } else if (model?.toLowerCase().includes('gemma') === true) {
279
+ return 'Gemma';
277
280
  } else if (model && model.includes('code')) {
278
281
  return 'Codey';
279
282
  }
@@ -288,8 +291,10 @@ export const getResponseSender = (endpointOption: t.TEndpointOption): string =>
288
291
  return chatGptLabel;
289
292
  } else if (model && extractOmniVersion(model)) {
290
293
  return extractOmniVersion(model);
291
- } else if (model && model.includes('mistral')) {
294
+ } else if (model && (model.includes('mistral') || model.includes('codestral'))) {
292
295
  return 'Mistral';
296
+ } else if (model && model.includes('deepseek')) {
297
+ return 'Deepseek';
293
298
  } else if (model && model.includes('gpt-')) {
294
299
  const gptVersion = extractGPTVersion(model);
295
300
  return gptVersion || 'GPT';
@@ -309,11 +314,10 @@ type CompactEndpointSchema =
309
314
  | typeof compactAgentsSchema
310
315
  | typeof compactGoogleSchema
311
316
  | typeof anthropicSchema
312
- | typeof compactChatGPTSchema
313
317
  | typeof bedrockInputSchema
314
318
  | typeof compactPluginsSchema;
315
319
 
316
- const compactEndpointSchemas: Record<string, CompactEndpointSchema> = {
320
+ const compactEndpointSchemas: Record<EndpointSchemaKey, CompactEndpointSchema> = {
317
321
  [EModelEndpoint.openAI]: openAISchema,
318
322
  [EModelEndpoint.azureOpenAI]: openAISchema,
319
323
  [EModelEndpoint.custom]: openAISchema,
@@ -323,7 +327,6 @@ const compactEndpointSchemas: Record<string, CompactEndpointSchema> = {
323
327
  [EModelEndpoint.google]: compactGoogleSchema,
324
328
  [EModelEndpoint.bedrock]: bedrockInputSchema,
325
329
  [EModelEndpoint.anthropic]: anthropicSchema,
326
- [EModelEndpoint.chatGPTBrowser]: compactChatGPTSchema,
327
330
  [EModelEndpoint.gptPlugins]: compactPluginsSchema,
328
331
  };
329
332
 
@@ -333,8 +336,8 @@ export const parseCompactConvo = ({
333
336
  conversation,
334
337
  possibleValues,
335
338
  }: {
336
- endpoint?: EModelEndpoint;
337
- endpointType?: EModelEndpoint | null;
339
+ endpoint?: EndpointSchemaKey;
340
+ endpointType?: EndpointSchemaKey | null;
338
341
  conversation: Partial<s.TConversation | s.TPreset>;
339
342
  possibleValues?: TPossibleValues;
340
343
  // TODO: POC for default schema
@@ -371,7 +374,10 @@ export const parseCompactConvo = ({
371
374
  return convo;
372
375
  };
373
376
 
374
- export function parseTextParts(contentParts: a.TMessageContentParts[]): string {
377
+ export function parseTextParts(
378
+ contentParts: a.TMessageContentParts[],
379
+ skipReasoning: boolean = false,
380
+ ): string {
375
381
  let result = '';
376
382
 
377
383
  for (const part of contentParts) {
@@ -390,7 +396,7 @@ export function parseTextParts(contentParts: a.TMessageContentParts[]): string {
390
396
  result += ' ';
391
397
  }
392
398
  result += textValue;
393
- } else if (part.type === ContentTypes.THINK) {
399
+ } else if (part.type === ContentTypes.THINK && !skipReasoning) {
394
400
  const textValue = typeof part.think === 'string' ? part.think : '';
395
401
  if (
396
402
  result.length > 0 &&
@@ -419,3 +425,28 @@ export function findLastSeparatorIndex(text: string, separators = SEPARATORS): n
419
425
  }
420
426
  return lastIndex;
421
427
  }
428
+
429
+ export function replaceSpecialVars({ text, user }: { text: string; user?: t.TUser | null }) {
430
+ let result = text;
431
+ if (!result) {
432
+ return result;
433
+ }
434
+
435
+ // e.g., "2024-04-29 (1)" (1=Monday)
436
+ const currentDate = dayjs().format('YYYY-MM-DD');
437
+ const dayNumber = dayjs().day();
438
+ const combinedDate = `${currentDate} (${dayNumber})`;
439
+ result = result.replace(/{{current_date}}/gi, combinedDate);
440
+
441
+ const currentDatetime = dayjs().format('YYYY-MM-DD HH:mm:ss');
442
+ result = result.replace(/{{current_datetime}}/gi, `${currentDatetime} (${dayNumber})`);
443
+
444
+ const isoDatetime = dayjs().toISOString();
445
+ result = result.replace(/{{iso_datetime}}/gi, isoDatetime);
446
+
447
+ if (user && user.name) {
448
+ result = result.replace(/{{current_user}}/gi, user.name);
449
+ }
450
+
451
+ return result;
452
+ }