@librechat/data-schemas 0.0.22 → 0.0.30
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 +2213 -1579
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +2179 -1554
- 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/token.d.ts +2 -2
- package/dist/types/models/plugins/mongoMeili.d.ts +2 -2
- 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/web.d.ts +3 -0
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -1,1873 +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
|
-
|
|
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
|
+
},
|
|
554
625
|
},
|
|
555
|
-
|
|
556
|
-
|
|
626
|
+
scrapers: {
|
|
627
|
+
firecrawl: {
|
|
628
|
+
firecrawlApiKey: 1,
|
|
629
|
+
/** Optional (0) */
|
|
630
|
+
firecrawlApiUrl: 0,
|
|
631
|
+
firecrawlVersion: 0,
|
|
632
|
+
},
|
|
633
|
+
serper: {
|
|
634
|
+
serperApiKey: 1,
|
|
635
|
+
},
|
|
557
636
|
},
|
|
558
|
-
|
|
559
|
-
|
|
637
|
+
rerankers: {
|
|
638
|
+
jina: {
|
|
639
|
+
jinaApiKey: 1,
|
|
640
|
+
/** Optional (0) */
|
|
641
|
+
jinaApiUrl: 0,
|
|
642
|
+
},
|
|
643
|
+
cohere: { cohereApiKey: 1 },
|
|
560
644
|
},
|
|
561
|
-
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
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
|
+
}
|
|
565
692
|
|
|
566
|
-
|
|
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({
|
|
567
1023
|
user: {
|
|
568
1024
|
type: mongoose.Schema.Types.ObjectId,
|
|
569
1025
|
ref: 'User',
|
|
570
1026
|
index: true,
|
|
571
1027
|
required: true,
|
|
572
1028
|
},
|
|
573
|
-
|
|
574
|
-
type: String,
|
|
575
|
-
ref: 'Conversation',
|
|
576
|
-
index: true,
|
|
577
|
-
},
|
|
578
|
-
file_id: {
|
|
1029
|
+
action_id: {
|
|
579
1030
|
type: String,
|
|
580
1031
|
index: true,
|
|
581
1032
|
required: true,
|
|
582
1033
|
},
|
|
583
|
-
temp_file_id: {
|
|
584
|
-
type: String,
|
|
585
|
-
},
|
|
586
|
-
bytes: {
|
|
587
|
-
type: Number,
|
|
588
|
-
required: true,
|
|
589
|
-
},
|
|
590
|
-
filename: {
|
|
591
|
-
type: String,
|
|
592
|
-
required: true,
|
|
593
|
-
},
|
|
594
|
-
filepath: {
|
|
595
|
-
type: String,
|
|
596
|
-
required: true,
|
|
597
|
-
},
|
|
598
|
-
object: {
|
|
599
|
-
type: String,
|
|
600
|
-
required: true,
|
|
601
|
-
default: 'file',
|
|
602
|
-
},
|
|
603
|
-
embedded: {
|
|
604
|
-
type: Boolean,
|
|
605
|
-
},
|
|
606
1034
|
type: {
|
|
607
1035
|
type: String,
|
|
608
|
-
|
|
609
|
-
},
|
|
610
|
-
text: {
|
|
611
|
-
type: String,
|
|
612
|
-
},
|
|
613
|
-
context: {
|
|
614
|
-
type: String,
|
|
615
|
-
},
|
|
616
|
-
usage: {
|
|
617
|
-
type: Number,
|
|
618
|
-
required: true,
|
|
619
|
-
default: 0,
|
|
620
|
-
},
|
|
621
|
-
source: {
|
|
622
|
-
type: String,
|
|
623
|
-
default: librechatDataProvider.FileSources.local,
|
|
624
|
-
},
|
|
625
|
-
model: {
|
|
626
|
-
type: String,
|
|
1036
|
+
default: 'action_prototype',
|
|
627
1037
|
},
|
|
628
|
-
|
|
629
|
-
|
|
1038
|
+
settings: mongoose.Schema.Types.Mixed,
|
|
1039
|
+
agent_id: String,
|
|
1040
|
+
assistant_id: String,
|
|
630
1041
|
metadata: {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
const keySchema = new mongoose.Schema({
|
|
643
|
-
userId: {
|
|
644
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
645
|
-
ref: 'User',
|
|
646
|
-
required: true,
|
|
647
|
-
},
|
|
648
|
-
name: {
|
|
649
|
-
type: String,
|
|
650
|
-
required: true,
|
|
651
|
-
},
|
|
652
|
-
value: {
|
|
653
|
-
type: String,
|
|
654
|
-
required: true,
|
|
655
|
-
},
|
|
656
|
-
expiresAt: {
|
|
657
|
-
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,
|
|
658
1052
|
},
|
|
659
1053
|
});
|
|
660
|
-
keySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
661
1054
|
|
|
662
|
-
const
|
|
663
|
-
|
|
664
|
-
type: String,
|
|
665
|
-
unique: true,
|
|
666
|
-
required: true,
|
|
667
|
-
index: true,
|
|
668
|
-
meiliIndex: true,
|
|
669
|
-
},
|
|
670
|
-
conversationId: {
|
|
1055
|
+
const agentSchema = new mongoose.Schema({
|
|
1056
|
+
id: {
|
|
671
1057
|
type: String,
|
|
672
1058
|
index: true,
|
|
1059
|
+
unique: true,
|
|
673
1060
|
required: true,
|
|
674
|
-
meiliIndex: true,
|
|
675
1061
|
},
|
|
676
|
-
|
|
1062
|
+
name: {
|
|
677
1063
|
type: String,
|
|
678
|
-
index: true,
|
|
679
|
-
required: true,
|
|
680
|
-
default: null,
|
|
681
1064
|
},
|
|
682
|
-
|
|
1065
|
+
description: {
|
|
683
1066
|
type: String,
|
|
684
|
-
default: null,
|
|
685
1067
|
},
|
|
686
|
-
|
|
1068
|
+
instructions: {
|
|
687
1069
|
type: String,
|
|
688
1070
|
},
|
|
689
|
-
|
|
1071
|
+
avatar: {
|
|
1072
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1073
|
+
default: undefined,
|
|
1074
|
+
},
|
|
1075
|
+
provider: {
|
|
690
1076
|
type: String,
|
|
1077
|
+
required: true,
|
|
691
1078
|
},
|
|
692
|
-
|
|
1079
|
+
model: {
|
|
693
1080
|
type: String,
|
|
1081
|
+
required: true,
|
|
694
1082
|
},
|
|
695
|
-
|
|
696
|
-
type:
|
|
1083
|
+
model_parameters: {
|
|
1084
|
+
type: Object,
|
|
697
1085
|
},
|
|
698
|
-
|
|
1086
|
+
artifacts: {
|
|
699
1087
|
type: String,
|
|
700
1088
|
},
|
|
701
|
-
|
|
1089
|
+
access_level: {
|
|
702
1090
|
type: Number,
|
|
703
1091
|
},
|
|
704
|
-
|
|
1092
|
+
recursion_limit: {
|
|
705
1093
|
type: Number,
|
|
706
1094
|
},
|
|
707
|
-
|
|
708
|
-
type: String,
|
|
709
|
-
|
|
1095
|
+
tools: {
|
|
1096
|
+
type: [String],
|
|
1097
|
+
default: undefined,
|
|
710
1098
|
},
|
|
711
|
-
|
|
712
|
-
type:
|
|
713
|
-
meiliIndex: true,
|
|
1099
|
+
tool_kwargs: {
|
|
1100
|
+
type: [{ type: mongoose.Schema.Types.Mixed }],
|
|
714
1101
|
},
|
|
715
|
-
|
|
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: {
|
|
716
1112
|
type: String,
|
|
1113
|
+
default: undefined,
|
|
717
1114
|
},
|
|
718
|
-
|
|
1115
|
+
hide_sequential_outputs: {
|
|
719
1116
|
type: Boolean,
|
|
720
|
-
required: true,
|
|
721
|
-
default: false,
|
|
722
1117
|
},
|
|
723
|
-
|
|
1118
|
+
end_after_tools: {
|
|
724
1119
|
type: Boolean,
|
|
725
|
-
default: false,
|
|
726
1120
|
},
|
|
727
|
-
|
|
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: {
|
|
728
1130
|
type: Boolean,
|
|
729
|
-
default:
|
|
1131
|
+
default: undefined,
|
|
730
1132
|
},
|
|
731
|
-
|
|
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: {
|
|
732
1151
|
type: String,
|
|
1152
|
+
trim: true,
|
|
1153
|
+
index: true,
|
|
1154
|
+
default: 'general',
|
|
733
1155
|
},
|
|
734
|
-
|
|
735
|
-
type:
|
|
736
|
-
rating: {
|
|
737
|
-
type: String,
|
|
738
|
-
enum: ['thumbsUp', 'thumbsDown'],
|
|
739
|
-
required: true,
|
|
740
|
-
},
|
|
741
|
-
tag: {
|
|
742
|
-
type: mongoose.Schema.Types.Mixed,
|
|
743
|
-
required: false,
|
|
744
|
-
},
|
|
745
|
-
text: {
|
|
746
|
-
type: String,
|
|
747
|
-
required: false,
|
|
748
|
-
},
|
|
749
|
-
},
|
|
1156
|
+
support_contact: {
|
|
1157
|
+
type: mongoose.Schema.Types.Mixed,
|
|
750
1158
|
default: undefined,
|
|
751
|
-
required: false,
|
|
752
1159
|
},
|
|
753
|
-
|
|
1160
|
+
is_promoted: {
|
|
754
1161
|
type: Boolean,
|
|
755
|
-
required: false,
|
|
756
|
-
select: false,
|
|
757
1162
|
default: false,
|
|
1163
|
+
index: true,
|
|
758
1164
|
},
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
type: String,
|
|
773
|
-
required: false,
|
|
774
|
-
},
|
|
775
|
-
},
|
|
776
|
-
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,
|
|
777
1178
|
},
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
meiliIndex: true,
|
|
1179
|
+
label: {
|
|
1180
|
+
type: String,
|
|
1181
|
+
required: true,
|
|
1182
|
+
trim: true,
|
|
783
1183
|
},
|
|
784
|
-
|
|
1184
|
+
description: {
|
|
785
1185
|
type: String,
|
|
1186
|
+
trim: true,
|
|
1187
|
+
default: '',
|
|
786
1188
|
},
|
|
787
|
-
|
|
788
|
-
|
|
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: {
|
|
789
1216
|
type: String,
|
|
1217
|
+
index: true,
|
|
1218
|
+
required: true,
|
|
790
1219
|
},
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
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,
|
|
812
1261
|
},
|
|
813
|
-
|
|
814
|
-
|
|
1262
|
+
refillIntervalUnit: {
|
|
1263
|
+
type: String,
|
|
1264
|
+
enum: ['seconds', 'minutes', 'hours', 'days', 'weeks', 'months'],
|
|
1265
|
+
default: 'days',
|
|
1266
|
+
},
|
|
1267
|
+
lastRefill: {
|
|
815
1268
|
type: Date,
|
|
1269
|
+
default: Date.now,
|
|
816
1270
|
},
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
1271
|
+
// amount to add on each refill
|
|
1272
|
+
refillAmount: {
|
|
1273
|
+
type: Number,
|
|
1274
|
+
default: 0,
|
|
1275
|
+
},
|
|
1276
|
+
});
|
|
821
1277
|
|
|
822
|
-
const
|
|
823
|
-
|
|
1278
|
+
const bannerSchema = new mongoose.Schema({
|
|
1279
|
+
bannerId: {
|
|
824
1280
|
type: String,
|
|
825
1281
|
required: true,
|
|
826
1282
|
},
|
|
827
|
-
|
|
1283
|
+
message: {
|
|
828
1284
|
type: String,
|
|
829
1285
|
required: true,
|
|
830
1286
|
},
|
|
831
|
-
|
|
832
|
-
type:
|
|
1287
|
+
displayFrom: {
|
|
1288
|
+
type: Date,
|
|
833
1289
|
required: true,
|
|
1290
|
+
default: Date.now,
|
|
834
1291
|
},
|
|
835
|
-
|
|
1292
|
+
displayTo: {
|
|
1293
|
+
type: Date,
|
|
1294
|
+
},
|
|
1295
|
+
type: {
|
|
836
1296
|
type: String,
|
|
1297
|
+
enum: ['banner', 'popup'],
|
|
1298
|
+
default: 'banner',
|
|
1299
|
+
},
|
|
1300
|
+
isPublic: {
|
|
1301
|
+
type: Boolean,
|
|
1302
|
+
default: false,
|
|
837
1303
|
},
|
|
838
1304
|
}, { timestamps: true });
|
|
839
1305
|
|
|
840
|
-
const
|
|
841
|
-
|
|
1306
|
+
const categoriesSchema = new mongoose.Schema({
|
|
1307
|
+
label: {
|
|
842
1308
|
type: String,
|
|
1309
|
+
required: true,
|
|
843
1310
|
unique: true,
|
|
1311
|
+
},
|
|
1312
|
+
value: {
|
|
1313
|
+
type: String,
|
|
844
1314
|
required: true,
|
|
845
|
-
|
|
1315
|
+
unique: true,
|
|
846
1316
|
},
|
|
847
|
-
|
|
1317
|
+
});
|
|
1318
|
+
|
|
1319
|
+
const conversationTag = new mongoose.Schema({
|
|
1320
|
+
tag: {
|
|
848
1321
|
type: String,
|
|
849
|
-
|
|
850
|
-
meiliIndex: true,
|
|
1322
|
+
index: true,
|
|
851
1323
|
},
|
|
852
1324
|
user: {
|
|
853
1325
|
type: String,
|
|
854
|
-
|
|
1326
|
+
index: true,
|
|
855
1327
|
},
|
|
856
|
-
|
|
857
|
-
type:
|
|
1328
|
+
description: {
|
|
1329
|
+
type: String,
|
|
1330
|
+
index: true,
|
|
858
1331
|
},
|
|
859
|
-
|
|
1332
|
+
count: {
|
|
860
1333
|
type: Number,
|
|
1334
|
+
default: 0,
|
|
861
1335
|
},
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
1336
|
+
position: {
|
|
1337
|
+
type: Number,
|
|
1338
|
+
default: 0,
|
|
1339
|
+
index: true,
|
|
866
1340
|
},
|
|
867
1341
|
}, { timestamps: true });
|
|
1342
|
+
// Create a compound index on tag and user with unique constraint.
|
|
1343
|
+
conversationTag.index({ tag: 1, user: 1 }, { unique: true });
|
|
868
1344
|
|
|
869
|
-
|
|
870
|
-
|
|
1345
|
+
// @ts-ignore
|
|
1346
|
+
const conversationPreset = {
|
|
1347
|
+
// endpoint: [azureOpenAI, openAI, anthropic, chatGPTBrowser]
|
|
1348
|
+
endpoint: {
|
|
871
1349
|
type: String,
|
|
1350
|
+
default: null,
|
|
872
1351
|
required: true,
|
|
873
|
-
index: true,
|
|
874
1352
|
},
|
|
875
|
-
|
|
876
|
-
type:
|
|
877
|
-
ref: 'PromptGroup',
|
|
878
|
-
default: [],
|
|
879
|
-
},
|
|
880
|
-
agentIds: {
|
|
881
|
-
type: [String],
|
|
882
|
-
ref: 'Agent',
|
|
883
|
-
default: [],
|
|
1353
|
+
endpointType: {
|
|
1354
|
+
type: String,
|
|
884
1355
|
},
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
const promptSchema = new mongoose.Schema({
|
|
890
|
-
groupId: {
|
|
891
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
892
|
-
ref: 'PromptGroup',
|
|
893
|
-
required: true,
|
|
894
|
-
index: true,
|
|
1356
|
+
// for azureOpenAI, openAI, chatGPTBrowser only
|
|
1357
|
+
model: {
|
|
1358
|
+
type: String,
|
|
1359
|
+
required: false,
|
|
895
1360
|
},
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
required:
|
|
1361
|
+
// for bedrock only
|
|
1362
|
+
region: {
|
|
1363
|
+
type: String,
|
|
1364
|
+
required: false,
|
|
900
1365
|
},
|
|
901
|
-
|
|
1366
|
+
// for azureOpenAI, openAI only
|
|
1367
|
+
chatGptLabel: {
|
|
902
1368
|
type: String,
|
|
903
|
-
required:
|
|
1369
|
+
required: false,
|
|
904
1370
|
},
|
|
905
|
-
|
|
1371
|
+
// for google only
|
|
1372
|
+
examples: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1373
|
+
modelLabel: {
|
|
906
1374
|
type: String,
|
|
907
|
-
|
|
908
|
-
required: true,
|
|
1375
|
+
required: false,
|
|
909
1376
|
},
|
|
910
|
-
|
|
911
|
-
timestamps: true,
|
|
912
|
-
});
|
|
913
|
-
promptSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
914
|
-
|
|
915
|
-
const promptGroupSchema = new mongoose.Schema({
|
|
916
|
-
name: {
|
|
1377
|
+
promptPrefix: {
|
|
917
1378
|
type: String,
|
|
918
|
-
required:
|
|
919
|
-
index: true,
|
|
1379
|
+
required: false,
|
|
920
1380
|
},
|
|
921
|
-
|
|
1381
|
+
temperature: {
|
|
922
1382
|
type: Number,
|
|
923
|
-
|
|
1383
|
+
required: false,
|
|
924
1384
|
},
|
|
925
|
-
|
|
926
|
-
type:
|
|
927
|
-
|
|
1385
|
+
top_p: {
|
|
1386
|
+
type: Number,
|
|
1387
|
+
required: false,
|
|
928
1388
|
},
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
1389
|
+
// for google only
|
|
1390
|
+
topP: {
|
|
1391
|
+
type: Number,
|
|
1392
|
+
required: false,
|
|
933
1393
|
},
|
|
934
|
-
|
|
935
|
-
type:
|
|
936
|
-
|
|
937
|
-
index: true,
|
|
938
|
-
default: [],
|
|
1394
|
+
topK: {
|
|
1395
|
+
type: Number,
|
|
1396
|
+
required: false,
|
|
939
1397
|
},
|
|
940
|
-
|
|
941
|
-
type:
|
|
942
|
-
|
|
943
|
-
required: true,
|
|
944
|
-
index: true,
|
|
1398
|
+
maxOutputTokens: {
|
|
1399
|
+
type: Number,
|
|
1400
|
+
required: false,
|
|
945
1401
|
},
|
|
946
|
-
|
|
947
|
-
type:
|
|
948
|
-
|
|
949
|
-
required: true,
|
|
950
|
-
index: true,
|
|
1402
|
+
maxTokens: {
|
|
1403
|
+
type: Number,
|
|
1404
|
+
required: false,
|
|
951
1405
|
},
|
|
952
|
-
|
|
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: {
|
|
953
1430
|
type: String,
|
|
954
|
-
required: true,
|
|
955
1431
|
},
|
|
956
|
-
|
|
1432
|
+
// files
|
|
1433
|
+
resendFiles: {
|
|
1434
|
+
type: Boolean,
|
|
1435
|
+
},
|
|
1436
|
+
imageDetail: {
|
|
957
1437
|
type: String,
|
|
958
|
-
index: true,
|
|
959
|
-
validate: {
|
|
960
|
-
validator: function (v) {
|
|
961
|
-
return v === undefined || v === null || v === '' || /^[a-z0-9-]+$/.test(v);
|
|
962
|
-
},
|
|
963
|
-
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.`; },
|
|
964
|
-
},
|
|
965
|
-
maxlength: [
|
|
966
|
-
librechatDataProvider.Constants.COMMANDS_MAX_LENGTH,
|
|
967
|
-
`Command cannot be longer than ${librechatDataProvider.Constants.COMMANDS_MAX_LENGTH} characters`,
|
|
968
|
-
],
|
|
969
|
-
}, // Casting here bypasses the type error for the command field.
|
|
970
|
-
}, {
|
|
971
|
-
timestamps: true,
|
|
972
|
-
});
|
|
973
|
-
promptGroupSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
974
|
-
|
|
975
|
-
/**
|
|
976
|
-
* Uses a sub-schema for permissions. Notice we disable `_id` for this subdocument.
|
|
977
|
-
*/
|
|
978
|
-
const rolePermissionsSchema = new mongoose.Schema({
|
|
979
|
-
[librechatDataProvider.PermissionTypes.BOOKMARKS]: {
|
|
980
|
-
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
981
1438
|
},
|
|
982
|
-
|
|
983
|
-
|
|
984
|
-
|
|
985
|
-
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1439
|
+
/* agents */
|
|
1440
|
+
agent_id: {
|
|
1441
|
+
type: String,
|
|
986
1442
|
},
|
|
987
|
-
|
|
988
|
-
|
|
989
|
-
|
|
990
|
-
[librechatDataProvider.Permissions.UPDATE]: { type: Boolean },
|
|
991
|
-
[librechatDataProvider.Permissions.READ]: { type: Boolean },
|
|
992
|
-
[librechatDataProvider.Permissions.OPT_OUT]: { type: Boolean },
|
|
1443
|
+
/* assistants */
|
|
1444
|
+
assistant_id: {
|
|
1445
|
+
type: String,
|
|
993
1446
|
},
|
|
994
|
-
|
|
995
|
-
|
|
996
|
-
[librechatDataProvider.Permissions.USE]: { type: Boolean },
|
|
997
|
-
[librechatDataProvider.Permissions.CREATE]: { type: Boolean },
|
|
1447
|
+
instructions: {
|
|
1448
|
+
type: String,
|
|
998
1449
|
},
|
|
999
|
-
[
|
|
1000
|
-
|
|
1450
|
+
stop: { type: [{ type: String }], default: undefined },
|
|
1451
|
+
isArchived: {
|
|
1452
|
+
type: Boolean,
|
|
1453
|
+
default: false,
|
|
1001
1454
|
},
|
|
1002
|
-
|
|
1003
|
-
|
|
1455
|
+
/* UI Components */
|
|
1456
|
+
iconURL: {
|
|
1457
|
+
type: String,
|
|
1004
1458
|
},
|
|
1005
|
-
|
|
1006
|
-
|
|
1459
|
+
greeting: {
|
|
1460
|
+
type: String,
|
|
1007
1461
|
},
|
|
1008
|
-
|
|
1009
|
-
|
|
1462
|
+
spec: {
|
|
1463
|
+
type: String,
|
|
1010
1464
|
},
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
[
|
|
1014
|
-
[librechatDataProvider.Permissions.VIEW_ROLES]: { type: Boolean },
|
|
1465
|
+
tags: {
|
|
1466
|
+
type: [String],
|
|
1467
|
+
default: [],
|
|
1015
1468
|
},
|
|
1016
|
-
[
|
|
1017
|
-
|
|
1469
|
+
tools: { type: [{ type: String }], default: undefined },
|
|
1470
|
+
maxContextTokens: {
|
|
1471
|
+
type: Number,
|
|
1018
1472
|
},
|
|
1019
|
-
|
|
1020
|
-
|
|
1473
|
+
max_tokens: {
|
|
1474
|
+
type: Number,
|
|
1021
1475
|
},
|
|
1022
|
-
|
|
1023
|
-
|
|
1476
|
+
useResponsesApi: {
|
|
1477
|
+
type: Boolean,
|
|
1024
1478
|
},
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
permissions: {
|
|
1029
|
-
type: rolePermissionsSchema,
|
|
1479
|
+
/** OpenAI Responses API / Anthropic API / Google API */
|
|
1480
|
+
web_search: {
|
|
1481
|
+
type: Boolean,
|
|
1030
1482
|
},
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1483
|
+
disableStreaming: {
|
|
1484
|
+
type: Boolean,
|
|
1485
|
+
},
|
|
1486
|
+
fileTokenLimit: {
|
|
1487
|
+
type: Number,
|
|
1488
|
+
},
|
|
1489
|
+
/** Reasoning models only */
|
|
1490
|
+
reasoning_effort: {
|
|
1035
1491
|
type: String,
|
|
1036
|
-
required: true,
|
|
1037
1492
|
},
|
|
1038
|
-
|
|
1039
|
-
type:
|
|
1040
|
-
required: true,
|
|
1041
|
-
expires: 0,
|
|
1493
|
+
reasoning_summary: {
|
|
1494
|
+
type: String,
|
|
1042
1495
|
},
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
required: true,
|
|
1496
|
+
/** Verbosity control */
|
|
1497
|
+
verbosity: {
|
|
1498
|
+
type: String,
|
|
1047
1499
|
},
|
|
1048
|
-
}
|
|
1500
|
+
};
|
|
1049
1501
|
|
|
1050
|
-
const
|
|
1502
|
+
const convoSchema = new mongoose.Schema({
|
|
1051
1503
|
conversationId: {
|
|
1052
1504
|
type: String,
|
|
1505
|
+
unique: true,
|
|
1053
1506
|
required: true,
|
|
1507
|
+
index: true,
|
|
1508
|
+
meiliIndex: true,
|
|
1054
1509
|
},
|
|
1055
1510
|
title: {
|
|
1056
1511
|
type: String,
|
|
1057
|
-
|
|
1512
|
+
default: 'New Chat',
|
|
1513
|
+
meiliIndex: true,
|
|
1058
1514
|
},
|
|
1059
1515
|
user: {
|
|
1060
1516
|
type: String,
|
|
1061
1517
|
index: true,
|
|
1518
|
+
meiliIndex: true,
|
|
1062
1519
|
},
|
|
1063
1520
|
messages: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Message' }],
|
|
1064
|
-
|
|
1521
|
+
agentOptions: {
|
|
1522
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1523
|
+
},
|
|
1524
|
+
...conversationPreset,
|
|
1525
|
+
agent_id: {
|
|
1065
1526
|
type: String,
|
|
1066
|
-
index: true,
|
|
1067
1527
|
},
|
|
1068
|
-
|
|
1069
|
-
type:
|
|
1070
|
-
default:
|
|
1528
|
+
tags: {
|
|
1529
|
+
type: [String],
|
|
1530
|
+
default: [],
|
|
1531
|
+
meiliIndex: true,
|
|
1532
|
+
},
|
|
1533
|
+
files: {
|
|
1534
|
+
type: [String],
|
|
1535
|
+
},
|
|
1536
|
+
expiredAt: {
|
|
1537
|
+
type: Date,
|
|
1071
1538
|
},
|
|
1072
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 });
|
|
1073
1543
|
|
|
1074
|
-
const
|
|
1075
|
-
|
|
1544
|
+
const file = new mongoose.Schema({
|
|
1545
|
+
user: {
|
|
1076
1546
|
type: mongoose.Schema.Types.ObjectId,
|
|
1547
|
+
ref: 'User',
|
|
1548
|
+
index: true,
|
|
1077
1549
|
required: true,
|
|
1078
|
-
ref: 'user',
|
|
1079
|
-
},
|
|
1080
|
-
email: {
|
|
1081
|
-
type: String,
|
|
1082
1550
|
},
|
|
1083
|
-
|
|
1084
|
-
type: String,
|
|
1085
|
-
},
|
|
1086
|
-
identifier: {
|
|
1551
|
+
conversationId: {
|
|
1087
1552
|
type: String,
|
|
1553
|
+
ref: 'Conversation',
|
|
1554
|
+
index: true,
|
|
1088
1555
|
},
|
|
1089
|
-
|
|
1556
|
+
file_id: {
|
|
1090
1557
|
type: String,
|
|
1558
|
+
index: true,
|
|
1091
1559
|
required: true,
|
|
1092
1560
|
},
|
|
1093
|
-
|
|
1094
|
-
type:
|
|
1095
|
-
required: true,
|
|
1096
|
-
default: Date.now,
|
|
1561
|
+
temp_file_id: {
|
|
1562
|
+
type: String,
|
|
1097
1563
|
},
|
|
1098
|
-
|
|
1099
|
-
type:
|
|
1564
|
+
bytes: {
|
|
1565
|
+
type: Number,
|
|
1100
1566
|
required: true,
|
|
1101
1567
|
},
|
|
1102
|
-
|
|
1103
|
-
type: Map,
|
|
1104
|
-
of: mongoose.Schema.Types.Mixed,
|
|
1105
|
-
},
|
|
1106
|
-
});
|
|
1107
|
-
tokenSchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1108
|
-
|
|
1109
|
-
const toolCallSchema = new mongoose.Schema({
|
|
1110
|
-
conversationId: {
|
|
1568
|
+
filename: {
|
|
1111
1569
|
type: String,
|
|
1112
1570
|
required: true,
|
|
1113
1571
|
},
|
|
1114
|
-
|
|
1572
|
+
filepath: {
|
|
1115
1573
|
type: String,
|
|
1116
1574
|
required: true,
|
|
1117
1575
|
},
|
|
1118
|
-
|
|
1576
|
+
object: {
|
|
1119
1577
|
type: String,
|
|
1120
1578
|
required: true,
|
|
1579
|
+
default: 'file',
|
|
1121
1580
|
},
|
|
1122
|
-
|
|
1123
|
-
type:
|
|
1124
|
-
ref: 'User',
|
|
1125
|
-
required: true,
|
|
1581
|
+
embedded: {
|
|
1582
|
+
type: Boolean,
|
|
1126
1583
|
},
|
|
1127
|
-
|
|
1128
|
-
type:
|
|
1584
|
+
type: {
|
|
1585
|
+
type: String,
|
|
1586
|
+
required: true,
|
|
1129
1587
|
},
|
|
1130
|
-
|
|
1131
|
-
type:
|
|
1588
|
+
text: {
|
|
1589
|
+
type: String,
|
|
1132
1590
|
},
|
|
1133
|
-
|
|
1134
|
-
type:
|
|
1591
|
+
context: {
|
|
1592
|
+
type: String,
|
|
1135
1593
|
},
|
|
1136
|
-
|
|
1594
|
+
usage: {
|
|
1137
1595
|
type: Number,
|
|
1138
|
-
},
|
|
1139
|
-
}, { timestamps: true });
|
|
1140
|
-
toolCallSchema.index({ messageId: 1, user: 1 });
|
|
1141
|
-
toolCallSchema.index({ conversationId: 1, user: 1 });
|
|
1142
|
-
|
|
1143
|
-
const transactionSchema = new mongoose.Schema({
|
|
1144
|
-
user: {
|
|
1145
|
-
type: mongoose.Schema.Types.ObjectId,
|
|
1146
|
-
ref: 'User',
|
|
1147
|
-
index: true,
|
|
1148
1596
|
required: true,
|
|
1597
|
+
default: 0,
|
|
1149
1598
|
},
|
|
1150
|
-
|
|
1151
|
-
type: String,
|
|
1152
|
-
ref: 'Conversation',
|
|
1153
|
-
index: true,
|
|
1154
|
-
},
|
|
1155
|
-
tokenType: {
|
|
1599
|
+
source: {
|
|
1156
1600
|
type: String,
|
|
1157
|
-
|
|
1158
|
-
required: true,
|
|
1601
|
+
default: librechatDataProvider.FileSources.local,
|
|
1159
1602
|
},
|
|
1160
1603
|
model: {
|
|
1161
1604
|
type: String,
|
|
1162
1605
|
},
|
|
1163
|
-
|
|
1164
|
-
|
|
1606
|
+
width: Number,
|
|
1607
|
+
height: Number,
|
|
1608
|
+
metadata: {
|
|
1609
|
+
fileIdentifier: String,
|
|
1165
1610
|
},
|
|
1166
|
-
|
|
1167
|
-
type:
|
|
1611
|
+
expiresAt: {
|
|
1612
|
+
type: Date,
|
|
1613
|
+
expires: 3600, // 1 hour in seconds
|
|
1168
1614
|
},
|
|
1169
|
-
rate: Number,
|
|
1170
|
-
rawAmount: Number,
|
|
1171
|
-
tokenValue: Number,
|
|
1172
|
-
inputTokens: { type: Number },
|
|
1173
|
-
writeTokens: { type: Number },
|
|
1174
|
-
readTokens: { type: Number },
|
|
1175
1615
|
}, {
|
|
1176
1616
|
timestamps: true,
|
|
1177
1617
|
});
|
|
1618
|
+
file.index({ createdAt: 1, updatedAt: 1 });
|
|
1178
1619
|
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1620
|
+
const keySchema = new mongoose.Schema({
|
|
1621
|
+
userId: {
|
|
1622
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1623
|
+
ref: 'User',
|
|
1624
|
+
required: true,
|
|
1184
1625
|
},
|
|
1185
|
-
}, { _id: false });
|
|
1186
|
-
// Backup code sub-schema
|
|
1187
|
-
const BackupCodeSchema = new mongoose.Schema({
|
|
1188
|
-
codeHash: { type: String, required: true },
|
|
1189
|
-
used: { type: Boolean, default: false },
|
|
1190
|
-
usedAt: { type: Date, default: null },
|
|
1191
|
-
}, { _id: false });
|
|
1192
|
-
const userSchema = new mongoose.Schema({
|
|
1193
1626
|
name: {
|
|
1194
1627
|
type: String,
|
|
1628
|
+
required: true,
|
|
1195
1629
|
},
|
|
1196
|
-
|
|
1630
|
+
value: {
|
|
1197
1631
|
type: String,
|
|
1198
|
-
|
|
1199
|
-
default: '',
|
|
1632
|
+
required: true,
|
|
1200
1633
|
},
|
|
1201
|
-
|
|
1634
|
+
expiresAt: {
|
|
1635
|
+
type: Date,
|
|
1636
|
+
},
|
|
1637
|
+
});
|
|
1638
|
+
keySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1639
|
+
|
|
1640
|
+
const messageSchema = new mongoose.Schema({
|
|
1641
|
+
messageId: {
|
|
1202
1642
|
type: String,
|
|
1203
|
-
required: [true, "can't be blank"],
|
|
1204
|
-
lowercase: true,
|
|
1205
1643
|
unique: true,
|
|
1206
|
-
|
|
1644
|
+
required: true,
|
|
1207
1645
|
index: true,
|
|
1646
|
+
meiliIndex: true,
|
|
1208
1647
|
},
|
|
1209
|
-
|
|
1210
|
-
type:
|
|
1648
|
+
conversationId: {
|
|
1649
|
+
type: String,
|
|
1650
|
+
index: true,
|
|
1211
1651
|
required: true,
|
|
1212
|
-
|
|
1652
|
+
meiliIndex: true,
|
|
1213
1653
|
},
|
|
1214
|
-
|
|
1654
|
+
user: {
|
|
1215
1655
|
type: String,
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1656
|
+
index: true,
|
|
1657
|
+
required: true,
|
|
1658
|
+
default: null,
|
|
1659
|
+
meiliIndex: true,
|
|
1220
1660
|
},
|
|
1221
|
-
|
|
1661
|
+
model: {
|
|
1222
1662
|
type: String,
|
|
1223
|
-
|
|
1663
|
+
default: null,
|
|
1224
1664
|
},
|
|
1225
|
-
|
|
1665
|
+
endpoint: {
|
|
1226
1666
|
type: String,
|
|
1227
|
-
required: true,
|
|
1228
|
-
default: 'local',
|
|
1229
1667
|
},
|
|
1230
|
-
|
|
1668
|
+
conversationSignature: {
|
|
1231
1669
|
type: String,
|
|
1232
|
-
default: librechatDataProvider.SystemRoles.USER,
|
|
1233
1670
|
},
|
|
1234
|
-
|
|
1671
|
+
clientId: {
|
|
1235
1672
|
type: String,
|
|
1236
|
-
unique: true,
|
|
1237
|
-
sparse: true,
|
|
1238
1673
|
},
|
|
1239
|
-
|
|
1240
|
-
type:
|
|
1241
|
-
unique: true,
|
|
1242
|
-
sparse: true,
|
|
1674
|
+
invocationId: {
|
|
1675
|
+
type: Number,
|
|
1243
1676
|
},
|
|
1244
|
-
|
|
1677
|
+
parentMessageId: {
|
|
1245
1678
|
type: String,
|
|
1246
|
-
unique: true,
|
|
1247
|
-
sparse: true,
|
|
1248
1679
|
},
|
|
1249
|
-
|
|
1250
|
-
type:
|
|
1251
|
-
unique: true,
|
|
1252
|
-
sparse: true,
|
|
1680
|
+
tokenCount: {
|
|
1681
|
+
type: Number,
|
|
1253
1682
|
},
|
|
1254
|
-
|
|
1255
|
-
type:
|
|
1256
|
-
unique: true,
|
|
1257
|
-
sparse: true,
|
|
1683
|
+
summaryTokenCount: {
|
|
1684
|
+
type: Number,
|
|
1258
1685
|
},
|
|
1259
|
-
|
|
1686
|
+
sender: {
|
|
1260
1687
|
type: String,
|
|
1261
|
-
|
|
1262
|
-
sparse: true,
|
|
1688
|
+
meiliIndex: true,
|
|
1263
1689
|
},
|
|
1264
|
-
|
|
1690
|
+
text: {
|
|
1265
1691
|
type: String,
|
|
1266
|
-
|
|
1267
|
-
sparse: true,
|
|
1692
|
+
meiliIndex: true,
|
|
1268
1693
|
},
|
|
1269
|
-
|
|
1694
|
+
summary: {
|
|
1270
1695
|
type: String,
|
|
1271
|
-
unique: true,
|
|
1272
|
-
sparse: true,
|
|
1273
|
-
},
|
|
1274
|
-
plugins: {
|
|
1275
|
-
type: Array,
|
|
1276
1696
|
},
|
|
1277
|
-
|
|
1697
|
+
isCreatedByUser: {
|
|
1278
1698
|
type: Boolean,
|
|
1699
|
+
required: true,
|
|
1279
1700
|
default: false,
|
|
1280
1701
|
},
|
|
1281
|
-
|
|
1282
|
-
type:
|
|
1283
|
-
|
|
1702
|
+
unfinished: {
|
|
1703
|
+
type: Boolean,
|
|
1704
|
+
default: false,
|
|
1284
1705
|
},
|
|
1285
|
-
|
|
1286
|
-
type:
|
|
1287
|
-
|
|
1706
|
+
error: {
|
|
1707
|
+
type: Boolean,
|
|
1708
|
+
default: false,
|
|
1288
1709
|
},
|
|
1289
|
-
|
|
1290
|
-
type:
|
|
1710
|
+
finish_reason: {
|
|
1711
|
+
type: String,
|
|
1291
1712
|
},
|
|
1292
|
-
|
|
1293
|
-
type:
|
|
1294
|
-
|
|
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,
|
|
1295
1731
|
},
|
|
1296
|
-
|
|
1732
|
+
_meiliIndex: {
|
|
1297
1733
|
type: Boolean,
|
|
1734
|
+
required: false,
|
|
1735
|
+
select: false,
|
|
1298
1736
|
default: false,
|
|
1299
1737
|
},
|
|
1300
|
-
|
|
1738
|
+
files: { type: [{ type: mongoose.Schema.Types.Mixed }], default: undefined },
|
|
1739
|
+
plugin: {
|
|
1301
1740
|
type: {
|
|
1302
|
-
|
|
1303
|
-
type:
|
|
1304
|
-
|
|
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,
|
|
1305
1753
|
},
|
|
1306
1754
|
},
|
|
1307
|
-
default:
|
|
1755
|
+
default: undefined,
|
|
1308
1756
|
},
|
|
1309
|
-
|
|
1310
|
-
|
|
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: {
|
|
1311
1764
|
type: String,
|
|
1312
|
-
|
|
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,
|
|
1313
1796
|
},
|
|
1314
1797
|
}, { timestamps: true });
|
|
1798
|
+
messageSchema.index({ expiredAt: 1 }, { expireAfterSeconds: 0 });
|
|
1799
|
+
messageSchema.index({ createdAt: 1 });
|
|
1800
|
+
messageSchema.index({ messageId: 1, user: 1 }, { unique: true });
|
|
1315
1801
|
|
|
1316
|
-
const
|
|
1317
|
-
|
|
1318
|
-
type:
|
|
1319
|
-
ref: 'User',
|
|
1320
|
-
index: true,
|
|
1802
|
+
const pluginAuthSchema = new mongoose.Schema({
|
|
1803
|
+
authField: {
|
|
1804
|
+
type: String,
|
|
1321
1805
|
required: true,
|
|
1322
1806
|
},
|
|
1323
|
-
|
|
1807
|
+
value: {
|
|
1324
1808
|
type: String,
|
|
1325
1809
|
required: true,
|
|
1326
|
-
validate: {
|
|
1327
|
-
validator: (v) => /^[a-z_]+$/.test(v),
|
|
1328
|
-
message: 'Key must only contain lowercase letters and underscores',
|
|
1329
|
-
},
|
|
1330
1810
|
},
|
|
1331
|
-
|
|
1811
|
+
userId: {
|
|
1332
1812
|
type: String,
|
|
1333
1813
|
required: true,
|
|
1334
1814
|
},
|
|
1335
|
-
|
|
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: {
|
|
1336
1840
|
type: Number,
|
|
1337
|
-
default: 0,
|
|
1338
1841
|
},
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1842
|
+
...conversationPreset,
|
|
1843
|
+
agentOptions: {
|
|
1844
|
+
type: mongoose.Schema.Types.Mixed,
|
|
1845
|
+
default: null,
|
|
1342
1846
|
},
|
|
1343
|
-
});
|
|
1847
|
+
}, { timestamps: true });
|
|
1344
1848
|
|
|
1345
|
-
const
|
|
1849
|
+
const projectSchema = new mongoose.Schema({
|
|
1346
1850
|
name: {
|
|
1347
1851
|
type: String,
|
|
1348
1852
|
required: true,
|
|
1349
1853
|
index: true,
|
|
1350
1854
|
},
|
|
1351
|
-
|
|
1352
|
-
type:
|
|
1353
|
-
|
|
1855
|
+
promptGroupIds: {
|
|
1856
|
+
type: [mongoose.Schema.Types.ObjectId],
|
|
1857
|
+
ref: 'PromptGroup',
|
|
1858
|
+
default: [],
|
|
1354
1859
|
},
|
|
1355
|
-
|
|
1356
|
-
type: String,
|
|
1357
|
-
|
|
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,
|
|
1358
1874
|
index: true,
|
|
1359
1875
|
},
|
|
1360
|
-
|
|
1361
|
-
type:
|
|
1362
|
-
|
|
1876
|
+
author: {
|
|
1877
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1878
|
+
ref: 'User',
|
|
1879
|
+
required: true,
|
|
1363
1880
|
},
|
|
1364
|
-
|
|
1365
|
-
{
|
|
1366
|
-
type: String,
|
|
1367
|
-
required: false,
|
|
1368
|
-
},
|
|
1369
|
-
],
|
|
1370
|
-
source: {
|
|
1881
|
+
prompt: {
|
|
1371
1882
|
type: String,
|
|
1372
|
-
|
|
1373
|
-
default: 'local',
|
|
1883
|
+
required: true,
|
|
1374
1884
|
},
|
|
1375
|
-
|
|
1376
|
-
idOnTheSource: {
|
|
1885
|
+
type: {
|
|
1377
1886
|
type: String,
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
required: function () {
|
|
1381
|
-
return this.source !== 'local';
|
|
1382
|
-
},
|
|
1887
|
+
enum: ['text', 'chat'],
|
|
1888
|
+
required: true,
|
|
1383
1889
|
},
|
|
1384
|
-
}, {
|
|
1385
|
-
|
|
1386
|
-
unique: true,
|
|
1387
|
-
partialFilterExpression: { idOnTheSource: { $exists: true } },
|
|
1890
|
+
}, {
|
|
1891
|
+
timestamps: true,
|
|
1388
1892
|
});
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
/**
|
|
1392
|
-
* ESM-native object traversal utility
|
|
1393
|
-
* Simplified implementation focused on the forEach use case
|
|
1394
|
-
*/
|
|
1395
|
-
function isObject(value) {
|
|
1396
|
-
if (value === null || typeof value !== 'object') {
|
|
1397
|
-
return false;
|
|
1398
|
-
}
|
|
1399
|
-
// Treat these built-in types as leaf nodes, not objects to traverse
|
|
1400
|
-
if (value instanceof Date)
|
|
1401
|
-
return false;
|
|
1402
|
-
if (value instanceof RegExp)
|
|
1403
|
-
return false;
|
|
1404
|
-
if (value instanceof Error)
|
|
1405
|
-
return false;
|
|
1406
|
-
if (value instanceof URL)
|
|
1407
|
-
return false;
|
|
1408
|
-
// Check for Buffer (Node.js)
|
|
1409
|
-
if (typeof Buffer !== 'undefined' && Buffer.isBuffer(value))
|
|
1410
|
-
return false;
|
|
1411
|
-
// Check for TypedArrays and ArrayBuffer
|
|
1412
|
-
if (ArrayBuffer.isView(value))
|
|
1413
|
-
return false;
|
|
1414
|
-
if (value instanceof ArrayBuffer)
|
|
1415
|
-
return false;
|
|
1416
|
-
if (value instanceof SharedArrayBuffer)
|
|
1417
|
-
return false;
|
|
1418
|
-
// Check for other built-in types that shouldn't be traversed
|
|
1419
|
-
if (value instanceof Promise)
|
|
1420
|
-
return false;
|
|
1421
|
-
if (value instanceof WeakMap)
|
|
1422
|
-
return false;
|
|
1423
|
-
if (value instanceof WeakSet)
|
|
1424
|
-
return false;
|
|
1425
|
-
if (value instanceof Map)
|
|
1426
|
-
return false;
|
|
1427
|
-
if (value instanceof Set)
|
|
1428
|
-
return false;
|
|
1429
|
-
// Check if it's a primitive wrapper object
|
|
1430
|
-
const stringTag = Object.prototype.toString.call(value);
|
|
1431
|
-
if (stringTag === '[object Boolean]' ||
|
|
1432
|
-
stringTag === '[object Number]' ||
|
|
1433
|
-
stringTag === '[object String]') {
|
|
1434
|
-
return false;
|
|
1435
|
-
}
|
|
1436
|
-
return true;
|
|
1437
|
-
}
|
|
1438
|
-
// Helper to safely set a property on an object or array
|
|
1439
|
-
function setProperty(obj, key, value) {
|
|
1440
|
-
if (Array.isArray(obj) && typeof key === 'number') {
|
|
1441
|
-
obj[key] = value;
|
|
1442
|
-
}
|
|
1443
|
-
else if (!Array.isArray(obj) && typeof key === 'string') {
|
|
1444
|
-
obj[key] = value;
|
|
1445
|
-
}
|
|
1446
|
-
else if (!Array.isArray(obj) && typeof key === 'number') {
|
|
1447
|
-
// Handle numeric keys on objects
|
|
1448
|
-
obj[key] = value;
|
|
1449
|
-
}
|
|
1450
|
-
}
|
|
1451
|
-
// Helper to safely delete a property from an object
|
|
1452
|
-
function deleteProperty(obj, key) {
|
|
1453
|
-
if (Array.isArray(obj) && typeof key === 'number') {
|
|
1454
|
-
// For arrays, we should use splice, but this is handled in remove()
|
|
1455
|
-
// This function is only called for non-array deletion
|
|
1456
|
-
return;
|
|
1457
|
-
}
|
|
1458
|
-
if (!Array.isArray(obj)) {
|
|
1459
|
-
delete obj[key];
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
|
-
function forEach(obj, callback) {
|
|
1463
|
-
const visited = new WeakSet();
|
|
1464
|
-
function walk(node, path = [], parent) {
|
|
1465
|
-
// Check for circular references
|
|
1466
|
-
let circular = null;
|
|
1467
|
-
if (isObject(node)) {
|
|
1468
|
-
if (visited.has(node)) {
|
|
1469
|
-
// Find the circular reference in the parent chain
|
|
1470
|
-
let p = parent;
|
|
1471
|
-
while (p) {
|
|
1472
|
-
if (p.node === node) {
|
|
1473
|
-
circular = p;
|
|
1474
|
-
break;
|
|
1475
|
-
}
|
|
1476
|
-
p = p.parent;
|
|
1477
|
-
}
|
|
1478
|
-
return; // Skip circular references
|
|
1479
|
-
}
|
|
1480
|
-
visited.add(node);
|
|
1481
|
-
}
|
|
1482
|
-
const key = path.length > 0 ? path[path.length - 1] : undefined;
|
|
1483
|
-
const isRoot = path.length === 0;
|
|
1484
|
-
const level = path.length;
|
|
1485
|
-
// Determine if this is a leaf node
|
|
1486
|
-
const isLeaf = !isObject(node) ||
|
|
1487
|
-
(Array.isArray(node) && node.length === 0) ||
|
|
1488
|
-
Object.keys(node).length === 0;
|
|
1489
|
-
// Create context
|
|
1490
|
-
const context = {
|
|
1491
|
-
node,
|
|
1492
|
-
path: [...path],
|
|
1493
|
-
parent,
|
|
1494
|
-
key,
|
|
1495
|
-
isLeaf,
|
|
1496
|
-
notLeaf: !isLeaf,
|
|
1497
|
-
isRoot,
|
|
1498
|
-
notRoot: !isRoot,
|
|
1499
|
-
level,
|
|
1500
|
-
circular,
|
|
1501
|
-
update(value) {
|
|
1502
|
-
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
1503
|
-
setProperty(parent.node, key, value);
|
|
1504
|
-
}
|
|
1505
|
-
this.node = value;
|
|
1506
|
-
},
|
|
1507
|
-
remove() {
|
|
1508
|
-
if (!isRoot && parent && key !== undefined && isObject(parent.node)) {
|
|
1509
|
-
if (Array.isArray(parent.node) && typeof key === 'number') {
|
|
1510
|
-
parent.node.splice(key, 1);
|
|
1511
|
-
}
|
|
1512
|
-
else {
|
|
1513
|
-
deleteProperty(parent.node, key);
|
|
1514
|
-
}
|
|
1515
|
-
}
|
|
1516
|
-
},
|
|
1517
|
-
};
|
|
1518
|
-
// Call the callback with the context
|
|
1519
|
-
callback.call(context, node);
|
|
1520
|
-
// Traverse children if not circular and is an object
|
|
1521
|
-
if (!circular && isObject(node) && !isLeaf) {
|
|
1522
|
-
if (Array.isArray(node)) {
|
|
1523
|
-
for (let i = 0; i < node.length; i++) {
|
|
1524
|
-
walk(node[i], [...path, i], context);
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
else {
|
|
1528
|
-
for (const [childKey, childValue] of Object.entries(node)) {
|
|
1529
|
-
walk(childValue, [...path, childKey], context);
|
|
1530
|
-
}
|
|
1531
|
-
}
|
|
1532
|
-
}
|
|
1533
|
-
}
|
|
1534
|
-
walk(obj);
|
|
1535
|
-
}
|
|
1536
|
-
// Main traverse function that returns an object with forEach method
|
|
1537
|
-
function traverse(obj) {
|
|
1538
|
-
return {
|
|
1539
|
-
forEach(callback) {
|
|
1540
|
-
forEach(obj, callback);
|
|
1541
|
-
},
|
|
1542
|
-
};
|
|
1543
|
-
}
|
|
1893
|
+
promptSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
1544
1894
|
|
|
1545
|
-
const
|
|
1546
|
-
|
|
1547
|
-
|
|
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
|
-
|
|
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,
|
|
1602
1952
|
});
|
|
1953
|
+
promptGroupSchema.index({ createdAt: 1, updatedAt: 1 });
|
|
1954
|
+
|
|
1603
1955
|
/**
|
|
1604
|
-
*
|
|
1605
|
-
*
|
|
1606
|
-
* @param value - The value to be inspected and potentially truncated.
|
|
1607
|
-
* @param length - The length at which to truncate the value. Default: 100.
|
|
1608
|
-
* @returns The truncated or original value.
|
|
1609
|
-
*/
|
|
1610
|
-
const truncateLongStrings = (value, length = 100) => {
|
|
1611
|
-
if (typeof value === 'string') {
|
|
1612
|
-
return value.length > length ? value.substring(0, length) + '... [truncated]' : value;
|
|
1613
|
-
}
|
|
1614
|
-
return value;
|
|
1615
|
-
};
|
|
1616
|
-
/**
|
|
1617
|
-
* An array mapping function that truncates long strings (objects converted to JSON strings).
|
|
1618
|
-
* @param item - The item to be condensed.
|
|
1619
|
-
* @returns The condensed item.
|
|
1620
|
-
*/
|
|
1621
|
-
const condenseArray = (item) => {
|
|
1622
|
-
if (typeof item === 'string') {
|
|
1623
|
-
return truncateLongStrings(JSON.stringify(item));
|
|
1624
|
-
}
|
|
1625
|
-
else if (typeof item === 'object') {
|
|
1626
|
-
return truncateLongStrings(JSON.stringify(item));
|
|
1627
|
-
}
|
|
1628
|
-
return item;
|
|
1629
|
-
};
|
|
1630
|
-
/**
|
|
1631
|
-
* Formats log messages for debugging purposes.
|
|
1632
|
-
* - Truncates long strings within log messages.
|
|
1633
|
-
* - Condenses arrays by truncating long strings and objects as strings within array items.
|
|
1634
|
-
* - Redacts sensitive information from log messages if the log level is 'error'.
|
|
1635
|
-
* - Converts log information object to a formatted string.
|
|
1636
|
-
*
|
|
1637
|
-
* @param options - The options for formatting log messages.
|
|
1638
|
-
* @returns The formatted log message.
|
|
1956
|
+
* Uses a sub-schema for permissions. Notice we disable `_id` for this subdocument.
|
|
1639
1957
|
*/
|
|
1640
|
-
const
|
|
1641
|
-
|
|
1642
|
-
|
|
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
|
-
}
|
|
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
|
+
},
|
|
1721
2092
|
});
|
|
1722
|
-
|
|
1723
|
-
|
|
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
|
-
|
|
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,
|
|
1755
2163
|
});
|
|
1756
2164
|
|
|
1757
|
-
|
|
1758
|
-
|
|
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
|
-
}
|
|
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 });
|
|
1787
2301
|
|
|
1788
|
-
const
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
1793
|
-
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
|
|
1807
|
-
|
|
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
|
+
},
|
|
1808
2329
|
});
|
|
1809
|
-
|
|
1810
|
-
|
|
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
|
-
else if (useConsoleJson) {
|
|
1854
|
-
transports$1.push(new winston.transports.Console({
|
|
1855
|
-
level: consoleLogLevel,
|
|
1856
|
-
format: winston.format.combine(fileFormat$1, jsonTruncateFormat(), winston.format.json()),
|
|
1857
|
-
}));
|
|
1858
|
-
}
|
|
1859
|
-
else {
|
|
1860
|
-
transports$1.push(new winston.transports.Console({
|
|
1861
|
-
level: consoleLogLevel,
|
|
1862
|
-
format: consoleFormat$1,
|
|
1863
|
-
}));
|
|
1864
|
-
}
|
|
1865
|
-
// Create logger
|
|
1866
|
-
const logger$1 = winston.createLogger({
|
|
1867
|
-
level: level$1(),
|
|
1868
|
-
levels: levels$1,
|
|
1869
|
-
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 } },
|
|
1870
2374
|
});
|
|
2375
|
+
groupSchema.index({ memberIds: 1 });
|
|
1871
2376
|
|
|
1872
2377
|
/**
|
|
1873
2378
|
* Checks if the connected MongoDB deployment supports transactions
|
|
@@ -2421,6 +2926,16 @@ function mongoMeili(schema, options) {
|
|
|
2421
2926
|
logger.error(`[mongoMeili] Error checking index ${indexName}:`, error);
|
|
2422
2927
|
}
|
|
2423
2928
|
}
|
|
2929
|
+
// Configure index settings to make 'user' field filterable
|
|
2930
|
+
try {
|
|
2931
|
+
await index.updateSettings({
|
|
2932
|
+
filterableAttributes: ['user'],
|
|
2933
|
+
});
|
|
2934
|
+
logger.debug(`[mongoMeili] Updated index ${indexName} settings to make 'user' filterable`);
|
|
2935
|
+
}
|
|
2936
|
+
catch (settingsError) {
|
|
2937
|
+
logger.error(`[mongoMeili] Error updating index settings for ${indexName}:`, settingsError);
|
|
2938
|
+
}
|
|
2424
2939
|
})();
|
|
2425
2940
|
// Collect attributes from the schema that should be indexed
|
|
2426
2941
|
const attributesToIndex = [
|
|
@@ -2429,6 +2944,12 @@ function mongoMeili(schema, options) {
|
|
|
2429
2944
|
return schemaValue.meiliIndex ? [...results, key] : results;
|
|
2430
2945
|
}, []),
|
|
2431
2946
|
];
|
|
2947
|
+
// CRITICAL: Always include 'user' field for proper filtering
|
|
2948
|
+
// This ensures existing deployments can filter by user after migration
|
|
2949
|
+
if (schema.obj.user && !attributesToIndex.includes('user')) {
|
|
2950
|
+
attributesToIndex.push('user');
|
|
2951
|
+
logger.debug(`[mongoMeili] Added 'user' field to ${indexName} index attributes`);
|
|
2952
|
+
}
|
|
2432
2953
|
schema.loadClass(createMeiliMongooseModel({ index, attributesToIndex, syncOptions }));
|
|
2433
2954
|
// Register Mongoose hooks
|
|
2434
2955
|
schema.post('save', function (doc, next) {
|
|
@@ -3086,7 +3607,7 @@ function createTokenMethods(mongoose) {
|
|
|
3086
3607
|
/**
|
|
3087
3608
|
* Finds a Token document that matches the provided query.
|
|
3088
3609
|
*/
|
|
3089
|
-
async function findToken(query) {
|
|
3610
|
+
async function findToken(query, options) {
|
|
3090
3611
|
try {
|
|
3091
3612
|
const Token = mongoose.models.Token;
|
|
3092
3613
|
const conditions = [];
|
|
@@ -3102,9 +3623,7 @@ function createTokenMethods(mongoose) {
|
|
|
3102
3623
|
if (query.identifier) {
|
|
3103
3624
|
conditions.push({ identifier: query.identifier });
|
|
3104
3625
|
}
|
|
3105
|
-
const token = await Token.findOne({
|
|
3106
|
-
$and: conditions,
|
|
3107
|
-
}).lean();
|
|
3626
|
+
const token = await Token.findOne({ $and: conditions }, null, options).lean();
|
|
3108
3627
|
return token;
|
|
3109
3628
|
}
|
|
3110
3629
|
catch (error) {
|
|
@@ -4750,6 +5269,68 @@ function anonymizeMessages(messages, newConvoId) {
|
|
|
4750
5269
|
};
|
|
4751
5270
|
});
|
|
4752
5271
|
}
|
|
5272
|
+
/**
|
|
5273
|
+
* Filter messages up to and including the target message (branch-specific)
|
|
5274
|
+
* Similar to getMessagesUpToTargetLevel from fork utilities
|
|
5275
|
+
*/
|
|
5276
|
+
function getMessagesUpToTarget(messages, targetMessageId) {
|
|
5277
|
+
var _a, _b;
|
|
5278
|
+
if (!messages || messages.length === 0) {
|
|
5279
|
+
return [];
|
|
5280
|
+
}
|
|
5281
|
+
// If only one message and it's the target, return it
|
|
5282
|
+
if (messages.length === 1 && ((_a = messages[0]) === null || _a === void 0 ? void 0 : _a.messageId) === targetMessageId) {
|
|
5283
|
+
return messages;
|
|
5284
|
+
}
|
|
5285
|
+
// Create a map of parentMessageId to children messages
|
|
5286
|
+
const parentToChildrenMap = new Map();
|
|
5287
|
+
for (const message of messages) {
|
|
5288
|
+
const parentId = message.parentMessageId || librechatDataProvider.Constants.NO_PARENT;
|
|
5289
|
+
if (!parentToChildrenMap.has(parentId)) {
|
|
5290
|
+
parentToChildrenMap.set(parentId, []);
|
|
5291
|
+
}
|
|
5292
|
+
(_b = parentToChildrenMap.get(parentId)) === null || _b === void 0 ? void 0 : _b.push(message);
|
|
5293
|
+
}
|
|
5294
|
+
// Find the target message
|
|
5295
|
+
const targetMessage = messages.find((msg) => msg.messageId === targetMessageId);
|
|
5296
|
+
if (!targetMessage) {
|
|
5297
|
+
// If target not found, return all messages for backwards compatibility
|
|
5298
|
+
return messages;
|
|
5299
|
+
}
|
|
5300
|
+
const visited = new Set();
|
|
5301
|
+
const rootMessages = parentToChildrenMap.get(librechatDataProvider.Constants.NO_PARENT) || [];
|
|
5302
|
+
let currentLevel = rootMessages.length > 0 ? [...rootMessages] : [targetMessage];
|
|
5303
|
+
const results = new Set(currentLevel);
|
|
5304
|
+
// Check if the target message is at the root level
|
|
5305
|
+
if (currentLevel.some((msg) => msg.messageId === targetMessageId) &&
|
|
5306
|
+
targetMessage.parentMessageId === librechatDataProvider.Constants.NO_PARENT) {
|
|
5307
|
+
return Array.from(results);
|
|
5308
|
+
}
|
|
5309
|
+
// Iterate level by level until the target is found
|
|
5310
|
+
let targetFound = false;
|
|
5311
|
+
while (!targetFound && currentLevel.length > 0) {
|
|
5312
|
+
const nextLevel = [];
|
|
5313
|
+
for (const node of currentLevel) {
|
|
5314
|
+
if (visited.has(node.messageId)) {
|
|
5315
|
+
continue;
|
|
5316
|
+
}
|
|
5317
|
+
visited.add(node.messageId);
|
|
5318
|
+
const children = parentToChildrenMap.get(node.messageId) || [];
|
|
5319
|
+
for (const child of children) {
|
|
5320
|
+
if (visited.has(child.messageId)) {
|
|
5321
|
+
continue;
|
|
5322
|
+
}
|
|
5323
|
+
nextLevel.push(child);
|
|
5324
|
+
results.add(child);
|
|
5325
|
+
if (child.messageId === targetMessageId) {
|
|
5326
|
+
targetFound = true;
|
|
5327
|
+
}
|
|
5328
|
+
}
|
|
5329
|
+
}
|
|
5330
|
+
currentLevel = nextLevel;
|
|
5331
|
+
}
|
|
5332
|
+
return Array.from(results);
|
|
5333
|
+
}
|
|
4753
5334
|
/** Factory function that takes mongoose instance and returns the methods */
|
|
4754
5335
|
function createShareMethods(mongoose) {
|
|
4755
5336
|
/**
|
|
@@ -4768,6 +5349,11 @@ function createShareMethods(mongoose) {
|
|
|
4768
5349
|
if (!(share === null || share === void 0 ? void 0 : share.conversationId) || !share.isPublic) {
|
|
4769
5350
|
return null;
|
|
4770
5351
|
}
|
|
5352
|
+
/** Filtered messages based on targetMessageId if present (branch-specific sharing) */
|
|
5353
|
+
let messagesToShare = share.messages;
|
|
5354
|
+
if (share.targetMessageId) {
|
|
5355
|
+
messagesToShare = getMessagesUpToTarget(share.messages, share.targetMessageId);
|
|
5356
|
+
}
|
|
4771
5357
|
const newConvoId = anonymizeConvoId(share.conversationId);
|
|
4772
5358
|
const result = {
|
|
4773
5359
|
shareId: share.shareId || shareId,
|
|
@@ -4776,7 +5362,7 @@ function createShareMethods(mongoose) {
|
|
|
4776
5362
|
createdAt: share.createdAt,
|
|
4777
5363
|
updatedAt: share.updatedAt,
|
|
4778
5364
|
conversationId: newConvoId,
|
|
4779
|
-
messages: anonymizeMessages(
|
|
5365
|
+
messages: anonymizeMessages(messagesToShare, newConvoId),
|
|
4780
5366
|
};
|
|
4781
5367
|
return result;
|
|
4782
5368
|
}
|
|
@@ -4807,7 +5393,9 @@ function createShareMethods(mongoose) {
|
|
|
4807
5393
|
}
|
|
4808
5394
|
if (search && search.trim()) {
|
|
4809
5395
|
try {
|
|
4810
|
-
const searchResults = await Conversation.meiliSearch(search
|
|
5396
|
+
const searchResults = await Conversation.meiliSearch(search, {
|
|
5397
|
+
filter: `user = "${user}"`,
|
|
5398
|
+
});
|
|
4811
5399
|
if (!((_a = searchResults === null || searchResults === void 0 ? void 0 : searchResults.hits) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
4812
5400
|
return {
|
|
4813
5401
|
links: [],
|
|
@@ -4882,10 +5470,34 @@ function createShareMethods(mongoose) {
|
|
|
4882
5470
|
throw new ShareServiceError('Error deleting shared links', 'BULK_DELETE_ERROR');
|
|
4883
5471
|
}
|
|
4884
5472
|
}
|
|
5473
|
+
/**
|
|
5474
|
+
* Delete shared links by conversation ID
|
|
5475
|
+
*/
|
|
5476
|
+
async function deleteConvoSharedLink(user, conversationId) {
|
|
5477
|
+
if (!user || !conversationId) {
|
|
5478
|
+
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
5479
|
+
}
|
|
5480
|
+
try {
|
|
5481
|
+
const SharedLink = mongoose.models.SharedLink;
|
|
5482
|
+
const result = await SharedLink.deleteMany({ user, conversationId });
|
|
5483
|
+
return {
|
|
5484
|
+
message: 'Shared links deleted successfully',
|
|
5485
|
+
deletedCount: result.deletedCount,
|
|
5486
|
+
};
|
|
5487
|
+
}
|
|
5488
|
+
catch (error) {
|
|
5489
|
+
logger$1.error('[deleteConvoSharedLink] Error deleting shared links', {
|
|
5490
|
+
error: error instanceof Error ? error.message : 'Unknown error',
|
|
5491
|
+
user,
|
|
5492
|
+
conversationId,
|
|
5493
|
+
});
|
|
5494
|
+
throw new ShareServiceError('Error deleting shared links', 'SHARE_DELETE_ERROR');
|
|
5495
|
+
}
|
|
5496
|
+
}
|
|
4885
5497
|
/**
|
|
4886
5498
|
* Create a new shared link for a conversation
|
|
4887
5499
|
*/
|
|
4888
|
-
async function createSharedLink(user, conversationId) {
|
|
5500
|
+
async function createSharedLink(user, conversationId, targetMessageId) {
|
|
4889
5501
|
if (!user || !conversationId) {
|
|
4890
5502
|
throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
|
|
4891
5503
|
}
|
|
@@ -4894,7 +5506,12 @@ function createShareMethods(mongoose) {
|
|
|
4894
5506
|
const SharedLink = mongoose.models.SharedLink;
|
|
4895
5507
|
const Conversation = mongoose.models.Conversation;
|
|
4896
5508
|
const [existingShare, conversationMessages] = await Promise.all([
|
|
4897
|
-
SharedLink.findOne({
|
|
5509
|
+
SharedLink.findOne({
|
|
5510
|
+
conversationId,
|
|
5511
|
+
user,
|
|
5512
|
+
isPublic: true,
|
|
5513
|
+
...(targetMessageId && { targetMessageId }),
|
|
5514
|
+
})
|
|
4898
5515
|
.select('-_id -__v -user')
|
|
4899
5516
|
.lean(),
|
|
4900
5517
|
Message.find({ conversationId, user }).sort({ createdAt: 1 }).lean(),
|
|
@@ -4903,11 +5520,16 @@ function createShareMethods(mongoose) {
|
|
|
4903
5520
|
logger$1.error('[createSharedLink] Share already exists', {
|
|
4904
5521
|
user,
|
|
4905
5522
|
conversationId,
|
|
5523
|
+
targetMessageId,
|
|
4906
5524
|
});
|
|
4907
5525
|
throw new ShareServiceError('Share already exists', 'SHARE_EXISTS');
|
|
4908
5526
|
}
|
|
4909
5527
|
else if (existingShare) {
|
|
4910
|
-
await SharedLink.deleteOne({
|
|
5528
|
+
await SharedLink.deleteOne({
|
|
5529
|
+
conversationId,
|
|
5530
|
+
user,
|
|
5531
|
+
...(targetMessageId && { targetMessageId }),
|
|
5532
|
+
});
|
|
4911
5533
|
}
|
|
4912
5534
|
const conversation = (await Conversation.findOne({ conversationId, user }).lean());
|
|
4913
5535
|
// Check if user owns the conversation
|
|
@@ -4926,6 +5548,7 @@ function createShareMethods(mongoose) {
|
|
|
4926
5548
|
messages: conversationMessages,
|
|
4927
5549
|
title,
|
|
4928
5550
|
user,
|
|
5551
|
+
...(targetMessageId && { targetMessageId }),
|
|
4929
5552
|
});
|
|
4930
5553
|
return { shareId, conversationId };
|
|
4931
5554
|
}
|
|
@@ -4937,6 +5560,7 @@ function createShareMethods(mongoose) {
|
|
|
4937
5560
|
error: error instanceof Error ? error.message : 'Unknown error',
|
|
4938
5561
|
user,
|
|
4939
5562
|
conversationId,
|
|
5563
|
+
targetMessageId,
|
|
4940
5564
|
});
|
|
4941
5565
|
throw new ShareServiceError('Error creating shared link', 'SHARE_CREATE_ERROR');
|
|
4942
5566
|
}
|
|
@@ -5049,6 +5673,7 @@ function createShareMethods(mongoose) {
|
|
|
5049
5673
|
deleteSharedLink,
|
|
5050
5674
|
getSharedMessages,
|
|
5051
5675
|
deleteAllSharedLinks,
|
|
5676
|
+
deleteConvoSharedLink,
|
|
5052
5677
|
};
|
|
5053
5678
|
}
|
|
5054
5679
|
|
|
@@ -5071,9 +5696,11 @@ function createMethods(mongoose) {
|
|
|
5071
5696
|
};
|
|
5072
5697
|
}
|
|
5073
5698
|
|
|
5699
|
+
exports.AppService = AppService;
|
|
5074
5700
|
exports.actionSchema = Action;
|
|
5075
5701
|
exports.agentCategorySchema = agentCategorySchema;
|
|
5076
5702
|
exports.agentSchema = agentSchema;
|
|
5703
|
+
exports.agentsConfigSetup = agentsConfigSetup;
|
|
5077
5704
|
exports.assistantSchema = assistantSchema;
|
|
5078
5705
|
exports.balanceSchema = balanceSchema;
|
|
5079
5706
|
exports.bannerSchema = bannerSchema;
|
|
@@ -5084,15 +5711,20 @@ exports.createMethods = createMethods;
|
|
|
5084
5711
|
exports.createModels = createModels;
|
|
5085
5712
|
exports.fileSchema = file;
|
|
5086
5713
|
exports.getTransactionSupport = getTransactionSupport;
|
|
5714
|
+
exports.getWebSearchKeys = getWebSearchKeys;
|
|
5087
5715
|
exports.groupSchema = groupSchema;
|
|
5088
5716
|
exports.hashToken = hashToken;
|
|
5089
5717
|
exports.keySchema = keySchema;
|
|
5718
|
+
exports.loadDefaultInterface = loadDefaultInterface;
|
|
5719
|
+
exports.loadTurnstileConfig = loadTurnstileConfig;
|
|
5720
|
+
exports.loadWebSearchConfig = loadWebSearchConfig;
|
|
5090
5721
|
exports.logger = logger$1;
|
|
5091
5722
|
exports.meiliLogger = logger;
|
|
5092
5723
|
exports.memorySchema = MemoryEntrySchema;
|
|
5093
5724
|
exports.messageSchema = messageSchema;
|
|
5094
5725
|
exports.pluginAuthSchema = pluginAuthSchema;
|
|
5095
5726
|
exports.presetSchema = presetSchema;
|
|
5727
|
+
exports.processModelSpecs = processModelSpecs;
|
|
5096
5728
|
exports.projectSchema = projectSchema;
|
|
5097
5729
|
exports.promptGroupSchema = promptGroupSchema;
|
|
5098
5730
|
exports.promptSchema = promptSchema;
|
|
@@ -5105,4 +5737,6 @@ exports.tokenSchema = tokenSchema;
|
|
|
5105
5737
|
exports.toolCallSchema = toolCallSchema;
|
|
5106
5738
|
exports.transactionSchema = transactionSchema;
|
|
5107
5739
|
exports.userSchema = userSchema;
|
|
5740
|
+
exports.webSearchAuth = webSearchAuth;
|
|
5741
|
+
exports.webSearchKeys = webSearchKeys;
|
|
5108
5742
|
//# sourceMappingURL=index.cjs.map
|