@mastra/mongodb 1.5.2 → 1.5.3

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.js CHANGED
@@ -12,7 +12,7 @@ import { saveScorePayloadSchema } from '@mastra/core/evals';
12
12
 
13
13
  // package.json
14
14
  var package_default = {
15
- version: "1.5.2"};
15
+ version: "1.5.3"};
16
16
  var MongoDBFilterTranslator = class extends BaseFilterTranslator {
17
17
  getSupportedOperators() {
18
18
  return {
@@ -3640,6 +3640,141 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends MemoryStorage {
3640
3640
  );
3641
3641
  }
3642
3642
  }
3643
+ async cloneThread(args) {
3644
+ const { sourceThreadId, newThreadId: providedThreadId, resourceId, title, metadata, options } = args;
3645
+ const sourceThread = await this.getThreadById({ threadId: sourceThreadId });
3646
+ if (!sourceThread) {
3647
+ throw new MastraError({
3648
+ id: createStorageErrorId("MONGODB", "CLONE_THREAD", "SOURCE_NOT_FOUND"),
3649
+ domain: ErrorDomain.STORAGE,
3650
+ category: ErrorCategory.USER,
3651
+ text: `Source thread with id ${sourceThreadId} not found`,
3652
+ details: { sourceThreadId }
3653
+ });
3654
+ }
3655
+ const newThreadId = providedThreadId || randomUUID();
3656
+ const existingThread = await this.getThreadById({ threadId: newThreadId });
3657
+ if (existingThread) {
3658
+ throw new MastraError({
3659
+ id: createStorageErrorId("MONGODB", "CLONE_THREAD", "THREAD_EXISTS"),
3660
+ domain: ErrorDomain.STORAGE,
3661
+ category: ErrorCategory.USER,
3662
+ text: `Thread with id ${newThreadId} already exists`,
3663
+ details: { newThreadId }
3664
+ });
3665
+ }
3666
+ try {
3667
+ const messagesCollection = await this.getCollection(TABLE_MESSAGES);
3668
+ const filter = { thread_id: sourceThreadId };
3669
+ if (options?.messageFilter?.startDate) {
3670
+ filter.createdAt = filter.createdAt || {};
3671
+ filter.createdAt.$gte = options.messageFilter.startDate instanceof Date ? options.messageFilter.startDate : new Date(options.messageFilter.startDate);
3672
+ }
3673
+ if (options?.messageFilter?.endDate) {
3674
+ filter.createdAt = filter.createdAt || {};
3675
+ filter.createdAt.$lte = options.messageFilter.endDate instanceof Date ? options.messageFilter.endDate : new Date(options.messageFilter.endDate);
3676
+ }
3677
+ if (options?.messageFilter?.messageIds && options.messageFilter.messageIds.length > 0) {
3678
+ filter.id = { $in: options.messageFilter.messageIds };
3679
+ }
3680
+ let query = messagesCollection.find(filter).sort({ createdAt: 1 });
3681
+ let sourceMessages;
3682
+ if (options?.messageLimit && options.messageLimit > 0) {
3683
+ const limited = await messagesCollection.find(filter).sort({ createdAt: -1 }).limit(options.messageLimit).toArray();
3684
+ sourceMessages = limited.reverse();
3685
+ } else {
3686
+ sourceMessages = await query.toArray();
3687
+ }
3688
+ const now = /* @__PURE__ */ new Date();
3689
+ const targetResourceId = resourceId || sourceThread.resourceId;
3690
+ const lastMessageId = sourceMessages.length > 0 ? sourceMessages[sourceMessages.length - 1].id : void 0;
3691
+ const cloneMetadata = {
3692
+ sourceThreadId,
3693
+ clonedAt: now,
3694
+ ...lastMessageId && { lastMessageId }
3695
+ };
3696
+ const newThread = {
3697
+ id: newThreadId,
3698
+ resourceId: targetResourceId,
3699
+ title: title || (sourceThread.title ? `Clone of ${sourceThread.title}` : ""),
3700
+ metadata: {
3701
+ ...metadata,
3702
+ clone: cloneMetadata
3703
+ },
3704
+ createdAt: now,
3705
+ updatedAt: now
3706
+ };
3707
+ const threadsCollection = await this.getCollection(TABLE_THREADS);
3708
+ await threadsCollection.insertOne({ ...newThread });
3709
+ const clonedMessages = [];
3710
+ const messageIdMap = {};
3711
+ if (sourceMessages.length > 0) {
3712
+ const messageDocs = [];
3713
+ for (const sourceMsg of sourceMessages) {
3714
+ const newMessageId = randomUUID();
3715
+ messageIdMap[sourceMsg.id] = newMessageId;
3716
+ let parsedContent = sourceMsg.content;
3717
+ if (typeof parsedContent === "string") {
3718
+ try {
3719
+ parsedContent = JSON.parse(parsedContent);
3720
+ } catch {
3721
+ parsedContent = { format: 2, parts: [{ type: "text", text: parsedContent }] };
3722
+ }
3723
+ }
3724
+ const newDoc = {
3725
+ id: newMessageId,
3726
+ thread_id: newThreadId,
3727
+ content: sourceMsg.content,
3728
+ role: sourceMsg.role,
3729
+ type: sourceMsg.type || "v2",
3730
+ createdAt: sourceMsg.createdAt,
3731
+ resourceId: targetResourceId
3732
+ };
3733
+ messageDocs.push(newDoc);
3734
+ clonedMessages.push({
3735
+ id: newMessageId,
3736
+ threadId: newThreadId,
3737
+ content: parsedContent,
3738
+ role: sourceMsg.role,
3739
+ type: sourceMsg.type || "v2",
3740
+ createdAt: formatDateForMongoDB(sourceMsg.createdAt),
3741
+ resourceId: targetResourceId
3742
+ });
3743
+ }
3744
+ try {
3745
+ await messagesCollection.insertMany(messageDocs);
3746
+ } catch (msgError) {
3747
+ try {
3748
+ await messagesCollection.deleteMany({ thread_id: newThreadId });
3749
+ } catch {
3750
+ }
3751
+ try {
3752
+ await threadsCollection.deleteOne({ id: newThreadId });
3753
+ } catch {
3754
+ }
3755
+ throw msgError;
3756
+ }
3757
+ }
3758
+ return {
3759
+ thread: newThread,
3760
+ clonedMessages,
3761
+ messageIdMap
3762
+ };
3763
+ } catch (error) {
3764
+ if (error instanceof MastraError) {
3765
+ throw error;
3766
+ }
3767
+ throw new MastraError(
3768
+ {
3769
+ id: createStorageErrorId("MONGODB", "CLONE_THREAD", "FAILED"),
3770
+ domain: ErrorDomain.STORAGE,
3771
+ category: ErrorCategory.THIRD_PARTY,
3772
+ details: { sourceThreadId, newThreadId }
3773
+ },
3774
+ error
3775
+ );
3776
+ }
3777
+ }
3643
3778
  // ============================================
3644
3779
  // Observational Memory Methods
3645
3780
  // ============================================
@@ -3789,6 +3924,55 @@ var MemoryStorageMongoDB = class _MemoryStorageMongoDB extends MemoryStorage {
3789
3924
  );
3790
3925
  }
3791
3926
  }
3927
+ async insertObservationalMemoryRecord(record) {
3928
+ try {
3929
+ const lookupKey = this.getOMKey(record.threadId, record.resourceId);
3930
+ const collection = await this.getCollection(OM_TABLE);
3931
+ await collection.insertOne({
3932
+ id: record.id,
3933
+ lookupKey,
3934
+ scope: record.scope,
3935
+ resourceId: record.resourceId,
3936
+ threadId: record.threadId || null,
3937
+ activeObservations: record.activeObservations || "",
3938
+ activeObservationsPendingUpdate: null,
3939
+ originType: record.originType || "initial",
3940
+ config: record.config || null,
3941
+ generationCount: record.generationCount || 0,
3942
+ lastObservedAt: record.lastObservedAt || null,
3943
+ lastReflectionAt: null,
3944
+ pendingMessageTokens: record.pendingMessageTokens || 0,
3945
+ totalTokensObserved: record.totalTokensObserved || 0,
3946
+ observationTokenCount: record.observationTokenCount || 0,
3947
+ observedMessageIds: record.observedMessageIds || null,
3948
+ bufferedObservationChunks: record.bufferedObservationChunks || null,
3949
+ bufferedReflection: record.bufferedReflection || null,
3950
+ bufferedReflectionTokens: record.bufferedReflectionTokens ?? null,
3951
+ bufferedReflectionInputTokens: record.bufferedReflectionInputTokens ?? null,
3952
+ reflectedObservationLineCount: record.reflectedObservationLineCount ?? null,
3953
+ isObserving: record.isObserving || false,
3954
+ isReflecting: record.isReflecting || false,
3955
+ isBufferingObservation: record.isBufferingObservation || false,
3956
+ isBufferingReflection: record.isBufferingReflection || false,
3957
+ lastBufferedAtTokens: record.lastBufferedAtTokens || 0,
3958
+ lastBufferedAtTime: record.lastBufferedAtTime || null,
3959
+ observedTimezone: record.observedTimezone || null,
3960
+ metadata: record.metadata || null,
3961
+ createdAt: record.createdAt,
3962
+ updatedAt: record.updatedAt
3963
+ });
3964
+ } catch (error) {
3965
+ throw new MastraError(
3966
+ {
3967
+ id: createStorageErrorId("MONGODB", "INSERT_OBSERVATIONAL_MEMORY_RECORD", "FAILED"),
3968
+ domain: ErrorDomain.STORAGE,
3969
+ category: ErrorCategory.THIRD_PARTY,
3970
+ details: { id: record.id, threadId: record.threadId, resourceId: record.resourceId }
3971
+ },
3972
+ error
3973
+ );
3974
+ }
3975
+ }
3792
3976
  async updateActiveObservations(input) {
3793
3977
  try {
3794
3978
  const now = /* @__PURE__ */ new Date();
@@ -7192,6 +7376,9 @@ var WorkflowsStorageMongoDB = class _WorkflowsStorageMongoDB extends WorkflowsSt
7192
7376
  (idx) => _WorkflowsStorageMongoDB.MANAGED_COLLECTIONS.includes(idx.collection)
7193
7377
  );
7194
7378
  }
7379
+ supportsConcurrentUpdates() {
7380
+ return true;
7381
+ }
7195
7382
  async getCollection(name) {
7196
7383
  return this.#connector.getCollection(name);
7197
7384
  }
@@ -7248,21 +7435,128 @@ var WorkflowsStorageMongoDB = class _WorkflowsStorageMongoDB extends WorkflowsSt
7248
7435
  const collection = await this.getCollection(TABLE_WORKFLOW_SNAPSHOT);
7249
7436
  await collection.deleteMany({});
7250
7437
  }
7251
- updateWorkflowResults({
7252
- // workflowName,
7253
- // runId,
7254
- // stepId,
7255
- // result,
7256
- // requestContext,
7438
+ async updateWorkflowResults({
7439
+ workflowName,
7440
+ runId,
7441
+ stepId,
7442
+ result,
7443
+ requestContext
7257
7444
  }) {
7258
- throw new Error("Method not implemented.");
7445
+ try {
7446
+ const collection = await this.getCollection(TABLE_WORKFLOW_SNAPSHOT);
7447
+ const now = /* @__PURE__ */ new Date();
7448
+ const defaultSnapshot = {
7449
+ context: {},
7450
+ activePaths: [],
7451
+ timestamp: Date.now(),
7452
+ suspendedPaths: {},
7453
+ activeStepsPath: {},
7454
+ resumeLabels: {},
7455
+ serializedStepGraph: [],
7456
+ status: "pending",
7457
+ value: {},
7458
+ waitingPaths: {},
7459
+ runId,
7460
+ requestContext: {}
7461
+ };
7462
+ const updatedDoc = await collection.findOneAndUpdate(
7463
+ { workflow_name: workflowName, run_id: runId },
7464
+ [
7465
+ {
7466
+ $set: {
7467
+ workflow_name: workflowName,
7468
+ run_id: runId,
7469
+ // If snapshot doesn't exist, use default; otherwise merge
7470
+ snapshot: {
7471
+ $mergeObjects: [
7472
+ // Start with default snapshot if document is new
7473
+ { $ifNull: ["$snapshot", defaultSnapshot] },
7474
+ // Merge the new context entry
7475
+ {
7476
+ context: {
7477
+ $mergeObjects: [{ $ifNull: [{ $ifNull: ["$snapshot.context", {}] }, {}] }, { [stepId]: result }]
7478
+ }
7479
+ },
7480
+ // Merge the new request context
7481
+ {
7482
+ requestContext: {
7483
+ $mergeObjects: [{ $ifNull: [{ $ifNull: ["$snapshot.requestContext", {}] }, {}] }, requestContext]
7484
+ }
7485
+ }
7486
+ ]
7487
+ },
7488
+ updatedAt: now,
7489
+ // Only set createdAt if it doesn't exist
7490
+ createdAt: { $ifNull: ["$createdAt", now] }
7491
+ }
7492
+ }
7493
+ ],
7494
+ { upsert: true, returnDocument: "after" }
7495
+ );
7496
+ const snapshot = typeof updatedDoc?.snapshot === "string" ? JSON.parse(updatedDoc.snapshot) : updatedDoc?.snapshot;
7497
+ return snapshot?.context || {};
7498
+ } catch (error) {
7499
+ throw new MastraError(
7500
+ {
7501
+ id: createStorageErrorId("MONGODB", "UPDATE_WORKFLOW_RESULTS", "FAILED"),
7502
+ domain: ErrorDomain.STORAGE,
7503
+ category: ErrorCategory.THIRD_PARTY,
7504
+ details: {
7505
+ workflowName,
7506
+ runId,
7507
+ stepId
7508
+ }
7509
+ },
7510
+ error
7511
+ );
7512
+ }
7259
7513
  }
7260
- updateWorkflowState({
7261
- // workflowName,
7262
- // runId,
7263
- // opts,
7514
+ async updateWorkflowState({
7515
+ workflowName,
7516
+ runId,
7517
+ opts
7264
7518
  }) {
7265
- throw new Error("Method not implemented.");
7519
+ try {
7520
+ const collection = await this.getCollection(TABLE_WORKFLOW_SNAPSHOT);
7521
+ const updatedDoc = await collection.findOneAndUpdate(
7522
+ {
7523
+ workflow_name: workflowName,
7524
+ run_id: runId,
7525
+ // Only update if snapshot exists and has context
7526
+ "snapshot.context": { $exists: true }
7527
+ },
7528
+ [
7529
+ {
7530
+ $set: {
7531
+ // Merge the new options into the existing snapshot
7532
+ snapshot: {
7533
+ $mergeObjects: ["$snapshot", opts]
7534
+ },
7535
+ updatedAt: /* @__PURE__ */ new Date()
7536
+ }
7537
+ }
7538
+ ],
7539
+ { returnDocument: "after" }
7540
+ );
7541
+ if (!updatedDoc) {
7542
+ return void 0;
7543
+ }
7544
+ const snapshot = typeof updatedDoc.snapshot === "string" ? JSON.parse(updatedDoc.snapshot) : updatedDoc.snapshot;
7545
+ return snapshot;
7546
+ } catch (error) {
7547
+ throw new MastraError(
7548
+ {
7549
+ id: createStorageErrorId("MONGODB", "UPDATE_WORKFLOW_STATE", "FAILED"),
7550
+ domain: ErrorDomain.STORAGE,
7551
+ category: ErrorCategory.THIRD_PARTY,
7552
+ details: {
7553
+ workflowName,
7554
+ runId
7555
+ }
7556
+ },
7557
+ error
7558
+ );
7559
+ }
7266
7560
  }
7267
7561
  async persistWorkflowSnapshot({
7268
7562
  workflowName,