@librechat/data-schemas 0.0.35 → 0.0.37
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 +403 -14
- package/dist/index.cjs.map +1 -1
- package/dist/index.es.js +403 -16
- package/dist/index.es.js.map +1 -1
- package/dist/types/methods/agentApiKey.d.ts +39 -0
- package/dist/types/methods/file.d.ts +8 -0
- package/dist/types/methods/index.d.ts +4 -2
- package/dist/types/methods/transaction.d.ts +46 -0
- package/dist/types/models/agentApiKey.d.ts +27 -0
- package/dist/types/models/index.d.ts +1 -0
- package/dist/types/schema/agentApiKey.d.ts +38 -0
- package/dist/types/schema/defaults.d.ts +6 -0
- package/dist/types/schema/index.d.ts +1 -0
- package/dist/types/schema/preset.d.ts +1 -0
- package/dist/types/schema/transaction.d.ts +1 -0
- package/dist/types/types/agent.d.ts +3 -1
- package/dist/types/types/agentApiKey.d.ts +65 -0
- package/dist/types/types/convo.d.ts +1 -0
- package/dist/types/types/file.d.ts +1 -0
- package/dist/types/types/index.d.ts +2 -0
- package/dist/types/types/transaction.d.ts +17 -0
- package/dist/types/utils/transactions.d.ts +1 -0
- package/package.json +3 -3
package/dist/index.es.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EModelEndpoint, agentsEndpointSchema, memorySchema, removeNullishValues, SafeSearchTypes, normalizeEndpointName, defaultAssistantsVersion, Capabilities, assistantEndpointSchema, validateAzureGroups, mapModelToAzureConfig, extractEnvVariable, envVarRegex, OCRStrategy, getConfigDefaults, PermissionBits, FileSources, Constants, PermissionTypes, Permissions, SystemRoles, parseTextParts, ResourceType, PrincipalType, PrincipalModel, roleDefaults, ErrorTypes, EToolResources,
|
|
1
|
+
import { EModelEndpoint, agentsEndpointSchema, memorySchema, removeNullishValues, SafeSearchTypes, normalizeEndpointName, defaultAssistantsVersion, Capabilities, assistantEndpointSchema, validateAzureGroups, mapModelToAzureConfig, extractEnvVariable, envVarRegex, OCRStrategy, getConfigDefaults, PermissionBits, FileSources, FileContext, Constants, PermissionTypes, Permissions, SystemRoles, parseTextParts, ResourceType, PrincipalType, PrincipalModel, roleDefaults, ErrorTypes, EToolResources, AccessRoleIds } from 'librechat-data-provider';
|
|
2
2
|
import winston from 'winston';
|
|
3
3
|
import 'winston-daily-rotate-file';
|
|
4
4
|
import { klona } from 'klona';
|
|
@@ -1460,12 +1460,57 @@ const agentSchema = new Schema({
|
|
|
1460
1460
|
default: [],
|
|
1461
1461
|
index: true,
|
|
1462
1462
|
},
|
|
1463
|
+
/** Per-tool configuration (defer_loading, allowed_callers) */
|
|
1464
|
+
tool_options: {
|
|
1465
|
+
type: Schema.Types.Mixed,
|
|
1466
|
+
default: undefined,
|
|
1467
|
+
},
|
|
1463
1468
|
}, {
|
|
1464
1469
|
timestamps: true,
|
|
1465
1470
|
});
|
|
1466
1471
|
agentSchema.index({ updatedAt: -1, _id: 1 });
|
|
1467
1472
|
agentSchema.index({ 'edges.to': 1 });
|
|
1468
1473
|
|
|
1474
|
+
const agentApiKeySchema = new Schema({
|
|
1475
|
+
userId: {
|
|
1476
|
+
type: mongoose.Schema.Types.ObjectId,
|
|
1477
|
+
ref: 'User',
|
|
1478
|
+
required: true,
|
|
1479
|
+
index: true,
|
|
1480
|
+
},
|
|
1481
|
+
name: {
|
|
1482
|
+
type: String,
|
|
1483
|
+
required: true,
|
|
1484
|
+
trim: true,
|
|
1485
|
+
maxlength: 100,
|
|
1486
|
+
},
|
|
1487
|
+
keyHash: {
|
|
1488
|
+
type: String,
|
|
1489
|
+
required: true,
|
|
1490
|
+
select: false,
|
|
1491
|
+
index: true,
|
|
1492
|
+
},
|
|
1493
|
+
keyPrefix: {
|
|
1494
|
+
type: String,
|
|
1495
|
+
required: true,
|
|
1496
|
+
index: true,
|
|
1497
|
+
},
|
|
1498
|
+
lastUsedAt: {
|
|
1499
|
+
type: Date,
|
|
1500
|
+
},
|
|
1501
|
+
expiresAt: {
|
|
1502
|
+
type: Date,
|
|
1503
|
+
},
|
|
1504
|
+
}, { timestamps: true });
|
|
1505
|
+
agentApiKeySchema.index({ userId: 1, name: 1 });
|
|
1506
|
+
/**
|
|
1507
|
+
* TTL index for automatic cleanup of expired keys.
|
|
1508
|
+
* MongoDB deletes documents when expiresAt passes (expireAfterSeconds: 0 means immediate).
|
|
1509
|
+
* Note: Expired keys are permanently removed, not soft-deleted.
|
|
1510
|
+
* If audit trails are needed, remove this index and check expiration programmatically.
|
|
1511
|
+
*/
|
|
1512
|
+
agentApiKeySchema.index({ expiresAt: 1 }, { expireAfterSeconds: 0 });
|
|
1513
|
+
|
|
1469
1514
|
const agentCategorySchema = new Schema({
|
|
1470
1515
|
value: {
|
|
1471
1516
|
type: String,
|
|
@@ -1728,6 +1773,12 @@ const conversationPreset = {
|
|
|
1728
1773
|
thinkingBudget: {
|
|
1729
1774
|
type: Number,
|
|
1730
1775
|
},
|
|
1776
|
+
thinkingLevel: {
|
|
1777
|
+
type: String,
|
|
1778
|
+
},
|
|
1779
|
+
effort: {
|
|
1780
|
+
type: String,
|
|
1781
|
+
},
|
|
1731
1782
|
system: {
|
|
1732
1783
|
type: String,
|
|
1733
1784
|
},
|
|
@@ -1854,6 +1905,10 @@ const file = new Schema({
|
|
|
1854
1905
|
ref: 'Conversation',
|
|
1855
1906
|
index: true,
|
|
1856
1907
|
},
|
|
1908
|
+
messageId: {
|
|
1909
|
+
type: String,
|
|
1910
|
+
index: true,
|
|
1911
|
+
},
|
|
1857
1912
|
file_id: {
|
|
1858
1913
|
type: String,
|
|
1859
1914
|
index: true,
|
|
@@ -1917,6 +1972,7 @@ const file = new Schema({
|
|
|
1917
1972
|
timestamps: true,
|
|
1918
1973
|
});
|
|
1919
1974
|
file.index({ createdAt: 1, updatedAt: 1 });
|
|
1975
|
+
file.index({ filename: 1, conversationId: 1, context: 1 }, { unique: true, partialFilterExpression: { context: FileContext.execute_code } });
|
|
1920
1976
|
|
|
1921
1977
|
const keySchema = new Schema({
|
|
1922
1978
|
userId: {
|
|
@@ -2294,6 +2350,12 @@ const rolePermissionsSchema = new Schema({
|
|
|
2294
2350
|
[Permissions.SHARE]: { type: Boolean },
|
|
2295
2351
|
[Permissions.SHARE_PUBLIC]: { type: Boolean },
|
|
2296
2352
|
},
|
|
2353
|
+
[PermissionTypes.REMOTE_AGENTS]: {
|
|
2354
|
+
[Permissions.USE]: { type: Boolean },
|
|
2355
|
+
[Permissions.CREATE]: { type: Boolean },
|
|
2356
|
+
[Permissions.SHARE]: { type: Boolean },
|
|
2357
|
+
[Permissions.SHARE_PUBLIC]: { type: Boolean },
|
|
2358
|
+
},
|
|
2297
2359
|
}, { _id: false });
|
|
2298
2360
|
const roleSchema = new Schema({
|
|
2299
2361
|
name: { type: String, required: true, unique: true, index: true },
|
|
@@ -2451,6 +2513,7 @@ const transactionSchema = new Schema({
|
|
|
2451
2513
|
inputTokens: { type: Number },
|
|
2452
2514
|
writeTokens: { type: Number },
|
|
2453
2515
|
readTokens: { type: Number },
|
|
2516
|
+
messageId: { type: String },
|
|
2454
2517
|
}, {
|
|
2455
2518
|
timestamps: true,
|
|
2456
2519
|
});
|
|
@@ -2678,6 +2741,7 @@ groupSchema.index({ idOnTheSource: 1, source: 1 }, {
|
|
|
2678
2741
|
});
|
|
2679
2742
|
groupSchema.index({ memberIds: 1 });
|
|
2680
2743
|
|
|
2744
|
+
const CANCEL_RATE = 1.15;
|
|
2681
2745
|
/**
|
|
2682
2746
|
* Checks if the connected MongoDB deployment supports transactions
|
|
2683
2747
|
* This requires a MongoDB replica set configuration
|
|
@@ -2868,8 +2932,8 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, syncOptions, }) =>
|
|
|
2868
2932
|
}
|
|
2869
2933
|
/**
|
|
2870
2934
|
* Synchronizes data between the MongoDB collection and the MeiliSearch index by
|
|
2871
|
-
* incrementally indexing only documents where `expiredAt` is `null` and `_meiliIndex` is `
|
|
2872
|
-
* (i.e., non-expired documents that have not yet been indexed).
|
|
2935
|
+
* incrementally indexing only documents where `expiredAt` is `null` and `_meiliIndex` is not `true`
|
|
2936
|
+
* (i.e., non-expired documents that have not yet been indexed, including those with missing or null `_meiliIndex`).
|
|
2873
2937
|
* */
|
|
2874
2938
|
static async syncWithMeili() {
|
|
2875
2939
|
const startTime = Date.now();
|
|
@@ -2894,7 +2958,7 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, syncOptions, }) =>
|
|
|
2894
2958
|
while (hasMore) {
|
|
2895
2959
|
const query = {
|
|
2896
2960
|
expiredAt: null,
|
|
2897
|
-
_meiliIndex:
|
|
2961
|
+
_meiliIndex: { $ne: true },
|
|
2898
2962
|
};
|
|
2899
2963
|
try {
|
|
2900
2964
|
const documents = await this.find(query)
|
|
@@ -3357,6 +3421,10 @@ function createAgentModel(mongoose) {
|
|
|
3357
3421
|
return mongoose.models.Agent || mongoose.model('Agent', agentSchema);
|
|
3358
3422
|
}
|
|
3359
3423
|
|
|
3424
|
+
function createAgentApiKeyModel(mongoose) {
|
|
3425
|
+
return (mongoose.models.AgentApiKey || mongoose.model('AgentApiKey', agentApiKeySchema));
|
|
3426
|
+
}
|
|
3427
|
+
|
|
3360
3428
|
/**
|
|
3361
3429
|
* Creates or returns the AgentCategory model using the provided mongoose instance and schema
|
|
3362
3430
|
*/
|
|
@@ -3520,7 +3588,7 @@ const accessRoleSchema = new Schema({
|
|
|
3520
3588
|
description: String,
|
|
3521
3589
|
resourceType: {
|
|
3522
3590
|
type: String,
|
|
3523
|
-
enum: ['agent', 'project', 'file', 'promptGroup', 'mcpServer'],
|
|
3591
|
+
enum: ['agent', 'project', 'file', 'promptGroup', 'mcpServer', 'remoteAgent'],
|
|
3524
3592
|
required: true,
|
|
3525
3593
|
default: 'agent',
|
|
3526
3594
|
},
|
|
@@ -3620,6 +3688,7 @@ function createModels(mongoose) {
|
|
|
3620
3688
|
Conversation: createConversationModel(mongoose),
|
|
3621
3689
|
Message: createMessageModel(mongoose),
|
|
3622
3690
|
Agent: createAgentModel(mongoose),
|
|
3691
|
+
AgentApiKey: createAgentApiKeyModel(mongoose),
|
|
3623
3692
|
AgentCategory: createAgentCategoryModel(mongoose),
|
|
3624
3693
|
MCPServer: createMCPServerModel(mongoose),
|
|
3625
3694
|
Role: createRoleModel(mongoose),
|
|
@@ -4433,30 +4502,33 @@ function createFileMethods(mongoose) {
|
|
|
4433
4502
|
return await query.sort(sortOptions).lean();
|
|
4434
4503
|
}
|
|
4435
4504
|
/**
|
|
4436
|
-
* Retrieves tool files (files that are embedded or have a fileIdentifier) from an array of file IDs
|
|
4505
|
+
* Retrieves tool files (files that are embedded or have a fileIdentifier) from an array of file IDs.
|
|
4506
|
+
* Note: execute_code files are handled separately by getCodeGeneratedFiles.
|
|
4437
4507
|
* @param fileIds - Array of file_id strings to search for
|
|
4438
4508
|
* @param toolResourceSet - Optional filter for tool resources
|
|
4439
4509
|
* @returns Files that match the criteria
|
|
4440
4510
|
*/
|
|
4441
4511
|
async function getToolFilesByIds(fileIds, toolResourceSet) {
|
|
4442
|
-
var _a, _b, _c;
|
|
4443
4512
|
if (!fileIds || !fileIds.length || !(toolResourceSet === null || toolResourceSet === void 0 ? void 0 : toolResourceSet.size)) {
|
|
4444
4513
|
return [];
|
|
4445
4514
|
}
|
|
4446
4515
|
try {
|
|
4447
|
-
const
|
|
4448
|
-
file_id: { $in: fileIds },
|
|
4449
|
-
$or: [],
|
|
4450
|
-
};
|
|
4516
|
+
const orConditions = [];
|
|
4451
4517
|
if (toolResourceSet.has(EToolResources.context)) {
|
|
4452
|
-
|
|
4518
|
+
orConditions.push({ text: { $exists: true, $ne: null }, context: FileContext.agents });
|
|
4453
4519
|
}
|
|
4454
4520
|
if (toolResourceSet.has(EToolResources.file_search)) {
|
|
4455
|
-
|
|
4521
|
+
orConditions.push({ embedded: true });
|
|
4456
4522
|
}
|
|
4457
|
-
|
|
4458
|
-
|
|
4523
|
+
// If no conditions to match, return empty
|
|
4524
|
+
if (orConditions.length === 0) {
|
|
4525
|
+
return [];
|
|
4459
4526
|
}
|
|
4527
|
+
const filter = {
|
|
4528
|
+
file_id: { $in: fileIds },
|
|
4529
|
+
context: { $ne: FileContext.execute_code },
|
|
4530
|
+
$or: orConditions,
|
|
4531
|
+
};
|
|
4460
4532
|
const selectFields = { text: 0 };
|
|
4461
4533
|
const sortOptions = { updatedAt: -1 };
|
|
4462
4534
|
const results = await getFiles(filter, sortOptions, selectFields);
|
|
@@ -4467,6 +4539,91 @@ function createFileMethods(mongoose) {
|
|
|
4467
4539
|
throw new Error('Error retrieving tool files');
|
|
4468
4540
|
}
|
|
4469
4541
|
}
|
|
4542
|
+
/**
|
|
4543
|
+
* Retrieves files generated by code execution for a given conversation.
|
|
4544
|
+
* These files are stored locally with fileIdentifier metadata for code env re-upload.
|
|
4545
|
+
*
|
|
4546
|
+
* @param conversationId - The conversation ID to search for
|
|
4547
|
+
* @param messageIds - Array of messageIds to filter by (for linear thread filtering).
|
|
4548
|
+
* While technically optional, this function returns empty if not provided.
|
|
4549
|
+
* This is intentional: code-generated files must be filtered by thread to avoid
|
|
4550
|
+
* including files from other branches of a conversation.
|
|
4551
|
+
* @returns Files generated by code execution in the conversation, filtered by messageIds
|
|
4552
|
+
*/
|
|
4553
|
+
async function getCodeGeneratedFiles(conversationId, messageIds) {
|
|
4554
|
+
if (!conversationId) {
|
|
4555
|
+
return [];
|
|
4556
|
+
}
|
|
4557
|
+
/**
|
|
4558
|
+
* Return early if messageIds not provided - this is intentional behavior.
|
|
4559
|
+
* Code-generated files must be filtered by thread messageIds to ensure we only
|
|
4560
|
+
* return files relevant to the current conversation branch, not orphaned files
|
|
4561
|
+
* from other branches or deleted messages.
|
|
4562
|
+
*/
|
|
4563
|
+
if (!messageIds || messageIds.length === 0) {
|
|
4564
|
+
return [];
|
|
4565
|
+
}
|
|
4566
|
+
try {
|
|
4567
|
+
const filter = {
|
|
4568
|
+
conversationId,
|
|
4569
|
+
context: FileContext.execute_code,
|
|
4570
|
+
messageId: { $exists: true, $in: messageIds },
|
|
4571
|
+
'metadata.fileIdentifier': { $exists: true },
|
|
4572
|
+
};
|
|
4573
|
+
const selectFields = { text: 0 };
|
|
4574
|
+
const sortOptions = { createdAt: 1 };
|
|
4575
|
+
const results = await getFiles(filter, sortOptions, selectFields);
|
|
4576
|
+
return results !== null && results !== void 0 ? results : [];
|
|
4577
|
+
}
|
|
4578
|
+
catch (error) {
|
|
4579
|
+
logger$1.error('[getCodeGeneratedFiles] Error retrieving code generated files:', error);
|
|
4580
|
+
return [];
|
|
4581
|
+
}
|
|
4582
|
+
}
|
|
4583
|
+
/**
|
|
4584
|
+
* Retrieves user-uploaded execute_code files (not code-generated) by their file IDs.
|
|
4585
|
+
* These are files with fileIdentifier metadata but context is NOT execute_code (e.g., agents or message_attachment).
|
|
4586
|
+
* File IDs should be collected from message.files arrays in the current thread.
|
|
4587
|
+
* @param fileIds - Array of file IDs to fetch (from message.files in the thread)
|
|
4588
|
+
* @returns User-uploaded execute_code files
|
|
4589
|
+
*/
|
|
4590
|
+
async function getUserCodeFiles(fileIds) {
|
|
4591
|
+
if (!fileIds || fileIds.length === 0) {
|
|
4592
|
+
return [];
|
|
4593
|
+
}
|
|
4594
|
+
try {
|
|
4595
|
+
const filter = {
|
|
4596
|
+
file_id: { $in: fileIds },
|
|
4597
|
+
context: { $ne: FileContext.execute_code },
|
|
4598
|
+
'metadata.fileIdentifier': { $exists: true },
|
|
4599
|
+
};
|
|
4600
|
+
const selectFields = { text: 0 };
|
|
4601
|
+
const sortOptions = { createdAt: 1 };
|
|
4602
|
+
const results = await getFiles(filter, sortOptions, selectFields);
|
|
4603
|
+
return results !== null && results !== void 0 ? results : [];
|
|
4604
|
+
}
|
|
4605
|
+
catch (error) {
|
|
4606
|
+
logger$1.error('[getUserCodeFiles] Error retrieving user code files:', error);
|
|
4607
|
+
return [];
|
|
4608
|
+
}
|
|
4609
|
+
}
|
|
4610
|
+
/**
|
|
4611
|
+
* Atomically claims a file_id for a code-execution output by compound key.
|
|
4612
|
+
* Uses $setOnInsert so concurrent calls for the same (filename, conversationId)
|
|
4613
|
+
* converge on a single record instead of creating duplicates.
|
|
4614
|
+
*/
|
|
4615
|
+
async function claimCodeFile(data) {
|
|
4616
|
+
const File = mongoose.models.File;
|
|
4617
|
+
const result = await File.findOneAndUpdate({
|
|
4618
|
+
filename: data.filename,
|
|
4619
|
+
conversationId: data.conversationId,
|
|
4620
|
+
context: FileContext.execute_code,
|
|
4621
|
+
}, { $setOnInsert: { file_id: data.file_id, user: data.user } }, { upsert: true, new: true }).lean();
|
|
4622
|
+
if (!result) {
|
|
4623
|
+
throw new Error(`[claimCodeFile] Failed to claim file "${data.filename}" for conversation ${data.conversationId}`);
|
|
4624
|
+
}
|
|
4625
|
+
return result;
|
|
4626
|
+
}
|
|
4470
4627
|
/**
|
|
4471
4628
|
* Creates a new file with a TTL of 1 hour.
|
|
4472
4629
|
* @param data - The file data to be created, must contain file_id
|
|
@@ -4606,6 +4763,9 @@ function createFileMethods(mongoose) {
|
|
|
4606
4763
|
findFileById,
|
|
4607
4764
|
getFiles,
|
|
4608
4765
|
getToolFilesByIds,
|
|
4766
|
+
getCodeGeneratedFiles,
|
|
4767
|
+
getUserCodeFiles,
|
|
4768
|
+
claimCodeFile,
|
|
4609
4769
|
createFile,
|
|
4610
4770
|
updateFile,
|
|
4611
4771
|
updateFileUsage,
|
|
@@ -4964,6 +5124,139 @@ function createAgentCategoryMethods(mongoose) {
|
|
|
4964
5124
|
};
|
|
4965
5125
|
}
|
|
4966
5126
|
|
|
5127
|
+
const API_KEY_PREFIX = 'sk-';
|
|
5128
|
+
const API_KEY_LENGTH = 32;
|
|
5129
|
+
function createAgentApiKeyMethods(mongoose) {
|
|
5130
|
+
async function generateApiKey() {
|
|
5131
|
+
const randomPart = await getRandomValues(API_KEY_LENGTH);
|
|
5132
|
+
const key = `${API_KEY_PREFIX}${randomPart}`;
|
|
5133
|
+
const keyHash = await hashToken(key);
|
|
5134
|
+
const keyPrefix = key.slice(0, 8);
|
|
5135
|
+
return { key, keyHash, keyPrefix };
|
|
5136
|
+
}
|
|
5137
|
+
async function createAgentApiKey(data) {
|
|
5138
|
+
try {
|
|
5139
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5140
|
+
const { key, keyHash, keyPrefix } = await generateApiKey();
|
|
5141
|
+
const apiKeyDoc = await AgentApiKey.create({
|
|
5142
|
+
userId: data.userId,
|
|
5143
|
+
name: data.name,
|
|
5144
|
+
keyHash,
|
|
5145
|
+
keyPrefix,
|
|
5146
|
+
expiresAt: data.expiresAt || undefined,
|
|
5147
|
+
});
|
|
5148
|
+
return {
|
|
5149
|
+
id: apiKeyDoc._id.toString(),
|
|
5150
|
+
name: apiKeyDoc.name,
|
|
5151
|
+
keyPrefix,
|
|
5152
|
+
key,
|
|
5153
|
+
createdAt: apiKeyDoc.createdAt,
|
|
5154
|
+
expiresAt: apiKeyDoc.expiresAt,
|
|
5155
|
+
};
|
|
5156
|
+
}
|
|
5157
|
+
catch (error) {
|
|
5158
|
+
logger$1.error('[createAgentApiKey] Error creating API key:', error);
|
|
5159
|
+
throw error;
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
async function validateAgentApiKey(apiKey) {
|
|
5163
|
+
try {
|
|
5164
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5165
|
+
const keyHash = await hashToken(apiKey);
|
|
5166
|
+
const keyDoc = (await AgentApiKey.findOne({ keyHash }).lean());
|
|
5167
|
+
if (!keyDoc) {
|
|
5168
|
+
return null;
|
|
5169
|
+
}
|
|
5170
|
+
if (keyDoc.expiresAt && new Date(keyDoc.expiresAt) < new Date()) {
|
|
5171
|
+
return null;
|
|
5172
|
+
}
|
|
5173
|
+
await AgentApiKey.updateOne({ _id: keyDoc._id }, { $set: { lastUsedAt: new Date() } });
|
|
5174
|
+
return {
|
|
5175
|
+
userId: keyDoc.userId,
|
|
5176
|
+
keyId: keyDoc._id,
|
|
5177
|
+
};
|
|
5178
|
+
}
|
|
5179
|
+
catch (error) {
|
|
5180
|
+
logger$1.error('[validateAgentApiKey] Error validating API key:', error);
|
|
5181
|
+
return null;
|
|
5182
|
+
}
|
|
5183
|
+
}
|
|
5184
|
+
async function listAgentApiKeys(userId) {
|
|
5185
|
+
try {
|
|
5186
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5187
|
+
const keys = (await AgentApiKey.find({ userId })
|
|
5188
|
+
.sort({ createdAt: -1 })
|
|
5189
|
+
.lean());
|
|
5190
|
+
return keys.map((key) => ({
|
|
5191
|
+
id: key._id.toString(),
|
|
5192
|
+
name: key.name,
|
|
5193
|
+
keyPrefix: key.keyPrefix,
|
|
5194
|
+
lastUsedAt: key.lastUsedAt,
|
|
5195
|
+
expiresAt: key.expiresAt,
|
|
5196
|
+
createdAt: key.createdAt,
|
|
5197
|
+
}));
|
|
5198
|
+
}
|
|
5199
|
+
catch (error) {
|
|
5200
|
+
logger$1.error('[listAgentApiKeys] Error listing API keys:', error);
|
|
5201
|
+
throw error;
|
|
5202
|
+
}
|
|
5203
|
+
}
|
|
5204
|
+
async function deleteAgentApiKey(keyId, userId) {
|
|
5205
|
+
try {
|
|
5206
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5207
|
+
const result = await AgentApiKey.deleteOne({ _id: keyId, userId });
|
|
5208
|
+
return result.deletedCount > 0;
|
|
5209
|
+
}
|
|
5210
|
+
catch (error) {
|
|
5211
|
+
logger$1.error('[deleteAgentApiKey] Error deleting API key:', error);
|
|
5212
|
+
throw error;
|
|
5213
|
+
}
|
|
5214
|
+
}
|
|
5215
|
+
async function deleteAllAgentApiKeys(userId) {
|
|
5216
|
+
try {
|
|
5217
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5218
|
+
const result = await AgentApiKey.deleteMany({ userId });
|
|
5219
|
+
return result.deletedCount;
|
|
5220
|
+
}
|
|
5221
|
+
catch (error) {
|
|
5222
|
+
logger$1.error('[deleteAllAgentApiKeys] Error deleting all API keys:', error);
|
|
5223
|
+
throw error;
|
|
5224
|
+
}
|
|
5225
|
+
}
|
|
5226
|
+
async function getAgentApiKeyById(keyId, userId) {
|
|
5227
|
+
try {
|
|
5228
|
+
const AgentApiKey = mongoose.models.AgentApiKey;
|
|
5229
|
+
const keyDoc = (await AgentApiKey.findOne({
|
|
5230
|
+
_id: keyId,
|
|
5231
|
+
userId,
|
|
5232
|
+
}).lean());
|
|
5233
|
+
if (!keyDoc) {
|
|
5234
|
+
return null;
|
|
5235
|
+
}
|
|
5236
|
+
return {
|
|
5237
|
+
id: keyDoc._id.toString(),
|
|
5238
|
+
name: keyDoc.name,
|
|
5239
|
+
keyPrefix: keyDoc.keyPrefix,
|
|
5240
|
+
lastUsedAt: keyDoc.lastUsedAt,
|
|
5241
|
+
expiresAt: keyDoc.expiresAt,
|
|
5242
|
+
createdAt: keyDoc.createdAt,
|
|
5243
|
+
};
|
|
5244
|
+
}
|
|
5245
|
+
catch (error) {
|
|
5246
|
+
logger$1.error('[getAgentApiKeyById] Error getting API key:', error);
|
|
5247
|
+
throw error;
|
|
5248
|
+
}
|
|
5249
|
+
}
|
|
5250
|
+
return {
|
|
5251
|
+
createAgentApiKey,
|
|
5252
|
+
validateAgentApiKey,
|
|
5253
|
+
listAgentApiKeys,
|
|
5254
|
+
deleteAgentApiKey,
|
|
5255
|
+
deleteAllAgentApiKeys,
|
|
5256
|
+
getAgentApiKeyById,
|
|
5257
|
+
};
|
|
5258
|
+
}
|
|
5259
|
+
|
|
4967
5260
|
const NORMALIZED_LIMIT_DEFAULT = 20;
|
|
4968
5261
|
const MAX_CREATE_RETRIES = 5;
|
|
4969
5262
|
const RETRY_BASE_DELAY_MS = 25;
|
|
@@ -5464,6 +5757,27 @@ function createAccessRoleMethods(mongoose) {
|
|
|
5464
5757
|
resourceType: ResourceType.MCPSERVER,
|
|
5465
5758
|
permBits: RoleBits.OWNER,
|
|
5466
5759
|
},
|
|
5760
|
+
{
|
|
5761
|
+
accessRoleId: AccessRoleIds.REMOTE_AGENT_VIEWER,
|
|
5762
|
+
name: 'com_ui_remote_agent_role_viewer',
|
|
5763
|
+
description: 'com_ui_remote_agent_role_viewer_desc',
|
|
5764
|
+
resourceType: ResourceType.REMOTE_AGENT,
|
|
5765
|
+
permBits: RoleBits.VIEWER,
|
|
5766
|
+
},
|
|
5767
|
+
{
|
|
5768
|
+
accessRoleId: AccessRoleIds.REMOTE_AGENT_EDITOR,
|
|
5769
|
+
name: 'com_ui_remote_agent_role_editor',
|
|
5770
|
+
description: 'com_ui_remote_agent_role_editor_desc',
|
|
5771
|
+
resourceType: ResourceType.REMOTE_AGENT,
|
|
5772
|
+
permBits: RoleBits.EDITOR,
|
|
5773
|
+
},
|
|
5774
|
+
{
|
|
5775
|
+
accessRoleId: AccessRoleIds.REMOTE_AGENT_OWNER,
|
|
5776
|
+
name: 'com_ui_remote_agent_role_owner',
|
|
5777
|
+
description: 'com_ui_remote_agent_role_owner_desc',
|
|
5778
|
+
resourceType: ResourceType.REMOTE_AGENT,
|
|
5779
|
+
permBits: RoleBits.OWNER,
|
|
5780
|
+
},
|
|
5467
5781
|
];
|
|
5468
5782
|
const result = {};
|
|
5469
5783
|
for (const role of defaultRoles) {
|
|
@@ -6701,6 +7015,77 @@ function createShareMethods(mongoose) {
|
|
|
6701
7015
|
};
|
|
6702
7016
|
}
|
|
6703
7017
|
|
|
7018
|
+
function createTransactionMethods(mongoose) {
|
|
7019
|
+
async function updateBalance({ user, incrementValue, setValues }) {
|
|
7020
|
+
var _a;
|
|
7021
|
+
const maxRetries = 10;
|
|
7022
|
+
let delay = 50;
|
|
7023
|
+
let lastError = null;
|
|
7024
|
+
const Balance = mongoose.models.Balance;
|
|
7025
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
7026
|
+
try {
|
|
7027
|
+
const currentBalanceDoc = await Balance.findOne({ user }).lean();
|
|
7028
|
+
const currentCredits = (_a = currentBalanceDoc === null || currentBalanceDoc === void 0 ? void 0 : currentBalanceDoc.tokenCredits) !== null && _a !== void 0 ? _a : 0;
|
|
7029
|
+
const newCredits = Math.max(0, currentCredits + incrementValue);
|
|
7030
|
+
const updatePayload = {
|
|
7031
|
+
$set: {
|
|
7032
|
+
tokenCredits: newCredits,
|
|
7033
|
+
...(setValues !== null && setValues !== void 0 ? setValues : {}),
|
|
7034
|
+
},
|
|
7035
|
+
};
|
|
7036
|
+
if (currentBalanceDoc) {
|
|
7037
|
+
const updatedBalance = await Balance.findOneAndUpdate({ user, tokenCredits: currentCredits }, updatePayload, { new: true }).lean();
|
|
7038
|
+
if (updatedBalance) {
|
|
7039
|
+
return updatedBalance;
|
|
7040
|
+
}
|
|
7041
|
+
lastError = new Error(`Concurrency conflict for user ${user} on attempt ${attempt}.`);
|
|
7042
|
+
}
|
|
7043
|
+
else {
|
|
7044
|
+
try {
|
|
7045
|
+
const updatedBalance = await Balance.findOneAndUpdate({ user }, updatePayload, {
|
|
7046
|
+
upsert: true,
|
|
7047
|
+
new: true,
|
|
7048
|
+
}).lean();
|
|
7049
|
+
if (updatedBalance) {
|
|
7050
|
+
return updatedBalance;
|
|
7051
|
+
}
|
|
7052
|
+
lastError = new Error(`Upsert race condition suspected for user ${user} on attempt ${attempt}.`);
|
|
7053
|
+
}
|
|
7054
|
+
catch (error) {
|
|
7055
|
+
if (error instanceof Error &&
|
|
7056
|
+
'code' in error &&
|
|
7057
|
+
error.code === 11000) {
|
|
7058
|
+
lastError = error;
|
|
7059
|
+
}
|
|
7060
|
+
else {
|
|
7061
|
+
throw error;
|
|
7062
|
+
}
|
|
7063
|
+
}
|
|
7064
|
+
}
|
|
7065
|
+
}
|
|
7066
|
+
catch (error) {
|
|
7067
|
+
logger$1.error(`[updateBalance] Error during attempt ${attempt} for user ${user}:`, error);
|
|
7068
|
+
lastError = error instanceof Error ? error : new Error(String(error));
|
|
7069
|
+
}
|
|
7070
|
+
if (attempt < maxRetries) {
|
|
7071
|
+
const jitter = Math.random() * delay * 0.5;
|
|
7072
|
+
await new Promise((resolve) => setTimeout(resolve, delay + jitter));
|
|
7073
|
+
delay = Math.min(delay * 2, 2000);
|
|
7074
|
+
}
|
|
7075
|
+
}
|
|
7076
|
+
logger$1.error(`[updateBalance] Failed to update balance for user ${user} after ${maxRetries} attempts.`);
|
|
7077
|
+
throw (lastError !== null && lastError !== void 0 ? lastError : new Error(`Failed to update balance for user ${user} after maximum retries due to persistent conflicts.`));
|
|
7078
|
+
}
|
|
7079
|
+
/** Bypasses document middleware; all computed fields must be pre-calculated before calling. */
|
|
7080
|
+
async function bulkInsertTransactions(docs) {
|
|
7081
|
+
const Transaction = mongoose.models.Transaction;
|
|
7082
|
+
if (docs.length) {
|
|
7083
|
+
await Transaction.insertMany(docs);
|
|
7084
|
+
}
|
|
7085
|
+
}
|
|
7086
|
+
return { updateBalance, bulkInsertTransactions };
|
|
7087
|
+
}
|
|
7088
|
+
|
|
6704
7089
|
/**
|
|
6705
7090
|
* Creates all database methods for all collections
|
|
6706
7091
|
* @param mongoose - Mongoose instance
|
|
@@ -6715,14 +7100,16 @@ function createMethods(mongoose) {
|
|
|
6715
7100
|
...createFileMethods(mongoose),
|
|
6716
7101
|
...createMemoryMethods(mongoose),
|
|
6717
7102
|
...createAgentCategoryMethods(mongoose),
|
|
7103
|
+
...createAgentApiKeyMethods(mongoose),
|
|
6718
7104
|
...createMCPServerMethods(mongoose),
|
|
6719
7105
|
...createAccessRoleMethods(mongoose),
|
|
6720
7106
|
...createUserGroupMethods(mongoose),
|
|
6721
7107
|
...createAclEntryMethods(mongoose),
|
|
6722
7108
|
...createShareMethods(mongoose),
|
|
6723
7109
|
...createPluginAuthMethods(mongoose),
|
|
7110
|
+
...createTransactionMethods(mongoose),
|
|
6724
7111
|
};
|
|
6725
7112
|
}
|
|
6726
7113
|
|
|
6727
|
-
export { AppService, DEFAULT_REFRESH_TOKEN_EXPIRY, DEFAULT_SESSION_EXPIRY, RoleBits, Action as actionSchema, agentCategorySchema, agentSchema, agentsConfigSetup, assistantSchema, balanceSchema, bannerSchema, categoriesSchema, conversationTag as conversationTagSchema, convoSchema, createMethods, createModels, decrypt, decryptV2, decryptV3, defaultVertexModels, encrypt, encryptV2, encryptV3, file as fileSchema, getRandomValues, getTransactionSupport, getWebSearchKeys, groupSchema, hashBackupCode, 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, validateVertexConfig, vertexConfigSetup, webSearchAuth, webSearchKeys };
|
|
7114
|
+
export { AppService, CANCEL_RATE, DEFAULT_REFRESH_TOKEN_EXPIRY, DEFAULT_SESSION_EXPIRY, RoleBits, Action as actionSchema, agentApiKeySchema, agentCategorySchema, agentSchema, agentsConfigSetup, assistantSchema, balanceSchema, bannerSchema, categoriesSchema, conversationTag as conversationTagSchema, convoSchema, createMethods, createModels, decrypt, decryptV2, decryptV3, defaultVertexModels, encrypt, encryptV2, encryptV3, file as fileSchema, getRandomValues, getTransactionSupport, getWebSearchKeys, groupSchema, hashBackupCode, 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, validateVertexConfig, vertexConfigSetup, webSearchAuth, webSearchKeys };
|
|
6728
7115
|
//# sourceMappingURL=index.es.js.map
|