@librechat/data-schemas 0.0.8 → 0.0.10

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 CHANGED
@@ -11,6 +11,7 @@ var winston = require('winston');
11
11
  require('winston-daily-rotate-file');
12
12
  var klona = require('klona');
13
13
  var traverse = require('traverse');
14
+ var nanoid = require('nanoid');
14
15
 
15
16
  async function signPayload({ payload, secret, expirationTime, }) {
16
17
  return jwt.sign(payload, secret, { expiresIn: expirationTime });
@@ -870,7 +871,7 @@ const promptGroupSchema = new mongoose.Schema({
870
871
  validator: function (v) {
871
872
  return v === undefined || v === null || v === '' || /^[a-z0-9-]+$/.test(v);
872
873
  },
873
- message: (props) => `${props.value} is not a valid command. Only lowercase alphanumeric characters and hyphens are allowed.`,
874
+ 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.`; },
874
875
  },
875
876
  maxlength: [
876
877
  librechatDataProvider.Constants.COMMANDS_MAX_LENGTH,
@@ -892,6 +893,13 @@ const rolePermissionsSchema = new mongoose.Schema({
892
893
  [librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
893
894
  [librechatDataProvider.Permissions.CREATE]: { type: Boolean, default: true },
894
895
  },
896
+ [librechatDataProvider.PermissionTypes.MEMORIES]: {
897
+ [librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
898
+ [librechatDataProvider.Permissions.CREATE]: { type: Boolean, default: true },
899
+ [librechatDataProvider.Permissions.UPDATE]: { type: Boolean, default: true },
900
+ [librechatDataProvider.Permissions.READ]: { type: Boolean, default: true },
901
+ [librechatDataProvider.Permissions.OPT_OUT]: { type: Boolean, default: true },
902
+ },
895
903
  [librechatDataProvider.PermissionTypes.AGENTS]: {
896
904
  [librechatDataProvider.Permissions.SHARED_GLOBAL]: { type: Boolean, default: false },
897
905
  [librechatDataProvider.Permissions.USE]: { type: Boolean, default: true },
@@ -921,6 +929,12 @@ const roleSchema = new mongoose.Schema({
921
929
  [librechatDataProvider.Permissions.USE]: true,
922
930
  [librechatDataProvider.Permissions.CREATE]: true,
923
931
  },
932
+ [librechatDataProvider.PermissionTypes.MEMORIES]: {
933
+ [librechatDataProvider.Permissions.USE]: true,
934
+ [librechatDataProvider.Permissions.CREATE]: true,
935
+ [librechatDataProvider.Permissions.UPDATE]: true,
936
+ [librechatDataProvider.Permissions.READ]: true,
937
+ },
924
938
  [librechatDataProvider.PermissionTypes.AGENTS]: {
925
939
  [librechatDataProvider.Permissions.SHARED_GLOBAL]: false,
926
940
  [librechatDataProvider.Permissions.USE]: true,
@@ -1198,8 +1212,46 @@ const userSchema = new mongoose.Schema({
1198
1212
  type: Boolean,
1199
1213
  default: false,
1200
1214
  },
1215
+ personalization: {
1216
+ type: {
1217
+ memories: {
1218
+ type: Boolean,
1219
+ default: true,
1220
+ },
1221
+ },
1222
+ default: {},
1223
+ },
1201
1224
  }, { timestamps: true });
1202
1225
 
1226
+ const MemoryEntrySchema = new mongoose.Schema({
1227
+ userId: {
1228
+ type: mongoose.Schema.Types.ObjectId,
1229
+ ref: 'User',
1230
+ index: true,
1231
+ required: true,
1232
+ },
1233
+ key: {
1234
+ type: String,
1235
+ required: true,
1236
+ validate: {
1237
+ validator: (v) => /^[a-z_]+$/.test(v),
1238
+ message: 'Key must only contain lowercase letters and underscores',
1239
+ },
1240
+ },
1241
+ value: {
1242
+ type: String,
1243
+ required: true,
1244
+ },
1245
+ tokenCount: {
1246
+ type: Number,
1247
+ default: 0,
1248
+ },
1249
+ updated_at: {
1250
+ type: Date,
1251
+ default: Date.now,
1252
+ },
1253
+ });
1254
+
1203
1255
  /**
1204
1256
  * Creates or returns the User model using the provided mongoose instance and schema
1205
1257
  */
@@ -1228,7 +1280,7 @@ function createBalanceModel(mongoose) {
1228
1280
  return mongoose.models.Balance || mongoose.model('Balance', balanceSchema);
1229
1281
  }
1230
1282
 
1231
- const logDir$1 = path.join(__dirname, '..', 'logs');
1283
+ const logDir$1 = path.join(__dirname, '..', '..', '..', 'api', 'logs');
1232
1284
  const { NODE_ENV: NODE_ENV$1, DEBUG_LOGGING: DEBUG_LOGGING$1 = 'false' } = process.env;
1233
1285
  const useDebugLogging$1 = (typeof DEBUG_LOGGING$1 === 'string' && DEBUG_LOGGING$1.toLowerCase() === 'true') ||
1234
1286
  DEBUG_LOGGING$1 === 'true';
@@ -1415,7 +1467,7 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
1415
1467
  }
1416
1468
  }
1417
1469
  catch (error) {
1418
- logger$1.error('[syncWithMeili] Error adding document to Meili', error);
1470
+ logger$1.error('[syncWithMeili] Error adding document to Meili:', error);
1419
1471
  }
1420
1472
  }
1421
1473
  /**
@@ -1473,30 +1525,52 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
1473
1525
  /**
1474
1526
  * Adds the current document to the MeiliSearch index
1475
1527
  */
1476
- async addObjectToMeili() {
1528
+ async addObjectToMeili(next) {
1477
1529
  const object = this.preprocessObjectForIndex();
1478
1530
  try {
1479
1531
  await index.addDocuments([object]);
1480
1532
  }
1481
1533
  catch (error) {
1482
- logger$1.error('[addObjectToMeili] Error adding document to Meili', error);
1534
+ logger$1.error('[addObjectToMeili] Error adding document to Meili:', error);
1535
+ return next();
1483
1536
  }
1484
- await this.collection.updateMany({ _id: this._id }, { $set: { _meiliIndex: true } });
1537
+ try {
1538
+ await this.collection.updateMany({ _id: this._id }, { $set: { _meiliIndex: true } });
1539
+ }
1540
+ catch (error) {
1541
+ logger$1.error('[addObjectToMeili] Error updating _meiliIndex field:', error);
1542
+ return next();
1543
+ }
1544
+ next();
1485
1545
  }
1486
1546
  /**
1487
1547
  * Updates the current document in the MeiliSearch index
1488
1548
  */
1489
- async updateObjectToMeili() {
1490
- const object = _.omitBy(_.pick(this.toJSON(), attributesToIndex), (v, k) => k.startsWith('$'));
1491
- await index.updateDocuments([object]);
1549
+ async updateObjectToMeili(next) {
1550
+ try {
1551
+ const object = _.omitBy(_.pick(this.toJSON(), attributesToIndex), (v, k) => k.startsWith('$'));
1552
+ await index.updateDocuments([object]);
1553
+ next();
1554
+ }
1555
+ catch (error) {
1556
+ logger$1.error('[updateObjectToMeili] Error updating document in Meili:', error);
1557
+ return next();
1558
+ }
1492
1559
  }
1493
1560
  /**
1494
1561
  * Deletes the current document from the MeiliSearch index.
1495
1562
  *
1496
1563
  * @returns {Promise<void>}
1497
1564
  */
1498
- async deleteObjectFromMeili() {
1499
- await index.deleteDocument(this._id);
1565
+ async deleteObjectFromMeili(next) {
1566
+ try {
1567
+ await index.deleteDocument(this._id);
1568
+ next();
1569
+ }
1570
+ catch (error) {
1571
+ logger$1.error('[deleteObjectFromMeili] Error deleting document from Meili:', error);
1572
+ return next();
1573
+ }
1500
1574
  }
1501
1575
  /**
1502
1576
  * Post-save hook to synchronize the document with MeiliSearch.
@@ -1504,12 +1578,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
1504
1578
  * If the document is already indexed (i.e. `_meiliIndex` is true), it updates it;
1505
1579
  * otherwise, it adds the document to the index.
1506
1580
  */
1507
- postSaveHook() {
1581
+ postSaveHook(next) {
1508
1582
  if (this._meiliIndex) {
1509
- this.updateObjectToMeili();
1583
+ this.updateObjectToMeili(next);
1510
1584
  }
1511
1585
  else {
1512
- this.addObjectToMeili();
1586
+ this.addObjectToMeili(next);
1513
1587
  }
1514
1588
  }
1515
1589
  /**
@@ -1518,9 +1592,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
1518
1592
  * This hook is triggered after a document update, ensuring that changes are
1519
1593
  * propagated to the MeiliSearch index if the document is indexed.
1520
1594
  */
1521
- postUpdateHook() {
1595
+ postUpdateHook(next) {
1522
1596
  if (this._meiliIndex) {
1523
- this.updateObjectToMeili();
1597
+ this.updateObjectToMeili(next);
1598
+ }
1599
+ else {
1600
+ next();
1524
1601
  }
1525
1602
  }
1526
1603
  /**
@@ -1529,9 +1606,12 @@ const createMeiliMongooseModel = ({ index, attributesToIndex, }) => {
1529
1606
  * This hook is triggered after a document is removed, ensuring that the document
1530
1607
  * is also removed from the MeiliSearch index if it was previously indexed.
1531
1608
  */
1532
- postRemoveHook() {
1609
+ postRemoveHook(next) {
1533
1610
  if (this._meiliIndex) {
1534
- this.deleteObjectFromMeili();
1611
+ this.deleteObjectFromMeili(next);
1612
+ }
1613
+ else {
1614
+ next();
1535
1615
  }
1536
1616
  }
1537
1617
  }
@@ -1579,17 +1659,17 @@ function mongoMeili(schema, options) {
1579
1659
  ];
1580
1660
  schema.loadClass(createMeiliMongooseModel({ index, attributesToIndex }));
1581
1661
  // Register Mongoose hooks
1582
- schema.post('save', function (doc) {
1662
+ schema.post('save', function (doc, next) {
1583
1663
  var _a;
1584
- (_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
1664
+ (_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
1585
1665
  });
1586
- schema.post('updateOne', function (doc) {
1666
+ schema.post('updateOne', function (doc, next) {
1587
1667
  var _a;
1588
- (_a = doc.postUpdateHook) === null || _a === void 0 ? void 0 : _a.call(doc);
1668
+ (_a = doc.postUpdateHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
1589
1669
  });
1590
- schema.post('deleteOne', function (doc) {
1670
+ schema.post('deleteOne', function (doc, next) {
1591
1671
  var _a;
1592
- (_a = doc.postRemoveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
1672
+ (_a = doc.postRemoveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
1593
1673
  });
1594
1674
  // Pre-deleteMany hook: remove corresponding documents from MeiliSearch when multiple documents are deleted.
1595
1675
  schema.pre('deleteMany', async function (next) {
@@ -1626,13 +1706,13 @@ function mongoMeili(schema, options) {
1626
1706
  }
1627
1707
  });
1628
1708
  // Post-findOneAndUpdate hook
1629
- schema.post('findOneAndUpdate', async function (doc) {
1709
+ schema.post('findOneAndUpdate', async function (doc, next) {
1630
1710
  var _a;
1631
1711
  if (!meiliEnabled) {
1632
- return;
1712
+ return next();
1633
1713
  }
1634
1714
  if (doc.unfinished) {
1635
- return;
1715
+ return next();
1636
1716
  }
1637
1717
  let meiliDoc;
1638
1718
  if (doc.messages) {
@@ -1645,9 +1725,9 @@ function mongoMeili(schema, options) {
1645
1725
  }
1646
1726
  }
1647
1727
  if (meiliDoc && meiliDoc.title === doc.title) {
1648
- return;
1728
+ return next();
1649
1729
  }
1650
- (_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc);
1730
+ (_a = doc.postSaveHook) === null || _a === void 0 ? void 0 : _a.call(doc, next);
1651
1731
  });
1652
1732
  }
1653
1733
 
@@ -1798,6 +1878,10 @@ function createToolCallModel(mongoose) {
1798
1878
  return mongoose.models.ToolCall || mongoose.model('ToolCall', toolCallSchema);
1799
1879
  }
1800
1880
 
1881
+ function createMemoryModel(mongoose) {
1882
+ return mongoose.models.MemoryEntry || mongoose.model('MemoryEntry', MemoryEntrySchema);
1883
+ }
1884
+
1801
1885
  /**
1802
1886
  * Creates all database models for all collections
1803
1887
  */
@@ -1825,6 +1909,7 @@ function createModels(mongoose) {
1825
1909
  ConversationTag: createConversationTagModel(mongoose),
1826
1910
  SharedLink: createSharedLinkModel(mongoose),
1827
1911
  ToolCall: createToolCallModel(mongoose),
1912
+ MemoryEntry: createMemoryModel(mongoose),
1828
1913
  };
1829
1914
  }
1830
1915
 
@@ -1960,6 +2045,28 @@ function createUserMethods(mongoose) {
1960
2045
  expirationTime: expires / 1000,
1961
2046
  });
1962
2047
  }
2048
+ /**
2049
+ * Update a user's personalization memories setting.
2050
+ * Handles the edge case where the personalization object doesn't exist.
2051
+ */
2052
+ async function toggleUserMemories(userId, memoriesEnabled) {
2053
+ const User = mongoose.models.User;
2054
+ // First, ensure the personalization object exists
2055
+ const user = await User.findById(userId);
2056
+ if (!user) {
2057
+ return null;
2058
+ }
2059
+ // Use $set to update the nested field, which will create the personalization object if it doesn't exist
2060
+ const updateOperation = {
2061
+ $set: {
2062
+ 'personalization.memories': memoriesEnabled,
2063
+ },
2064
+ };
2065
+ return (await User.findByIdAndUpdate(userId, updateOperation, {
2066
+ new: true,
2067
+ runValidators: true,
2068
+ }).lean());
2069
+ }
1963
2070
  // Return all methods
1964
2071
  return {
1965
2072
  findUser,
@@ -1969,6 +2076,7 @@ function createUserMethods(mongoose) {
1969
2076
  getUserById,
1970
2077
  deleteUserById,
1971
2078
  generateToken,
2079
+ toggleUserMemories,
1972
2080
  };
1973
2081
  }
1974
2082
 
@@ -2173,14 +2281,11 @@ const jsonTruncateFormat = winston.format((info) => {
2173
2281
  return truncateObject(info);
2174
2282
  });
2175
2283
 
2176
- // Define log directory
2177
- const logDir = path.join(__dirname, '..', 'logs');
2178
- // Type-safe environment variables
2284
+ const logDir = path.join(__dirname, '..', '..', '..', 'api', 'logs');
2179
2285
  const { NODE_ENV, DEBUG_LOGGING, CONSOLE_JSON, DEBUG_CONSOLE } = process.env;
2180
2286
  const useConsoleJson = typeof CONSOLE_JSON === 'string' && CONSOLE_JSON.toLowerCase() === 'true';
2181
2287
  const useDebugConsole = typeof DEBUG_CONSOLE === 'string' && DEBUG_CONSOLE.toLowerCase() === 'true';
2182
2288
  const useDebugLogging = typeof DEBUG_LOGGING === 'string' && DEBUG_LOGGING.toLowerCase() === 'true';
2183
- // Define custom log levels
2184
2289
  const levels = {
2185
2290
  error: 0,
2186
2291
  warn: 1,
@@ -2260,7 +2365,7 @@ const logger = winston.createLogger({
2260
2365
  transports,
2261
2366
  });
2262
2367
 
2263
- var _a, _b;
2368
+ var _a;
2264
2369
  class SessionError extends Error {
2265
2370
  constructor(message, code = 'SESSION_ERROR') {
2266
2371
  super(message);
@@ -2269,7 +2374,9 @@ class SessionError extends Error {
2269
2374
  }
2270
2375
  }
2271
2376
  const { REFRESH_TOKEN_EXPIRY } = (_a = process.env) !== null && _a !== void 0 ? _a : {};
2272
- const expires = (_b = eval(REFRESH_TOKEN_EXPIRY !== null && REFRESH_TOKEN_EXPIRY !== void 0 ? REFRESH_TOKEN_EXPIRY : '0')) !== null && _b !== void 0 ? _b : 1000 * 60 * 60 * 24 * 7; // 7 days default
2377
+ const expires = REFRESH_TOKEN_EXPIRY
2378
+ ? eval(REFRESH_TOKEN_EXPIRY)
2379
+ : 1000 * 60 * 60 * 24 * 7; // 7 days default
2273
2380
  // Factory function that takes mongoose instance and returns the methods
2274
2381
  function createSessionMethods(mongoose) {
2275
2382
  const Session = mongoose.models.Session;
@@ -2599,6 +2706,584 @@ function createRoleMethods(mongoose) {
2599
2706
  };
2600
2707
  }
2601
2708
 
2709
+ /**
2710
+ * Formats a date in YYYY-MM-DD format
2711
+ */
2712
+ const formatDate = (date) => {
2713
+ return date.toISOString().split('T')[0];
2714
+ };
2715
+ // Factory function that takes mongoose instance and returns the methods
2716
+ function createMemoryMethods(mongoose) {
2717
+ const MemoryEntry = mongoose.models.MemoryEntry;
2718
+ /**
2719
+ * Creates a new memory entry for a user
2720
+ * Throws an error if a memory with the same key already exists
2721
+ */
2722
+ async function createMemory({ userId, key, value, tokenCount = 0, }) {
2723
+ try {
2724
+ if ((key === null || key === void 0 ? void 0 : key.toLowerCase()) === 'nothing') {
2725
+ return { ok: false };
2726
+ }
2727
+ const existingMemory = await MemoryEntry.findOne({ userId, key });
2728
+ if (existingMemory) {
2729
+ throw new Error('Memory with this key already exists');
2730
+ }
2731
+ await MemoryEntry.create({
2732
+ userId,
2733
+ key,
2734
+ value,
2735
+ tokenCount,
2736
+ updated_at: new Date(),
2737
+ });
2738
+ return { ok: true };
2739
+ }
2740
+ catch (error) {
2741
+ throw new Error(`Failed to create memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
2742
+ }
2743
+ }
2744
+ /**
2745
+ * Sets or updates a memory entry for a user
2746
+ */
2747
+ async function setMemory({ userId, key, value, tokenCount = 0, }) {
2748
+ try {
2749
+ if ((key === null || key === void 0 ? void 0 : key.toLowerCase()) === 'nothing') {
2750
+ return { ok: false };
2751
+ }
2752
+ await MemoryEntry.findOneAndUpdate({ userId, key }, {
2753
+ value,
2754
+ tokenCount,
2755
+ updated_at: new Date(),
2756
+ }, {
2757
+ upsert: true,
2758
+ new: true,
2759
+ });
2760
+ return { ok: true };
2761
+ }
2762
+ catch (error) {
2763
+ throw new Error(`Failed to set memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
2764
+ }
2765
+ }
2766
+ /**
2767
+ * Deletes a specific memory entry for a user
2768
+ */
2769
+ async function deleteMemory({ userId, key }) {
2770
+ try {
2771
+ const result = await MemoryEntry.findOneAndDelete({ userId, key });
2772
+ return { ok: !!result };
2773
+ }
2774
+ catch (error) {
2775
+ throw new Error(`Failed to delete memory: ${error instanceof Error ? error.message : 'Unknown error'}`);
2776
+ }
2777
+ }
2778
+ /**
2779
+ * Gets all memory entries for a user
2780
+ */
2781
+ async function getAllUserMemories(userId) {
2782
+ try {
2783
+ return (await MemoryEntry.find({ userId }).lean());
2784
+ }
2785
+ catch (error) {
2786
+ throw new Error(`Failed to get all memories: ${error instanceof Error ? error.message : 'Unknown error'}`);
2787
+ }
2788
+ }
2789
+ /**
2790
+ * Gets and formats all memories for a user in two different formats
2791
+ */
2792
+ async function getFormattedMemories({ userId, }) {
2793
+ try {
2794
+ const memories = await getAllUserMemories(userId);
2795
+ if (!memories || memories.length === 0) {
2796
+ return { withKeys: '', withoutKeys: '', totalTokens: 0 };
2797
+ }
2798
+ const sortedMemories = memories.sort((a, b) => new Date(a.updated_at).getTime() - new Date(b.updated_at).getTime());
2799
+ const totalTokens = sortedMemories.reduce((sum, memory) => {
2800
+ return sum + (memory.tokenCount || 0);
2801
+ }, 0);
2802
+ const withKeys = sortedMemories
2803
+ .map((memory, index) => {
2804
+ const date = formatDate(new Date(memory.updated_at));
2805
+ const tokenInfo = memory.tokenCount ? ` [${memory.tokenCount} tokens]` : '';
2806
+ return `${index + 1}. [${date}]. ["key": "${memory.key}"]${tokenInfo}. ["value": "${memory.value}"]`;
2807
+ })
2808
+ .join('\n\n');
2809
+ const withoutKeys = sortedMemories
2810
+ .map((memory, index) => {
2811
+ const date = formatDate(new Date(memory.updated_at));
2812
+ return `${index + 1}. [${date}]. ${memory.value}`;
2813
+ })
2814
+ .join('\n\n');
2815
+ return { withKeys, withoutKeys, totalTokens };
2816
+ }
2817
+ catch (error) {
2818
+ logger.error('Failed to get formatted memories:', error);
2819
+ return { withKeys: '', withoutKeys: '', totalTokens: 0 };
2820
+ }
2821
+ }
2822
+ return {
2823
+ setMemory,
2824
+ createMemory,
2825
+ deleteMemory,
2826
+ getAllUserMemories,
2827
+ getFormattedMemories,
2828
+ };
2829
+ }
2830
+
2831
+ class ShareServiceError extends Error {
2832
+ constructor(message, code) {
2833
+ super(message);
2834
+ this.name = 'ShareServiceError';
2835
+ this.code = code;
2836
+ }
2837
+ }
2838
+ function memoizedAnonymizeId(prefix) {
2839
+ const memo = new Map();
2840
+ return (id) => {
2841
+ if (!memo.has(id)) {
2842
+ memo.set(id, `${prefix}_${nanoid.nanoid()}`);
2843
+ }
2844
+ return memo.get(id);
2845
+ };
2846
+ }
2847
+ const anonymizeConvoId = memoizedAnonymizeId('convo');
2848
+ const anonymizeAssistantId = memoizedAnonymizeId('a');
2849
+ const anonymizeMessageId = (id) => id === librechatDataProvider.Constants.NO_PARENT ? id : memoizedAnonymizeId('msg')(id);
2850
+ function anonymizeConvo(conversation) {
2851
+ if (!conversation) {
2852
+ return null;
2853
+ }
2854
+ const newConvo = { ...conversation };
2855
+ if (newConvo.assistant_id) {
2856
+ newConvo.assistant_id = anonymizeAssistantId(newConvo.assistant_id);
2857
+ }
2858
+ return newConvo;
2859
+ }
2860
+ function anonymizeMessages(messages, newConvoId) {
2861
+ if (!Array.isArray(messages)) {
2862
+ return [];
2863
+ }
2864
+ const idMap = new Map();
2865
+ return messages.map((message) => {
2866
+ var _a, _b;
2867
+ const newMessageId = anonymizeMessageId(message.messageId);
2868
+ idMap.set(message.messageId, newMessageId);
2869
+ const anonymizedAttachments = (_a = message.attachments) === null || _a === void 0 ? void 0 : _a.map((attachment) => {
2870
+ return {
2871
+ ...attachment,
2872
+ messageId: newMessageId,
2873
+ conversationId: newConvoId,
2874
+ };
2875
+ });
2876
+ return {
2877
+ ...message,
2878
+ messageId: newMessageId,
2879
+ parentMessageId: idMap.get(message.parentMessageId || '') ||
2880
+ anonymizeMessageId(message.parentMessageId || ''),
2881
+ conversationId: newConvoId,
2882
+ model: ((_b = message.model) === null || _b === void 0 ? void 0 : _b.startsWith('asst_'))
2883
+ ? anonymizeAssistantId(message.model)
2884
+ : message.model,
2885
+ attachments: anonymizedAttachments,
2886
+ };
2887
+ });
2888
+ }
2889
+ /** Factory function that takes mongoose instance and returns the methods */
2890
+ function createShareMethods(mongoose) {
2891
+ /**
2892
+ * Get shared messages for a public share link
2893
+ */
2894
+ async function getSharedMessages(shareId) {
2895
+ try {
2896
+ const SharedLink = mongoose.models.SharedLink;
2897
+ const share = (await SharedLink.findOne({ shareId, isPublic: true })
2898
+ .populate({
2899
+ path: 'messages',
2900
+ select: '-_id -__v -user',
2901
+ })
2902
+ .select('-_id -__v -user')
2903
+ .lean());
2904
+ if (!(share === null || share === void 0 ? void 0 : share.conversationId) || !share.isPublic) {
2905
+ return null;
2906
+ }
2907
+ const newConvoId = anonymizeConvoId(share.conversationId);
2908
+ const result = {
2909
+ shareId: share.shareId || shareId,
2910
+ title: share.title,
2911
+ isPublic: share.isPublic,
2912
+ createdAt: share.createdAt,
2913
+ updatedAt: share.updatedAt,
2914
+ conversationId: newConvoId,
2915
+ messages: anonymizeMessages(share.messages, newConvoId),
2916
+ };
2917
+ return result;
2918
+ }
2919
+ catch (error) {
2920
+ logger.error('[getSharedMessages] Error getting share link', {
2921
+ error: error instanceof Error ? error.message : 'Unknown error',
2922
+ shareId,
2923
+ });
2924
+ throw new ShareServiceError('Error getting share link', 'SHARE_FETCH_ERROR');
2925
+ }
2926
+ }
2927
+ /**
2928
+ * Get shared links for a specific user with pagination and search
2929
+ */
2930
+ async function getSharedLinks(user, pageParam, pageSize = 10, isPublic = true, sortBy = 'createdAt', sortDirection = 'desc', search) {
2931
+ var _a;
2932
+ try {
2933
+ const SharedLink = mongoose.models.SharedLink;
2934
+ const Conversation = mongoose.models.Conversation;
2935
+ const query = { user, isPublic };
2936
+ if (pageParam) {
2937
+ if (sortDirection === 'desc') {
2938
+ query[sortBy] = { $lt: pageParam };
2939
+ }
2940
+ else {
2941
+ query[sortBy] = { $gt: pageParam };
2942
+ }
2943
+ }
2944
+ if (search && search.trim()) {
2945
+ try {
2946
+ const searchResults = await Conversation.meiliSearch(search);
2947
+ if (!((_a = searchResults === null || searchResults === void 0 ? void 0 : searchResults.hits) === null || _a === void 0 ? void 0 : _a.length)) {
2948
+ return {
2949
+ links: [],
2950
+ nextCursor: undefined,
2951
+ hasNextPage: false,
2952
+ };
2953
+ }
2954
+ const conversationIds = searchResults.hits.map((hit) => hit.conversationId);
2955
+ query['conversationId'] = { $in: conversationIds };
2956
+ }
2957
+ catch (searchError) {
2958
+ logger.error('[getSharedLinks] Meilisearch error', {
2959
+ error: searchError instanceof Error ? searchError.message : 'Unknown error',
2960
+ user,
2961
+ });
2962
+ return {
2963
+ links: [],
2964
+ nextCursor: undefined,
2965
+ hasNextPage: false,
2966
+ };
2967
+ }
2968
+ }
2969
+ const sort = {};
2970
+ sort[sortBy] = sortDirection === 'desc' ? -1 : 1;
2971
+ const sharedLinks = await SharedLink.find(query)
2972
+ .sort(sort)
2973
+ .limit(pageSize + 1)
2974
+ .select('-__v -user')
2975
+ .lean();
2976
+ const hasNextPage = sharedLinks.length > pageSize;
2977
+ const links = sharedLinks.slice(0, pageSize);
2978
+ const nextCursor = hasNextPage
2979
+ ? links[links.length - 1][sortBy]
2980
+ : undefined;
2981
+ return {
2982
+ links: links.map((link) => ({
2983
+ shareId: link.shareId || '',
2984
+ title: (link === null || link === void 0 ? void 0 : link.title) || 'Untitled',
2985
+ isPublic: link.isPublic,
2986
+ createdAt: link.createdAt || new Date(),
2987
+ conversationId: link.conversationId,
2988
+ })),
2989
+ nextCursor,
2990
+ hasNextPage,
2991
+ };
2992
+ }
2993
+ catch (error) {
2994
+ logger.error('[getSharedLinks] Error getting shares', {
2995
+ error: error instanceof Error ? error.message : 'Unknown error',
2996
+ user,
2997
+ });
2998
+ throw new ShareServiceError('Error getting shares', 'SHARES_FETCH_ERROR');
2999
+ }
3000
+ }
3001
+ /**
3002
+ * Delete all shared links for a user
3003
+ */
3004
+ async function deleteAllSharedLinks(user) {
3005
+ try {
3006
+ const SharedLink = mongoose.models.SharedLink;
3007
+ const result = await SharedLink.deleteMany({ user });
3008
+ return {
3009
+ message: 'All shared links deleted successfully',
3010
+ deletedCount: result.deletedCount,
3011
+ };
3012
+ }
3013
+ catch (error) {
3014
+ logger.error('[deleteAllSharedLinks] Error deleting shared links', {
3015
+ error: error instanceof Error ? error.message : 'Unknown error',
3016
+ user,
3017
+ });
3018
+ throw new ShareServiceError('Error deleting shared links', 'BULK_DELETE_ERROR');
3019
+ }
3020
+ }
3021
+ /**
3022
+ * Create a new shared link for a conversation
3023
+ */
3024
+ async function createSharedLink(user, conversationId) {
3025
+ if (!user || !conversationId) {
3026
+ throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
3027
+ }
3028
+ try {
3029
+ const Message = mongoose.models.Message;
3030
+ const SharedLink = mongoose.models.SharedLink;
3031
+ const Conversation = mongoose.models.Conversation;
3032
+ const [existingShare, conversationMessages] = await Promise.all([
3033
+ SharedLink.findOne({ conversationId, user, isPublic: true })
3034
+ .select('-_id -__v -user')
3035
+ .lean(),
3036
+ Message.find({ conversationId, user }).sort({ createdAt: 1 }).lean(),
3037
+ ]);
3038
+ if (existingShare && existingShare.isPublic) {
3039
+ logger.error('[createSharedLink] Share already exists', {
3040
+ user,
3041
+ conversationId,
3042
+ });
3043
+ throw new ShareServiceError('Share already exists', 'SHARE_EXISTS');
3044
+ }
3045
+ else if (existingShare) {
3046
+ await SharedLink.deleteOne({ conversationId, user });
3047
+ }
3048
+ const conversation = (await Conversation.findOne({ conversationId, user }).lean());
3049
+ // Check if user owns the conversation
3050
+ if (!conversation) {
3051
+ throw new ShareServiceError('Conversation not found or access denied', 'CONVERSATION_NOT_FOUND');
3052
+ }
3053
+ // Check if there are any messages to share
3054
+ if (!conversationMessages || conversationMessages.length === 0) {
3055
+ throw new ShareServiceError('No messages to share', 'NO_MESSAGES');
3056
+ }
3057
+ const title = conversation.title || 'Untitled';
3058
+ const shareId = nanoid.nanoid();
3059
+ await SharedLink.create({
3060
+ shareId,
3061
+ conversationId,
3062
+ messages: conversationMessages,
3063
+ title,
3064
+ user,
3065
+ });
3066
+ return { shareId, conversationId };
3067
+ }
3068
+ catch (error) {
3069
+ if (error instanceof ShareServiceError) {
3070
+ throw error;
3071
+ }
3072
+ logger.error('[createSharedLink] Error creating shared link', {
3073
+ error: error instanceof Error ? error.message : 'Unknown error',
3074
+ user,
3075
+ conversationId,
3076
+ });
3077
+ throw new ShareServiceError('Error creating shared link', 'SHARE_CREATE_ERROR');
3078
+ }
3079
+ }
3080
+ /**
3081
+ * Get a shared link for a conversation
3082
+ */
3083
+ async function getSharedLink(user, conversationId) {
3084
+ if (!user || !conversationId) {
3085
+ throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
3086
+ }
3087
+ try {
3088
+ const SharedLink = mongoose.models.SharedLink;
3089
+ const share = (await SharedLink.findOne({ conversationId, user, isPublic: true })
3090
+ .select('shareId -_id')
3091
+ .lean());
3092
+ if (!share) {
3093
+ return { shareId: null, success: false };
3094
+ }
3095
+ return { shareId: share.shareId || null, success: true };
3096
+ }
3097
+ catch (error) {
3098
+ logger.error('[getSharedLink] Error getting shared link', {
3099
+ error: error instanceof Error ? error.message : 'Unknown error',
3100
+ user,
3101
+ conversationId,
3102
+ });
3103
+ throw new ShareServiceError('Error getting shared link', 'SHARE_FETCH_ERROR');
3104
+ }
3105
+ }
3106
+ /**
3107
+ * Update a shared link with new messages
3108
+ */
3109
+ async function updateSharedLink(user, shareId) {
3110
+ if (!user || !shareId) {
3111
+ throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
3112
+ }
3113
+ try {
3114
+ const SharedLink = mongoose.models.SharedLink;
3115
+ const Message = mongoose.models.Message;
3116
+ const share = (await SharedLink.findOne({ shareId, user })
3117
+ .select('-_id -__v -user')
3118
+ .lean());
3119
+ if (!share) {
3120
+ throw new ShareServiceError('Share not found', 'SHARE_NOT_FOUND');
3121
+ }
3122
+ const updatedMessages = await Message.find({ conversationId: share.conversationId, user })
3123
+ .sort({ createdAt: 1 })
3124
+ .lean();
3125
+ const newShareId = nanoid.nanoid();
3126
+ const update = {
3127
+ messages: updatedMessages,
3128
+ user,
3129
+ shareId: newShareId,
3130
+ };
3131
+ const updatedShare = (await SharedLink.findOneAndUpdate({ shareId, user }, update, {
3132
+ new: true,
3133
+ upsert: false,
3134
+ runValidators: true,
3135
+ }).lean());
3136
+ if (!updatedShare) {
3137
+ throw new ShareServiceError('Share update failed', 'SHARE_UPDATE_ERROR');
3138
+ }
3139
+ anonymizeConvo(updatedShare);
3140
+ return { shareId: newShareId, conversationId: updatedShare.conversationId };
3141
+ }
3142
+ catch (error) {
3143
+ logger.error('[updateSharedLink] Error updating shared link', {
3144
+ error: error instanceof Error ? error.message : 'Unknown error',
3145
+ user,
3146
+ shareId,
3147
+ });
3148
+ throw new ShareServiceError(error instanceof ShareServiceError ? error.message : 'Error updating shared link', error instanceof ShareServiceError ? error.code : 'SHARE_UPDATE_ERROR');
3149
+ }
3150
+ }
3151
+ /**
3152
+ * Delete a shared link
3153
+ */
3154
+ async function deleteSharedLink(user, shareId) {
3155
+ if (!user || !shareId) {
3156
+ throw new ShareServiceError('Missing required parameters', 'INVALID_PARAMS');
3157
+ }
3158
+ try {
3159
+ const SharedLink = mongoose.models.SharedLink;
3160
+ const result = await SharedLink.findOneAndDelete({ shareId, user }).lean();
3161
+ if (!result) {
3162
+ return null;
3163
+ }
3164
+ return {
3165
+ success: true,
3166
+ shareId,
3167
+ message: 'Share deleted successfully',
3168
+ };
3169
+ }
3170
+ catch (error) {
3171
+ logger.error('[deleteSharedLink] Error deleting shared link', {
3172
+ error: error instanceof Error ? error.message : 'Unknown error',
3173
+ user,
3174
+ shareId,
3175
+ });
3176
+ throw new ShareServiceError('Error deleting shared link', 'SHARE_DELETE_ERROR');
3177
+ }
3178
+ }
3179
+ // Return all methods
3180
+ return {
3181
+ getSharedLink,
3182
+ getSharedLinks,
3183
+ createSharedLink,
3184
+ updateSharedLink,
3185
+ deleteSharedLink,
3186
+ getSharedMessages,
3187
+ deleteAllSharedLinks,
3188
+ };
3189
+ }
3190
+
3191
+ // Factory function that takes mongoose instance and returns the methods
3192
+ function createPluginAuthMethods(mongoose) {
3193
+ const PluginAuth = mongoose.models.PluginAuth;
3194
+ /**
3195
+ * Finds a single plugin auth entry by userId and authField
3196
+ */
3197
+ async function findOnePluginAuth({ userId, authField, }) {
3198
+ try {
3199
+ return await PluginAuth.findOne({ userId, authField }).lean();
3200
+ }
3201
+ catch (error) {
3202
+ throw new Error(`Failed to find plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
3203
+ }
3204
+ }
3205
+ /**
3206
+ * Finds multiple plugin auth entries by userId and pluginKeys
3207
+ */
3208
+ async function findPluginAuthsByKeys({ userId, pluginKeys, }) {
3209
+ try {
3210
+ if (!pluginKeys || pluginKeys.length === 0) {
3211
+ return [];
3212
+ }
3213
+ return await PluginAuth.find({
3214
+ userId,
3215
+ pluginKey: { $in: pluginKeys },
3216
+ }).lean();
3217
+ }
3218
+ catch (error) {
3219
+ throw new Error(`Failed to find plugin auths: ${error instanceof Error ? error.message : 'Unknown error'}`);
3220
+ }
3221
+ }
3222
+ /**
3223
+ * Updates or creates a plugin auth entry
3224
+ */
3225
+ async function updatePluginAuth({ userId, authField, pluginKey, value, }) {
3226
+ try {
3227
+ const existingAuth = await PluginAuth.findOne({ userId, pluginKey, authField }).lean();
3228
+ if (existingAuth) {
3229
+ return await PluginAuth.findOneAndUpdate({ userId, pluginKey, authField }, { $set: { value } }, { new: true, upsert: true }).lean();
3230
+ }
3231
+ else {
3232
+ const newPluginAuth = await new PluginAuth({
3233
+ userId,
3234
+ authField,
3235
+ value,
3236
+ pluginKey,
3237
+ });
3238
+ await newPluginAuth.save();
3239
+ return newPluginAuth.toObject();
3240
+ }
3241
+ }
3242
+ catch (error) {
3243
+ throw new Error(`Failed to update plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
3244
+ }
3245
+ }
3246
+ /**
3247
+ * Deletes plugin auth entries based on provided parameters
3248
+ */
3249
+ async function deletePluginAuth({ userId, authField, pluginKey, all = false, }) {
3250
+ try {
3251
+ if (all) {
3252
+ const filter = { userId };
3253
+ if (pluginKey) {
3254
+ filter.pluginKey = pluginKey;
3255
+ }
3256
+ return await PluginAuth.deleteMany(filter);
3257
+ }
3258
+ if (!authField) {
3259
+ throw new Error('authField is required when all is false');
3260
+ }
3261
+ return await PluginAuth.deleteOne({ userId, authField });
3262
+ }
3263
+ catch (error) {
3264
+ throw new Error(`Failed to delete plugin auth: ${error instanceof Error ? error.message : 'Unknown error'}`);
3265
+ }
3266
+ }
3267
+ /**
3268
+ * Deletes all plugin auth entries for a user
3269
+ */
3270
+ async function deleteAllUserPluginAuths(userId) {
3271
+ try {
3272
+ return await PluginAuth.deleteMany({ userId });
3273
+ }
3274
+ catch (error) {
3275
+ throw new Error(`Failed to delete all user plugin auths: ${error instanceof Error ? error.message : 'Unknown error'}`);
3276
+ }
3277
+ }
3278
+ return {
3279
+ findOnePluginAuth,
3280
+ findPluginAuthsByKeys,
3281
+ updatePluginAuth,
3282
+ deletePluginAuth,
3283
+ deleteAllUserPluginAuths,
3284
+ };
3285
+ }
3286
+
2602
3287
  /**
2603
3288
  * Creates all database methods for all collections
2604
3289
  */
@@ -2608,6 +3293,9 @@ function createMethods(mongoose) {
2608
3293
  ...createSessionMethods(mongoose),
2609
3294
  ...createTokenMethods(mongoose),
2610
3295
  ...createRoleMethods(mongoose),
3296
+ ...createMemoryMethods(mongoose),
3297
+ ...createShareMethods(mongoose),
3298
+ ...createPluginAuthMethods(mongoose),
2611
3299
  };
2612
3300
  }
2613
3301
 
@@ -2626,6 +3314,7 @@ exports.hashToken = hashToken;
2626
3314
  exports.keySchema = keySchema;
2627
3315
  exports.logger = logger;
2628
3316
  exports.meiliLogger = logger$1;
3317
+ exports.memorySchema = MemoryEntrySchema;
2629
3318
  exports.messageSchema = messageSchema;
2630
3319
  exports.pluginAuthSchema = pluginAuthSchema;
2631
3320
  exports.presetSchema = presetSchema;