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