@librechat/data-schemas 0.0.23 → 0.0.31
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.cjs +2223 -1580
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +2189 -1555
- package/dist/index.es.js.map +1 -1
- package/dist/types/app/agents.d.ts +10 -0
- package/dist/types/app/assistants.d.ts +19 -0
- package/dist/types/app/azure.d.ts +7 -0
- package/dist/types/app/endpoints.d.ts +16 -0
- package/dist/types/app/index.d.ts +6 -0
- package/dist/types/app/interface.d.ts +13 -0
- package/dist/types/app/memory.d.ts +3 -0
- package/dist/types/app/ocr.d.ts +2 -0
- package/dist/types/app/service.d.ts +23 -0
- package/dist/types/app/specs.d.ts +9 -0
- package/dist/types/app/turnstile.d.ts +17 -0
- package/dist/types/app/web.d.ts +41 -0
- package/dist/types/app/web.spec.d.ts +1 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/methods/share.d.ts +2 -1
- package/dist/types/methods/user.methods.spec.d.ts +1 -0
- package/dist/types/schema/share.d.ts +1 -0
- package/dist/types/types/agent.d.ts +3 -0
- package/dist/types/types/app.d.ts +98 -0
- package/dist/types/types/index.d.ts +2 -0
- package/dist/types/types/message.d.ts +1 -0
- package/dist/types/types/role.d.ts +1 -4
- package/dist/types/types/share.d.ts +1 -0
- package/dist/types/types/token.d.ts +1 -0
- package/dist/types/types/web.d.ts +3 -0
- package/package.json +5 -5
package/dist/index.cjs
CHANGED
|
@@ -1,1875 +1,2378 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var librechatDataProvider = require('librechat-data-provider');
|
|
4
|
-
var jwt = require('jsonwebtoken');
|
|
5
|
-
var node_crypto = require('node:crypto');
|
|
6
|
-
var mongoose = require('mongoose');
|
|
7
4
|
var winston = require('winston');
|
|
8
5
|
require('winston-daily-rotate-file');
|
|
9
6
|
var klona = require('klona');
|
|
10
7
|
var path = require('path');
|
|
8
|
+
var jwt = require('jsonwebtoken');
|
|
9
|
+
var node_crypto = require('node:crypto');
|
|
10
|
+
var mongoose = require('mongoose');
|
|
11
11
|
var _ = require('lodash');
|
|
12
12
|
var meilisearch = require('meilisearch');
|
|
13
13
|
var nanoid = require('nanoid');
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Sets up the Agents configuration from the config (`librechat.yaml`) file.
|
|
17
|
+
* If no agents config is defined, uses the provided defaults or parses empty object.
|
|
18
|
+
*
|
|
19
|
+
* @param config - The loaded custom configuration.
|
|
20
|
+
* @param [defaultConfig] - Default configuration from getConfigDefaults.
|
|
21
|
+
* @returns The Agents endpoint configuration.
|
|
17
22
|
*/
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
RoleBits[RoleBits["OWNER"] = librechatDataProvider.PermissionBits.VIEW | librechatDataProvider.PermissionBits.EDIT | librechatDataProvider.PermissionBits.DELETE | librechatDataProvider.PermissionBits.SHARE] = "OWNER";
|
|
28
|
-
})(exports.RoleBits || (exports.RoleBits = {}));
|
|
23
|
+
function agentsConfigSetup(config, defaultConfig) {
|
|
24
|
+
var _a;
|
|
25
|
+
const agentsConfig = (_a = config === null || config === void 0 ? void 0 : config.endpoints) === null || _a === void 0 ? void 0 : _a[librechatDataProvider.EModelEndpoint.agents];
|
|
26
|
+
if (!agentsConfig) {
|
|
27
|
+
return defaultConfig || librechatDataProvider.agentsEndpointSchema.parse({});
|
|
28
|
+
}
|
|
29
|
+
const parsedConfig = librechatDataProvider.agentsEndpointSchema.parse(agentsConfig);
|
|
30
|
+
return parsedConfig;
|
|
31
|
+
}
|
|
29
32
|
|
|
30
|
-
|
|
31
|
-
|
|
33
|
+
const hasValidAgent = (agent) => !!agent &&
|
|
34
|
+
(('id' in agent && !!agent.id) ||
|
|
35
|
+
('provider' in agent && 'model' in agent && !!agent.provider && !!agent.model));
|
|
36
|
+
const isDisabled = (config) => !config || config.disabled === true;
|
|
37
|
+
function loadMemoryConfig(config) {
|
|
38
|
+
var _a;
|
|
39
|
+
if (!config)
|
|
40
|
+
return undefined;
|
|
41
|
+
if (isDisabled(config))
|
|
42
|
+
return config;
|
|
43
|
+
if (!hasValidAgent(config.agent)) {
|
|
44
|
+
return { ...config, disabled: true };
|
|
45
|
+
}
|
|
46
|
+
const charLimit = (_a = librechatDataProvider.memorySchema.shape.charLimit.safeParse(config.charLimit).data) !== null && _a !== void 0 ? _a : 10000;
|
|
47
|
+
return { ...config, charLimit };
|
|
32
48
|
}
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
return
|
|
49
|
+
function isMemoryEnabled(config) {
|
|
50
|
+
if (isDisabled(config))
|
|
51
|
+
return false;
|
|
52
|
+
return hasValidAgent(config.agent);
|
|
37
53
|
}
|
|
38
54
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
55
|
+
/**
|
|
56
|
+
* Loads the default interface object.
|
|
57
|
+
* @param params - The loaded custom configuration.
|
|
58
|
+
* @param params.config - The loaded custom configuration.
|
|
59
|
+
* @param params.configDefaults - The custom configuration default values.
|
|
60
|
+
* @returns default interface object.
|
|
61
|
+
*/
|
|
62
|
+
async function loadDefaultInterface({ config, configDefaults, }) {
|
|
63
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q;
|
|
64
|
+
const { interface: interfaceConfig } = config !== null && config !== void 0 ? config : {};
|
|
65
|
+
const { interface: defaults } = configDefaults;
|
|
66
|
+
const hasModelSpecs = ((_c = (_b = (_a = config === null || config === void 0 ? void 0 : config.modelSpecs) === null || _a === void 0 ? void 0 : _a.list) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 0;
|
|
67
|
+
const includesAddedEndpoints = ((_f = (_e = (_d = config === null || config === void 0 ? void 0 : config.modelSpecs) === null || _d === void 0 ? void 0 : _d.addedEndpoints) === null || _e === void 0 ? void 0 : _e.length) !== null && _f !== void 0 ? _f : 0) > 0;
|
|
68
|
+
const memoryConfig = config === null || config === void 0 ? void 0 : config.memory;
|
|
69
|
+
const memoryEnabled = isMemoryEnabled(memoryConfig);
|
|
70
|
+
/** Only disable memories if memory config is present but disabled/invalid */
|
|
71
|
+
const shouldDisableMemories = memoryConfig && !memoryEnabled;
|
|
72
|
+
const loadedInterface = librechatDataProvider.removeNullishValues({
|
|
73
|
+
// UI elements - use schema defaults
|
|
74
|
+
endpointsMenu: (_g = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.endpointsMenu) !== null && _g !== void 0 ? _g : (hasModelSpecs ? false : defaults.endpointsMenu),
|
|
75
|
+
modelSelect: (_h = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.modelSelect) !== null && _h !== void 0 ? _h : (hasModelSpecs ? includesAddedEndpoints : defaults.modelSelect),
|
|
76
|
+
parameters: (_j = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.parameters) !== null && _j !== void 0 ? _j : (hasModelSpecs ? false : defaults.parameters),
|
|
77
|
+
presets: (_k = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.presets) !== null && _k !== void 0 ? _k : (hasModelSpecs ? false : defaults.presets),
|
|
78
|
+
sidePanel: (_l = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.sidePanel) !== null && _l !== void 0 ? _l : defaults.sidePanel,
|
|
79
|
+
privacyPolicy: (_m = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.privacyPolicy) !== null && _m !== void 0 ? _m : defaults.privacyPolicy,
|
|
80
|
+
termsOfService: (_o = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.termsOfService) !== null && _o !== void 0 ? _o : defaults.termsOfService,
|
|
81
|
+
mcpServers: (_p = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.mcpServers) !== null && _p !== void 0 ? _p : defaults.mcpServers,
|
|
82
|
+
customWelcome: (_q = interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.customWelcome) !== null && _q !== void 0 ? _q : defaults.customWelcome,
|
|
83
|
+
// Permissions - only include if explicitly configured
|
|
84
|
+
bookmarks: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.bookmarks,
|
|
85
|
+
memories: shouldDisableMemories ? false : interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.memories,
|
|
86
|
+
prompts: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.prompts,
|
|
87
|
+
multiConvo: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.multiConvo,
|
|
88
|
+
agents: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.agents,
|
|
89
|
+
temporaryChat: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.temporaryChat,
|
|
90
|
+
runCode: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.runCode,
|
|
91
|
+
webSearch: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.webSearch,
|
|
92
|
+
fileSearch: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.fileSearch,
|
|
93
|
+
fileCitations: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.fileCitations,
|
|
94
|
+
peoplePicker: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.peoplePicker,
|
|
95
|
+
marketplace: interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.marketplace,
|
|
96
|
+
});
|
|
97
|
+
return loadedInterface;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* ESM-native object traversal utility
|
|
102
|
+
* Simplified implementation focused on the forEach use case
|
|
103
|
+
*/
|
|
104
|
+
function isObject(value) {
|
|
105
|
+
if (value === null || typeof value !== 'object') {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
// Treat these built-in types as leaf nodes, not objects to traverse
|
|
109
|
+
if (value instanceof Date)
|
|
110
|
+
return false;
|
|
111
|
+
if (value instanceof RegExp)
|
|
112
|
+
return false;
|
|
113
|
+
if (value instanceof Error)
|
|
114
|
+
return false;
|
|
115
|
+
if (value instanceof URL)
|
|
116
|
+
return false;
|
|
117
|
+
// Check for Buffer (Node.js)
|
|
118
|
+
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value))
|
|
119
|
+
return false;
|
|
120
|
+
// Check for TypedArrays and ArrayBuffer
|
|
121
|
+
if (ArrayBuffer.isView(value))
|
|
122
|
+
return false;
|
|
123
|
+
if (value instanceof ArrayBuffer)
|
|
124
|
+
return false;
|
|
125
|
+
if (value instanceof SharedArrayBuffer)
|
|
126
|
+
return false;
|
|
127
|
+
// Check for other built-in types that shouldn't be traversed
|
|
128
|
+
if (value instanceof Promise)
|
|
129
|
+
return false;
|
|
130
|
+
if (value instanceof WeakMap)
|
|
131
|
+
return false;
|
|
132
|
+
if (value instanceof WeakSet)
|
|
133
|
+
return false;
|
|
134
|
+
if (value instanceof Map)
|
|
135
|
+
return false;
|
|
136
|
+
if (value instanceof Set)
|
|
137
|
+
return false;
|
|
138
|
+
// Check if it's a primitive wrapper object
|
|
139
|
+
const stringTag = Object.prototype.toString.call(value);
|
|
140
|
+
if (stringTag === '[object Boolean]' ||
|
|
141
|
+
stringTag === '[object Number]' ||
|
|
142
|
+
stringTag === '[object String]') {
|
|
143
|
+
return false;
|
|
144
|
+
}
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
// Helper to safely set a property on an object or array
|
|
148
|
+
function setProperty(obj, key, value) {
|
|
149
|
+
if (Array.isArray(obj) && typeof key === 'number') {
|
|
150
|
+
obj[key] = value;
|
|
151
|
+
}
|
|
152
|
+
else if (!Array.isArray(obj) && typeof key === 'string') {
|
|
153
|
+
obj[key] = value;
|
|
154
|
+
}
|
|
155
|
+
else if (!Array.isArray(obj) && typeof key === 'number') {
|
|
156
|
+
// Handle numeric keys on objects
|
|
157
|
+
obj[key] = value;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
// Helper to safely delete a property from an object
|
|
161
|
+
function deleteProperty(obj, key) {
|
|
162
|
+
if (Array.isArray(obj) && typeof key === 'number') {
|
|
163
|
+
// For arrays, we should use splice, but this is handled in remove()
|
|
164
|
+
// This function is only called for non-array deletion
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
if (!Array.isArray(obj)) {
|
|
168
|
+
delete obj[key];
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
function forEach(obj, callback) {
|
|
172
|
+
const visited = new WeakSet();
|
|
173
|
+
function walk(node, path = [], parent) {
|
|
174
|
+
// Check for circular references
|
|
175
|
+
let circular = null;
|
|
176
|
+
if (isObject(node)) {
|
|
177
|
+
if (visited.has(node)) {
|
|
178
|
+
// Find the circular reference in the parent chain
|
|
179
|
+
let p = parent;
|
|
180
|
+
while (p) {
|
|
181
|
+
if (p.node === node) {
|
|
182
|
+
circular = p;
|
|
183
|
+
break;
|
|
184
|
+
}
|
|
185
|
+
p = p.parent;
|
|
186
|
+
}
|
|
187
|
+
return; // Skip circular references
|
|
188
|
+
}
|
|
189
|
+
visited.add(node);
|
|
190
|
+
}
|
|
191
|
+
const key = path.length > 0 ? path[path.length - 1] : undefined;
|
|
192
|
+
const isRoot = path.length === 0;
|
|
193
|
+
const level = path.length;
|
|
194
|
+
// Determine if this is a leaf node
|
|
195
|
+
const isLeaf = !isObject(node) ||
|
|
196
|
+
(Array.isArray(node) && node.length === 0) ||
|
|
197
|
+
Object.keys(node).length === 0;
|
|
198
|
+
// Create context
|
|
199
|
+
const context = {
|
|
200
|
+
node,
|
|
201
|
+
path: [...path],
|
|
202
|
+
parent,
|
|
203
|
+
key,
|
|
204
|
+
isLeaf,
|
|
205
|
+
notLeaf: !isLeaf,
|
|
206
|
+
isRoot,
|
|
207
|
+
notRoot: !isRoot,
|
|
208
|
+
level,
|
|
209
|
+
circular,
|
|
210
|
+
update(value) {
|
|
211
|
+
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
212
|
+
setProperty(parent.node, key, value);
|
|
213
|
+
}
|
|
214
|
+
this.node = value;
|
|
215
|
+
},
|
|
216
|
+
remove() {
|
|
217
|
+
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
218
|
+
if (Array.isArray(parent.node) && typeof key === 'number') {
|
|
219
|
+
parent.node.splice(key, 1);
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
deleteProperty(parent.node, key);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
// Call the callback with the context
|
|
228
|
+
callback.call(context, node);
|
|
229
|
+
// Traverse children if not circular and is an object
|
|
230
|
+
if (!circular && isObject(node) && !isLeaf) {
|
|
231
|
+
if (Array.isArray(node)) {
|
|
232
|
+
for (let i = 0; i < node.length; i++) {
|
|
233
|
+
walk(node[i], [...path, i], context);
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
for (const [childKey, childValue] of Object.entries(node)) {
|
|
238
|
+
walk(childValue, [...path, childKey], context);
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
walk(obj);
|
|
244
|
+
}
|
|
245
|
+
// Main traverse function that returns an object with forEach method
|
|
246
|
+
function traverse(obj) {
|
|
247
|
+
return {
|
|
248
|
+
forEach(callback) {
|
|
249
|
+
forEach(obj, callback);
|
|
75
250
|
},
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
oauth_client_id: String,
|
|
79
|
-
oauth_client_secret: String,
|
|
80
|
-
},
|
|
81
|
-
});
|
|
251
|
+
};
|
|
252
|
+
}
|
|
82
253
|
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
default: undefined,
|
|
142
|
-
},
|
|
143
|
-
hide_sequential_outputs: {
|
|
144
|
-
type: Boolean,
|
|
145
|
-
},
|
|
146
|
-
end_after_tools: {
|
|
147
|
-
type: Boolean,
|
|
148
|
-
},
|
|
149
|
-
agent_ids: {
|
|
150
|
-
type: [String],
|
|
151
|
-
},
|
|
152
|
-
isCollaborative: {
|
|
153
|
-
type: Boolean,
|
|
154
|
-
default: undefined,
|
|
155
|
-
},
|
|
156
|
-
conversation_starters: {
|
|
157
|
-
type: [String],
|
|
158
|
-
default: [],
|
|
159
|
-
},
|
|
160
|
-
tool_resources: {
|
|
161
|
-
type: mongoose.Schema.Types.Mixed,
|
|
162
|
-
default: {},
|
|
163
|
-
},
|
|
164
|
-
projectIds: {
|
|
165
|
-
type: [mongoose.Schema.Types.ObjectId],
|
|
166
|
-
ref: 'Project',
|
|
167
|
-
index: true,
|
|
168
|
-
},
|
|
169
|
-
versions: {
|
|
170
|
-
type: [mongoose.Schema.Types.Mixed],
|
|
171
|
-
default: [],
|
|
172
|
-
},
|
|
173
|
-
category: {
|
|
174
|
-
type: String,
|
|
175
|
-
trim: true,
|
|
176
|
-
index: true,
|
|
177
|
-
default: 'general',
|
|
178
|
-
},
|
|
179
|
-
support_contact: {
|
|
180
|
-
type: mongoose.Schema.Types.Mixed,
|
|
181
|
-
default: undefined,
|
|
182
|
-
},
|
|
183
|
-
is_promoted: {
|
|
184
|
-
type: Boolean,
|
|
185
|
-
default: false,
|
|
186
|
-
index: true,
|
|
187
|
-
},
|
|
188
|
-
}, {
|
|
189
|
-
timestamps: true,
|
|
190
|
-
});
|
|
191
|
-
agentSchema.index({ updatedAt: -1, _id: 1 });
|
|
192
|
-
|
|
193
|
-
const agentCategorySchema = new mongoose.Schema({
|
|
194
|
-
value: {
|
|
195
|
-
type: String,
|
|
196
|
-
required: true,
|
|
197
|
-
unique: true,
|
|
198
|
-
trim: true,
|
|
199
|
-
lowercase: true,
|
|
200
|
-
index: true,
|
|
201
|
-
},
|
|
202
|
-
label: {
|
|
203
|
-
type: String,
|
|
204
|
-
required: true,
|
|
205
|
-
trim: true,
|
|
206
|
-
},
|
|
207
|
-
description: {
|
|
208
|
-
type: String,
|
|
209
|
-
trim: true,
|
|
210
|
-
default: '',
|
|
211
|
-
},
|
|
212
|
-
order: {
|
|
213
|
-
type: Number,
|
|
214
|
-
default: 0,
|
|
215
|
-
index: true,
|
|
216
|
-
},
|
|
217
|
-
isActive: {
|
|
218
|
-
type: Boolean,
|
|
219
|
-
default: true,
|
|
220
|
-
index: true,
|
|
221
|
-
},
|
|
222
|
-
custom: {
|
|
223
|
-
type: Boolean,
|
|
224
|
-
default: false,
|
|
225
|
-
},
|
|
226
|
-
}, {
|
|
227
|
-
timestamps: true,
|
|
228
|
-
});
|
|
229
|
-
agentCategorySchema.index({ isActive: 1, order: 1 });
|
|
230
|
-
agentCategorySchema.index({ order: 1, label: 1 });
|
|
231
|
-
|
|
232
|
-
const assistantSchema = new mongoose.Schema({
|
|
233
|
-
user: {
|
|
234
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
235
|
-
ref: 'User',
|
|
236
|
-
required: true,
|
|
237
|
-
},
|
|
238
|
-
assistant_id: {
|
|
239
|
-
type: String,
|
|
240
|
-
index: true,
|
|
241
|
-
required: true,
|
|
242
|
-
},
|
|
243
|
-
avatar: {
|
|
244
|
-
type: mongoose.Schema.Types.Mixed,
|
|
245
|
-
default: undefined,
|
|
246
|
-
},
|
|
247
|
-
conversation_starters: {
|
|
248
|
-
type: [String],
|
|
249
|
-
default: [],
|
|
250
|
-
},
|
|
251
|
-
access_level: {
|
|
252
|
-
type: Number,
|
|
253
|
-
},
|
|
254
|
-
file_ids: { type: [String], default: undefined },
|
|
255
|
-
actions: { type: [String], default: undefined },
|
|
256
|
-
append_current_datetime: {
|
|
257
|
-
type: Boolean,
|
|
258
|
-
default: false,
|
|
259
|
-
},
|
|
260
|
-
}, {
|
|
261
|
-
timestamps: true,
|
|
262
|
-
});
|
|
263
|
-
|
|
264
|
-
const balanceSchema = new mongoose.Schema({
|
|
265
|
-
user: {
|
|
266
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
267
|
-
ref: 'User',
|
|
268
|
-
index: true,
|
|
269
|
-
required: true,
|
|
270
|
-
},
|
|
271
|
-
// 1000 tokenCredits = 1 mill ($0.001 USD)
|
|
272
|
-
tokenCredits: {
|
|
273
|
-
type: Number,
|
|
274
|
-
default: 0,
|
|
275
|
-
},
|
|
276
|
-
// Automatic refill settings
|
|
277
|
-
autoRefillEnabled: {
|
|
278
|
-
type: Boolean,
|
|
279
|
-
default: false,
|
|
280
|
-
},
|
|
281
|
-
refillIntervalValue: {
|
|
282
|
-
type: Number,
|
|
283
|
-
default: 30,
|
|
284
|
-
},
|
|
285
|
-
refillIntervalUnit: {
|
|
286
|
-
type: String,
|
|
287
|
-
enum: ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months'],
|
|
288
|
-
default: 'days',
|
|
289
|
-
},
|
|
290
|
-
lastRefill: {
|
|
291
|
-
type: Date,
|
|
292
|
-
default: Date.now,
|
|
293
|
-
},
|
|
294
|
-
// amount to add on each refill
|
|
295
|
-
refillAmount: {
|
|
296
|
-
type: Number,
|
|
297
|
-
default: 0,
|
|
298
|
-
},
|
|
299
|
-
});
|
|
300
|
-
|
|
301
|
-
const bannerSchema = new mongoose.Schema({
|
|
302
|
-
bannerId: {
|
|
303
|
-
type: String,
|
|
304
|
-
required: true,
|
|
305
|
-
},
|
|
306
|
-
message: {
|
|
307
|
-
type: String,
|
|
308
|
-
required: true,
|
|
309
|
-
},
|
|
310
|
-
displayFrom: {
|
|
311
|
-
type: Date,
|
|
312
|
-
required: true,
|
|
313
|
-
default: Date.now,
|
|
314
|
-
},
|
|
315
|
-
displayTo: {
|
|
316
|
-
type: Date,
|
|
317
|
-
},
|
|
318
|
-
type: {
|
|
319
|
-
type: String,
|
|
320
|
-
enum: ['banner', 'popup'],
|
|
321
|
-
default: 'banner',
|
|
322
|
-
},
|
|
323
|
-
isPublic: {
|
|
324
|
-
type: Boolean,
|
|
325
|
-
default: false,
|
|
326
|
-
},
|
|
327
|
-
}, { timestamps: true });
|
|
328
|
-
|
|
329
|
-
const categoriesSchema = new mongoose.Schema({
|
|
330
|
-
label: {
|
|
331
|
-
type: String,
|
|
332
|
-
required: true,
|
|
333
|
-
unique: true,
|
|
334
|
-
},
|
|
335
|
-
value: {
|
|
336
|
-
type: String,
|
|
337
|
-
required: true,
|
|
338
|
-
unique: true,
|
|
339
|
-
},
|
|
254
|
+
const SPLAT_SYMBOL = Symbol.for('splat');
|
|
255
|
+
const MESSAGE_SYMBOL = Symbol.for('message');
|
|
256
|
+
const CONSOLE_JSON_STRING_LENGTH = parseInt(process.env.CONSOLE_JSON_STRING_LENGTH || '', 10) || 255;
|
|
257
|
+
const DEBUG_MESSAGE_LENGTH = parseInt(process.env.DEBUG_MESSAGE_LENGTH || '', 10) || 150;
|
|
258
|
+
const sensitiveKeys = [
|
|
259
|
+
/^(sk-)[^\s]+/, // OpenAI API key pattern
|
|
260
|
+
/(Bearer )[^\s]+/, // Header: Bearer token pattern
|
|
261
|
+
/(api-key:? )[^\s]+/, // Header: API key pattern
|
|
262
|
+
/(key=)[^\s]+/, // URL query param: sensitive key pattern (Google)
|
|
263
|
+
];
|
|
264
|
+
/**
|
|
265
|
+
* Determines if a given value string is sensitive and returns matching regex patterns.
|
|
266
|
+
*
|
|
267
|
+
* @param valueStr - The value string to check.
|
|
268
|
+
* @returns An array of regex patterns that match the value string.
|
|
269
|
+
*/
|
|
270
|
+
function getMatchingSensitivePatterns(valueStr) {
|
|
271
|
+
if (valueStr) {
|
|
272
|
+
// Filter and return all regex patterns that match the value string
|
|
273
|
+
return sensitiveKeys.filter((regex) => regex.test(valueStr));
|
|
274
|
+
}
|
|
275
|
+
return [];
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Redacts sensitive information from a console message and trims it to a specified length if provided.
|
|
279
|
+
* @param str - The console message to be redacted.
|
|
280
|
+
* @param trimLength - The optional length at which to trim the redacted message.
|
|
281
|
+
* @returns The redacted and optionally trimmed console message.
|
|
282
|
+
*/
|
|
283
|
+
function redactMessage(str, trimLength) {
|
|
284
|
+
if (!str) {
|
|
285
|
+
return '';
|
|
286
|
+
}
|
|
287
|
+
const patterns = getMatchingSensitivePatterns(str);
|
|
288
|
+
patterns.forEach((pattern) => {
|
|
289
|
+
str = str.replace(pattern, '$1[REDACTED]');
|
|
290
|
+
});
|
|
291
|
+
return str;
|
|
292
|
+
}
|
|
293
|
+
/**
|
|
294
|
+
* Redacts sensitive information from log messages if the log level is 'error'.
|
|
295
|
+
* Note: Intentionally mutates the object.
|
|
296
|
+
* @param info - The log information object.
|
|
297
|
+
* @returns The modified log information object.
|
|
298
|
+
*/
|
|
299
|
+
const redactFormat = winston.format((info) => {
|
|
300
|
+
if (info.level === 'error') {
|
|
301
|
+
// Type guard to ensure message is a string
|
|
302
|
+
if (typeof info.message === 'string') {
|
|
303
|
+
info.message = redactMessage(info.message);
|
|
304
|
+
}
|
|
305
|
+
// Handle MESSAGE_SYMBOL with type safety
|
|
306
|
+
const symbolValue = info[MESSAGE_SYMBOL];
|
|
307
|
+
if (typeof symbolValue === 'string') {
|
|
308
|
+
info[MESSAGE_SYMBOL] = redactMessage(symbolValue);
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
return info;
|
|
340
312
|
});
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
// @ts-ignore
|
|
369
|
-
const conversationPreset = {
|
|
370
|
-
// endpoint: [azureOpenAI, openAI, anthropic, chatGPTBrowser]
|
|
371
|
-
endpoint: {
|
|
372
|
-
type: String,
|
|
373
|
-
default: null,
|
|
374
|
-
required: true,
|
|
375
|
-
},
|
|
376
|
-
endpointType: {
|
|
377
|
-
type: String,
|
|
378
|
-
},
|
|
379
|
-
// for azureOpenAI, openAI, chatGPTBrowser only
|
|
380
|
-
model: {
|
|
381
|
-
type: String,
|
|
382
|
-
required: false,
|
|
383
|
-
},
|
|
384
|
-
// for bedrock only
|
|
385
|
-
region: {
|
|
386
|
-
type: String,
|
|
387
|
-
required: false,
|
|
388
|
-
},
|
|
389
|
-
// for azureOpenAI, openAI only
|
|
390
|
-
chatGptLabel: {
|
|
391
|
-
type: String,
|
|
392
|
-
required: false,
|
|
393
|
-
},
|
|
394
|
-
// for google only
|
|
395
|
-
examples: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
396
|
-
modelLabel: {
|
|
397
|
-
type: String,
|
|
398
|
-
required: false,
|
|
399
|
-
},
|
|
400
|
-
promptPrefix: {
|
|
401
|
-
type: String,
|
|
402
|
-
required: false,
|
|
403
|
-
},
|
|
404
|
-
temperature: {
|
|
405
|
-
type: Number,
|
|
406
|
-
required: false,
|
|
407
|
-
},
|
|
408
|
-
top_p: {
|
|
409
|
-
type: Number,
|
|
410
|
-
required: false,
|
|
411
|
-
},
|
|
412
|
-
// for google only
|
|
413
|
-
topP: {
|
|
414
|
-
type: Number,
|
|
415
|
-
required: false,
|
|
416
|
-
},
|
|
417
|
-
topK: {
|
|
418
|
-
type: Number,
|
|
419
|
-
required: false,
|
|
420
|
-
},
|
|
421
|
-
maxOutputTokens: {
|
|
422
|
-
type: Number,
|
|
423
|
-
required: false,
|
|
424
|
-
},
|
|
425
|
-
maxTokens: {
|
|
426
|
-
type: Number,
|
|
427
|
-
required: false,
|
|
428
|
-
},
|
|
429
|
-
presence_penalty: {
|
|
430
|
-
type: Number,
|
|
431
|
-
required: false,
|
|
432
|
-
},
|
|
433
|
-
frequency_penalty: {
|
|
434
|
-
type: Number,
|
|
435
|
-
required: false,
|
|
436
|
-
},
|
|
437
|
-
file_ids: { type: [{ type: String }], default: undefined },
|
|
438
|
-
// deprecated
|
|
439
|
-
resendImages: {
|
|
440
|
-
type: Boolean,
|
|
441
|
-
},
|
|
442
|
-
/* Anthropic only */
|
|
443
|
-
promptCache: {
|
|
444
|
-
type: Boolean,
|
|
445
|
-
},
|
|
446
|
-
thinking: {
|
|
447
|
-
type: Boolean,
|
|
448
|
-
},
|
|
449
|
-
thinkingBudget: {
|
|
450
|
-
type: Number,
|
|
451
|
-
},
|
|
452
|
-
system: {
|
|
453
|
-
type: String,
|
|
454
|
-
},
|
|
455
|
-
// files
|
|
456
|
-
resendFiles: {
|
|
457
|
-
type: Boolean,
|
|
458
|
-
},
|
|
459
|
-
imageDetail: {
|
|
460
|
-
type: String,
|
|
461
|
-
},
|
|
462
|
-
/* agents */
|
|
463
|
-
agent_id: {
|
|
464
|
-
type: String,
|
|
465
|
-
},
|
|
466
|
-
/* assistants */
|
|
467
|
-
assistant_id: {
|
|
468
|
-
type: String,
|
|
469
|
-
},
|
|
470
|
-
instructions: {
|
|
471
|
-
type: String,
|
|
472
|
-
},
|
|
473
|
-
stop: { type: [{ type: String }], default: undefined },
|
|
474
|
-
isArchived: {
|
|
475
|
-
type: Boolean,
|
|
476
|
-
default: false,
|
|
477
|
-
},
|
|
478
|
-
/* UI Components */
|
|
479
|
-
iconURL: {
|
|
480
|
-
type: String,
|
|
481
|
-
},
|
|
482
|
-
greeting: {
|
|
483
|
-
type: String,
|
|
484
|
-
},
|
|
485
|
-
spec: {
|
|
486
|
-
type: String,
|
|
487
|
-
},
|
|
488
|
-
tags: {
|
|
489
|
-
type: [String],
|
|
490
|
-
default: [],
|
|
491
|
-
},
|
|
492
|
-
tools: { type: [{ type: String }], default: undefined },
|
|
493
|
-
maxContextTokens: {
|
|
494
|
-
type: Number,
|
|
495
|
-
},
|
|
496
|
-
max_tokens: {
|
|
497
|
-
type: Number,
|
|
498
|
-
},
|
|
499
|
-
useResponsesApi: {
|
|
500
|
-
type: Boolean,
|
|
501
|
-
},
|
|
502
|
-
/** OpenAI Responses API / Anthropic API / Google API */
|
|
503
|
-
web_search: {
|
|
504
|
-
type: Boolean,
|
|
505
|
-
},
|
|
506
|
-
disableStreaming: {
|
|
507
|
-
type: Boolean,
|
|
508
|
-
},
|
|
509
|
-
fileTokenLimit: {
|
|
510
|
-
type: Number,
|
|
511
|
-
},
|
|
512
|
-
/** Reasoning models only */
|
|
513
|
-
reasoning_effort: {
|
|
514
|
-
type: String,
|
|
515
|
-
},
|
|
516
|
-
reasoning_summary: {
|
|
517
|
-
type: String,
|
|
518
|
-
},
|
|
519
|
-
/** Verbosity control */
|
|
520
|
-
verbosity: {
|
|
521
|
-
type: String,
|
|
522
|
-
},
|
|
313
|
+
/**
|
|
314
|
+
* Truncates long strings, especially base64 image data, within log messages.
|
|
315
|
+
*
|
|
316
|
+
* @param value - The value to be inspected and potentially truncated.
|
|
317
|
+
* @param length - The length at which to truncate the value. Default: 100.
|
|
318
|
+
* @returns The truncated or original value.
|
|
319
|
+
*/
|
|
320
|
+
const truncateLongStrings = (value, length = 100) => {
|
|
321
|
+
if (typeof value === 'string') {
|
|
322
|
+
return value.length > length ? value.substring(0, length) + '... [truncated]' : value;
|
|
323
|
+
}
|
|
324
|
+
return value;
|
|
325
|
+
};
|
|
326
|
+
/**
|
|
327
|
+
* An array mapping function that truncates long strings (objects converted to JSON strings).
|
|
328
|
+
* @param item - The item to be condensed.
|
|
329
|
+
* @returns The condensed item.
|
|
330
|
+
*/
|
|
331
|
+
const condenseArray = (item) => {
|
|
332
|
+
if (typeof item === 'string') {
|
|
333
|
+
return truncateLongStrings(JSON.stringify(item));
|
|
334
|
+
}
|
|
335
|
+
else if (typeof item === 'object') {
|
|
336
|
+
return truncateLongStrings(JSON.stringify(item));
|
|
337
|
+
}
|
|
338
|
+
return item;
|
|
523
339
|
};
|
|
340
|
+
/**
|
|
341
|
+
* Formats log messages for debugging purposes.
|
|
342
|
+
* - Truncates long strings within log messages.
|
|
343
|
+
* - Condenses arrays by truncating long strings and objects as strings within array items.
|
|
344
|
+
* - Redacts sensitive information from log messages if the log level is 'error'.
|
|
345
|
+
* - Converts log information object to a formatted string.
|
|
346
|
+
*
|
|
347
|
+
* @param options - The options for formatting log messages.
|
|
348
|
+
* @returns The formatted log message.
|
|
349
|
+
*/
|
|
350
|
+
const debugTraverse = winston.format.printf(({ level, message, timestamp, ...metadata }) => {
|
|
351
|
+
if (!message) {
|
|
352
|
+
return `${timestamp} ${level}`;
|
|
353
|
+
}
|
|
354
|
+
// Type-safe version of the CJS logic: !message?.trim || typeof message !== 'string'
|
|
355
|
+
if (typeof message !== 'string' || !message.trim) {
|
|
356
|
+
return `${timestamp} ${level}: ${JSON.stringify(message)}`;
|
|
357
|
+
}
|
|
358
|
+
const msgParts = [
|
|
359
|
+
`${timestamp} ${level}: ${truncateLongStrings(message.trim(), DEBUG_MESSAGE_LENGTH)}`,
|
|
360
|
+
];
|
|
361
|
+
try {
|
|
362
|
+
if (level !== 'debug') {
|
|
363
|
+
return msgParts[0];
|
|
364
|
+
}
|
|
365
|
+
if (!metadata) {
|
|
366
|
+
return msgParts[0];
|
|
367
|
+
}
|
|
368
|
+
// Type-safe access to SPLAT_SYMBOL using bracket notation
|
|
369
|
+
const metadataRecord = metadata;
|
|
370
|
+
const splatArray = metadataRecord[SPLAT_SYMBOL];
|
|
371
|
+
const debugValue = Array.isArray(splatArray) ? splatArray[0] : undefined;
|
|
372
|
+
if (!debugValue) {
|
|
373
|
+
return msgParts[0];
|
|
374
|
+
}
|
|
375
|
+
if (debugValue && Array.isArray(debugValue)) {
|
|
376
|
+
msgParts.push(`\n${JSON.stringify(debugValue.map(condenseArray))}`);
|
|
377
|
+
return msgParts.join('');
|
|
378
|
+
}
|
|
379
|
+
if (typeof debugValue !== 'object') {
|
|
380
|
+
msgParts.push(` ${debugValue}`);
|
|
381
|
+
return msgParts.join('');
|
|
382
|
+
}
|
|
383
|
+
msgParts.push('\n{');
|
|
384
|
+
const copy = klona.klona(metadata);
|
|
385
|
+
try {
|
|
386
|
+
const traversal = traverse(copy);
|
|
387
|
+
traversal.forEach(function (value) {
|
|
388
|
+
var _a;
|
|
389
|
+
if (typeof (this === null || this === void 0 ? void 0 : this.key) === 'symbol') {
|
|
390
|
+
return;
|
|
391
|
+
}
|
|
392
|
+
let _parentKey = '';
|
|
393
|
+
const parent = this.parent;
|
|
394
|
+
if (typeof (parent === null || parent === void 0 ? void 0 : parent.key) !== 'symbol' && (parent === null || parent === void 0 ? void 0 : parent.key) !== undefined) {
|
|
395
|
+
_parentKey = String(parent.key);
|
|
396
|
+
}
|
|
397
|
+
const parentKey = `${parent && parent.notRoot ? _parentKey + '.' : ''}`;
|
|
398
|
+
const tabs = `${parent && parent.notRoot ? ' ' : ' '}`;
|
|
399
|
+
const currentKey = (_a = this === null || this === void 0 ? void 0 : this.key) !== null && _a !== void 0 ? _a : 'unknown';
|
|
400
|
+
if (this.isLeaf && typeof value === 'string') {
|
|
401
|
+
const truncatedText = truncateLongStrings(value);
|
|
402
|
+
msgParts.push(`\n${tabs}${parentKey}${currentKey}: ${JSON.stringify(truncatedText)},`);
|
|
403
|
+
}
|
|
404
|
+
else if (this.notLeaf && Array.isArray(value) && value.length > 0) {
|
|
405
|
+
const currentMessage = `\n${tabs}// ${value.length} ${String(currentKey).replace(/s$/, '')}(s)`;
|
|
406
|
+
this.update(currentMessage);
|
|
407
|
+
msgParts.push(currentMessage);
|
|
408
|
+
const stringifiedArray = value.map(condenseArray);
|
|
409
|
+
msgParts.push(`\n${tabs}${parentKey}${currentKey}: [${stringifiedArray}],`);
|
|
410
|
+
}
|
|
411
|
+
else if (this.isLeaf && typeof value === 'function') {
|
|
412
|
+
msgParts.push(`\n${tabs}${parentKey}${currentKey}: function,`);
|
|
413
|
+
}
|
|
414
|
+
else if (this.isLeaf) {
|
|
415
|
+
msgParts.push(`\n${tabs}${parentKey}${currentKey}: ${value},`);
|
|
416
|
+
}
|
|
417
|
+
});
|
|
418
|
+
}
|
|
419
|
+
catch (e) {
|
|
420
|
+
const errorMessage = e instanceof Error ? e.message : 'Unknown error';
|
|
421
|
+
msgParts.push(`\n[LOGGER TRAVERSAL ERROR] ${errorMessage}`);
|
|
422
|
+
}
|
|
423
|
+
msgParts.push('\n}');
|
|
424
|
+
return msgParts.join('');
|
|
425
|
+
}
|
|
426
|
+
catch (e) {
|
|
427
|
+
const errorMessage = e instanceof Error ? e.message : 'Unknown error';
|
|
428
|
+
msgParts.push(`\n[LOGGER PARSING ERROR] ${errorMessage}`);
|
|
429
|
+
return msgParts.join('');
|
|
430
|
+
}
|
|
431
|
+
});
|
|
432
|
+
/**
|
|
433
|
+
* Truncates long string values in JSON log objects.
|
|
434
|
+
* Prevents outputting extremely long values (e.g., base64, blobs).
|
|
435
|
+
*/
|
|
436
|
+
const jsonTruncateFormat = winston.format((info) => {
|
|
437
|
+
const truncateLongStrings = (str, maxLength) => str.length > maxLength ? str.substring(0, maxLength) + '...' : str;
|
|
438
|
+
const seen = new WeakSet();
|
|
439
|
+
const truncateObject = (obj) => {
|
|
440
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
441
|
+
return obj;
|
|
442
|
+
}
|
|
443
|
+
// Handle circular references - now with proper object type
|
|
444
|
+
if (seen.has(obj)) {
|
|
445
|
+
return '[Circular]';
|
|
446
|
+
}
|
|
447
|
+
seen.add(obj);
|
|
448
|
+
if (Array.isArray(obj)) {
|
|
449
|
+
return obj.map((item) => truncateObject(item));
|
|
450
|
+
}
|
|
451
|
+
// We know this is an object at this point
|
|
452
|
+
const objectRecord = obj;
|
|
453
|
+
const newObj = {};
|
|
454
|
+
Object.entries(objectRecord).forEach(([key, value]) => {
|
|
455
|
+
if (typeof value === 'string') {
|
|
456
|
+
newObj[key] = truncateLongStrings(value, CONSOLE_JSON_STRING_LENGTH);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
newObj[key] = truncateObject(value);
|
|
460
|
+
}
|
|
461
|
+
});
|
|
462
|
+
return newObj;
|
|
463
|
+
};
|
|
464
|
+
return truncateObject(info);
|
|
465
|
+
});
|
|
524
466
|
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
467
|
+
/**
|
|
468
|
+
* Determine the log directory in a cross-compatible way.
|
|
469
|
+
* Priority:
|
|
470
|
+
* 1. LIBRECHAT_LOG_DIR environment variable
|
|
471
|
+
* 2. If running within LibreChat monorepo (when cwd ends with /api), use api/logs
|
|
472
|
+
* 3. If api/logs exists relative to cwd, use that (for running from project root)
|
|
473
|
+
* 4. Otherwise, use logs directory relative to process.cwd()
|
|
474
|
+
*
|
|
475
|
+
* This avoids using __dirname which is not available in ESM modules
|
|
476
|
+
*/
|
|
477
|
+
const getLogDirectory = () => {
|
|
478
|
+
if (process.env.LIBRECHAT_LOG_DIR) {
|
|
479
|
+
return process.env.LIBRECHAT_LOG_DIR;
|
|
480
|
+
}
|
|
481
|
+
const cwd = process.cwd();
|
|
482
|
+
// Check if we're running from within the api directory
|
|
483
|
+
if (cwd.endsWith('/api') || cwd.endsWith('\\api')) {
|
|
484
|
+
return path.join(cwd, 'logs');
|
|
485
|
+
}
|
|
486
|
+
// Check if api/logs exists relative to current directory (running from project root)
|
|
487
|
+
// We'll just use the path and let the file system create it if needed
|
|
488
|
+
const apiLogsPath = path.join(cwd, 'api', 'logs');
|
|
489
|
+
// For LibreChat project structure, use api/logs
|
|
490
|
+
// For external consumers, they should set LIBRECHAT_LOG_DIR
|
|
491
|
+
if (cwd.includes('LibreChat')) {
|
|
492
|
+
return apiLogsPath;
|
|
493
|
+
}
|
|
494
|
+
// Default to logs directory relative to current working directory
|
|
495
|
+
return path.join(cwd, 'logs');
|
|
496
|
+
};
|
|
497
|
+
|
|
498
|
+
const logDir$1 = getLogDirectory();
|
|
499
|
+
const { NODE_ENV: NODE_ENV$1, DEBUG_LOGGING: DEBUG_LOGGING$1, CONSOLE_JSON, DEBUG_CONSOLE } = process.env;
|
|
500
|
+
const useConsoleJson = typeof CONSOLE_JSON === 'string' && CONSOLE_JSON.toLowerCase() === 'true';
|
|
501
|
+
const useDebugConsole = typeof DEBUG_CONSOLE === 'string' && DEBUG_CONSOLE.toLowerCase() === 'true';
|
|
502
|
+
const useDebugLogging$1 = typeof DEBUG_LOGGING$1 === 'string' && DEBUG_LOGGING$1.toLowerCase() === 'true';
|
|
503
|
+
const levels$1 = {
|
|
504
|
+
error: 0,
|
|
505
|
+
warn: 1,
|
|
506
|
+
info: 2,
|
|
507
|
+
http: 3,
|
|
508
|
+
verbose: 4,
|
|
509
|
+
debug: 5,
|
|
510
|
+
activity: 6,
|
|
511
|
+
silly: 7,
|
|
512
|
+
};
|
|
513
|
+
winston.addColors({
|
|
514
|
+
info: 'green',
|
|
515
|
+
warn: 'italic yellow',
|
|
516
|
+
error: 'red',
|
|
517
|
+
debug: 'blue',
|
|
518
|
+
});
|
|
519
|
+
const level$1 = () => {
|
|
520
|
+
const env = NODE_ENV$1 || 'development';
|
|
521
|
+
return env === 'development' ? 'debug' : 'warn';
|
|
522
|
+
};
|
|
523
|
+
const fileFormat$1 = winston.format.combine(redactFormat(), winston.format.timestamp({ format: () => new Date().toISOString() }), winston.format.errors({ stack: true }), winston.format.splat());
|
|
524
|
+
const transports$1 = [
|
|
525
|
+
new winston.transports.DailyRotateFile({
|
|
526
|
+
level: 'error',
|
|
527
|
+
filename: `${logDir$1}/error-%DATE%.log`,
|
|
528
|
+
datePattern: 'YYYY-MM-DD',
|
|
529
|
+
zippedArchive: true,
|
|
530
|
+
maxSize: '20m',
|
|
531
|
+
maxFiles: '14d',
|
|
532
|
+
format: winston.format.combine(fileFormat$1, winston.format.json()),
|
|
533
|
+
}),
|
|
534
|
+
];
|
|
535
|
+
if (useDebugLogging$1) {
|
|
536
|
+
transports$1.push(new winston.transports.DailyRotateFile({
|
|
537
|
+
level: 'debug',
|
|
538
|
+
filename: `${logDir$1}/debug-%DATE%.log`,
|
|
539
|
+
datePattern: 'YYYY-MM-DD',
|
|
540
|
+
zippedArchive: true,
|
|
541
|
+
maxSize: '20m',
|
|
542
|
+
maxFiles: '14d',
|
|
543
|
+
format: winston.format.combine(fileFormat$1, debugTraverse),
|
|
544
|
+
}));
|
|
545
|
+
}
|
|
546
|
+
const consoleFormat$1 = winston.format.combine(redactFormat(), winston.format.colorize({ all: true }), winston.format.timestamp({ format: 'YYYY-MM-DD HH:mm:ss' }), winston.format.printf((info) => {
|
|
547
|
+
const message = `${info.timestamp} ${info.level}: ${info.message}`;
|
|
548
|
+
return info.level.includes('error') ? redactMessage(message) : message;
|
|
549
|
+
}));
|
|
550
|
+
let consoleLogLevel = 'info';
|
|
551
|
+
if (useDebugConsole) {
|
|
552
|
+
consoleLogLevel = 'debug';
|
|
553
|
+
}
|
|
554
|
+
// Add console transport
|
|
555
|
+
if (useDebugConsole) {
|
|
556
|
+
transports$1.push(new winston.transports.Console({
|
|
557
|
+
level: consoleLogLevel,
|
|
558
|
+
format: useConsoleJson
|
|
559
|
+
? winston.format.combine(fileFormat$1, jsonTruncateFormat(), winston.format.json())
|
|
560
|
+
: winston.format.combine(fileFormat$1, debugTraverse),
|
|
561
|
+
}));
|
|
562
|
+
}
|
|
563
|
+
else if (useConsoleJson) {
|
|
564
|
+
transports$1.push(new winston.transports.Console({
|
|
565
|
+
level: consoleLogLevel,
|
|
566
|
+
format: winston.format.combine(fileFormat$1, jsonTruncateFormat(), winston.format.json()),
|
|
567
|
+
}));
|
|
568
|
+
}
|
|
569
|
+
else {
|
|
570
|
+
transports$1.push(new winston.transports.Console({
|
|
571
|
+
level: consoleLogLevel,
|
|
572
|
+
format: consoleFormat$1,
|
|
573
|
+
}));
|
|
574
|
+
}
|
|
575
|
+
// Create logger
|
|
576
|
+
const logger$1 = winston.createLogger({
|
|
577
|
+
level: level$1(),
|
|
578
|
+
levels: levels$1,
|
|
579
|
+
transports: transports$1,
|
|
580
|
+
});
|
|
581
|
+
|
|
582
|
+
/**
|
|
583
|
+
* Loads and maps the Cloudflare Turnstile configuration.
|
|
584
|
+
*
|
|
585
|
+
* Expected config structure:
|
|
586
|
+
*
|
|
587
|
+
* turnstile:
|
|
588
|
+
* siteKey: "your-site-key-here"
|
|
589
|
+
* options:
|
|
590
|
+
* language: "auto" // "auto" or an ISO 639-1 language code (e.g. en)
|
|
591
|
+
* size: "normal" // Options: "normal", "compact", "flexible", or "invisible"
|
|
592
|
+
*
|
|
593
|
+
* @param config - The loaded custom configuration.
|
|
594
|
+
* @param configDefaults - The custom configuration default values.
|
|
595
|
+
* @returns The mapped Turnstile configuration.
|
|
596
|
+
*/
|
|
597
|
+
function loadTurnstileConfig(config, configDefaults) {
|
|
598
|
+
var _a, _b;
|
|
599
|
+
const { turnstile: customTurnstile } = config !== null && config !== void 0 ? config : {};
|
|
600
|
+
const { turnstile: defaults } = configDefaults;
|
|
601
|
+
const loadedTurnstile = librechatDataProvider.removeNullishValues({
|
|
602
|
+
siteKey: (_a = customTurnstile === null || customTurnstile === void 0 ? void 0 : customTurnstile.siteKey) !== null && _a !== void 0 ? _a : defaults === null || defaults === void 0 ? void 0 : defaults.siteKey,
|
|
603
|
+
options: (_b = customTurnstile === null || customTurnstile === void 0 ? void 0 : customTurnstile.options) !== null && _b !== void 0 ? _b : defaults === null || defaults === void 0 ? void 0 : defaults.options,
|
|
604
|
+
});
|
|
605
|
+
const enabled = Boolean(loadedTurnstile.siteKey);
|
|
606
|
+
if (enabled) {
|
|
607
|
+
logger$1.debug('Turnstile is ENABLED with configuration:\n' + JSON.stringify(loadedTurnstile, null, 2));
|
|
608
|
+
}
|
|
609
|
+
else {
|
|
610
|
+
logger$1.debug('Turnstile is DISABLED (no siteKey provided).');
|
|
611
|
+
}
|
|
612
|
+
return loadedTurnstile;
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
const webSearchAuth = {
|
|
616
|
+
providers: {
|
|
617
|
+
serper: {
|
|
618
|
+
serperApiKey: 1,
|
|
619
|
+
},
|
|
620
|
+
searxng: {
|
|
621
|
+
searxngInstanceUrl: 1,
|
|
622
|
+
/** Optional (0) */
|
|
623
|
+
searxngApiKey: 0,
|
|
624
|
+
},
|
|
555
625
|
},
|
|
556
|
-
|
|
557
|
-
|
|
626
|
+
scrapers: {
|
|
627
|
+
firecrawl: {
|
|
628
|
+
firecrawlApiKey: 1,
|
|
629
|
+
/** Optional (0) */
|
|
630
|
+
firecrawlApiUrl: 0,
|
|
631
|
+
firecrawlVersion: 0,
|
|
632
|
+
},
|
|
633
|
+
serper: {
|
|
634
|
+
serperApiKey: 1,
|
|
635
|
+
},
|
|
558
636
|
},
|
|
559
|
-
|
|
560
|
-
|
|
637
|
+
rerankers: {
|
|
638
|
+
jina: {
|
|
639
|
+
jinaApiKey: 1,
|
|
640
|
+
/** Optional (0) */
|
|
641
|
+
jinaApiUrl: 0,
|
|
642
|
+
},
|
|
643
|
+
cohere: { cohereApiKey: 1 },
|
|
561
644
|
},
|
|
562
|
-
}
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
645
|
+
};
|
|
646
|
+
/**
|
|
647
|
+
* Extracts all unique API keys from the webSearchAuth configuration object
|
|
648
|
+
*/
|
|
649
|
+
function getWebSearchKeys() {
|
|
650
|
+
const keysSet = new Set();
|
|
651
|
+
// Iterate through each category (providers, scrapers, rerankers)
|
|
652
|
+
for (const category of Object.keys(webSearchAuth)) {
|
|
653
|
+
const categoryObj = webSearchAuth[category];
|
|
654
|
+
// Iterate through each service within the category
|
|
655
|
+
for (const service of Object.keys(categoryObj)) {
|
|
656
|
+
const serviceObj = categoryObj[service];
|
|
657
|
+
// Extract the API keys from the service and add to set for deduplication
|
|
658
|
+
for (const key of Object.keys(serviceObj)) {
|
|
659
|
+
keysSet.add(key);
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
return Array.from(keysSet);
|
|
664
|
+
}
|
|
665
|
+
const webSearchKeys = getWebSearchKeys();
|
|
666
|
+
function loadWebSearchConfig(config) {
|
|
667
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
668
|
+
const serperApiKey = (_a = config === null || config === void 0 ? void 0 : config.serperApiKey) !== null && _a !== void 0 ? _a : '${SERPER_API_KEY}';
|
|
669
|
+
const searxngInstanceUrl = (_b = config === null || config === void 0 ? void 0 : config.searxngInstanceUrl) !== null && _b !== void 0 ? _b : '${SEARXNG_INSTANCE_URL}';
|
|
670
|
+
const searxngApiKey = (_c = config === null || config === void 0 ? void 0 : config.searxngApiKey) !== null && _c !== void 0 ? _c : '${SEARXNG_API_KEY}';
|
|
671
|
+
const firecrawlApiKey = (_d = config === null || config === void 0 ? void 0 : config.firecrawlApiKey) !== null && _d !== void 0 ? _d : '${FIRECRAWL_API_KEY}';
|
|
672
|
+
const firecrawlApiUrl = (_e = config === null || config === void 0 ? void 0 : config.firecrawlApiUrl) !== null && _e !== void 0 ? _e : '${FIRECRAWL_API_URL}';
|
|
673
|
+
const firecrawlVersion = (_f = config === null || config === void 0 ? void 0 : config.firecrawlVersion) !== null && _f !== void 0 ? _f : '${FIRECRAWL_VERSION}';
|
|
674
|
+
const jinaApiKey = (_g = config === null || config === void 0 ? void 0 : config.jinaApiKey) !== null && _g !== void 0 ? _g : '${JINA_API_KEY}';
|
|
675
|
+
const jinaApiUrl = (_h = config === null || config === void 0 ? void 0 : config.jinaApiUrl) !== null && _h !== void 0 ? _h : '${JINA_API_URL}';
|
|
676
|
+
const cohereApiKey = (_j = config === null || config === void 0 ? void 0 : config.cohereApiKey) !== null && _j !== void 0 ? _j : '${COHERE_API_KEY}';
|
|
677
|
+
const safeSearch = (_k = config === null || config === void 0 ? void 0 : config.safeSearch) !== null && _k !== void 0 ? _k : librechatDataProvider.SafeSearchTypes.MODERATE;
|
|
678
|
+
return {
|
|
679
|
+
...config,
|
|
680
|
+
safeSearch,
|
|
681
|
+
jinaApiKey,
|
|
682
|
+
jinaApiUrl,
|
|
683
|
+
cohereApiKey,
|
|
684
|
+
serperApiKey,
|
|
685
|
+
searxngApiKey,
|
|
686
|
+
firecrawlApiKey,
|
|
687
|
+
firecrawlApiUrl,
|
|
688
|
+
firecrawlVersion,
|
|
689
|
+
searxngInstanceUrl,
|
|
690
|
+
};
|
|
691
|
+
}
|
|
566
692
|
|
|
567
|
-
|
|
693
|
+
/**
|
|
694
|
+
* Sets up Model Specs from the config (`librechat.yaml`) file.
|
|
695
|
+
* @param [endpoints] - The loaded custom configuration for endpoints.
|
|
696
|
+
* @param [modelSpecs] - The loaded custom configuration for model specs.
|
|
697
|
+
* @param [interfaceConfig] - The loaded interface configuration.
|
|
698
|
+
* @returns The processed model specs, if any.
|
|
699
|
+
*/
|
|
700
|
+
function processModelSpecs(endpoints, _modelSpecs, interfaceConfig) {
|
|
701
|
+
var _a, _b, _c, _d;
|
|
702
|
+
if (!_modelSpecs) {
|
|
703
|
+
return undefined;
|
|
704
|
+
}
|
|
705
|
+
const list = _modelSpecs.list;
|
|
706
|
+
const modelSpecs = [];
|
|
707
|
+
const customEndpoints = (_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints[librechatDataProvider.EModelEndpoint.custom]) !== null && _a !== void 0 ? _a : [];
|
|
708
|
+
if ((interfaceConfig === null || interfaceConfig === void 0 ? void 0 : interfaceConfig.modelSelect) !== true && ((_c = (_b = _modelSpecs.addedEndpoints) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 0) {
|
|
709
|
+
logger$1.warn(`To utilize \`addedEndpoints\`, which allows provider/model selections alongside model specs, set \`modelSelect: true\` in the interface configuration.
|
|
710
|
+
|
|
711
|
+
Example:
|
|
712
|
+
\`\`\`yaml
|
|
713
|
+
interface:
|
|
714
|
+
modelSelect: true
|
|
715
|
+
\`\`\`
|
|
716
|
+
`);
|
|
717
|
+
}
|
|
718
|
+
if (!list || list.length === 0) {
|
|
719
|
+
return undefined;
|
|
720
|
+
}
|
|
721
|
+
for (const spec of list) {
|
|
722
|
+
const currentEndpoint = (_d = spec.preset) === null || _d === void 0 ? void 0 : _d.endpoint;
|
|
723
|
+
if (!currentEndpoint) {
|
|
724
|
+
logger$1.warn('A model spec is missing the `endpoint` field within its `preset`. Skipping model spec...');
|
|
725
|
+
continue;
|
|
726
|
+
}
|
|
727
|
+
if (librechatDataProvider.EModelEndpoint[currentEndpoint] && currentEndpoint !== librechatDataProvider.EModelEndpoint.custom) {
|
|
728
|
+
modelSpecs.push(spec);
|
|
729
|
+
continue;
|
|
730
|
+
}
|
|
731
|
+
else if (currentEndpoint === librechatDataProvider.EModelEndpoint.custom) {
|
|
732
|
+
logger$1.warn(`Model Spec with endpoint "${currentEndpoint}" is not supported. You must specify the name of the custom endpoint (case-sensitive, as defined in your config). Skipping model spec...`);
|
|
733
|
+
continue;
|
|
734
|
+
}
|
|
735
|
+
const normalizedName = librechatDataProvider.normalizeEndpointName(currentEndpoint);
|
|
736
|
+
const endpoint = customEndpoints.find((customEndpoint) => normalizedName === librechatDataProvider.normalizeEndpointName(customEndpoint.name));
|
|
737
|
+
if (!endpoint) {
|
|
738
|
+
logger$1.warn(`Model spec with endpoint "${currentEndpoint}" was skipped: Endpoint not found in configuration. The \`endpoint\` value must exactly match either a system-defined endpoint or a custom endpoint defined by the user.
|
|
739
|
+
|
|
740
|
+
For more information, see the documentation at https://www.librechat.ai/docs/configuration/librechat_yaml/object_structure/model_specs#endpoint`);
|
|
741
|
+
continue;
|
|
742
|
+
}
|
|
743
|
+
modelSpecs.push({
|
|
744
|
+
...spec,
|
|
745
|
+
preset: {
|
|
746
|
+
...spec.preset,
|
|
747
|
+
endpoint: normalizedName,
|
|
748
|
+
},
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
return {
|
|
752
|
+
..._modelSpecs,
|
|
753
|
+
list: modelSpecs,
|
|
754
|
+
};
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/**
|
|
758
|
+
* Sets up the minimum, default Assistants configuration if Azure OpenAI Assistants option is enabled.
|
|
759
|
+
* @returns The Assistants endpoint configuration.
|
|
760
|
+
*/
|
|
761
|
+
function azureAssistantsDefaults() {
|
|
762
|
+
return {
|
|
763
|
+
capabilities: [librechatDataProvider.Capabilities.tools, librechatDataProvider.Capabilities.actions, librechatDataProvider.Capabilities.code_interpreter],
|
|
764
|
+
version: librechatDataProvider.defaultAssistantsVersion.azureAssistants,
|
|
765
|
+
};
|
|
766
|
+
}
|
|
767
|
+
/**
|
|
768
|
+
* Sets up the Assistants configuration from the config (`librechat.yaml`) file.
|
|
769
|
+
* @param config - The loaded custom configuration.
|
|
770
|
+
* @param assistantsEndpoint - The Assistants endpoint name.
|
|
771
|
+
* - The previously loaded assistants configuration from Azure OpenAI Assistants option.
|
|
772
|
+
* @param [prevConfig]
|
|
773
|
+
* @returns The Assistants endpoint configuration.
|
|
774
|
+
*/
|
|
775
|
+
function assistantsConfigSetup(config, assistantsEndpoint, prevConfig = {}) {
|
|
776
|
+
var _a, _b, _c, _d, _e;
|
|
777
|
+
const assistantsConfig = (_a = config.endpoints) === null || _a === void 0 ? void 0 : _a[assistantsEndpoint];
|
|
778
|
+
const parsedConfig = librechatDataProvider.assistantEndpointSchema.parse(assistantsConfig);
|
|
779
|
+
if (((_b = assistantsConfig === null || assistantsConfig === void 0 ? void 0 : assistantsConfig.supportedIds) === null || _b === void 0 ? void 0 : _b.length) && ((_c = assistantsConfig.excludedIds) === null || _c === void 0 ? void 0 : _c.length)) {
|
|
780
|
+
logger$1.warn(`Configuration conflict: The '${assistantsEndpoint}' endpoint has both 'supportedIds' and 'excludedIds' defined. The 'excludedIds' will be ignored.`);
|
|
781
|
+
}
|
|
782
|
+
if ((assistantsConfig === null || assistantsConfig === void 0 ? void 0 : assistantsConfig.privateAssistants) &&
|
|
783
|
+
(((_d = assistantsConfig.supportedIds) === null || _d === void 0 ? void 0 : _d.length) || ((_e = assistantsConfig.excludedIds) === null || _e === void 0 ? void 0 : _e.length))) {
|
|
784
|
+
logger$1.warn(`Configuration conflict: The '${assistantsEndpoint}' endpoint has both 'privateAssistants' and 'supportedIds' or 'excludedIds' defined. The 'supportedIds' and 'excludedIds' will be ignored.`);
|
|
785
|
+
}
|
|
786
|
+
return {
|
|
787
|
+
...prevConfig,
|
|
788
|
+
retrievalModels: parsedConfig.retrievalModels,
|
|
789
|
+
disableBuilder: parsedConfig.disableBuilder,
|
|
790
|
+
pollIntervalMs: parsedConfig.pollIntervalMs,
|
|
791
|
+
supportedIds: parsedConfig.supportedIds,
|
|
792
|
+
capabilities: parsedConfig.capabilities,
|
|
793
|
+
excludedIds: parsedConfig.excludedIds,
|
|
794
|
+
privateAssistants: parsedConfig.privateAssistants,
|
|
795
|
+
timeoutMs: parsedConfig.timeoutMs,
|
|
796
|
+
streamRate: parsedConfig.streamRate,
|
|
797
|
+
titlePrompt: parsedConfig.titlePrompt,
|
|
798
|
+
titleMethod: parsedConfig.titleMethod,
|
|
799
|
+
titleModel: parsedConfig.titleModel,
|
|
800
|
+
titleEndpoint: parsedConfig.titleEndpoint,
|
|
801
|
+
titlePromptTemplate: parsedConfig.titlePromptTemplate,
|
|
802
|
+
};
|
|
803
|
+
}
|
|
804
|
+
|
|
805
|
+
/**
|
|
806
|
+
* Sets up the Azure OpenAI configuration from the config (`librechat.yaml`) file.
|
|
807
|
+
* @param config - The loaded custom configuration.
|
|
808
|
+
* @returns The Azure OpenAI configuration.
|
|
809
|
+
*/
|
|
810
|
+
function azureConfigSetup(config) {
|
|
811
|
+
var _a, _b, _c;
|
|
812
|
+
const azureConfig = (_a = config.endpoints) === null || _a === void 0 ? void 0 : _a[librechatDataProvider.EModelEndpoint.azureOpenAI];
|
|
813
|
+
if (!azureConfig) {
|
|
814
|
+
throw new Error('Azure OpenAI configuration is missing.');
|
|
815
|
+
}
|
|
816
|
+
const { groups, ...azureConfiguration } = azureConfig;
|
|
817
|
+
const { isValid, modelNames, modelGroupMap, groupMap, errors } = librechatDataProvider.validateAzureGroups(groups);
|
|
818
|
+
if (!isValid) {
|
|
819
|
+
const errorString = errors.join('\n');
|
|
820
|
+
const errorMessage = 'Invalid Azure OpenAI configuration:\n' + errorString;
|
|
821
|
+
logger$1.error(errorMessage);
|
|
822
|
+
throw new Error(errorMessage);
|
|
823
|
+
}
|
|
824
|
+
const assistantModels = [];
|
|
825
|
+
const assistantGroups = new Set();
|
|
826
|
+
for (const modelName of modelNames) {
|
|
827
|
+
librechatDataProvider.mapModelToAzureConfig({ modelName, modelGroupMap, groupMap });
|
|
828
|
+
const groupName = (_b = modelGroupMap === null || modelGroupMap === void 0 ? void 0 : modelGroupMap[modelName]) === null || _b === void 0 ? void 0 : _b.group;
|
|
829
|
+
const modelGroup = groupMap === null || groupMap === void 0 ? void 0 : groupMap[groupName];
|
|
830
|
+
const supportsAssistants = (modelGroup === null || modelGroup === void 0 ? void 0 : modelGroup.assistants) || ((_c = modelGroup === null || modelGroup === void 0 ? void 0 : modelGroup[modelName]) === null || _c === void 0 ? void 0 : _c.assistants);
|
|
831
|
+
if (supportsAssistants) {
|
|
832
|
+
assistantModels.push(modelName);
|
|
833
|
+
if (!assistantGroups.has(groupName)) {
|
|
834
|
+
assistantGroups.add(groupName);
|
|
835
|
+
}
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
if (azureConfiguration.assistants && assistantModels.length === 0) {
|
|
839
|
+
throw new Error('No Azure models are configured to support assistants. Please remove the `assistants` field or configure at least one model to support assistants.');
|
|
840
|
+
}
|
|
841
|
+
if (azureConfiguration.assistants &&
|
|
842
|
+
process.env.ENDPOINTS &&
|
|
843
|
+
!process.env.ENDPOINTS.includes(librechatDataProvider.EModelEndpoint.azureAssistants)) {
|
|
844
|
+
logger$1.warn(`Azure Assistants are configured, but the endpoint will not be accessible as it's not included in the ENDPOINTS environment variable.
|
|
845
|
+
Please add the value "${librechatDataProvider.EModelEndpoint.azureAssistants}" to the ENDPOINTS list if expected.`);
|
|
846
|
+
}
|
|
847
|
+
return {
|
|
848
|
+
errors,
|
|
849
|
+
isValid,
|
|
850
|
+
groupMap,
|
|
851
|
+
modelNames,
|
|
852
|
+
modelGroupMap,
|
|
853
|
+
assistantModels,
|
|
854
|
+
assistantGroups: Array.from(assistantGroups),
|
|
855
|
+
...azureConfiguration,
|
|
856
|
+
};
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
/**
|
|
860
|
+
* Loads custom config endpoints
|
|
861
|
+
* @param [config]
|
|
862
|
+
* @param [agentsDefaults]
|
|
863
|
+
*/
|
|
864
|
+
const loadEndpoints = (config, agentsDefaults) => {
|
|
865
|
+
var _a;
|
|
866
|
+
const loadedEndpoints = {};
|
|
867
|
+
const endpoints = config === null || config === void 0 ? void 0 : config.endpoints;
|
|
868
|
+
if (endpoints === null || endpoints === void 0 ? void 0 : endpoints[librechatDataProvider.EModelEndpoint.azureOpenAI]) {
|
|
869
|
+
loadedEndpoints[librechatDataProvider.EModelEndpoint.azureOpenAI] = azureConfigSetup(config);
|
|
870
|
+
}
|
|
871
|
+
if ((_a = endpoints === null || endpoints === void 0 ? void 0 : endpoints[librechatDataProvider.EModelEndpoint.azureOpenAI]) === null || _a === void 0 ? void 0 : _a.assistants) {
|
|
872
|
+
loadedEndpoints[librechatDataProvider.EModelEndpoint.azureAssistants] = azureAssistantsDefaults();
|
|
873
|
+
}
|
|
874
|
+
if (endpoints === null || endpoints === void 0 ? void 0 : endpoints[librechatDataProvider.EModelEndpoint.azureAssistants]) {
|
|
875
|
+
loadedEndpoints[librechatDataProvider.EModelEndpoint.azureAssistants] = assistantsConfigSetup(config, librechatDataProvider.EModelEndpoint.azureAssistants, loadedEndpoints[librechatDataProvider.EModelEndpoint.azureAssistants]);
|
|
876
|
+
}
|
|
877
|
+
if (endpoints === null || endpoints === void 0 ? void 0 : endpoints[librechatDataProvider.EModelEndpoint.assistants]) {
|
|
878
|
+
loadedEndpoints[librechatDataProvider.EModelEndpoint.assistants] = assistantsConfigSetup(config, librechatDataProvider.EModelEndpoint.assistants, loadedEndpoints[librechatDataProvider.EModelEndpoint.assistants]);
|
|
879
|
+
}
|
|
880
|
+
loadedEndpoints[librechatDataProvider.EModelEndpoint.agents] = agentsConfigSetup(config, agentsDefaults);
|
|
881
|
+
const endpointKeys = [
|
|
882
|
+
librechatDataProvider.EModelEndpoint.openAI,
|
|
883
|
+
librechatDataProvider.EModelEndpoint.google,
|
|
884
|
+
librechatDataProvider.EModelEndpoint.custom,
|
|
885
|
+
librechatDataProvider.EModelEndpoint.bedrock,
|
|
886
|
+
librechatDataProvider.EModelEndpoint.anthropic,
|
|
887
|
+
];
|
|
888
|
+
endpointKeys.forEach((key) => {
|
|
889
|
+
const currentKey = key;
|
|
890
|
+
if (endpoints === null || endpoints === void 0 ? void 0 : endpoints[currentKey]) {
|
|
891
|
+
loadedEndpoints[currentKey] = endpoints[currentKey];
|
|
892
|
+
}
|
|
893
|
+
});
|
|
894
|
+
if (endpoints === null || endpoints === void 0 ? void 0 : endpoints.all) {
|
|
895
|
+
loadedEndpoints.all = endpoints.all;
|
|
896
|
+
}
|
|
897
|
+
return loadedEndpoints;
|
|
898
|
+
};
|
|
899
|
+
|
|
900
|
+
function loadOCRConfig(config) {
|
|
901
|
+
var _a, _b, _c, _d;
|
|
902
|
+
if (!config)
|
|
903
|
+
return;
|
|
904
|
+
const baseURL = (_a = config === null || config === void 0 ? void 0 : config.baseURL) !== null && _a !== void 0 ? _a : '';
|
|
905
|
+
const apiKey = (_b = config === null || config === void 0 ? void 0 : config.apiKey) !== null && _b !== void 0 ? _b : '';
|
|
906
|
+
const mistralModel = (_c = config === null || config === void 0 ? void 0 : config.mistralModel) !== null && _c !== void 0 ? _c : '';
|
|
907
|
+
return {
|
|
908
|
+
apiKey,
|
|
909
|
+
baseURL,
|
|
910
|
+
mistralModel,
|
|
911
|
+
strategy: (_d = config === null || config === void 0 ? void 0 : config.strategy) !== null && _d !== void 0 ? _d : librechatDataProvider.OCRStrategy.MISTRAL_OCR,
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Loads custom config and initializes app-wide variables.
|
|
917
|
+
* @function AppService
|
|
918
|
+
*/
|
|
919
|
+
const AppService = async (params) => {
|
|
920
|
+
var _a, _b, _c, _d, _e, _f;
|
|
921
|
+
const { config, paths, systemTools } = params || {};
|
|
922
|
+
if (!config) {
|
|
923
|
+
throw new Error('Config is required');
|
|
924
|
+
}
|
|
925
|
+
const configDefaults = librechatDataProvider.getConfigDefaults();
|
|
926
|
+
const ocr = loadOCRConfig(config.ocr);
|
|
927
|
+
const webSearch = loadWebSearchConfig(config.webSearch);
|
|
928
|
+
const memory = loadMemoryConfig(config.memory);
|
|
929
|
+
const filteredTools = config.filteredTools;
|
|
930
|
+
const includedTools = config.includedTools;
|
|
931
|
+
const fileStrategy = ((_a = config.fileStrategy) !== null && _a !== void 0 ? _a : configDefaults.fileStrategy);
|
|
932
|
+
const startBalance = process.env.START_BALANCE;
|
|
933
|
+
const balance = (_b = config.balance) !== null && _b !== void 0 ? _b : {
|
|
934
|
+
enabled: ((_c = process.env.CHECK_BALANCE) === null || _c === void 0 ? void 0 : _c.toLowerCase().trim()) === 'true',
|
|
935
|
+
startBalance: startBalance ? parseInt(startBalance, 10) : undefined,
|
|
936
|
+
};
|
|
937
|
+
const transactions = (_d = config.transactions) !== null && _d !== void 0 ? _d : configDefaults.transactions;
|
|
938
|
+
const imageOutputType = (_e = config === null || config === void 0 ? void 0 : config.imageOutputType) !== null && _e !== void 0 ? _e : configDefaults.imageOutputType;
|
|
939
|
+
process.env.CDN_PROVIDER = fileStrategy;
|
|
940
|
+
const availableTools = systemTools;
|
|
941
|
+
const mcpConfig = config.mcpServers || null;
|
|
942
|
+
const registration = (_f = config.registration) !== null && _f !== void 0 ? _f : configDefaults.registration;
|
|
943
|
+
const interfaceConfig = await loadDefaultInterface({ config, configDefaults });
|
|
944
|
+
const turnstileConfig = loadTurnstileConfig(config, configDefaults);
|
|
945
|
+
const speech = config.speech;
|
|
946
|
+
const defaultConfig = {
|
|
947
|
+
ocr,
|
|
948
|
+
paths,
|
|
949
|
+
config,
|
|
950
|
+
memory,
|
|
951
|
+
speech,
|
|
952
|
+
balance,
|
|
953
|
+
transactions,
|
|
954
|
+
mcpConfig,
|
|
955
|
+
webSearch,
|
|
956
|
+
fileStrategy,
|
|
957
|
+
registration,
|
|
958
|
+
filteredTools,
|
|
959
|
+
includedTools,
|
|
960
|
+
availableTools,
|
|
961
|
+
imageOutputType,
|
|
962
|
+
interfaceConfig,
|
|
963
|
+
turnstileConfig,
|
|
964
|
+
fileStrategies: config.fileStrategies,
|
|
965
|
+
};
|
|
966
|
+
const agentsDefaults = agentsConfigSetup(config);
|
|
967
|
+
if (!Object.keys(config).length) {
|
|
968
|
+
const appConfig = {
|
|
969
|
+
...defaultConfig,
|
|
970
|
+
endpoints: {
|
|
971
|
+
[librechatDataProvider.EModelEndpoint.agents]: agentsDefaults,
|
|
972
|
+
},
|
|
973
|
+
};
|
|
974
|
+
return appConfig;
|
|
975
|
+
}
|
|
976
|
+
const loadedEndpoints = loadEndpoints(config, agentsDefaults);
|
|
977
|
+
const appConfig = {
|
|
978
|
+
...defaultConfig,
|
|
979
|
+
fileConfig: config === null || config === void 0 ? void 0 : config.fileConfig,
|
|
980
|
+
secureImageLinks: config === null || config === void 0 ? void 0 : config.secureImageLinks,
|
|
981
|
+
modelSpecs: processModelSpecs(config === null || config === void 0 ? void 0 : config.endpoints, config.modelSpecs, interfaceConfig),
|
|
982
|
+
endpoints: loadedEndpoints,
|
|
983
|
+
};
|
|
984
|
+
return appConfig;
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
/**
|
|
988
|
+
* Common role combinations
|
|
989
|
+
*/
|
|
990
|
+
exports.RoleBits = void 0;
|
|
991
|
+
(function (RoleBits) {
|
|
992
|
+
/** 0001 = 1 */
|
|
993
|
+
RoleBits[RoleBits["VIEWER"] = librechatDataProvider.PermissionBits.VIEW] = "VIEWER";
|
|
994
|
+
/** 0011 = 3 */
|
|
995
|
+
RoleBits[RoleBits["EDITOR"] = librechatDataProvider.PermissionBits.VIEW | librechatDataProvider.PermissionBits.EDIT] = "EDITOR";
|
|
996
|
+
/** 0111 = 7 */
|
|
997
|
+
RoleBits[RoleBits["MANAGER"] = librechatDataProvider.PermissionBits.VIEW | librechatDataProvider.PermissionBits.EDIT | librechatDataProvider.PermissionBits.DELETE] = "MANAGER";
|
|
998
|
+
/** 1111 = 15 */
|
|
999
|
+
RoleBits[RoleBits["OWNER"] = librechatDataProvider.PermissionBits.VIEW | librechatDataProvider.PermissionBits.EDIT | librechatDataProvider.PermissionBits.DELETE | librechatDataProvider.PermissionBits.SHARE] = "OWNER";
|
|
1000
|
+
})(exports.RoleBits || (exports.RoleBits = {}));
|
|
1001
|
+
|
|
1002
|
+
async function signPayload({ payload, secret, expirationTime, }) {
|
|
1003
|
+
return jwt.sign(payload, secret, { expiresIn: expirationTime });
|
|
1004
|
+
}
|
|
1005
|
+
async function hashToken(str) {
|
|
1006
|
+
const data = new TextEncoder().encode(str);
|
|
1007
|
+
const hashBuffer = await node_crypto.webcrypto.subtle.digest('SHA-256', data);
|
|
1008
|
+
return Buffer.from(hashBuffer).toString('hex');
|
|
1009
|
+
}
|
|
1010
|
+
|
|
1011
|
+
// Define the Auth sub-schema with type-safety.
|
|
1012
|
+
const AuthSchema = new mongoose.Schema({
|
|
1013
|
+
authorization_type: { type: String },
|
|
1014
|
+
custom_auth_header: { type: String },
|
|
1015
|
+
type: { type: String, enum: ['service_http', 'oauth', 'none'] },
|
|
1016
|
+
authorization_content_type: { type: String },
|
|
1017
|
+
authorization_url: { type: String },
|
|
1018
|
+
client_url: { type: String },
|
|
1019
|
+
scope: { type: String },
|
|
1020
|
+
token_exchange_method: { type: String, enum: ['default_post', 'basic_auth_header', null] },
|
|
1021
|
+
}, { _id: false });
|
|
1022
|
+
const Action = new mongoose.Schema({
|
|
568
1023
|
user: {
|
|
569
1024
|
type: mongoose.Schema.Types.ObjectId,
|
|
570
1025
|
ref: 'User',
|
|
571
1026
|
index: true,
|
|
572
1027
|
required: true,
|
|
573
1028
|
},
|
|
574
|
-
|
|
575
|
-
type: String,
|
|
576
|
-
ref: 'Conversation',
|
|
577
|
-
index: true,
|
|
578
|
-
},
|
|
579
|
-
file_id: {
|
|
1029
|
+
action_id: {
|
|
580
1030
|
type: String,
|
|
581
1031
|
index: true,
|
|
582
1032
|
required: true,
|
|
583
1033
|
},
|
|
584
|
-
temp_file_id: {
|
|
585
|
-
type: String,
|
|
586
|
-
},
|
|
587
|
-
bytes: {
|
|
588
|
-
type: Number,
|
|
589
|
-
required: true,
|
|
590
|
-
},
|
|
591
|
-
filename: {
|
|
592
|
-
type: String,
|
|
593
|
-
required: true,
|
|
594
|
-
},
|
|
595
|
-
filepath: {
|
|
596
|
-
type: String,
|
|
597
|
-
required: true,
|
|
598
|
-
},
|
|
599
|
-
object: {
|
|
600
|
-
type: String,
|
|
601
|
-
required: true,
|
|
602
|
-
default: 'file',
|
|
603
|
-
},
|
|
604
|
-
embedded: {
|
|
605
|
-
type: Boolean,
|
|
606
|
-
},
|
|
607
1034
|
type: {
|
|
608
1035
|
type: String,
|
|
609
|
-
|
|
610
|
-
},
|
|
611
|
-
text: {
|
|
612
|
-
type: String,
|
|
613
|
-
},
|
|
614
|
-
context: {
|
|
615
|
-
type: String,
|
|
616
|
-
},
|
|
617
|
-
usage: {
|
|
618
|
-
type: Number,
|
|
619
|
-
required: true,
|
|
620
|
-
default: 0,
|
|
621
|
-
},
|
|
622
|
-
source: {
|
|
623
|
-
type: String,
|
|
624
|
-
default: librechatDataProvider.FileSources.local,
|
|
625
|
-
},
|
|
626
|
-
model: {
|
|
627
|
-
type: String,
|
|
1036
|
+
default: 'action_prototype',
|
|
628
1037
|
},
|
|
629
|
-
|
|
630
|
-
|
|
1038
|
+
settings: mongoose.Schema.Types.Mixed,
|
|
1039
|
+
agent_id: String,
|
|
1040
|
+
assistant_id: String,
|
|
631
1041
|
metadata: {
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
const keySchema = new mongoose.Schema({
|
|
644
|
-
userId: {
|
|
645
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
646
|
-
ref: 'User',
|
|
647
|
-
required: true,
|
|
648
|
-
},
|
|
649
|
-
name: {
|
|
650
|
-
type: String,
|
|
651
|
-
required: true,
|
|
652
|
-
},
|
|
653
|
-
value: {
|
|
654
|
-
type: String,
|
|
655
|
-
required: true,
|
|
656
|
-
},
|
|
657
|
-
expiresAt: {
|
|
658
|
-
type: Date,
|
|
1042
|
+
api_key: String,
|
|
1043
|
+
auth: AuthSchema,
|
|
1044
|
+
domain: {
|
|
1045
|
+
type: String,
|
|
1046
|
+
required: true,
|
|
1047
|
+
},
|
|
1048
|
+
privacy_policy_url: String,
|
|
1049
|
+
raw_spec: String,
|
|
1050
|
+
oauth_client_id: String,
|
|
1051
|
+
oauth_client_secret: String,
|
|
659
1052
|
},
|
|
660
1053
|
});
|
|
661
|
-
keySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
662
1054
|
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
type: String,
|
|
666
|
-
unique: true,
|
|
667
|
-
required: true,
|
|
668
|
-
index: true,
|
|
669
|
-
meiliIndex: true,
|
|
670
|
-
},
|
|
671
|
-
conversationId: {
|
|
1055
|
+
const agentSchema = new mongoose.Schema({
|
|
1056
|
+
id: {
|
|
672
1057
|
type: String,
|
|
673
1058
|
index: true,
|
|
1059
|
+
unique: true,
|
|
674
1060
|
required: true,
|
|
675
|
-
meiliIndex: true,
|
|
676
1061
|
},
|
|
677
|
-
|
|
1062
|
+
name: {
|
|
678
1063
|
type: String,
|
|
679
|
-
index: true,
|
|
680
|
-
required: true,
|
|
681
|
-
default: null,
|
|
682
|
-
meiliIndex: true,
|
|
683
1064
|
},
|
|
684
|
-
|
|
1065
|
+
description: {
|
|
685
1066
|
type: String,
|
|
686
|
-
default: null,
|
|
687
1067
|
},
|
|
688
|
-
|
|
1068
|
+
instructions: {
|
|
689
1069
|
type: String,
|
|
690
1070
|
},
|
|
691
|
-
|
|
1071
|
+
avatar: {
|
|
1072
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1073
|
+
default: undefined,
|
|
1074
|
+
},
|
|
1075
|
+
provider: {
|
|
692
1076
|
type: String,
|
|
1077
|
+
required: true,
|
|
693
1078
|
},
|
|
694
|
-
|
|
1079
|
+
model: {
|
|
695
1080
|
type: String,
|
|
1081
|
+
required: true,
|
|
696
1082
|
},
|
|
697
|
-
|
|
698
|
-
type:
|
|
1083
|
+
model_parameters: {
|
|
1084
|
+
type: Object,
|
|
699
1085
|
},
|
|
700
|
-
|
|
1086
|
+
artifacts: {
|
|
701
1087
|
type: String,
|
|
702
1088
|
},
|
|
703
|
-
|
|
1089
|
+
access_level: {
|
|
704
1090
|
type: Number,
|
|
705
1091
|
},
|
|
706
|
-
|
|
1092
|
+
recursion_limit: {
|
|
707
1093
|
type: Number,
|
|
708
1094
|
},
|
|
709
|
-
|
|
710
|
-
type: String,
|
|
711
|
-
|
|
1095
|
+
tools: {
|
|
1096
|
+
type: [String],
|
|
1097
|
+
default: undefined,
|
|
712
1098
|
},
|
|
713
|
-
|
|
714
|
-
type:
|
|
715
|
-
meiliIndex: true,
|
|
1099
|
+
tool_kwargs: {
|
|
1100
|
+
type: [{ type: mongoose.Schema.Types.Mixed }],
|
|
716
1101
|
},
|
|
717
|
-
|
|
1102
|
+
actions: {
|
|
1103
|
+
type: [String],
|
|
1104
|
+
default: undefined,
|
|
1105
|
+
},
|
|
1106
|
+
author: {
|
|
1107
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1108
|
+
ref: 'User',
|
|
1109
|
+
required: true,
|
|
1110
|
+
},
|
|
1111
|
+
authorName: {
|
|
718
1112
|
type: String,
|
|
1113
|
+
default: undefined,
|
|
719
1114
|
},
|
|
720
|
-
|
|
1115
|
+
hide_sequential_outputs: {
|
|
721
1116
|
type: Boolean,
|
|
722
|
-
required: true,
|
|
723
|
-
default: false,
|
|
724
1117
|
},
|
|
725
|
-
|
|
1118
|
+
end_after_tools: {
|
|
726
1119
|
type: Boolean,
|
|
727
|
-
default: false,
|
|
728
1120
|
},
|
|
729
|
-
|
|
1121
|
+
/** @deprecated Use edges instead */
|
|
1122
|
+
agent_ids: {
|
|
1123
|
+
type: [String],
|
|
1124
|
+
},
|
|
1125
|
+
edges: {
|
|
1126
|
+
type: [{ type: mongoose.Schema.Types.Mixed }],
|
|
1127
|
+
default: [],
|
|
1128
|
+
},
|
|
1129
|
+
isCollaborative: {
|
|
730
1130
|
type: Boolean,
|
|
731
|
-
default:
|
|
1131
|
+
default: undefined,
|
|
732
1132
|
},
|
|
733
|
-
|
|
1133
|
+
conversation_starters: {
|
|
1134
|
+
type: [String],
|
|
1135
|
+
default: [],
|
|
1136
|
+
},
|
|
1137
|
+
tool_resources: {
|
|
1138
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1139
|
+
default: {},
|
|
1140
|
+
},
|
|
1141
|
+
projectIds: {
|
|
1142
|
+
type: [mongoose.Schema.Types.ObjectId],
|
|
1143
|
+
ref: 'Project',
|
|
1144
|
+
index: true,
|
|
1145
|
+
},
|
|
1146
|
+
versions: {
|
|
1147
|
+
type: [mongoose.Schema.Types.Mixed],
|
|
1148
|
+
default: [],
|
|
1149
|
+
},
|
|
1150
|
+
category: {
|
|
734
1151
|
type: String,
|
|
1152
|
+
trim: true,
|
|
1153
|
+
index: true,
|
|
1154
|
+
default: 'general',
|
|
735
1155
|
},
|
|
736
|
-
|
|
737
|
-
type:
|
|
738
|
-
rating: {
|
|
739
|
-
type: String,
|
|
740
|
-
enum: ['thumbsUp', 'thumbsDown'],
|
|
741
|
-
required: true,
|
|
742
|
-
},
|
|
743
|
-
tag: {
|
|
744
|
-
type: mongoose.Schema.Types.Mixed,
|
|
745
|
-
required: false,
|
|
746
|
-
},
|
|
747
|
-
text: {
|
|
748
|
-
type: String,
|
|
749
|
-
required: false,
|
|
750
|
-
},
|
|
751
|
-
},
|
|
1156
|
+
support_contact: {
|
|
1157
|
+
type: mongoose.Schema.Types.Mixed,
|
|
752
1158
|
default: undefined,
|
|
753
|
-
required: false,
|
|
754
1159
|
},
|
|
755
|
-
|
|
1160
|
+
is_promoted: {
|
|
756
1161
|
type: Boolean,
|
|
757
|
-
required: false,
|
|
758
|
-
select: false,
|
|
759
1162
|
default: false,
|
|
1163
|
+
index: true,
|
|
760
1164
|
},
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
type: String,
|
|
775
|
-
required: false,
|
|
776
|
-
},
|
|
777
|
-
},
|
|
778
|
-
default: undefined,
|
|
1165
|
+
}, {
|
|
1166
|
+
timestamps: true,
|
|
1167
|
+
});
|
|
1168
|
+
agentSchema.index({ updatedAt: -1, _id: 1 });
|
|
1169
|
+
|
|
1170
|
+
const agentCategorySchema = new mongoose.Schema({
|
|
1171
|
+
value: {
|
|
1172
|
+
type: String,
|
|
1173
|
+
required: true,
|
|
1174
|
+
unique: true,
|
|
1175
|
+
trim: true,
|
|
1176
|
+
lowercase: true,
|
|
1177
|
+
index: true,
|
|
779
1178
|
},
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
meiliIndex: true,
|
|
1179
|
+
label: {
|
|
1180
|
+
type: String,
|
|
1181
|
+
required: true,
|
|
1182
|
+
trim: true,
|
|
785
1183
|
},
|
|
786
|
-
|
|
1184
|
+
description: {
|
|
787
1185
|
type: String,
|
|
1186
|
+
trim: true,
|
|
1187
|
+
default: '',
|
|
788
1188
|
},
|
|
789
|
-
|
|
790
|
-
|
|
1189
|
+
order: {
|
|
1190
|
+
type: Number,
|
|
1191
|
+
default: 0,
|
|
1192
|
+
index: true,
|
|
1193
|
+
},
|
|
1194
|
+
isActive: {
|
|
1195
|
+
type: Boolean,
|
|
1196
|
+
default: true,
|
|
1197
|
+
index: true,
|
|
1198
|
+
},
|
|
1199
|
+
custom: {
|
|
1200
|
+
type: Boolean,
|
|
1201
|
+
default: false,
|
|
1202
|
+
},
|
|
1203
|
+
}, {
|
|
1204
|
+
timestamps: true,
|
|
1205
|
+
});
|
|
1206
|
+
agentCategorySchema.index({ isActive: 1, order: 1 });
|
|
1207
|
+
agentCategorySchema.index({ order: 1, label: 1 });
|
|
1208
|
+
|
|
1209
|
+
const assistantSchema = new mongoose.Schema({
|
|
1210
|
+
user: {
|
|
1211
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1212
|
+
ref: 'User',
|
|
1213
|
+
required: true,
|
|
1214
|
+
},
|
|
1215
|
+
assistant_id: {
|
|
791
1216
|
type: String,
|
|
1217
|
+
index: true,
|
|
1218
|
+
required: true,
|
|
792
1219
|
},
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
1220
|
+
avatar: {
|
|
1221
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1222
|
+
default: undefined,
|
|
1223
|
+
},
|
|
1224
|
+
conversation_starters: {
|
|
1225
|
+
type: [String],
|
|
1226
|
+
default: [],
|
|
1227
|
+
},
|
|
1228
|
+
access_level: {
|
|
1229
|
+
type: Number,
|
|
1230
|
+
},
|
|
1231
|
+
file_ids: { type: [String], default: undefined },
|
|
1232
|
+
actions: { type: [String], default: undefined },
|
|
1233
|
+
append_current_datetime: {
|
|
1234
|
+
type: Boolean,
|
|
1235
|
+
default: false,
|
|
1236
|
+
},
|
|
1237
|
+
}, {
|
|
1238
|
+
timestamps: true,
|
|
1239
|
+
});
|
|
1240
|
+
|
|
1241
|
+
const balanceSchema = new mongoose.Schema({
|
|
1242
|
+
user: {
|
|
1243
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1244
|
+
ref: 'User',
|
|
1245
|
+
index: true,
|
|
1246
|
+
required: true,
|
|
1247
|
+
},
|
|
1248
|
+
// 1000 tokenCredits = 1 mill ($0.001 USD)
|
|
1249
|
+
tokenCredits: {
|
|
1250
|
+
type: Number,
|
|
1251
|
+
default: 0,
|
|
1252
|
+
},
|
|
1253
|
+
// Automatic refill settings
|
|
1254
|
+
autoRefillEnabled: {
|
|
1255
|
+
type: Boolean,
|
|
1256
|
+
default: false,
|
|
1257
|
+
},
|
|
1258
|
+
refillIntervalValue: {
|
|
1259
|
+
type: Number,
|
|
1260
|
+
default: 30,
|
|
814
1261
|
},
|
|
815
|
-
|
|
816
|
-
|
|
1262
|
+
refillIntervalUnit: {
|
|
1263
|
+
type: String,
|
|
1264
|
+
enum: ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months'],
|
|
1265
|
+
default: 'days',
|
|
1266
|
+
},
|
|
1267
|
+
lastRefill: {
|
|
817
1268
|
type: Date,
|
|
1269
|
+
default: Date.now,
|
|
818
1270
|
},
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
1271
|
+
// amount to add on each refill
|
|
1272
|
+
refillAmount: {
|
|
1273
|
+
type: Number,
|
|
1274
|
+
default: 0,
|
|
1275
|
+
},
|
|
1276
|
+
});
|
|
823
1277
|
|
|
824
|
-
const
|
|
825
|
-
|
|
1278
|
+
const bannerSchema = new mongoose.Schema({
|
|
1279
|
+
bannerId: {
|
|
826
1280
|
type: String,
|
|
827
1281
|
required: true,
|
|
828
1282
|
},
|
|
829
|
-
|
|
1283
|
+
message: {
|
|
830
1284
|
type: String,
|
|
831
1285
|
required: true,
|
|
832
1286
|
},
|
|
833
|
-
|
|
834
|
-
type:
|
|
1287
|
+
displayFrom: {
|
|
1288
|
+
type: Date,
|
|
835
1289
|
required: true,
|
|
1290
|
+
default: Date.now,
|
|
836
1291
|
},
|
|
837
|
-
|
|
1292
|
+
displayTo: {
|
|
1293
|
+
type: Date,
|
|
1294
|
+
},
|
|
1295
|
+
type: {
|
|
838
1296
|
type: String,
|
|
1297
|
+
enum: ['banner', 'popup'],
|
|
1298
|
+
default: 'banner',
|
|
1299
|
+
},
|
|
1300
|
+
isPublic: {
|
|
1301
|
+
type: Boolean,
|
|
1302
|
+
default: false,
|
|
839
1303
|
},
|
|
840
1304
|
}, { timestamps: true });
|
|
841
1305
|
|
|
842
|
-
const
|
|
843
|
-
|
|
1306
|
+
const categoriesSchema = new mongoose.Schema({
|
|
1307
|
+
label: {
|
|
844
1308
|
type: String,
|
|
1309
|
+
required: true,
|
|
845
1310
|
unique: true,
|
|
1311
|
+
},
|
|
1312
|
+
value: {
|
|
1313
|
+
type: String,
|
|
846
1314
|
required: true,
|
|
847
|
-
|
|
1315
|
+
unique: true,
|
|
848
1316
|
},
|
|
849
|
-
|
|
1317
|
+
});
|
|
1318
|
+
|
|
1319
|
+
const conversationTag = new mongoose.Schema({
|
|
1320
|
+
tag: {
|
|
850
1321
|
type: String,
|
|
851
|
-
|
|
852
|
-
meiliIndex: true,
|
|
1322
|
+
index: true,
|
|
853
1323
|
},
|
|
854
1324
|
user: {
|
|
855
1325
|
type: String,
|
|
856
|
-
|
|
1326
|
+
index: true,
|
|
857
1327
|
},
|
|
858
|
-
|
|
859
|
-
type:
|
|
1328
|
+
description: {
|
|
1329
|
+
type: String,
|
|
1330
|
+
index: true,
|
|
860
1331
|
},
|
|
861
|
-
|
|
1332
|
+
count: {
|
|
862
1333
|
type: Number,
|
|
1334
|
+
default: 0,
|
|
863
1335
|
},
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
1336
|
+
position: {
|
|
1337
|
+
type: Number,
|
|
1338
|
+
default: 0,
|
|
1339
|
+
index: true,
|
|
868
1340
|
},
|
|
869
1341
|
}, { timestamps: true });
|
|
1342
|
+
// Create a compound index on tag and user with unique constraint.
|
|
1343
|
+
conversationTag.index({ tag: 1, user: 1 }, { unique: true });
|
|
870
1344
|
|
|
871
|
-
|
|
872
|
-
|
|
1345
|
+
// @ts-ignore
|
|
1346
|
+
const conversationPreset = {
|
|
1347
|
+
// endpoint: [azureOpenAI, openAI, anthropic, chatGPTBrowser]
|
|
1348
|
+
endpoint: {
|
|
873
1349
|
type: String,
|
|
1350
|
+
default: null,
|
|
874
1351
|
required: true,
|
|
875
|
-
index: true,
|
|
876
1352
|
},
|
|
877
|
-
|
|
878
|
-
type:
|
|
879
|
-
ref: 'PromptGroup',
|
|
880
|
-
default: [],
|
|
881
|
-
},
|
|
882
|
-
agentIds: {
|
|
883
|
-
type: [String],
|
|
884
|
-
ref: 'Agent',
|
|
885
|
-
default: [],
|
|
1353
|
+
endpointType: {
|
|
1354
|
+
type: String,
|
|
886
1355
|
},
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
const promptSchema = new mongoose.Schema({
|
|
892
|
-
groupId: {
|
|
893
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
894
|
-
ref: 'PromptGroup',
|
|
895
|
-
required: true,
|
|
896
|
-
index: true,
|
|
1356
|
+
// for azureOpenAI, openAI, chatGPTBrowser only
|
|
1357
|
+
model: {
|
|
1358
|
+
type: String,
|
|
1359
|
+
required: false,
|
|
897
1360
|
},
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
required:
|
|
1361
|
+
// for bedrock only
|
|
1362
|
+
region: {
|
|
1363
|
+
type: String,
|
|
1364
|
+
required: false,
|
|
902
1365
|
},
|
|
903
|
-
|
|
1366
|
+
// for azureOpenAI, openAI only
|
|
1367
|
+
chatGptLabel: {
|
|
904
1368
|
type: String,
|
|
905
|
-
required:
|
|
1369
|
+
required: false,
|
|
906
1370
|
},
|
|
907
|
-
|
|
1371
|
+
// for google only
|
|
1372
|
+
examples: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1373
|
+
modelLabel: {
|
|
908
1374
|
type: String,
|
|
909
|
-
|
|
910
|
-
required: true,
|
|
1375
|
+
required: false,
|
|
911
1376
|
},
|
|
912
|
-
|
|
913
|
-
timestamps: true,
|
|
914
|
-
});
|
|
915
|
-
promptSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
916
|
-
|
|
917
|
-
const promptGroupSchema = new mongoose.Schema({
|
|
918
|
-
name: {
|
|
1377
|
+
promptPrefix: {
|
|
919
1378
|
type: String,
|
|
920
|
-
required:
|
|
921
|
-
index: true,
|
|
1379
|
+
required: false,
|
|
922
1380
|
},
|
|
923
|
-
|
|
1381
|
+
temperature: {
|
|
924
1382
|
type: Number,
|
|
925
|
-
|
|
1383
|
+
required: false,
|
|
926
1384
|
},
|
|
927
|
-
|
|
928
|
-
type:
|
|
929
|
-
|
|
1385
|
+
top_p: {
|
|
1386
|
+
type: Number,
|
|
1387
|
+
required: false,
|
|
930
1388
|
},
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
1389
|
+
// for google only
|
|
1390
|
+
topP: {
|
|
1391
|
+
type: Number,
|
|
1392
|
+
required: false,
|
|
935
1393
|
},
|
|
936
|
-
|
|
937
|
-
type:
|
|
938
|
-
|
|
939
|
-
index: true,
|
|
940
|
-
default: [],
|
|
1394
|
+
topK: {
|
|
1395
|
+
type: Number,
|
|
1396
|
+
required: false,
|
|
941
1397
|
},
|
|
942
|
-
|
|
943
|
-
type:
|
|
944
|
-
|
|
945
|
-
required: true,
|
|
946
|
-
index: true,
|
|
1398
|
+
maxOutputTokens: {
|
|
1399
|
+
type: Number,
|
|
1400
|
+
required: false,
|
|
947
1401
|
},
|
|
948
|
-
|
|
949
|
-
type:
|
|
950
|
-
|
|
951
|
-
required: true,
|
|
952
|
-
index: true,
|
|
1402
|
+
maxTokens: {
|
|
1403
|
+
type: Number,
|
|
1404
|
+
required: false,
|
|
953
1405
|
},
|
|
954
|
-
|
|
1406
|
+
presence_penalty: {
|
|
1407
|
+
type: Number,
|
|
1408
|
+
required: false,
|
|
1409
|
+
},
|
|
1410
|
+
frequency_penalty: {
|
|
1411
|
+
type: Number,
|
|
1412
|
+
required: false,
|
|
1413
|
+
},
|
|
1414
|
+
file_ids: { type: [{ type: String }], default: undefined },
|
|
1415
|
+
// deprecated
|
|
1416
|
+
resendImages: {
|
|
1417
|
+
type: Boolean,
|
|
1418
|
+
},
|
|
1419
|
+
/* Anthropic only */
|
|
1420
|
+
promptCache: {
|
|
1421
|
+
type: Boolean,
|
|
1422
|
+
},
|
|
1423
|
+
thinking: {
|
|
1424
|
+
type: Boolean,
|
|
1425
|
+
},
|
|
1426
|
+
thinkingBudget: {
|
|
1427
|
+
type: Number,
|
|
1428
|
+
},
|
|
1429
|
+
system: {
|
|
955
1430
|
type: String,
|
|
956
|
-
required: true,
|
|
957
1431
|
},
|
|
958
|
-
|
|
1432
|
+
// files
|
|
1433
|
+
resendFiles: {
|
|
1434
|
+
type: Boolean,
|
|
1435
|
+
},
|
|
1436
|
+
imageDetail: {
|
|
959
1437
|
type: String,
|
|
960
|
-
index: true,
|
|
961
|
-
validate: {
|
|
962
|
-
validator: function (v) {
|
|
963
|
-
return v === undefined || v === null || v === '' || /^[a-z0-9-]+$/.test(v);
|
|
964
|
-
},
|
|
965
|
-
message: (props) => { var _a; return `${(_a = props === null || props === void 0 ? void 0 : props.value) !== null && _a !== void 0 ? _a : 'Value'} is not a valid command. Only lowercase alphanumeric characters and hyphens are allowed.`; },
|
|
966
|
-
},
|
|
967
|
-
maxlength: [
|
|
968
|
-
librechatDataProvider.Constants.COMMANDS_MAX_LENGTH,
|
|
969
|
-
`Command cannot be longer than ${librechatDataProvider.Constants.COMMANDS_MAX_LENGTH} characters`,
|
|
970
|
-
],
|
|
971
|
-
}, // Casting here bypasses the type error for the command field.
|
|
972
|
-
}, {
|
|
973
|
-
timestamps: true,
|
|
974
|
-
});
|
|
975
|
-
promptGroupSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
976
|
-
|
|
977
|
-
/**
|
|
978
|
-
* Uses a sub-schema for permissions. Notice we disable `_id` for this subdocument.
|
|
979
|
-
*/
|
|
980
|
-
const rolePermissionsSchema = new mongoose.Schema({
|
|
981
|
-
[librechatDataProvider.PermissionTypes.BOOKMARKS]: {
|
|
982
|
-
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
983
1438
|
},
|
|
984
|
-
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1439
|
+
/* agents */
|
|
1440
|
+
agent_id: {
|
|
1441
|
+
type: String,
|
|
988
1442
|
},
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
[librechatDataProvider.Permissions.UPDATE]: { type: Boolean },
|
|
993
|
-
[librechatDataProvider.Permissions.READ]: { type: Boolean },
|
|
994
|
-
[librechatDataProvider.Permissions.OPT_OUT]: { type: Boolean },
|
|
1443
|
+
/* assistants */
|
|
1444
|
+
assistant_id: {
|
|
1445
|
+
type: String,
|
|
995
1446
|
},
|
|
996
|
-
|
|
997
|
-
|
|
998
|
-
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
999
|
-
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1447
|
+
instructions: {
|
|
1448
|
+
type: String,
|
|
1000
1449
|
},
|
|
1001
|
-
[
|
|
1002
|
-
|
|
1450
|
+
stop: { type: [{ type: String }], default: undefined },
|
|
1451
|
+
isArchived: {
|
|
1452
|
+
type: Boolean,
|
|
1453
|
+
default: false,
|
|
1003
1454
|
},
|
|
1004
|
-
|
|
1005
|
-
|
|
1455
|
+
/* UI Components */
|
|
1456
|
+
iconURL: {
|
|
1457
|
+
type: String,
|
|
1006
1458
|
},
|
|
1007
|
-
|
|
1008
|
-
|
|
1459
|
+
greeting: {
|
|
1460
|
+
type: String,
|
|
1009
1461
|
},
|
|
1010
|
-
|
|
1011
|
-
|
|
1462
|
+
spec: {
|
|
1463
|
+
type: String,
|
|
1012
1464
|
},
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
[
|
|
1016
|
-
[librechatDataProvider.Permissions.VIEW_ROLES]: { type: Boolean },
|
|
1465
|
+
tags: {
|
|
1466
|
+
type: [String],
|
|
1467
|
+
default: [],
|
|
1017
1468
|
},
|
|
1018
|
-
[
|
|
1019
|
-
|
|
1469
|
+
tools: { type: [{ type: String }], default: undefined },
|
|
1470
|
+
maxContextTokens: {
|
|
1471
|
+
type: Number,
|
|
1020
1472
|
},
|
|
1021
|
-
|
|
1022
|
-
|
|
1473
|
+
max_tokens: {
|
|
1474
|
+
type: Number,
|
|
1023
1475
|
},
|
|
1024
|
-
|
|
1025
|
-
|
|
1476
|
+
useResponsesApi: {
|
|
1477
|
+
type: Boolean,
|
|
1026
1478
|
},
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
permissions: {
|
|
1031
|
-
type: rolePermissionsSchema,
|
|
1479
|
+
/** OpenAI Responses API / Anthropic API / Google API */
|
|
1480
|
+
web_search: {
|
|
1481
|
+
type: Boolean,
|
|
1032
1482
|
},
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1483
|
+
disableStreaming: {
|
|
1484
|
+
type: Boolean,
|
|
1485
|
+
},
|
|
1486
|
+
fileTokenLimit: {
|
|
1487
|
+
type: Number,
|
|
1488
|
+
},
|
|
1489
|
+
/** Reasoning models only */
|
|
1490
|
+
reasoning_effort: {
|
|
1037
1491
|
type: String,
|
|
1038
|
-
required: true,
|
|
1039
1492
|
},
|
|
1040
|
-
|
|
1041
|
-
type:
|
|
1042
|
-
required: true,
|
|
1043
|
-
expires: 0,
|
|
1493
|
+
reasoning_summary: {
|
|
1494
|
+
type: String,
|
|
1044
1495
|
},
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
required: true,
|
|
1496
|
+
/** Verbosity control */
|
|
1497
|
+
verbosity: {
|
|
1498
|
+
type: String,
|
|
1049
1499
|
},
|
|
1050
|
-
}
|
|
1500
|
+
};
|
|
1051
1501
|
|
|
1052
|
-
const
|
|
1502
|
+
const convoSchema = new mongoose.Schema({
|
|
1053
1503
|
conversationId: {
|
|
1054
1504
|
type: String,
|
|
1505
|
+
unique: true,
|
|
1055
1506
|
required: true,
|
|
1507
|
+
index: true,
|
|
1508
|
+
meiliIndex: true,
|
|
1056
1509
|
},
|
|
1057
1510
|
title: {
|
|
1058
1511
|
type: String,
|
|
1059
|
-
|
|
1512
|
+
default: 'New Chat',
|
|
1513
|
+
meiliIndex: true,
|
|
1060
1514
|
},
|
|
1061
1515
|
user: {
|
|
1062
1516
|
type: String,
|
|
1063
1517
|
index: true,
|
|
1518
|
+
meiliIndex: true,
|
|
1064
1519
|
},
|
|
1065
1520
|
messages: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }],
|
|
1066
|
-
|
|
1521
|
+
agentOptions: {
|
|
1522
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1523
|
+
},
|
|
1524
|
+
...conversationPreset,
|
|
1525
|
+
agent_id: {
|
|
1067
1526
|
type: String,
|
|
1068
|
-
index: true,
|
|
1069
1527
|
},
|
|
1070
|
-
|
|
1071
|
-
type:
|
|
1072
|
-
default:
|
|
1528
|
+
tags: {
|
|
1529
|
+
type: [String],
|
|
1530
|
+
default: [],
|
|
1531
|
+
meiliIndex: true,
|
|
1532
|
+
},
|
|
1533
|
+
files: {
|
|
1534
|
+
type: [String],
|
|
1535
|
+
},
|
|
1536
|
+
expiredAt: {
|
|
1537
|
+
type: Date,
|
|
1073
1538
|
},
|
|
1074
1539
|
}, { timestamps: true });
|
|
1540
|
+
convoSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|
1541
|
+
convoSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
1542
|
+
convoSchema.index({ conversationId: 1, user: 1 }, { unique: true });
|
|
1075
1543
|
|
|
1076
|
-
const
|
|
1077
|
-
|
|
1544
|
+
const file = new mongoose.Schema({
|
|
1545
|
+
user: {
|
|
1078
1546
|
type: mongoose.Schema.Types.ObjectId,
|
|
1547
|
+
ref: 'User',
|
|
1548
|
+
index: true,
|
|
1079
1549
|
required: true,
|
|
1080
|
-
ref: 'user',
|
|
1081
|
-
},
|
|
1082
|
-
email: {
|
|
1083
|
-
type: String,
|
|
1084
1550
|
},
|
|
1085
|
-
|
|
1086
|
-
type: String,
|
|
1087
|
-
},
|
|
1088
|
-
identifier: {
|
|
1551
|
+
conversationId: {
|
|
1089
1552
|
type: String,
|
|
1553
|
+
ref: 'Conversation',
|
|
1554
|
+
index: true,
|
|
1090
1555
|
},
|
|
1091
|
-
|
|
1556
|
+
file_id: {
|
|
1092
1557
|
type: String,
|
|
1558
|
+
index: true,
|
|
1093
1559
|
required: true,
|
|
1094
1560
|
},
|
|
1095
|
-
|
|
1096
|
-
type:
|
|
1097
|
-
required: true,
|
|
1098
|
-
default: Date.now,
|
|
1561
|
+
temp_file_id: {
|
|
1562
|
+
type: String,
|
|
1099
1563
|
},
|
|
1100
|
-
|
|
1101
|
-
type:
|
|
1564
|
+
bytes: {
|
|
1565
|
+
type: Number,
|
|
1102
1566
|
required: true,
|
|
1103
1567
|
},
|
|
1104
|
-
|
|
1105
|
-
type: Map,
|
|
1106
|
-
of: mongoose.Schema.Types.Mixed,
|
|
1107
|
-
},
|
|
1108
|
-
});
|
|
1109
|
-
tokenSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1110
|
-
|
|
1111
|
-
const toolCallSchema = new mongoose.Schema({
|
|
1112
|
-
conversationId: {
|
|
1568
|
+
filename: {
|
|
1113
1569
|
type: String,
|
|
1114
1570
|
required: true,
|
|
1115
1571
|
},
|
|
1116
|
-
|
|
1572
|
+
filepath: {
|
|
1117
1573
|
type: String,
|
|
1118
1574
|
required: true,
|
|
1119
1575
|
},
|
|
1120
|
-
|
|
1576
|
+
object: {
|
|
1121
1577
|
type: String,
|
|
1122
1578
|
required: true,
|
|
1579
|
+
default: 'file',
|
|
1123
1580
|
},
|
|
1124
|
-
|
|
1125
|
-
type:
|
|
1126
|
-
ref: 'User',
|
|
1127
|
-
required: true,
|
|
1581
|
+
embedded: {
|
|
1582
|
+
type: Boolean,
|
|
1128
1583
|
},
|
|
1129
|
-
|
|
1130
|
-
type:
|
|
1584
|
+
type: {
|
|
1585
|
+
type: String,
|
|
1586
|
+
required: true,
|
|
1131
1587
|
},
|
|
1132
|
-
|
|
1133
|
-
type:
|
|
1588
|
+
text: {
|
|
1589
|
+
type: String,
|
|
1134
1590
|
},
|
|
1135
|
-
|
|
1136
|
-
type:
|
|
1591
|
+
context: {
|
|
1592
|
+
type: String,
|
|
1137
1593
|
},
|
|
1138
|
-
|
|
1594
|
+
usage: {
|
|
1139
1595
|
type: Number,
|
|
1140
|
-
},
|
|
1141
|
-
}, { timestamps: true });
|
|
1142
|
-
toolCallSchema.index({ messageId: 1, user: 1 });
|
|
1143
|
-
toolCallSchema.index({ conversationId: 1, user: 1 });
|
|
1144
|
-
|
|
1145
|
-
const transactionSchema = new mongoose.Schema({
|
|
1146
|
-
user: {
|
|
1147
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
1148
|
-
ref: 'User',
|
|
1149
|
-
index: true,
|
|
1150
1596
|
required: true,
|
|
1597
|
+
default: 0,
|
|
1151
1598
|
},
|
|
1152
|
-
|
|
1153
|
-
type: String,
|
|
1154
|
-
ref: 'Conversation',
|
|
1155
|
-
index: true,
|
|
1156
|
-
},
|
|
1157
|
-
tokenType: {
|
|
1599
|
+
source: {
|
|
1158
1600
|
type: String,
|
|
1159
|
-
|
|
1160
|
-
required: true,
|
|
1601
|
+
default: librechatDataProvider.FileSources.local,
|
|
1161
1602
|
},
|
|
1162
1603
|
model: {
|
|
1163
1604
|
type: String,
|
|
1164
1605
|
},
|
|
1165
|
-
|
|
1166
|
-
|
|
1606
|
+
width: Number,
|
|
1607
|
+
height: Number,
|
|
1608
|
+
metadata: {
|
|
1609
|
+
fileIdentifier: String,
|
|
1167
1610
|
},
|
|
1168
|
-
|
|
1169
|
-
type:
|
|
1611
|
+
expiresAt: {
|
|
1612
|
+
type: Date,
|
|
1613
|
+
expires: 3600, // 1 hour in seconds
|
|
1170
1614
|
},
|
|
1171
|
-
rate: Number,
|
|
1172
|
-
rawAmount: Number,
|
|
1173
|
-
tokenValue: Number,
|
|
1174
|
-
inputTokens: { type: Number },
|
|
1175
|
-
writeTokens: { type: Number },
|
|
1176
|
-
readTokens: { type: Number },
|
|
1177
1615
|
}, {
|
|
1178
1616
|
timestamps: true,
|
|
1179
1617
|
});
|
|
1618
|
+
file.index({ createdAt: 1, updatedAt: 1 });
|
|
1180
1619
|
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1620
|
+
const keySchema = new mongoose.Schema({
|
|
1621
|
+
userId: {
|
|
1622
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1623
|
+
ref: 'User',
|
|
1624
|
+
required: true,
|
|
1186
1625
|
},
|
|
1187
|
-
}, { _id: false });
|
|
1188
|
-
// Backup code sub-schema
|
|
1189
|
-
const BackupCodeSchema = new mongoose.Schema({
|
|
1190
|
-
codeHash: { type: String, required: true },
|
|
1191
|
-
used: { type: Boolean, default: false },
|
|
1192
|
-
usedAt: { type: Date, default: null },
|
|
1193
|
-
}, { _id: false });
|
|
1194
|
-
const userSchema = new mongoose.Schema({
|
|
1195
1626
|
name: {
|
|
1196
1627
|
type: String,
|
|
1628
|
+
required: true,
|
|
1197
1629
|
},
|
|
1198
|
-
|
|
1630
|
+
value: {
|
|
1199
1631
|
type: String,
|
|
1200
|
-
|
|
1201
|
-
default: '',
|
|
1632
|
+
required: true,
|
|
1202
1633
|
},
|
|
1203
|
-
|
|
1634
|
+
expiresAt: {
|
|
1635
|
+
type: Date,
|
|
1636
|
+
},
|
|
1637
|
+
});
|
|
1638
|
+
keySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1639
|
+
|
|
1640
|
+
const messageSchema = new mongoose.Schema({
|
|
1641
|
+
messageId: {
|
|
1204
1642
|
type: String,
|
|
1205
|
-
required: [true, "can't be blank"],
|
|
1206
|
-
lowercase: true,
|
|
1207
1643
|
unique: true,
|
|
1208
|
-
|
|
1644
|
+
required: true,
|
|
1209
1645
|
index: true,
|
|
1646
|
+
meiliIndex: true,
|
|
1210
1647
|
},
|
|
1211
|
-
|
|
1212
|
-
type:
|
|
1648
|
+
conversationId: {
|
|
1649
|
+
type: String,
|
|
1650
|
+
index: true,
|
|
1213
1651
|
required: true,
|
|
1214
|
-
|
|
1652
|
+
meiliIndex: true,
|
|
1215
1653
|
},
|
|
1216
|
-
|
|
1654
|
+
user: {
|
|
1217
1655
|
type: String,
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1656
|
+
index: true,
|
|
1657
|
+
required: true,
|
|
1658
|
+
default: null,
|
|
1659
|
+
meiliIndex: true,
|
|
1222
1660
|
},
|
|
1223
|
-
|
|
1661
|
+
model: {
|
|
1224
1662
|
type: String,
|
|
1225
|
-
|
|
1663
|
+
default: null,
|
|
1226
1664
|
},
|
|
1227
|
-
|
|
1665
|
+
endpoint: {
|
|
1228
1666
|
type: String,
|
|
1229
|
-
required: true,
|
|
1230
|
-
default: 'local',
|
|
1231
1667
|
},
|
|
1232
|
-
|
|
1668
|
+
conversationSignature: {
|
|
1233
1669
|
type: String,
|
|
1234
|
-
default: librechatDataProvider.SystemRoles.USER,
|
|
1235
1670
|
},
|
|
1236
|
-
|
|
1671
|
+
clientId: {
|
|
1237
1672
|
type: String,
|
|
1238
|
-
unique: true,
|
|
1239
|
-
sparse: true,
|
|
1240
1673
|
},
|
|
1241
|
-
|
|
1242
|
-
type:
|
|
1243
|
-
unique: true,
|
|
1244
|
-
sparse: true,
|
|
1674
|
+
invocationId: {
|
|
1675
|
+
type: Number,
|
|
1245
1676
|
},
|
|
1246
|
-
|
|
1677
|
+
parentMessageId: {
|
|
1247
1678
|
type: String,
|
|
1248
|
-
unique: true,
|
|
1249
|
-
sparse: true,
|
|
1250
1679
|
},
|
|
1251
|
-
|
|
1252
|
-
type:
|
|
1253
|
-
unique: true,
|
|
1254
|
-
sparse: true,
|
|
1680
|
+
tokenCount: {
|
|
1681
|
+
type: Number,
|
|
1255
1682
|
},
|
|
1256
|
-
|
|
1257
|
-
type:
|
|
1258
|
-
unique: true,
|
|
1259
|
-
sparse: true,
|
|
1683
|
+
summaryTokenCount: {
|
|
1684
|
+
type: Number,
|
|
1260
1685
|
},
|
|
1261
|
-
|
|
1686
|
+
sender: {
|
|
1262
1687
|
type: String,
|
|
1263
|
-
|
|
1264
|
-
sparse: true,
|
|
1688
|
+
meiliIndex: true,
|
|
1265
1689
|
},
|
|
1266
|
-
|
|
1690
|
+
text: {
|
|
1267
1691
|
type: String,
|
|
1268
|
-
|
|
1269
|
-
sparse: true,
|
|
1692
|
+
meiliIndex: true,
|
|
1270
1693
|
},
|
|
1271
|
-
|
|
1694
|
+
summary: {
|
|
1272
1695
|
type: String,
|
|
1273
|
-
unique: true,
|
|
1274
|
-
sparse: true,
|
|
1275
|
-
},
|
|
1276
|
-
plugins: {
|
|
1277
|
-
type: Array,
|
|
1278
1696
|
},
|
|
1279
|
-
|
|
1697
|
+
isCreatedByUser: {
|
|
1280
1698
|
type: Boolean,
|
|
1699
|
+
required: true,
|
|
1281
1700
|
default: false,
|
|
1282
1701
|
},
|
|
1283
|
-
|
|
1284
|
-
type:
|
|
1285
|
-
|
|
1702
|
+
unfinished: {
|
|
1703
|
+
type: Boolean,
|
|
1704
|
+
default: false,
|
|
1286
1705
|
},
|
|
1287
|
-
|
|
1288
|
-
type:
|
|
1289
|
-
|
|
1706
|
+
error: {
|
|
1707
|
+
type: Boolean,
|
|
1708
|
+
default: false,
|
|
1290
1709
|
},
|
|
1291
|
-
|
|
1292
|
-
type:
|
|
1710
|
+
finish_reason: {
|
|
1711
|
+
type: String,
|
|
1293
1712
|
},
|
|
1294
|
-
|
|
1295
|
-
type:
|
|
1296
|
-
|
|
1713
|
+
feedback: {
|
|
1714
|
+
type: {
|
|
1715
|
+
rating: {
|
|
1716
|
+
type: String,
|
|
1717
|
+
enum: ['thumbsUp', 'thumbsDown'],
|
|
1718
|
+
required: true,
|
|
1719
|
+
},
|
|
1720
|
+
tag: {
|
|
1721
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1722
|
+
required: false,
|
|
1723
|
+
},
|
|
1724
|
+
text: {
|
|
1725
|
+
type: String,
|
|
1726
|
+
required: false,
|
|
1727
|
+
},
|
|
1728
|
+
},
|
|
1729
|
+
default: undefined,
|
|
1730
|
+
required: false,
|
|
1297
1731
|
},
|
|
1298
|
-
|
|
1732
|
+
_meiliIndex: {
|
|
1299
1733
|
type: Boolean,
|
|
1734
|
+
required: false,
|
|
1735
|
+
select: false,
|
|
1300
1736
|
default: false,
|
|
1301
1737
|
},
|
|
1302
|
-
|
|
1738
|
+
files: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1739
|
+
plugin: {
|
|
1303
1740
|
type: {
|
|
1304
|
-
|
|
1305
|
-
type:
|
|
1306
|
-
|
|
1741
|
+
latest: {
|
|
1742
|
+
type: String,
|
|
1743
|
+
required: false,
|
|
1744
|
+
},
|
|
1745
|
+
inputs: {
|
|
1746
|
+
type: [mongoose.Schema.Types.Mixed],
|
|
1747
|
+
required: false,
|
|
1748
|
+
default: undefined,
|
|
1749
|
+
},
|
|
1750
|
+
outputs: {
|
|
1751
|
+
type: String,
|
|
1752
|
+
required: false,
|
|
1307
1753
|
},
|
|
1308
1754
|
},
|
|
1309
|
-
default:
|
|
1755
|
+
default: undefined,
|
|
1310
1756
|
},
|
|
1311
|
-
|
|
1312
|
-
|
|
1757
|
+
plugins: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1758
|
+
content: {
|
|
1759
|
+
type: [{ type: mongoose.Schema.Types.Mixed }],
|
|
1760
|
+
default: undefined,
|
|
1761
|
+
meiliIndex: true,
|
|
1762
|
+
},
|
|
1763
|
+
thread_id: {
|
|
1313
1764
|
type: String,
|
|
1314
|
-
|
|
1765
|
+
},
|
|
1766
|
+
/* frontend components */
|
|
1767
|
+
iconURL: {
|
|
1768
|
+
type: String,
|
|
1769
|
+
},
|
|
1770
|
+
metadata: { type: mongoose.Schema.Types.Mixed },
|
|
1771
|
+
attachments: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1772
|
+
/*
|
|
1773
|
+
attachments: {
|
|
1774
|
+
type: [
|
|
1775
|
+
{
|
|
1776
|
+
file_id: String,
|
|
1777
|
+
filename: String,
|
|
1778
|
+
filepath: String,
|
|
1779
|
+
expiresAt: Date,
|
|
1780
|
+
width: Number,
|
|
1781
|
+
height: Number,
|
|
1782
|
+
type: String,
|
|
1783
|
+
conversationId: String,
|
|
1784
|
+
messageId: {
|
|
1785
|
+
type: String,
|
|
1786
|
+
required: true,
|
|
1787
|
+
},
|
|
1788
|
+
toolCallId: String,
|
|
1789
|
+
},
|
|
1790
|
+
],
|
|
1791
|
+
default: undefined,
|
|
1792
|
+
},
|
|
1793
|
+
*/
|
|
1794
|
+
expiredAt: {
|
|
1795
|
+
type: Date,
|
|
1315
1796
|
},
|
|
1316
1797
|
}, { timestamps: true });
|
|
1798
|
+
messageSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|
1799
|
+
messageSchema.index({ createdAt: 1 });
|
|
1800
|
+
messageSchema.index({ messageId: 1, user: 1 }, { unique: true });
|
|
1317
1801
|
|
|
1318
|
-
const
|
|
1319
|
-
|
|
1320
|
-
type:
|
|
1321
|
-
ref: 'User',
|
|
1322
|
-
index: true,
|
|
1802
|
+
const pluginAuthSchema = new mongoose.Schema({
|
|
1803
|
+
authField: {
|
|
1804
|
+
type: String,
|
|
1323
1805
|
required: true,
|
|
1324
1806
|
},
|
|
1325
|
-
|
|
1807
|
+
value: {
|
|
1326
1808
|
type: String,
|
|
1327
1809
|
required: true,
|
|
1328
|
-
validate: {
|
|
1329
|
-
validator: (v) => /^[a-z_]+$/.test(v),
|
|
1330
|
-
message: 'Key must only contain lowercase letters and underscores',
|
|
1331
|
-
},
|
|
1332
1810
|
},
|
|
1333
|
-
|
|
1811
|
+
userId: {
|
|
1334
1812
|
type: String,
|
|
1335
1813
|
required: true,
|
|
1336
1814
|
},
|
|
1337
|
-
|
|
1815
|
+
pluginKey: {
|
|
1816
|
+
type: String,
|
|
1817
|
+
},
|
|
1818
|
+
}, { timestamps: true });
|
|
1819
|
+
|
|
1820
|
+
const presetSchema = new mongoose.Schema({
|
|
1821
|
+
presetId: {
|
|
1822
|
+
type: String,
|
|
1823
|
+
unique: true,
|
|
1824
|
+
required: true,
|
|
1825
|
+
index: true,
|
|
1826
|
+
},
|
|
1827
|
+
title: {
|
|
1828
|
+
type: String,
|
|
1829
|
+
default: 'New Chat',
|
|
1830
|
+
meiliIndex: true,
|
|
1831
|
+
},
|
|
1832
|
+
user: {
|
|
1833
|
+
type: String,
|
|
1834
|
+
default: null,
|
|
1835
|
+
},
|
|
1836
|
+
defaultPreset: {
|
|
1837
|
+
type: Boolean,
|
|
1838
|
+
},
|
|
1839
|
+
order: {
|
|
1338
1840
|
type: Number,
|
|
1339
|
-
default: 0,
|
|
1340
1841
|
},
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1842
|
+
...conversationPreset,
|
|
1843
|
+
agentOptions: {
|
|
1844
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1845
|
+
default: null,
|
|
1344
1846
|
},
|
|
1345
|
-
});
|
|
1847
|
+
}, { timestamps: true });
|
|
1346
1848
|
|
|
1347
|
-
const
|
|
1849
|
+
const projectSchema = new mongoose.Schema({
|
|
1348
1850
|
name: {
|
|
1349
1851
|
type: String,
|
|
1350
1852
|
required: true,
|
|
1351
1853
|
index: true,
|
|
1352
1854
|
},
|
|
1353
|
-
|
|
1354
|
-
type:
|
|
1355
|
-
|
|
1855
|
+
promptGroupIds: {
|
|
1856
|
+
type: [mongoose.Schema.Types.ObjectId],
|
|
1857
|
+
ref: 'PromptGroup',
|
|
1858
|
+
default: [],
|
|
1356
1859
|
},
|
|
1357
|
-
|
|
1358
|
-
type: String,
|
|
1359
|
-
|
|
1860
|
+
agentIds: {
|
|
1861
|
+
type: [String],
|
|
1862
|
+
ref: 'Agent',
|
|
1863
|
+
default: [],
|
|
1864
|
+
},
|
|
1865
|
+
}, {
|
|
1866
|
+
timestamps: true,
|
|
1867
|
+
});
|
|
1868
|
+
|
|
1869
|
+
const promptSchema = new mongoose.Schema({
|
|
1870
|
+
groupId: {
|
|
1871
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1872
|
+
ref: 'PromptGroup',
|
|
1873
|
+
required: true,
|
|
1360
1874
|
index: true,
|
|
1361
1875
|
},
|
|
1362
|
-
|
|
1363
|
-
type:
|
|
1364
|
-
|
|
1876
|
+
author: {
|
|
1877
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1878
|
+
ref: 'User',
|
|
1879
|
+
required: true,
|
|
1365
1880
|
},
|
|
1366
|
-
|
|
1367
|
-
{
|
|
1368
|
-
type: String,
|
|
1369
|
-
required: false,
|
|
1370
|
-
},
|
|
1371
|
-
],
|
|
1372
|
-
source: {
|
|
1881
|
+
prompt: {
|
|
1373
1882
|
type: String,
|
|
1374
|
-
|
|
1375
|
-
default: 'local',
|
|
1883
|
+
required: true,
|
|
1376
1884
|
},
|
|
1377
|
-
|
|
1378
|
-
idOnTheSource: {
|
|
1885
|
+
type: {
|
|
1379
1886
|
type: String,
|
|
1380
|
-
|
|
1381
|
-
|
|
1382
|
-
required: function () {
|
|
1383
|
-
return this.source !== 'local';
|
|
1384
|
-
},
|
|
1887
|
+
enum: ['text', 'chat'],
|
|
1888
|
+
required: true,
|
|
1385
1889
|
},
|
|
1386
|
-
}, {
|
|
1387
|
-
|
|
1388
|
-
unique: true,
|
|
1389
|
-
partialFilterExpression: { idOnTheSource: { $exists: true } },
|
|
1890
|
+
}, {
|
|
1891
|
+
timestamps: true,
|
|
1390
1892
|
});
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
/**
|
|
1394
|
-
* ESM-native object traversal utility
|
|
1395
|
-
* Simplified implementation focused on the forEach use case
|
|
1396
|
-
*/
|
|
1397
|
-
function isObject(value) {
|
|
1398
|
-
if (value === null || typeof value !== 'object') {
|
|
1399
|
-
return false;
|
|
1400
|
-
}
|
|
1401
|
-
// Treat these built-in types as leaf nodes, not objects to traverse
|
|
1402
|
-
if (value instanceof Date)
|
|
1403
|
-
return false;
|
|
1404
|
-
if (value instanceof RegExp)
|
|
1405
|
-
return false;
|
|
1406
|
-
if (value instanceof Error)
|
|
1407
|
-
return false;
|
|
1408
|
-
if (value instanceof URL)
|
|
1409
|
-
return false;
|
|
1410
|
-
// Check for Buffer (Node.js)
|
|
1411
|
-
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value))
|
|
1412
|
-
return false;
|
|
1413
|
-
// Check for TypedArrays and ArrayBuffer
|
|
1414
|
-
if (ArrayBuffer.isView(value))
|
|
1415
|
-
return false;
|
|
1416
|
-
if (value instanceof ArrayBuffer)
|
|
1417
|
-
return false;
|
|
1418
|
-
if (value instanceof SharedArrayBuffer)
|
|
1419
|
-
return false;
|
|
1420
|
-
// Check for other built-in types that shouldn't be traversed
|
|
1421
|
-
if (value instanceof Promise)
|
|
1422
|
-
return false;
|
|
1423
|
-
if (value instanceof WeakMap)
|
|
1424
|
-
return false;
|
|
1425
|
-
if (value instanceof WeakSet)
|
|
1426
|
-
return false;
|
|
1427
|
-
if (value instanceof Map)
|
|
1428
|
-
return false;
|
|
1429
|
-
if (value instanceof Set)
|
|
1430
|
-
return false;
|
|
1431
|
-
// Check if it's a primitive wrapper object
|
|
1432
|
-
const stringTag = Object.prototype.toString.call(value);
|
|
1433
|
-
if (stringTag === '[object Boolean]' ||
|
|
1434
|
-
stringTag === '[object Number]' ||
|
|
1435
|
-
stringTag === '[object String]') {
|
|
1436
|
-
return false;
|
|
1437
|
-
}
|
|
1438
|
-
return true;
|
|
1439
|
-
}
|
|
1440
|
-
// Helper to safely set a property on an object or array
|
|
1441
|
-
function setProperty(obj, key, value) {
|
|
1442
|
-
if (Array.isArray(obj) && typeof key === 'number') {
|
|
1443
|
-
obj[key] = value;
|
|
1444
|
-
}
|
|
1445
|
-
else if (!Array.isArray(obj) && typeof key === 'string') {
|
|
1446
|
-
obj[key] = value;
|
|
1447
|
-
}
|
|
1448
|
-
else if (!Array.isArray(obj) && typeof key === 'number') {
|
|
1449
|
-
// Handle numeric keys on objects
|
|
1450
|
-
obj[key] = value;
|
|
1451
|
-
}
|
|
1452
|
-
}
|
|
1453
|
-
// Helper to safely delete a property from an object
|
|
1454
|
-
function deleteProperty(obj, key) {
|
|
1455
|
-
if (Array.isArray(obj) && typeof key === 'number') {
|
|
1456
|
-
// For arrays, we should use splice, but this is handled in remove()
|
|
1457
|
-
// This function is only called for non-array deletion
|
|
1458
|
-
return;
|
|
1459
|
-
}
|
|
1460
|
-
if (!Array.isArray(obj)) {
|
|
1461
|
-
delete obj[key];
|
|
1462
|
-
}
|
|
1463
|
-
}
|
|
1464
|
-
function forEach(obj, callback) {
|
|
1465
|
-
const visited = new WeakSet();
|
|
1466
|
-
function walk(node, path = [], parent) {
|
|
1467
|
-
// Check for circular references
|
|
1468
|
-
let circular = null;
|
|
1469
|
-
if (isObject(node)) {
|
|
1470
|
-
if (visited.has(node)) {
|
|
1471
|
-
// Find the circular reference in the parent chain
|
|
1472
|
-
let p = parent;
|
|
1473
|
-
while (p) {
|
|
1474
|
-
if (p.node === node) {
|
|
1475
|
-
circular = p;
|
|
1476
|
-
break;
|
|
1477
|
-
}
|
|
1478
|
-
p = p.parent;
|
|
1479
|
-
}
|
|
1480
|
-
return; // Skip circular references
|
|
1481
|
-
}
|
|
1482
|
-
visited.add(node);
|
|
1483
|
-
}
|
|
1484
|
-
const key = path.length > 0 ? path[path.length - 1] : undefined;
|
|
1485
|
-
const isRoot = path.length === 0;
|
|
1486
|
-
const level = path.length;
|
|
1487
|
-
// Determine if this is a leaf node
|
|
1488
|
-
const isLeaf = !isObject(node) ||
|
|
1489
|
-
(Array.isArray(node) && node.length === 0) ||
|
|
1490
|
-
Object.keys(node).length === 0;
|
|
1491
|
-
// Create context
|
|
1492
|
-
const context = {
|
|
1493
|
-
node,
|
|
1494
|
-
path: [...path],
|
|
1495
|
-
parent,
|
|
1496
|
-
key,
|
|
1497
|
-
isLeaf,
|
|
1498
|
-
notLeaf: !isLeaf,
|
|
1499
|
-
isRoot,
|
|
1500
|
-
notRoot: !isRoot,
|
|
1501
|
-
level,
|
|
1502
|
-
circular,
|
|
1503
|
-
update(value) {
|
|
1504
|
-
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
1505
|
-
setProperty(parent.node, key, value);
|
|
1506
|
-
}
|
|
1507
|
-
this.node = value;
|
|
1508
|
-
},
|
|
1509
|
-
remove() {
|
|
1510
|
-
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
1511
|
-
if (Array.isArray(parent.node) && typeof key === 'number') {
|
|
1512
|
-
parent.node.splice(key, 1);
|
|
1513
|
-
}
|
|
1514
|
-
else {
|
|
1515
|
-
deleteProperty(parent.node, key);
|
|
1516
|
-
}
|
|
1517
|
-
}
|
|
1518
|
-
},
|
|
1519
|
-
};
|
|
1520
|
-
// Call the callback with the context
|
|
1521
|
-
callback.call(context, node);
|
|
1522
|
-
// Traverse children if not circular and is an object
|
|
1523
|
-
if (!circular && isObject(node) && !isLeaf) {
|
|
1524
|
-
if (Array.isArray(node)) {
|
|
1525
|
-
for (let i = 0; i < node.length; i++) {
|
|
1526
|
-
walk(node[i], [...path, i], context);
|
|
1527
|
-
}
|
|
1528
|
-
}
|
|
1529
|
-
else {
|
|
1530
|
-
for (const [childKey, childValue] of Object.entries(node)) {
|
|
1531
|
-
walk(childValue, [...path, childKey], context);
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
}
|
|
1535
|
-
}
|
|
1536
|
-
walk(obj);
|
|
1537
|
-
}
|
|
1538
|
-
// Main traverse function that returns an object with forEach method
|
|
1539
|
-
function traverse(obj) {
|
|
1540
|
-
return {
|
|
1541
|
-
forEach(callback) {
|
|
1542
|
-
forEach(obj, callback);
|
|
1543
|
-
},
|
|
1544
|
-
};
|
|
1545
|
-
}
|
|
1893
|
+
promptSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
1546
1894
|
|
|
1547
|
-
const
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1558
|
-
|
|
1559
|
-
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
1572
|
-
|
|
1573
|
-
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
|
|
1581
|
-
|
|
1582
|
-
|
|
1583
|
-
|
|
1584
|
-
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
}
|
|
1597
|
-
|
|
1598
|
-
|
|
1599
|
-
|
|
1600
|
-
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1895
|
+
const promptGroupSchema = new mongoose.Schema({
|
|
1896
|
+
name: {
|
|
1897
|
+
type: String,
|
|
1898
|
+
required: true,
|
|
1899
|
+
index: true,
|
|
1900
|
+
},
|
|
1901
|
+
numberOfGenerations: {
|
|
1902
|
+
type: Number,
|
|
1903
|
+
default: 0,
|
|
1904
|
+
},
|
|
1905
|
+
oneliner: {
|
|
1906
|
+
type: String,
|
|
1907
|
+
default: '',
|
|
1908
|
+
},
|
|
1909
|
+
category: {
|
|
1910
|
+
type: String,
|
|
1911
|
+
default: '',
|
|
1912
|
+
index: true,
|
|
1913
|
+
},
|
|
1914
|
+
projectIds: {
|
|
1915
|
+
type: [mongoose.Schema.Types.ObjectId],
|
|
1916
|
+
ref: 'Project',
|
|
1917
|
+
index: true,
|
|
1918
|
+
default: [],
|
|
1919
|
+
},
|
|
1920
|
+
productionId: {
|
|
1921
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1922
|
+
ref: 'Prompt',
|
|
1923
|
+
required: true,
|
|
1924
|
+
index: true,
|
|
1925
|
+
},
|
|
1926
|
+
author: {
|
|
1927
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1928
|
+
ref: 'User',
|
|
1929
|
+
required: true,
|
|
1930
|
+
index: true,
|
|
1931
|
+
},
|
|
1932
|
+
authorName: {
|
|
1933
|
+
type: String,
|
|
1934
|
+
required: true,
|
|
1935
|
+
},
|
|
1936
|
+
command: {
|
|
1937
|
+
type: String,
|
|
1938
|
+
index: true,
|
|
1939
|
+
validate: {
|
|
1940
|
+
validator: function (v) {
|
|
1941
|
+
return v === undefined || v === null || v === '' || /^[a-z0-9-]+$/.test(v);
|
|
1942
|
+
},
|
|
1943
|
+
message: (props) => { var _a; return `${(_a = props === null || props === void 0 ? void 0 : props.value) !== null && _a !== void 0 ? _a : 'Value'} is not a valid command. Only lowercase alphanumeric characters and hyphens are allowed.`; },
|
|
1944
|
+
},
|
|
1945
|
+
maxlength: [
|
|
1946
|
+
librechatDataProvider.Constants.COMMANDS_MAX_LENGTH,
|
|
1947
|
+
`Command cannot be longer than ${librechatDataProvider.Constants.COMMANDS_MAX_LENGTH} characters`,
|
|
1948
|
+
],
|
|
1949
|
+
}, // Casting here bypasses the type error for the command field.
|
|
1950
|
+
}, {
|
|
1951
|
+
timestamps: true,
|
|
1604
1952
|
});
|
|
1953
|
+
promptGroupSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
1954
|
+
|
|
1605
1955
|
/**
|
|
1606
|
-
*
|
|
1607
|
-
*
|
|
1608
|
-
* @param value - The value to be inspected and potentially truncated.
|
|
1609
|
-
* @param length - The length at which to truncate the value. Default: 100.
|
|
1610
|
-
* @returns The truncated or original value.
|
|
1611
|
-
*/
|
|
1612
|
-
const truncateLongStrings = (value, length = 100) => {
|
|
1613
|
-
if (typeof value === 'string') {
|
|
1614
|
-
return value.length > length ? value.substring(0, length) + '... [truncated]' : value;
|
|
1615
|
-
}
|
|
1616
|
-
return value;
|
|
1617
|
-
};
|
|
1618
|
-
/**
|
|
1619
|
-
* An array mapping function that truncates long strings (objects converted to JSON strings).
|
|
1620
|
-
* @param item - The item to be condensed.
|
|
1621
|
-
* @returns The condensed item.
|
|
1622
|
-
*/
|
|
1623
|
-
const condenseArray = (item) => {
|
|
1624
|
-
if (typeof item === 'string') {
|
|
1625
|
-
return truncateLongStrings(JSON.stringify(item));
|
|
1626
|
-
}
|
|
1627
|
-
else if (typeof item === 'object') {
|
|
1628
|
-
return truncateLongStrings(JSON.stringify(item));
|
|
1629
|
-
}
|
|
1630
|
-
return item;
|
|
1631
|
-
};
|
|
1632
|
-
/**
|
|
1633
|
-
* Formats log messages for debugging purposes.
|
|
1634
|
-
* - Truncates long strings within log messages.
|
|
1635
|
-
* - Condenses arrays by truncating long strings and objects as strings within array items.
|
|
1636
|
-
* - Redacts sensitive information from log messages if the log level is 'error'.
|
|
1637
|
-
* - Converts log information object to a formatted string.
|
|
1638
|
-
*
|
|
1639
|
-
* @param options - The options for formatting log messages.
|
|
1640
|
-
* @returns The formatted log message.
|
|
1956
|
+
* Uses a sub-schema for permissions. Notice we disable `_id` for this subdocument.
|
|
1641
1957
|
*/
|
|
1642
|
-
const
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
}
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1655
|
-
|
|
1656
|
-
}
|
|
1657
|
-
|
|
1658
|
-
|
|
1659
|
-
}
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
}
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
1701
|
-
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
}
|
|
1958
|
+
const rolePermissionsSchema = new mongoose.Schema({
|
|
1959
|
+
[librechatDataProvider.PermissionTypes.BOOKMARKS]: {
|
|
1960
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1961
|
+
},
|
|
1962
|
+
[librechatDataProvider.PermissionTypes.PROMPTS]: {
|
|
1963
|
+
[librechatDataProvider.Permissions.SHARED_GLOBAL]: { type: Boolean },
|
|
1964
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1965
|
+
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1966
|
+
},
|
|
1967
|
+
[librechatDataProvider.PermissionTypes.MEMORIES]: {
|
|
1968
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1969
|
+
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1970
|
+
[librechatDataProvider.Permissions.UPDATE]: { type: Boolean },
|
|
1971
|
+
[librechatDataProvider.Permissions.READ]: { type: Boolean },
|
|
1972
|
+
[librechatDataProvider.Permissions.OPT_OUT]: { type: Boolean },
|
|
1973
|
+
},
|
|
1974
|
+
[librechatDataProvider.PermissionTypes.AGENTS]: {
|
|
1975
|
+
[librechatDataProvider.Permissions.SHARED_GLOBAL]: { type: Boolean },
|
|
1976
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1977
|
+
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1978
|
+
},
|
|
1979
|
+
[librechatDataProvider.PermissionTypes.MULTI_CONVO]: {
|
|
1980
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1981
|
+
},
|
|
1982
|
+
[librechatDataProvider.PermissionTypes.TEMPORARY_CHAT]: {
|
|
1983
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1984
|
+
},
|
|
1985
|
+
[librechatDataProvider.PermissionTypes.RUN_CODE]: {
|
|
1986
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1987
|
+
},
|
|
1988
|
+
[librechatDataProvider.PermissionTypes.WEB_SEARCH]: {
|
|
1989
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1990
|
+
},
|
|
1991
|
+
[librechatDataProvider.PermissionTypes.PEOPLE_PICKER]: {
|
|
1992
|
+
[librechatDataProvider.Permissions.VIEW_USERS]: { type: Boolean },
|
|
1993
|
+
[librechatDataProvider.Permissions.VIEW_GROUPS]: { type: Boolean },
|
|
1994
|
+
[librechatDataProvider.Permissions.VIEW_ROLES]: { type: Boolean },
|
|
1995
|
+
},
|
|
1996
|
+
[librechatDataProvider.PermissionTypes.MARKETPLACE]: {
|
|
1997
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
1998
|
+
},
|
|
1999
|
+
[librechatDataProvider.PermissionTypes.FILE_SEARCH]: {
|
|
2000
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
2001
|
+
},
|
|
2002
|
+
[librechatDataProvider.PermissionTypes.FILE_CITATIONS]: {
|
|
2003
|
+
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
2004
|
+
},
|
|
2005
|
+
}, { _id: false });
|
|
2006
|
+
const roleSchema = new mongoose.Schema({
|
|
2007
|
+
name: { type: String, required: true, unique: true, index: true },
|
|
2008
|
+
permissions: {
|
|
2009
|
+
type: rolePermissionsSchema,
|
|
2010
|
+
},
|
|
2011
|
+
});
|
|
2012
|
+
|
|
2013
|
+
const sessionSchema = new mongoose.Schema({
|
|
2014
|
+
refreshTokenHash: {
|
|
2015
|
+
type: String,
|
|
2016
|
+
required: true,
|
|
2017
|
+
},
|
|
2018
|
+
expiration: {
|
|
2019
|
+
type: Date,
|
|
2020
|
+
required: true,
|
|
2021
|
+
expires: 0,
|
|
2022
|
+
},
|
|
2023
|
+
user: {
|
|
2024
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
2025
|
+
ref: 'User',
|
|
2026
|
+
required: true,
|
|
2027
|
+
},
|
|
2028
|
+
});
|
|
2029
|
+
|
|
2030
|
+
const shareSchema = new mongoose.Schema({
|
|
2031
|
+
conversationId: {
|
|
2032
|
+
type: String,
|
|
2033
|
+
required: true,
|
|
2034
|
+
},
|
|
2035
|
+
title: {
|
|
2036
|
+
type: String,
|
|
2037
|
+
index: true,
|
|
2038
|
+
},
|
|
2039
|
+
user: {
|
|
2040
|
+
type: String,
|
|
2041
|
+
index: true,
|
|
2042
|
+
},
|
|
2043
|
+
messages: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }],
|
|
2044
|
+
shareId: {
|
|
2045
|
+
type: String,
|
|
2046
|
+
index: true,
|
|
2047
|
+
},
|
|
2048
|
+
targetMessageId: {
|
|
2049
|
+
type: String,
|
|
2050
|
+
required: false,
|
|
2051
|
+
index: true,
|
|
2052
|
+
},
|
|
2053
|
+
isPublic: {
|
|
2054
|
+
type: Boolean,
|
|
2055
|
+
default: true,
|
|
2056
|
+
},
|
|
2057
|
+
}, { timestamps: true });
|
|
2058
|
+
shareSchema.index({ conversationId: 1, user: 1, targetMessageId: 1 });
|
|
2059
|
+
|
|
2060
|
+
const tokenSchema = new mongoose.Schema({
|
|
2061
|
+
userId: {
|
|
2062
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
2063
|
+
required: true,
|
|
2064
|
+
ref: 'user',
|
|
2065
|
+
},
|
|
2066
|
+
email: {
|
|
2067
|
+
type: String,
|
|
2068
|
+
},
|
|
2069
|
+
type: {
|
|
2070
|
+
type: String,
|
|
2071
|
+
},
|
|
2072
|
+
identifier: {
|
|
2073
|
+
type: String,
|
|
2074
|
+
},
|
|
2075
|
+
token: {
|
|
2076
|
+
type: String,
|
|
2077
|
+
required: true,
|
|
2078
|
+
},
|
|
2079
|
+
createdAt: {
|
|
2080
|
+
type: Date,
|
|
2081
|
+
required: true,
|
|
2082
|
+
default: Date.now,
|
|
2083
|
+
},
|
|
2084
|
+
expiresAt: {
|
|
2085
|
+
type: Date,
|
|
2086
|
+
required: true,
|
|
2087
|
+
},
|
|
2088
|
+
metadata: {
|
|
2089
|
+
type: Map,
|
|
2090
|
+
of: mongoose.Schema.Types.Mixed,
|
|
2091
|
+
},
|
|
1723
2092
|
});
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1743
|
-
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
|
|
1747
|
-
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
}
|
|
1756
|
-
|
|
2093
|
+
tokenSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
2094
|
+
|
|
2095
|
+
const toolCallSchema = new mongoose.Schema({
|
|
2096
|
+
conversationId: {
|
|
2097
|
+
type: String,
|
|
2098
|
+
required: true,
|
|
2099
|
+
},
|
|
2100
|
+
messageId: {
|
|
2101
|
+
type: String,
|
|
2102
|
+
required: true,
|
|
2103
|
+
},
|
|
2104
|
+
toolId: {
|
|
2105
|
+
type: String,
|
|
2106
|
+
required: true,
|
|
2107
|
+
},
|
|
2108
|
+
user: {
|
|
2109
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
2110
|
+
ref: 'User',
|
|
2111
|
+
required: true,
|
|
2112
|
+
},
|
|
2113
|
+
result: {
|
|
2114
|
+
type: mongoose.Schema.Types.Mixed,
|
|
2115
|
+
},
|
|
2116
|
+
attachments: {
|
|
2117
|
+
type: mongoose.Schema.Types.Mixed,
|
|
2118
|
+
},
|
|
2119
|
+
blockIndex: {
|
|
2120
|
+
type: Number,
|
|
2121
|
+
},
|
|
2122
|
+
partIndex: {
|
|
2123
|
+
type: Number,
|
|
2124
|
+
},
|
|
2125
|
+
}, { timestamps: true });
|
|
2126
|
+
toolCallSchema.index({ messageId: 1, user: 1 });
|
|
2127
|
+
toolCallSchema.index({ conversationId: 1, user: 1 });
|
|
2128
|
+
|
|
2129
|
+
const transactionSchema = new mongoose.Schema({
|
|
2130
|
+
user: {
|
|
2131
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
2132
|
+
ref: 'User',
|
|
2133
|
+
index: true,
|
|
2134
|
+
required: true,
|
|
2135
|
+
},
|
|
2136
|
+
conversationId: {
|
|
2137
|
+
type: String,
|
|
2138
|
+
ref: 'Conversation',
|
|
2139
|
+
index: true,
|
|
2140
|
+
},
|
|
2141
|
+
tokenType: {
|
|
2142
|
+
type: String,
|
|
2143
|
+
enum: ['prompt', 'completion', 'credits'],
|
|
2144
|
+
required: true,
|
|
2145
|
+
},
|
|
2146
|
+
model: {
|
|
2147
|
+
type: String,
|
|
2148
|
+
},
|
|
2149
|
+
context: {
|
|
2150
|
+
type: String,
|
|
2151
|
+
},
|
|
2152
|
+
valueKey: {
|
|
2153
|
+
type: String,
|
|
2154
|
+
},
|
|
2155
|
+
rate: Number,
|
|
2156
|
+
rawAmount: Number,
|
|
2157
|
+
tokenValue: Number,
|
|
2158
|
+
inputTokens: { type: Number },
|
|
2159
|
+
writeTokens: { type: Number },
|
|
2160
|
+
readTokens: { type: Number },
|
|
2161
|
+
}, {
|
|
2162
|
+
timestamps: true,
|
|
1757
2163
|
});
|
|
1758
2164
|
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1775
|
-
|
|
1776
|
-
|
|
1777
|
-
|
|
1778
|
-
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
|
|
1782
|
-
|
|
1783
|
-
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
}
|
|
2165
|
+
// Session sub-schema
|
|
2166
|
+
const SessionSchema = new mongoose.Schema({
|
|
2167
|
+
refreshToken: {
|
|
2168
|
+
type: String,
|
|
2169
|
+
default: '',
|
|
2170
|
+
},
|
|
2171
|
+
}, { _id: false });
|
|
2172
|
+
// Backup code sub-schema
|
|
2173
|
+
const BackupCodeSchema = new mongoose.Schema({
|
|
2174
|
+
codeHash: { type: String, required: true },
|
|
2175
|
+
used: { type: Boolean, default: false },
|
|
2176
|
+
usedAt: { type: Date, default: null },
|
|
2177
|
+
}, { _id: false });
|
|
2178
|
+
const userSchema = new mongoose.Schema({
|
|
2179
|
+
name: {
|
|
2180
|
+
type: String,
|
|
2181
|
+
},
|
|
2182
|
+
username: {
|
|
2183
|
+
type: String,
|
|
2184
|
+
lowercase: true,
|
|
2185
|
+
default: '',
|
|
2186
|
+
},
|
|
2187
|
+
email: {
|
|
2188
|
+
type: String,
|
|
2189
|
+
required: [true, "can't be blank"],
|
|
2190
|
+
lowercase: true,
|
|
2191
|
+
unique: true,
|
|
2192
|
+
match: [/\S+@\S+\.\S+/, 'is invalid'],
|
|
2193
|
+
index: true,
|
|
2194
|
+
},
|
|
2195
|
+
emailVerified: {
|
|
2196
|
+
type: Boolean,
|
|
2197
|
+
required: true,
|
|
2198
|
+
default: false,
|
|
2199
|
+
},
|
|
2200
|
+
password: {
|
|
2201
|
+
type: String,
|
|
2202
|
+
trim: true,
|
|
2203
|
+
minlength: 8,
|
|
2204
|
+
maxlength: 128,
|
|
2205
|
+
select: false,
|
|
2206
|
+
},
|
|
2207
|
+
avatar: {
|
|
2208
|
+
type: String,
|
|
2209
|
+
required: false,
|
|
2210
|
+
},
|
|
2211
|
+
provider: {
|
|
2212
|
+
type: String,
|
|
2213
|
+
required: true,
|
|
2214
|
+
default: 'local',
|
|
2215
|
+
},
|
|
2216
|
+
role: {
|
|
2217
|
+
type: String,
|
|
2218
|
+
default: librechatDataProvider.SystemRoles.USER,
|
|
2219
|
+
},
|
|
2220
|
+
googleId: {
|
|
2221
|
+
type: String,
|
|
2222
|
+
unique: true,
|
|
2223
|
+
sparse: true,
|
|
2224
|
+
},
|
|
2225
|
+
facebookId: {
|
|
2226
|
+
type: String,
|
|
2227
|
+
unique: true,
|
|
2228
|
+
sparse: true,
|
|
2229
|
+
},
|
|
2230
|
+
openidId: {
|
|
2231
|
+
type: String,
|
|
2232
|
+
unique: true,
|
|
2233
|
+
sparse: true,
|
|
2234
|
+
},
|
|
2235
|
+
samlId: {
|
|
2236
|
+
type: String,
|
|
2237
|
+
unique: true,
|
|
2238
|
+
sparse: true,
|
|
2239
|
+
},
|
|
2240
|
+
ldapId: {
|
|
2241
|
+
type: String,
|
|
2242
|
+
unique: true,
|
|
2243
|
+
sparse: true,
|
|
2244
|
+
},
|
|
2245
|
+
githubId: {
|
|
2246
|
+
type: String,
|
|
2247
|
+
unique: true,
|
|
2248
|
+
sparse: true,
|
|
2249
|
+
},
|
|
2250
|
+
discordId: {
|
|
2251
|
+
type: String,
|
|
2252
|
+
unique: true,
|
|
2253
|
+
sparse: true,
|
|
2254
|
+
},
|
|
2255
|
+
appleId: {
|
|
2256
|
+
type: String,
|
|
2257
|
+
unique: true,
|
|
2258
|
+
sparse: true,
|
|
2259
|
+
},
|
|
2260
|
+
plugins: {
|
|
2261
|
+
type: Array,
|
|
2262
|
+
},
|
|
2263
|
+
twoFactorEnabled: {
|
|
2264
|
+
type: Boolean,
|
|
2265
|
+
default: false,
|
|
2266
|
+
},
|
|
2267
|
+
totpSecret: {
|
|
2268
|
+
type: String,
|
|
2269
|
+
select: false,
|
|
2270
|
+
},
|
|
2271
|
+
backupCodes: {
|
|
2272
|
+
type: [BackupCodeSchema],
|
|
2273
|
+
select: false,
|
|
2274
|
+
},
|
|
2275
|
+
refreshToken: {
|
|
2276
|
+
type: [SessionSchema],
|
|
2277
|
+
},
|
|
2278
|
+
expiresAt: {
|
|
2279
|
+
type: Date,
|
|
2280
|
+
expires: 604800, // 7 days in seconds
|
|
2281
|
+
},
|
|
2282
|
+
termsAccepted: {
|
|
2283
|
+
type: Boolean,
|
|
2284
|
+
default: false,
|
|
2285
|
+
},
|
|
2286
|
+
personalization: {
|
|
2287
|
+
type: {
|
|
2288
|
+
memories: {
|
|
2289
|
+
type: Boolean,
|
|
2290
|
+
default: true,
|
|
2291
|
+
},
|
|
2292
|
+
},
|
|
2293
|
+
default: {},
|
|
2294
|
+
},
|
|
2295
|
+
/** Field for external source identification (for consistency with TPrincipal schema) */
|
|
2296
|
+
idOnTheSource: {
|
|
2297
|
+
type: String,
|
|
2298
|
+
sparse: true,
|
|
2299
|
+
},
|
|
2300
|
+
}, { timestamps: true });
|
|
1789
2301
|
|
|
1790
|
-
const
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
}
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
1808
|
-
|
|
1809
|
-
|
|
2302
|
+
const MemoryEntrySchema = new mongoose.Schema({
|
|
2303
|
+
userId: {
|
|
2304
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
2305
|
+
ref: 'User',
|
|
2306
|
+
index: true,
|
|
2307
|
+
required: true,
|
|
2308
|
+
},
|
|
2309
|
+
key: {
|
|
2310
|
+
type: String,
|
|
2311
|
+
required: true,
|
|
2312
|
+
validate: {
|
|
2313
|
+
validator: (v) => /^[a-z_]+$/.test(v),
|
|
2314
|
+
message: 'Key must only contain lowercase letters and underscores',
|
|
2315
|
+
},
|
|
2316
|
+
},
|
|
2317
|
+
value: {
|
|
2318
|
+
type: String,
|
|
2319
|
+
required: true,
|
|
2320
|
+
},
|
|
2321
|
+
tokenCount: {
|
|
2322
|
+
type: Number,
|
|
2323
|
+
default: 0,
|
|
2324
|
+
},
|
|
2325
|
+
updated_at: {
|
|
2326
|
+
type: Date,
|
|
2327
|
+
default: Date.now,
|
|
2328
|
+
},
|
|
1810
2329
|
});
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1816
|
-
|
|
1817
|
-
|
|
1818
|
-
|
|
1819
|
-
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1837
|
-
|
|
1838
|
-
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
}
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
}
|
|
1855
|
-
else if (useConsoleJson) {
|
|
1856
|
-
transports$1.push(new winston.transports.Console({
|
|
1857
|
-
level: consoleLogLevel,
|
|
1858
|
-
format: winston.format.combine(fileFormat$1, jsonTruncateFormat(), winston.format.json()),
|
|
1859
|
-
}));
|
|
1860
|
-
}
|
|
1861
|
-
else {
|
|
1862
|
-
transports$1.push(new winston.transports.Console({
|
|
1863
|
-
level: consoleLogLevel,
|
|
1864
|
-
format: consoleFormat$1,
|
|
1865
|
-
}));
|
|
1866
|
-
}
|
|
1867
|
-
// Create logger
|
|
1868
|
-
const logger$1 = winston.createLogger({
|
|
1869
|
-
level: level$1(),
|
|
1870
|
-
levels: levels$1,
|
|
1871
|
-
transports: transports$1,
|
|
2330
|
+
|
|
2331
|
+
const groupSchema = new mongoose.Schema({
|
|
2332
|
+
name: {
|
|
2333
|
+
type: String,
|
|
2334
|
+
required: true,
|
|
2335
|
+
index: true,
|
|
2336
|
+
},
|
|
2337
|
+
description: {
|
|
2338
|
+
type: String,
|
|
2339
|
+
required: false,
|
|
2340
|
+
},
|
|
2341
|
+
email: {
|
|
2342
|
+
type: String,
|
|
2343
|
+
required: false,
|
|
2344
|
+
index: true,
|
|
2345
|
+
},
|
|
2346
|
+
avatar: {
|
|
2347
|
+
type: String,
|
|
2348
|
+
required: false,
|
|
2349
|
+
},
|
|
2350
|
+
memberIds: [
|
|
2351
|
+
{
|
|
2352
|
+
type: String,
|
|
2353
|
+
required: false,
|
|
2354
|
+
},
|
|
2355
|
+
],
|
|
2356
|
+
source: {
|
|
2357
|
+
type: String,
|
|
2358
|
+
enum: ['local', 'entra'],
|
|
2359
|
+
default: 'local',
|
|
2360
|
+
},
|
|
2361
|
+
/** External ID (e.g., Entra ID) */
|
|
2362
|
+
idOnTheSource: {
|
|
2363
|
+
type: String,
|
|
2364
|
+
sparse: true,
|
|
2365
|
+
index: true,
|
|
2366
|
+
required: function () {
|
|
2367
|
+
return this.source !== 'local';
|
|
2368
|
+
},
|
|
2369
|
+
},
|
|
2370
|
+
}, { timestamps: true });
|
|
2371
|
+
groupSchema.index({ idOnTheSource: 1, source: 1 }, {
|
|
2372
|
+
unique: true,
|
|
2373
|
+
partialFilterExpression: { idOnTheSource: { $exists: true } },
|
|
1872
2374
|
});
|
|
2375
|
+
groupSchema.index({ memberIds: 1 });
|
|
1873
2376
|
|
|
1874
2377
|
/**
|
|
1875
2378
|
* Checks if the connected MongoDB deployment supports transactions
|
|
@@ -3060,7 +3563,11 @@ function createTokenMethods(mongoose) {
|
|
|
3060
3563
|
async function updateToken(query, updateData) {
|
|
3061
3564
|
try {
|
|
3062
3565
|
const Token = mongoose.models.Token;
|
|
3063
|
-
|
|
3566
|
+
const dataToUpdate = { ...updateData };
|
|
3567
|
+
if ((updateData === null || updateData === void 0 ? void 0 : updateData.expiresIn) !== undefined) {
|
|
3568
|
+
dataToUpdate.expiresAt = new Date(Date.now() + updateData.expiresIn * 1000);
|
|
3569
|
+
}
|
|
3570
|
+
return await Token.findOneAndUpdate(query, dataToUpdate, { new: true });
|
|
3064
3571
|
}
|
|
3065
3572
|
catch (error) {
|
|
3066
3573
|
logger$1.debug('An error occurred while updating token:', error);
|
|
@@ -3069,6 +3576,7 @@ function createTokenMethods(mongoose) {
|
|
|
3069
3576
|
}
|
|
3070
3577
|
/**
|
|
3071
3578
|
* Deletes all Token documents that match the provided token, user ID, or email.
|
|
3579
|
+
* Email is automatically normalized to lowercase for case-insensitive matching.
|
|
3072
3580
|
*/
|
|
3073
3581
|
async function deleteTokens(query) {
|
|
3074
3582
|
try {
|
|
@@ -3081,7 +3589,7 @@ function createTokenMethods(mongoose) {
|
|
|
3081
3589
|
conditions.push({ token: query.token });
|
|
3082
3590
|
}
|
|
3083
3591
|
if (query.email !== undefined) {
|
|
3084
|
-
conditions.push({ email: query.email });
|
|
3592
|
+
conditions.push({ email: query.email.trim().toLowerCase() });
|
|
3085
3593
|
}
|
|
3086
3594
|
if (query.identifier !== undefined) {
|
|
3087
3595
|
conditions.push({ identifier: query.identifier });
|
|
@@ -3103,6 +3611,7 @@ function createTokenMethods(mongoose) {
|
|
|
3103
3611
|
}
|
|
3104
3612
|
/**
|
|
3105
3613
|
* Finds a Token document that matches the provided query.
|
|
3614
|
+
* Email is automatically normalized to lowercase for case-insensitive matching.
|
|
3106
3615
|
*/
|
|
3107
3616
|
async function findToken(query, options) {
|
|
3108
3617
|
try {
|
|
@@ -3115,7 +3624,7 @@ function createTokenMethods(mongoose) {
|
|
|
3115
3624
|
conditions.push({ token: query.token });
|
|
3116
3625
|
}
|
|
3117
3626
|
if (query.email) {
|
|
3118
|
-
conditions.push({ email: query.email });
|
|
3627
|
+
conditions.push({ email: query.email.trim().toLowerCase() });
|
|
3119
3628
|
}
|
|
3120
3629
|
if (query.identifier) {
|
|
3121
3630
|
conditions.push({ identifier: query.identifier });
|
|
@@ -3182,12 +3691,33 @@ function createRoleMethods(mongoose) {
|
|
|
3182
3691
|
|
|
3183
3692
|
/** Factory function that takes mongoose instance and returns the methods */
|
|
3184
3693
|
function createUserMethods(mongoose) {
|
|
3694
|
+
/**
|
|
3695
|
+
* Normalizes email fields in search criteria to lowercase and trimmed.
|
|
3696
|
+
* Handles both direct email fields and $or arrays containing email conditions.
|
|
3697
|
+
*/
|
|
3698
|
+
function normalizeEmailInCriteria(criteria) {
|
|
3699
|
+
const normalized = { ...criteria };
|
|
3700
|
+
if (typeof normalized.email === 'string') {
|
|
3701
|
+
normalized.email = normalized.email.trim().toLowerCase();
|
|
3702
|
+
}
|
|
3703
|
+
if (Array.isArray(normalized.$or)) {
|
|
3704
|
+
normalized.$or = normalized.$or.map((condition) => {
|
|
3705
|
+
if (typeof condition.email === 'string') {
|
|
3706
|
+
return { ...condition, email: condition.email.trim().toLowerCase() };
|
|
3707
|
+
}
|
|
3708
|
+
return condition;
|
|
3709
|
+
});
|
|
3710
|
+
}
|
|
3711
|
+
return normalized;
|
|
3712
|
+
}
|
|
3185
3713
|
/**
|
|
3186
3714
|
* Search for a single user based on partial data and return matching user document as plain object.
|
|
3715
|
+
* Email fields in searchCriteria are automatically normalized to lowercase for case-insensitive matching.
|
|
3187
3716
|
*/
|
|
3188
3717
|
async function findUser(searchCriteria, fieldsToSelect) {
|
|
3189
3718
|
const User = mongoose.models.User;
|
|
3190
|
-
const
|
|
3719
|
+
const normalizedCriteria = normalizeEmailInCriteria(searchCriteria);
|
|
3720
|
+
const query = User.findOne(normalizedCriteria);
|
|
3191
3721
|
if (fieldsToSelect) {
|
|
3192
3722
|
query.select(fieldsToSelect);
|
|
3193
3723
|
}
|
|
@@ -4766,6 +5296,68 @@ function anonymizeMessages(messages, newConvoId) {
|
|
|
4766
5296
|
};
|
|
4767
5297
|
});
|
|
4768
5298
|
}
|
|
5299
|
+
/**
|
|
5300
|
+
* Filter messages up to and including the target message (branch-specific)
|
|
5301
|
+
* Similar to getMessagesUpToTargetLevel from fork utilities
|
|
5302
|
+
*/
|
|
5303
|
+
function getMessagesUpToTarget(messages, targetMessageId) {
|
|
5304
|
+
var _a, _b;
|
|
5305
|
+
if (!messages || messages.length === 0) {
|
|
5306
|
+
return [];
|
|
5307
|
+
}
|
|
5308
|
+
// If only one message and it's the target, return it
|
|
5309
|
+
if (messages.length === 1 && ((_a = messages[0]) === null || _a === void 0 ? void 0 : _a.messageId) === targetMessageId) {
|
|
5310
|
+
return messages;
|
|
5311
|
+
}
|
|
5312
|
+
// Create a map of parentMessageId to children messages
|
|
5313
|
+
const parentToChildrenMap = new Map();
|
|
5314
|
+
for (const message of messages) {
|
|
5315
|
+
const parentId = message.parentMessageId || librechatDataProvider.Constants.NO_PARENT;
|
|
5316
|
+
if (!parentToChildrenMap.has(parentId)) {
|
|
5317
|
+
parentToChildrenMap.set(parentId, []);
|
|
5318
|
+
}
|
|
5319
|
+
(_b = parentToChildrenMap.get(parentId)) === null || _b === void 0 ? void 0 : _b.push(message);
|
|
5320
|
+
}
|
|
5321
|
+
// Find the target message
|
|
5322
|
+
const targetMessage = messages.find((msg) => msg.messageId === targetMessageId);
|
|
5323
|
+
if (!targetMessage) {
|
|
5324
|
+
// If target not found, return all messages for backwards compatibility
|
|
5325
|
+
return messages;
|
|
5326
|
+
}
|
|
5327
|
+
const visited = new Set();
|
|
5328
|
+
const rootMessages = parentToChildrenMap.get(librechatDataProvider.Constants.NO_PARENT) || [];
|
|
5329
|
+
let currentLevel = rootMessages.length > 0 ? [...rootMessages] : [targetMessage];
|
|
5330
|
+
const results = new Set(currentLevel);
|
|
5331
|
+
// Check if the target message is at the root level
|
|
5332
|
+
if (currentLevel.some((msg) => msg.messageId === targetMessageId) &&
|
|
5333
|
+
targetMessage.parentMessageId === librechatDataProvider.Constants.NO_PARENT) {
|
|
5334
|
+
return Array.from(results);
|
|
5335
|
+
}
|
|
5336
|
+
// Iterate level by level until the target is found
|
|
5337
|
+
let targetFound = false;
|
|
5338
|
+
while (!targetFound && currentLevel.length > 0) {
|
|
5339
|
+
const nextLevel = [];
|
|
5340
|
+
for (const node of currentLevel) {
|
|
5341
|
+
if (visited.has(node.messageId)) {
|
|
5342
|
+
continue;
|
|
5343
|
+
}
|
|
5344
|
+
visited.add(node.messageId);
|
|
5345
|
+
const children = parentToChildrenMap.get(node.messageId) || [];
|
|
5346
|
+
for (const child of children) {
|
|
5347
|
+
if (visited.has(child.messageId)) {
|
|
5348
|
+
continue;
|
|
5349
|
+
}
|
|
5350
|
+
nextLevel.push(child);
|
|
5351
|
+
results.add(child);
|
|
5352
|
+
if (child.messageId === targetMessageId) {
|
|
5353
|
+
targetFound = true;
|
|
5354
|
+
}
|
|
5355
|
+
}
|
|
5356
|
+
}
|
|
5357
|
+
currentLevel = nextLevel;
|
|
5358
|
+
}
|
|
5359
|
+
return Array.from(results);
|
|
5360
|
+
}
|
|
4769
5361
|
/** Factory function that takes mongoose instance and returns the methods */
|
|
4770
5362
|
function createShareMethods(mongoose) {
|
|
4771
5363
|
/**
|
|
@@ -4784,6 +5376,11 @@ function createShareMethods(mongoose) {
|
|
|
4784
5376
|
if (!(share === null || share === void 0 ? void 0 : share.conversationId) || !share.isPublic) {
|
|
4785
5377
|
return null;
|
|
4786
5378
|
}
|
|
5379
|
+
/** Filtered messages based on targetMessageId if present (branch-specific sharing) */
|
|
5380
|
+
let messagesToShare = share.messages;
|
|
5381
|
+
if (share.targetMessageId) {
|
|
5382
|
+
messagesToShare = getMessagesUpToTarget(share.messages, share.targetMessageId);
|
|
5383
|
+
}
|
|
4787
5384
|
const newConvoId = anonymizeConvoId(share.conversationId);
|
|
4788
5385
|
const result = {
|
|
4789
5386
|
shareId: share.shareId || shareId,
|
|
@@ -4792,7 +5389,7 @@ function createShareMethods(mongoose) {
|
|
|
4792
5389
|
createdAt: share.createdAt,
|
|
4793
5390
|
updatedAt: share.updatedAt,
|
|
4794
5391
|
conversationId: newConvoId,
|
|
4795
|
-
messages: anonymizeMessages(
|
|
5392
|
+
messages: anonymizeMessages(messagesToShare, newConvoId),
|
|
4796
5393
|
};
|
|
4797
5394
|
return result;
|
|
4798
5395
|
}
|
|
@@ -4900,10 +5497,34 @@ function createShareMethods(mongoose) {
|
|
|
4900
5497
|
throw new ShareServiceError('Error deleting shared links', 'BULK_DELETE_ERROR');
|
|
4901
5498
|
}
|
|
4902
5499
|
}
|
|
5500
|
+
/**
|
|
5501
|
+
* Delete shared links by conversation ID
|
|
5502
|
+
*/
|
|
5503
|
+
async function deleteConvoSharedLink(user, conversationId) {
|
|
5504
|
+
if (!user || !conversationId) {
|
|
5505
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
5506
|
+
}
|
|
5507
|
+
try {
|
|
5508
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
5509
|
+
const result = await SharedLink.deleteMany({ user, conversationId });
|
|
5510
|
+
return {
|
|
5511
|
+
message: 'Shared links deleted successfully',
|
|
5512
|
+
deletedCount: result.deletedCount,
|
|
5513
|
+
};
|
|
5514
|
+
}
|
|
5515
|
+
catch (error) {
|
|
5516
|
+
logger$1.error('[deleteConvoSharedLink] Error deleting shared links', {
|
|
5517
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
5518
|
+
user,
|
|
5519
|
+
conversationId,
|
|
5520
|
+
});
|
|
5521
|
+
throw new ShareServiceError('Error deleting shared links', 'SHARE_DELETE_ERROR');
|
|
5522
|
+
}
|
|
5523
|
+
}
|
|
4903
5524
|
/**
|
|
4904
5525
|
* Create a new shared link for a conversation
|
|
4905
5526
|
*/
|
|
4906
|
-
async function createSharedLink(user, conversationId) {
|
|
5527
|
+
async function createSharedLink(user, conversationId, targetMessageId) {
|
|
4907
5528
|
if (!user || !conversationId) {
|
|
4908
5529
|
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
4909
5530
|
}
|
|
@@ -4912,7 +5533,12 @@ function createShareMethods(mongoose) {
|
|
|
4912
5533
|
const SharedLink = mongoose.models.SharedLink;
|
|
4913
5534
|
const Conversation = mongoose.models.Conversation;
|
|
4914
5535
|
const [existingShare, conversationMessages] = await Promise.all([
|
|
4915
|
-
SharedLink.findOne({
|
|
5536
|
+
SharedLink.findOne({
|
|
5537
|
+
conversationId,
|
|
5538
|
+
user,
|
|
5539
|
+
isPublic: true,
|
|
5540
|
+
...(targetMessageId && { targetMessageId }),
|
|
5541
|
+
})
|
|
4916
5542
|
.select('-_id -__v -user')
|
|
4917
5543
|
.lean(),
|
|
4918
5544
|
Message.find({ conversationId, user }).sort({ createdAt: 1 }).lean(),
|
|
@@ -4921,11 +5547,16 @@ function createShareMethods(mongoose) {
|
|
|
4921
5547
|
logger$1.error('[createSharedLink] Share already exists', {
|
|
4922
5548
|
user,
|
|
4923
5549
|
conversationId,
|
|
5550
|
+
targetMessageId,
|
|
4924
5551
|
});
|
|
4925
5552
|
throw new ShareServiceError('Share already exists', 'SHARE_EXISTS');
|
|
4926
5553
|
}
|
|
4927
5554
|
else if (existingShare) {
|
|
4928
|
-
await SharedLink.deleteOne({
|
|
5555
|
+
await SharedLink.deleteOne({
|
|
5556
|
+
conversationId,
|
|
5557
|
+
user,
|
|
5558
|
+
...(targetMessageId && { targetMessageId }),
|
|
5559
|
+
});
|
|
4929
5560
|
}
|
|
4930
5561
|
const conversation = (await Conversation.findOne({ conversationId, user }).lean());
|
|
4931
5562
|
// Check if user owns the conversation
|
|
@@ -4944,6 +5575,7 @@ function createShareMethods(mongoose) {
|
|
|
4944
5575
|
messages: conversationMessages,
|
|
4945
5576
|
title,
|
|
4946
5577
|
user,
|
|
5578
|
+
...(targetMessageId && { targetMessageId }),
|
|
4947
5579
|
});
|
|
4948
5580
|
return { shareId, conversationId };
|
|
4949
5581
|
}
|
|
@@ -4955,6 +5587,7 @@ function createShareMethods(mongoose) {
|
|
|
4955
5587
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
4956
5588
|
user,
|
|
4957
5589
|
conversationId,
|
|
5590
|
+
targetMessageId,
|
|
4958
5591
|
});
|
|
4959
5592
|
throw new ShareServiceError('Error creating shared link', 'SHARE_CREATE_ERROR');
|
|
4960
5593
|
}
|
|
@@ -5067,6 +5700,7 @@ function createShareMethods(mongoose) {
|
|
|
5067
5700
|
deleteSharedLink,
|
|
5068
5701
|
getSharedMessages,
|
|
5069
5702
|
deleteAllSharedLinks,
|
|
5703
|
+
deleteConvoSharedLink,
|
|
5070
5704
|
};
|
|
5071
5705
|
}
|
|
5072
5706
|
|
|
@@ -5089,9 +5723,11 @@ function createMethods(mongoose) {
|
|
|
5089
5723
|
};
|
|
5090
5724
|
}
|
|
5091
5725
|
|
|
5726
|
+
exports.AppService = AppService;
|
|
5092
5727
|
exports.actionSchema = Action;
|
|
5093
5728
|
exports.agentCategorySchema = agentCategorySchema;
|
|
5094
5729
|
exports.agentSchema = agentSchema;
|
|
5730
|
+
exports.agentsConfigSetup = agentsConfigSetup;
|
|
5095
5731
|
exports.assistantSchema = assistantSchema;
|
|
5096
5732
|
exports.balanceSchema = balanceSchema;
|
|
5097
5733
|
exports.bannerSchema = bannerSchema;
|
|
@@ -5102,15 +5738,20 @@ exports.createMethods = createMethods;
|
|
|
5102
5738
|
exports.createModels = createModels;
|
|
5103
5739
|
exports.fileSchema = file;
|
|
5104
5740
|
exports.getTransactionSupport = getTransactionSupport;
|
|
5741
|
+
exports.getWebSearchKeys = getWebSearchKeys;
|
|
5105
5742
|
exports.groupSchema = groupSchema;
|
|
5106
5743
|
exports.hashToken = hashToken;
|
|
5107
5744
|
exports.keySchema = keySchema;
|
|
5745
|
+
exports.loadDefaultInterface = loadDefaultInterface;
|
|
5746
|
+
exports.loadTurnstileConfig = loadTurnstileConfig;
|
|
5747
|
+
exports.loadWebSearchConfig = loadWebSearchConfig;
|
|
5108
5748
|
exports.logger = logger$1;
|
|
5109
5749
|
exports.meiliLogger = logger;
|
|
5110
5750
|
exports.memorySchema = MemoryEntrySchema;
|
|
5111
5751
|
exports.messageSchema = messageSchema;
|
|
5112
5752
|
exports.pluginAuthSchema = pluginAuthSchema;
|
|
5113
5753
|
exports.presetSchema = presetSchema;
|
|
5754
|
+
exports.processModelSpecs = processModelSpecs;
|
|
5114
5755
|
exports.projectSchema = projectSchema;
|
|
5115
5756
|
exports.promptGroupSchema = promptGroupSchema;
|
|
5116
5757
|
exports.promptSchema = promptSchema;
|
|
@@ -5123,4 +5764,6 @@ exports.tokenSchema = tokenSchema;
|
|
|
5123
5764
|
exports.toolCallSchema = toolCallSchema;
|
|
5124
5765
|
exports.transactionSchema = transactionSchema;
|
|
5125
5766
|
exports.userSchema = userSchema;
|
|
5767
|
+
exports.webSearchAuth = webSearchAuth;
|
|
5768
|
+
exports.webSearchKeys = webSearchKeys;
|
|
5126
5769
|
//# sourceMappingURL=index.cjs.map
|