@mastra/convex 1.7.2 → 1.7.3-alpha.1

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.
Files changed (42) hide show
  1. package/dist/_types/@internal_core/dist/memory/index.d.ts +102 -0
  2. package/dist/_types/@internal_core/package.json +1 -0
  3. package/dist/docs/SKILL.md +1 -1
  4. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  5. package/dist/docs/references/reference-vectors-convex.md +1 -3
  6. package/dist/index.cjs +370 -161
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.js +371 -162
  9. package/dist/index.js.map +1 -1
  10. package/dist/schema.cjs +1 -0
  11. package/dist/schema.cjs.map +1 -1
  12. package/dist/schema.d.ts +3 -1
  13. package/dist/schema.d.ts.map +1 -1
  14. package/dist/schema.js +1 -0
  15. package/dist/schema.js.map +1 -1
  16. package/dist/server/index.cjs +1 -1
  17. package/dist/server/index.js +1 -1
  18. package/dist/server/observational-memory.d.ts +26 -1
  19. package/dist/server/observational-memory.d.ts.map +1 -1
  20. package/dist/server/run-fencing.d.ts +14 -0
  21. package/dist/server/run-fencing.d.ts.map +1 -0
  22. package/dist/server/storage.d.ts +2 -2
  23. package/dist/server/storage.d.ts.map +1 -1
  24. package/dist/{server-D3SG5LQf.js → server-B8RSiOmu.js} +454 -56
  25. package/dist/server-B8RSiOmu.js.map +1 -0
  26. package/dist/{server-D_scBUwi.cjs → server-Bcgr5CcA.cjs} +454 -56
  27. package/dist/server-Bcgr5CcA.cjs.map +1 -0
  28. package/dist/storage/client.d.ts +3 -3
  29. package/dist/storage/client.d.ts.map +1 -1
  30. package/dist/storage/db/index.d.ts +33 -6
  31. package/dist/storage/db/index.d.ts.map +1 -1
  32. package/dist/storage/domains/memory/index.d.ts +20 -7
  33. package/dist/storage/domains/memory/index.d.ts.map +1 -1
  34. package/dist/storage/domains/workflows/index.d.ts +16 -5
  35. package/dist/storage/domains/workflows/index.d.ts.map +1 -1
  36. package/dist/storage/run-fencing.d.ts +28 -0
  37. package/dist/storage/run-fencing.d.ts.map +1 -0
  38. package/dist/storage/types.d.ts +114 -1
  39. package/dist/storage/types.d.ts.map +1 -1
  40. package/package.json +5 -4
  41. package/dist/server-D3SG5LQf.js.map +0 -1
  42. package/dist/server-D_scBUwi.cjs.map +0 -1
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_server = require("./server-D_scBUwi.cjs");
2
+ const require_server = require("./server-Bcgr5CcA.cjs");
3
3
  const require_schema = require("./schema.cjs");
4
4
  let _mastra_core_cache = require("@mastra/core/cache");
5
5
  let _mastra_core_storage = require("@mastra/core/storage");
@@ -254,6 +254,154 @@ var ConvexAdminClient = class {
254
254
  }
255
255
  };
256
256
  //#endregion
257
+ //#region src/storage/run-fencing.ts
258
+ const READ_OPS = /* @__PURE__ */ new Set([
259
+ "load",
260
+ "loadMany",
261
+ "queryTable",
262
+ "omGetLatest",
263
+ "omGetHistory",
264
+ "listDueSchedules",
265
+ "listScheduleTriggers"
266
+ ]);
267
+ async function callRunClaim(client, request, operation) {
268
+ try {
269
+ return await client.callStorageRaw(request);
270
+ } catch (error) {
271
+ const { code, message } = error;
272
+ if (code === _mastra_core_storage.RUN_FENCE_CONFLICT_ERROR_ID && request.op === "fenced") throw new _mastra_core_storage.RunFenceConflictError(request.fence, operation);
273
+ if (typeof message === "string" && message.startsWith(`Unsupported operation ${request.op}`)) throw new Error(`The deployed Convex storage function does not support run fencing (${request.op}). Redeploy your Convex functions with the installed version of @mastra/convex.`, { cause: error });
274
+ throw error;
275
+ }
276
+ }
277
+ /** Sends writes inside a fenced operation, so each is applied only while `check.fence` holds the run. */
278
+ var FencedStorageCaller = class {
279
+ client;
280
+ check;
281
+ constructor(client, check) {
282
+ this.client = client;
283
+ this.check = check;
284
+ }
285
+ callStorageRaw(request) {
286
+ if (READ_OPS.has(request.op)) return this.client.callStorageRaw(request);
287
+ return callRunClaim(this.client, {
288
+ op: "fenced",
289
+ tableName: this.check.claims,
290
+ fence: toFence(this.check.fence),
291
+ request
292
+ }, this.check.operation);
293
+ }
294
+ async callStorage(request) {
295
+ return (await this.callStorageRaw(request)).result;
296
+ }
297
+ };
298
+ /** The client, or one that fences every write when `check` is set. */
299
+ function fencedCaller(client, check) {
300
+ return check ? new FencedStorageCaller(client, check) : client;
301
+ }
302
+ /**
303
+ * Rejects a fenced write that turns out to have nothing to write when its
304
+ * fence is no longer current, as the write itself would have been rejected.
305
+ */
306
+ async function assertRunFence(client, check) {
307
+ if (!check) return;
308
+ await callRunClaim(client, {
309
+ op: "fenced",
310
+ tableName: check.claims,
311
+ fence: toFence(check.fence)
312
+ }, check.operation);
313
+ }
314
+ function toFence({ runId, generation, ownerId }) {
315
+ return {
316
+ runId,
317
+ generation,
318
+ ownerId
319
+ };
320
+ }
321
+ function toRecord(claim, now) {
322
+ if (!claim) return null;
323
+ const { runId, generation, ownerId, leaseExpiresAt } = claim;
324
+ return {
325
+ runId,
326
+ generation,
327
+ ownerId,
328
+ leaseExpiresAt: leaseExpiresAt === null ? null : new Date(leaseExpiresAt),
329
+ live: leaseExpiresAt !== null && leaseExpiresAt > now
330
+ };
331
+ }
332
+ async function ownerOperation(client, request) {
333
+ const { result } = await callRunClaim(client, request, request.op);
334
+ return {
335
+ applied: result.applied,
336
+ record: toRecord(result.claim, result.now)
337
+ };
338
+ }
339
+ async function claimRunOwnership(client, { runId, ownerId, leaseMs, force, expectedGeneration }) {
340
+ const { applied, record } = await ownerOperation(client, {
341
+ op: "claimRunOwnership",
342
+ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
343
+ runId,
344
+ ownerId,
345
+ leaseMs,
346
+ force: force ?? false,
347
+ ...expectedGeneration !== void 0 ? { expectedGeneration } : {}
348
+ });
349
+ return applied ? {
350
+ acquired: true,
351
+ record
352
+ } : {
353
+ acquired: false,
354
+ record
355
+ };
356
+ }
357
+ async function renewRunOwnership(client, { leaseMs, ...fence }) {
358
+ const { applied, record } = await ownerOperation(client, {
359
+ op: "renewRunOwnership",
360
+ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
361
+ fence: toFence(fence),
362
+ leaseMs
363
+ });
364
+ return applied ? {
365
+ renewed: true,
366
+ record
367
+ } : {
368
+ renewed: false,
369
+ record
370
+ };
371
+ }
372
+ async function releaseRunOwnership(client, fence) {
373
+ const { applied } = await ownerOperation(client, {
374
+ op: "releaseRunOwnership",
375
+ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
376
+ fence: toFence(fence)
377
+ });
378
+ return applied;
379
+ }
380
+ async function getRunOwnership(client, runId) {
381
+ const { record } = await ownerOperation(client, {
382
+ op: "getRunOwnership",
383
+ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
384
+ runId
385
+ });
386
+ return record;
387
+ }
388
+ async function raiseRunFence(client, fence) {
389
+ const { applied } = await ownerOperation(client, {
390
+ op: "raiseRunFence",
391
+ tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
392
+ fence: toFence(fence)
393
+ });
394
+ return applied;
395
+ }
396
+ async function retireRunFence(client, fence) {
397
+ const { applied } = await ownerOperation(client, {
398
+ op: "retireRunFence",
399
+ tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
400
+ fence: toFence(fence)
401
+ });
402
+ return applied;
403
+ }
404
+ //#endregion
257
405
  //#region src/storage/types.ts
258
406
  /**
259
407
  * Observational memory table name. Defined locally (not value-imported from
@@ -272,11 +420,17 @@ function resolveConvexConfig(config) {
272
420
  if ("client" in config) return config.client;
273
421
  return new ConvexAdminClient(config);
274
422
  }
275
- var ConvexDB = class extends _mastra_core_base.MastraBase {
423
+ var ConvexDB = class ConvexDB extends _mastra_core_base.MastraBase {
424
+ adminClient;
276
425
  client;
277
- constructor(client) {
426
+ constructor(adminClient, check) {
278
427
  super({ name: "convex-db" });
279
- this.client = client;
428
+ this.adminClient = adminClient;
429
+ this.client = fencedCaller(adminClient, check);
430
+ }
431
+ /** This store with every write applied only while `check.fence` holds the run, or itself without a check. */
432
+ fenced(check) {
433
+ return check ? new ConvexDB(this.adminClient, check) : this;
280
434
  }
281
435
  async hasColumn(_table, _column) {
282
436
  return true;
@@ -489,15 +643,43 @@ var ConvexDB = class extends _mastra_core_base.MastraBase {
489
643
  ...args
490
644
  });
491
645
  }
492
- async omUpdateActive(args) {
646
+ async omInitialize(record) {
647
+ return this.client.callStorage({
648
+ op: "omInitialize",
649
+ tableName: TABLE_OBSERVATIONAL_MEMORY$1,
650
+ record
651
+ });
652
+ }
653
+ async omCreateReflectionGeneration(args) {
654
+ return this.client.callStorage({
655
+ op: "omCreateReflectionGeneration",
656
+ tableName: TABLE_OBSERVATIONAL_MEMORY$1,
657
+ ...args
658
+ });
659
+ }
660
+ async omSetPendingMessageTokens(args) {
493
661
  await this.client.callStorage({
662
+ op: "omSetPendingMessageTokens",
663
+ tableName: TABLE_OBSERVATIONAL_MEMORY$1,
664
+ ...args
665
+ });
666
+ }
667
+ async omSetBufferingObservationFlag(args) {
668
+ await this.client.callStorage({
669
+ op: "omSetBufferingObservationFlag",
670
+ tableName: TABLE_OBSERVATIONAL_MEMORY$1,
671
+ ...args
672
+ });
673
+ }
674
+ async omUpdateActive(args) {
675
+ return this.client.callStorage({
494
676
  op: "omUpdateActive",
495
677
  tableName: TABLE_OBSERVATIONAL_MEMORY$1,
496
678
  ...args
497
679
  });
498
680
  }
499
681
  async omAppendBufferedChunk(args) {
500
- await this.client.callStorage({
682
+ return this.client.callStorage({
501
683
  op: "omAppendBufferedChunk",
502
684
  tableName: TABLE_OBSERVATIONAL_MEMORY$1,
503
685
  ...args
@@ -902,6 +1084,17 @@ var ChannelsConvex = class extends _mastra_core_storage.ChannelsStorage {
902
1084
  }
903
1085
  };
904
1086
  //#endregion
1087
+ //#region ../../packages/_internal-core/dist/memory/index.js
1088
+ /**
1089
+ * Backs `updateActiveObservations` in adapters that implement `commitActiveObservations`.
1090
+ * Callers of `updateActiveObservations` (which resolves `void`) can't see a commit result, so a
1091
+ * write that was not applied throws instead of resolving as if it had committed.
1092
+ */
1093
+ function assertActiveObservationsApplied(result, id) {
1094
+ if (result.applied) return;
1095
+ throw new Error(result.reason === "retired" ? `Observational memory record ${id} was superseded by a newer generation; observations were not written` : `Observational memory record ${id} changed since the observations were composed; observations were not written`);
1096
+ }
1097
+ //#endregion
905
1098
  //#region src/storage/domains/memory/index.ts
906
1099
  function parseStoredThread(row) {
907
1100
  return {
@@ -977,7 +1170,8 @@ function parseStoredOMRecord(doc) {
977
1170
  config: config ?? {},
978
1171
  metadata: metadata ?? void 0,
979
1172
  observedMessageIds: doc.observedMessageIds || void 0,
980
- observedTimezone: doc.observedTimezone || void 0
1173
+ observedTimezone: doc.observedTimezone || void 0,
1174
+ supersededBy: doc.supersededBy ?? null
981
1175
  };
982
1176
  }
983
1177
  var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
@@ -985,10 +1179,32 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
985
1179
  supportsObservationalMemory = true;
986
1180
  supportsObservationalMemoryHistorySearch = true;
987
1181
  #db;
1182
+ #client;
988
1183
  constructor(config) {
989
1184
  super();
990
- const client = resolveConvexConfig(config);
991
- this.#db = new ConvexDB(client);
1185
+ this.#client = resolveConvexConfig(config);
1186
+ this.#db = new ConvexDB(this.#client);
1187
+ }
1188
+ supportsRunFencing() {
1189
+ return true;
1190
+ }
1191
+ async raiseRunFence(fence) {
1192
+ return raiseRunFence(this.#client, fence);
1193
+ }
1194
+ async retireRunFence(fence) {
1195
+ return retireRunFence(this.#client, fence);
1196
+ }
1197
+ #runFenceCheck(fence, operation) {
1198
+ const resolved = (0, _mastra_core_storage.resolveRunFence)(this, fence);
1199
+ return resolved && {
1200
+ claims: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
1201
+ fence: resolved,
1202
+ operation
1203
+ };
1204
+ }
1205
+ /** The store to write through: fenced when the write carries or inherits a fence. */
1206
+ #dbFor(fence, operation) {
1207
+ return this.#db.fenced(this.#runFenceCheck(fence, operation));
992
1208
  }
993
1209
  async init() {}
994
1210
  async dangerouslyClearAll() {
@@ -996,6 +1212,7 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
996
1212
  await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_MESSAGES });
997
1213
  await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_RESOURCES });
998
1214
  await this.#db.clearTable({ tableName: TABLE_OBSERVATIONAL_MEMORY$1 });
1215
+ await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES });
999
1216
  }
1000
1217
  async getThreadById({ threadId, resourceId }) {
1001
1218
  const row = await this.#db.load({
@@ -1005,8 +1222,8 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1005
1222
  if (!row || resourceId !== void 0 && row.resourceId !== resourceId) return null;
1006
1223
  return parseStoredThread(row);
1007
1224
  }
1008
- async saveThread({ thread }) {
1009
- await this.#db.insert({
1225
+ async saveThread({ thread, fence }) {
1226
+ await this.#dbFor(fence, "saveThread").insert({
1010
1227
  tableName: _mastra_core_storage.TABLE_THREADS,
1011
1228
  record: {
1012
1229
  ...thread,
@@ -1015,8 +1232,8 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1015
1232
  });
1016
1233
  return thread;
1017
1234
  }
1018
- async updateThread({ id, title, metadata }) {
1019
- const updated = await this.#db.updateThread({
1235
+ async updateThread({ id, title, metadata, fence }) {
1236
+ const updated = await this.#dbFor(fence, "updateThread").updateThread({
1020
1237
  id,
1021
1238
  title,
1022
1239
  metadata,
@@ -1206,8 +1423,9 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1206
1423
  const filtered = (await this.#db.loadMany(_mastra_core_storage.TABLE_MESSAGES, messageIds)).map((row) => this.parseStoredMessage(row));
1207
1424
  return { messages: new _mastra_core_agent.MessageList().add(filtered, "memory").get.all.db() };
1208
1425
  }
1209
- async saveMessages({ messages }) {
1426
+ async saveMessages({ messages, fence }) {
1210
1427
  if (messages.length === 0) return { messages: [] };
1428
+ const db = this.#dbFor(fence, "saveMessages");
1211
1429
  const normalized = messages.map((message) => {
1212
1430
  if (!message.threadId) throw new Error("Thread ID is required");
1213
1431
  if (!message.resourceId) throw new Error("Resource ID is required");
@@ -1222,21 +1440,23 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1222
1440
  resourceId: message.resourceId
1223
1441
  };
1224
1442
  });
1225
- await this.#db.batchInsert({
1443
+ await db.batchInsert({
1226
1444
  tableName: _mastra_core_storage.TABLE_MESSAGES,
1227
1445
  records: normalized
1228
1446
  });
1229
1447
  const threadIds = [...new Set(messages.map((m) => m.threadId).filter(Boolean))];
1230
1448
  const now = /* @__PURE__ */ new Date();
1231
- for (const threadId of threadIds) await this.#db.patch({
1449
+ for (const threadId of threadIds) await db.patch({
1232
1450
  tableName: _mastra_core_storage.TABLE_THREADS,
1233
1451
  id: threadId,
1234
1452
  record: { updatedAt: now.toISOString() }
1235
1453
  });
1236
1454
  return { messages: new _mastra_core_agent.MessageList().add(messages, "memory").get.all.db() };
1237
1455
  }
1238
- async updateMessages({ messages }) {
1456
+ async updateMessages({ messages, fence }) {
1239
1457
  if (messages.length === 0) return [];
1458
+ const check = this.#runFenceCheck(fence, "updateMessages");
1459
+ const db = this.#db.fenced(check);
1240
1460
  const existingRows = await this.#db.loadMany(_mastra_core_storage.TABLE_MESSAGES, messages.map((message) => message.id));
1241
1461
  const existing = new Map(existingRows.map((row) => [row.id, row]));
1242
1462
  const updated = [];
@@ -1264,22 +1484,26 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1264
1484
  };
1265
1485
  current.content = JSON.stringify(mergedContent);
1266
1486
  }
1267
- await this.#db.insert({
1487
+ await db.insert({
1268
1488
  tableName: _mastra_core_storage.TABLE_MESSAGES,
1269
1489
  record: current
1270
1490
  });
1271
1491
  updated.push(this.parseStoredMessage(current));
1272
1492
  }
1493
+ if (updated.length === 0) {
1494
+ await assertRunFence(this.#client, check);
1495
+ return updated;
1496
+ }
1273
1497
  const now = /* @__PURE__ */ new Date();
1274
- for (const threadId of affectedThreadIds) await this.#db.patch({
1498
+ for (const threadId of affectedThreadIds) await db.patch({
1275
1499
  tableName: _mastra_core_storage.TABLE_THREADS,
1276
1500
  id: threadId,
1277
1501
  record: { updatedAt: now.toISOString() }
1278
1502
  });
1279
1503
  return updated;
1280
1504
  }
1281
- async deleteMessages(messageIds) {
1282
- await this.#db.deleteMany(_mastra_core_storage.TABLE_MESSAGES, messageIds);
1505
+ async deleteMessages(messageIds, options) {
1506
+ await this.#dbFor(options?.fence, "deleteMessages").deleteMany(_mastra_core_storage.TABLE_MESSAGES, messageIds);
1283
1507
  }
1284
1508
  async saveResource({ resource }) {
1285
1509
  const record = {
@@ -1302,9 +1526,9 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1302
1526
  if (!record) return null;
1303
1527
  return parseStoredResource(record);
1304
1528
  }
1305
- async updateResource({ resourceId, workingMemory, metadata }) {
1529
+ async updateResource({ resourceId, workingMemory, metadata, fence }) {
1306
1530
  const now = /* @__PURE__ */ new Date();
1307
- return parseStoredResource(await this.#db.updateResource({
1531
+ return parseStoredResource(await this.#dbFor(fence, "updateResource").updateResource({
1308
1532
  resourceId,
1309
1533
  workingMemory,
1310
1534
  metadata,
@@ -1465,9 +1689,9 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1465
1689
  })).map((doc) => parseStoredOMRecord(doc));
1466
1690
  }
1467
1691
  async initializeObservationalMemory(input) {
1468
- const id = crypto.randomUUID();
1469
1692
  const now = /* @__PURE__ */ new Date();
1470
1693
  const lookupKey = this.getOMKey(input.threadId, input.resourceId);
1694
+ const id = crypto.randomUUID();
1471
1695
  const record = {
1472
1696
  id,
1473
1697
  scope: input.scope,
@@ -1489,38 +1713,36 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1489
1713
  lastBufferedAtTokens: 0,
1490
1714
  lastBufferedAtTime: null,
1491
1715
  config: input.config,
1492
- observedTimezone: input.observedTimezone
1716
+ observedTimezone: input.observedTimezone,
1717
+ supersededBy: null
1493
1718
  };
1494
- await this.#db.insert({
1495
- tableName: TABLE_OBSERVATIONAL_MEMORY$1,
1496
- record: {
1497
- id,
1498
- lookupKey,
1499
- scope: input.scope,
1500
- resourceId: input.resourceId,
1501
- threadId: input.threadId || null,
1502
- activeObservations: "",
1503
- activeObservationsPendingUpdate: null,
1504
- originType: "initial",
1505
- config: JSON.stringify(input.config ?? {}),
1506
- generationCount: 0,
1507
- lastObservedAt: null,
1508
- lastReflectionAt: null,
1509
- pendingMessageTokens: 0,
1510
- totalTokensObserved: 0,
1511
- observationTokenCount: 0,
1512
- isObserving: false,
1513
- isReflecting: false,
1514
- isBufferingObservation: false,
1515
- isBufferingReflection: false,
1516
- lastBufferedAtTokens: 0,
1517
- lastBufferedAtTime: null,
1518
- observedTimezone: input.observedTimezone || null,
1519
- createdAt: now.toISOString(),
1520
- updatedAt: now.toISOString()
1521
- }
1719
+ const doc = await this.#db.omInitialize({
1720
+ id,
1721
+ lookupKey,
1722
+ scope: input.scope,
1723
+ resourceId: input.resourceId,
1724
+ threadId: input.threadId || null,
1725
+ activeObservations: "",
1726
+ activeObservationsPendingUpdate: null,
1727
+ originType: "initial",
1728
+ config: JSON.stringify(input.config ?? {}),
1729
+ generationCount: 0,
1730
+ lastObservedAt: null,
1731
+ lastReflectionAt: null,
1732
+ pendingMessageTokens: 0,
1733
+ totalTokensObserved: 0,
1734
+ observationTokenCount: 0,
1735
+ isObserving: false,
1736
+ isReflecting: false,
1737
+ isBufferingObservation: false,
1738
+ isBufferingReflection: false,
1739
+ lastBufferedAtTokens: 0,
1740
+ lastBufferedAtTime: null,
1741
+ observedTimezone: input.observedTimezone || null,
1742
+ createdAt: now.toISOString(),
1743
+ updatedAt: now.toISOString()
1522
1744
  });
1523
- return record;
1745
+ return doc ? parseStoredOMRecord(doc) : record;
1524
1746
  }
1525
1747
  async insertObservationalMemoryRecord(record) {
1526
1748
  const lookupKey = this.getOMKey(record.threadId, record.resourceId);
@@ -1556,22 +1778,30 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1556
1778
  lastBufferedAtTime: record.lastBufferedAtTime ? toISO(record.lastBufferedAtTime) : null,
1557
1779
  observedTimezone: record.observedTimezone || null,
1558
1780
  metadata: record.metadata ? JSON.stringify(record.metadata) : null,
1781
+ supersededBy: record.supersededBy ?? null,
1559
1782
  createdAt: toISO(record.createdAt),
1560
1783
  updatedAt: toISO(record.updatedAt)
1561
1784
  }
1562
1785
  });
1563
1786
  }
1564
1787
  async updateActiveObservations(input) {
1565
- await this.#db.omUpdateActive({
1788
+ assertActiveObservationsApplied(await this.commitActiveObservations(input), input.id);
1789
+ }
1790
+ async commitActiveObservations(input) {
1791
+ return await this.#dbFor(void 0, "commitActiveObservations").omUpdateActive({
1566
1792
  id: input.id,
1567
1793
  observations: input.observations,
1568
1794
  tokenCount: input.tokenCount,
1569
1795
  lastObservedAt: toISO(input.lastObservedAt),
1570
1796
  observedMessageIds: input.observedMessageIds ?? null,
1571
- updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1572
- });
1797
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1798
+ ...input.expectedActiveObservations !== void 0 ? { expectedActiveObservations: input.expectedActiveObservations } : {}
1799
+ }) ?? { applied: true };
1573
1800
  }
1574
1801
  async updateBufferedObservations(input) {
1802
+ await this.appendBufferedObservations(input);
1803
+ }
1804
+ async appendBufferedObservations(input) {
1575
1805
  const chunk = {
1576
1806
  id: `ombuf-${crypto.randomUUID()}`,
1577
1807
  cycleId: input.chunk.cycleId,
@@ -1587,15 +1817,18 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1587
1817
  extractedValues: input.chunk.extractedValues,
1588
1818
  extractionFailures: input.chunk.extractionFailures
1589
1819
  };
1590
- await this.#db.omAppendBufferedChunk({
1820
+ return await this.#dbFor(void 0, "appendBufferedObservations").omAppendBufferedChunk({
1591
1821
  id: input.id,
1592
1822
  chunk,
1593
1823
  lastBufferedAtTime: input.lastBufferedAtTime ? toISO(input.lastBufferedAtTime) : void 0,
1594
1824
  updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1595
- });
1825
+ }) ?? {
1826
+ persisted: true,
1827
+ recordId: input.id
1828
+ };
1596
1829
  }
1597
1830
  async swapBufferedToActive(input) {
1598
- return this.#db.omSwapBuffered({
1831
+ return this.#dbFor(void 0, "swapBufferedToActive").omSwapBuffered({
1599
1832
  id: input.id,
1600
1833
  activationRatio: input.activationRatio,
1601
1834
  messageTokensThreshold: input.messageTokensThreshold,
@@ -1606,68 +1839,36 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1606
1839
  now: (/* @__PURE__ */ new Date()).toISOString()
1607
1840
  });
1608
1841
  }
1609
- async createReflectionGeneration(input) {
1610
- const id = crypto.randomUUID();
1611
- const now = /* @__PURE__ */ new Date();
1612
- const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
1613
- const record = {
1614
- id,
1615
- scope: input.currentRecord.scope,
1616
- threadId: input.currentRecord.threadId,
1617
- resourceId: input.currentRecord.resourceId,
1618
- createdAt: now,
1619
- updatedAt: now,
1620
- lastObservedAt: input.currentRecord.lastObservedAt,
1621
- originType: "reflection",
1622
- generationCount: input.currentRecord.generationCount + 1,
1623
- activeObservations: input.reflection,
1624
- totalTokensObserved: input.currentRecord.totalTokensObserved,
1625
- observationTokenCount: input.tokenCount,
1626
- pendingMessageTokens: 0,
1627
- isReflecting: false,
1628
- isObserving: false,
1629
- isBufferingObservation: false,
1630
- isBufferingReflection: false,
1631
- lastBufferedAtTokens: 0,
1632
- lastBufferedAtTime: null,
1633
- config: input.currentRecord.config,
1634
- metadata: input.currentRecord.metadata,
1635
- observedTimezone: input.currentRecord.observedTimezone
1842
+ /** The caller's snapshot as the server's rollover ops expect it. */
1843
+ #serializeCurrentRecord(currentRecord) {
1844
+ return {
1845
+ id: currentRecord.id,
1846
+ lookupKey: this.getOMKey(currentRecord.threadId, currentRecord.resourceId),
1847
+ scope: currentRecord.scope,
1848
+ threadId: currentRecord.threadId || null,
1849
+ resourceId: currentRecord.resourceId,
1850
+ config: JSON.stringify(currentRecord.config ?? {}),
1851
+ metadata: currentRecord.metadata ? JSON.stringify(currentRecord.metadata) : null,
1852
+ observedTimezone: currentRecord.observedTimezone || null,
1853
+ lastObservedAt: currentRecord.lastObservedAt ? toISO(currentRecord.lastObservedAt) : null,
1854
+ totalTokensObserved: currentRecord.totalTokensObserved,
1855
+ generationCount: currentRecord.generationCount,
1856
+ activeObservations: currentRecord.activeObservations ?? "",
1857
+ observationTokenCount: currentRecord.observationTokenCount ?? 0
1636
1858
  };
1637
- await this.#db.insert({
1638
- tableName: TABLE_OBSERVATIONAL_MEMORY$1,
1639
- record: {
1640
- id,
1641
- lookupKey,
1642
- scope: record.scope,
1643
- resourceId: record.resourceId,
1644
- threadId: record.threadId || null,
1645
- activeObservations: input.reflection,
1646
- activeObservationsPendingUpdate: null,
1647
- originType: "reflection",
1648
- config: JSON.stringify(record.config ?? {}),
1649
- generationCount: record.generationCount,
1650
- lastObservedAt: record.lastObservedAt ? toISO(record.lastObservedAt) : null,
1651
- lastReflectionAt: now.toISOString(),
1652
- pendingMessageTokens: 0,
1653
- totalTokensObserved: record.totalTokensObserved,
1654
- observationTokenCount: record.observationTokenCount,
1655
- isObserving: false,
1656
- isReflecting: false,
1657
- isBufferingObservation: false,
1658
- isBufferingReflection: false,
1659
- lastBufferedAtTokens: 0,
1660
- lastBufferedAtTime: null,
1661
- observedTimezone: record.observedTimezone || null,
1662
- metadata: record.metadata ? JSON.stringify(record.metadata) : null,
1663
- createdAt: now.toISOString(),
1664
- updatedAt: now.toISOString()
1665
- }
1859
+ }
1860
+ async createReflectionGeneration(input) {
1861
+ const doc = await this.#dbFor(void 0, "createReflectionGeneration").omCreateReflectionGeneration({
1862
+ currentRecord: this.#serializeCurrentRecord(input.currentRecord),
1863
+ newId: input.newRecordId ?? crypto.randomUUID(),
1864
+ reflection: input.reflection,
1865
+ tokenCount: input.tokenCount,
1866
+ now: (/* @__PURE__ */ new Date()).toISOString()
1666
1867
  });
1667
- return record;
1868
+ return doc ? parseStoredOMRecord(doc) : input.currentRecord;
1668
1869
  }
1669
1870
  async updateBufferedReflection(input) {
1670
- await this.#db.omUpdateBufferedReflection({
1871
+ await this.#dbFor(void 0, "updateBufferedReflection").omUpdateBufferedReflection({
1671
1872
  id: input.id,
1672
1873
  reflection: input.reflection,
1673
1874
  tokenCount: input.tokenCount,
@@ -1677,26 +1878,13 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1677
1878
  });
1678
1879
  }
1679
1880
  async swapBufferedReflectionToActive(input) {
1680
- const { currentRecord } = input;
1681
- const serializedCurrentRecord = {
1682
- id: currentRecord.id,
1683
- lookupKey: this.getOMKey(currentRecord.threadId, currentRecord.resourceId),
1684
- scope: currentRecord.scope,
1685
- threadId: currentRecord.threadId || null,
1686
- resourceId: currentRecord.resourceId,
1687
- config: JSON.stringify(currentRecord.config ?? {}),
1688
- metadata: currentRecord.metadata ? JSON.stringify(currentRecord.metadata) : null,
1689
- observedTimezone: currentRecord.observedTimezone || null,
1690
- lastObservedAt: currentRecord.lastObservedAt ? toISO(currentRecord.lastObservedAt) : null,
1691
- totalTokensObserved: currentRecord.totalTokensObserved,
1692
- generationCount: currentRecord.generationCount
1693
- };
1694
- return parseStoredOMRecord(await this.#db.omSwapBufferedReflection({
1695
- currentRecord: serializedCurrentRecord,
1696
- newId: crypto.randomUUID(),
1881
+ const doc = await this.#dbFor(void 0, "swapBufferedReflectionToActive").omSwapBufferedReflection({
1882
+ currentRecord: this.#serializeCurrentRecord(input.currentRecord),
1883
+ newId: input.newRecordId ?? crypto.randomUUID(),
1697
1884
  tokenCount: input.tokenCount,
1698
1885
  now: (/* @__PURE__ */ new Date()).toISOString()
1699
- }));
1886
+ });
1887
+ return doc ? parseStoredOMRecord(doc) : input.currentRecord;
1700
1888
  }
1701
1889
  async setReflectingFlag(id, isReflecting) {
1702
1890
  if (!await this.#db.patch({
@@ -1719,15 +1907,12 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1719
1907
  })) throw this.omRecordNotFound("SET_OBSERVING_FLAG", id);
1720
1908
  }
1721
1909
  async setBufferingObservationFlag(id, isBuffering, lastBufferedAtTokens) {
1722
- if (!await this.#db.patch({
1723
- tableName: "mastra_observational_memory",
1910
+ await this.#db.omSetBufferingObservationFlag({
1724
1911
  id,
1725
- record: {
1726
- isBufferingObservation: isBuffering,
1727
- ...lastBufferedAtTokens !== void 0 ? { lastBufferedAtTokens } : {},
1728
- updatedAt: /* @__PURE__ */ new Date()
1729
- }
1730
- })) throw this.omRecordNotFound("SET_BUFFERING_OBSERVATION_FLAG", id);
1912
+ isBuffering,
1913
+ ...lastBufferedAtTokens !== void 0 ? { lastBufferedAtTokens } : {},
1914
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1915
+ });
1731
1916
  }
1732
1917
  async setBufferingReflectionFlag(id, isBuffering) {
1733
1918
  if (!await this.#db.patch({
@@ -1750,14 +1935,11 @@ var MemoryConvex = class extends _mastra_core_storage.MemoryStorage {
1750
1935
  tokenCount
1751
1936
  }
1752
1937
  });
1753
- if (!await this.#db.patch({
1754
- tableName: "mastra_observational_memory",
1938
+ await this.#db.omSetPendingMessageTokens({
1755
1939
  id,
1756
- record: {
1757
- pendingMessageTokens: tokenCount,
1758
- updatedAt: /* @__PURE__ */ new Date()
1759
- }
1760
- })) throw this.omRecordNotFound("SET_PENDING_MESSAGE_TOKENS", id);
1940
+ tokenCount,
1941
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
1942
+ });
1761
1943
  }
1762
1944
  async clearObservationalMemory(threadId, resourceId) {
1763
1945
  const lookupKey = this.getOMKey(threadId, resourceId);
@@ -2092,25 +2274,52 @@ var ScoresConvex = class extends _mastra_core_storage.ScoresStorage {
2092
2274
  //#region src/storage/domains/workflows/index.ts
2093
2275
  var WorkflowsConvex = class extends _mastra_core_storage.WorkflowsStorage {
2094
2276
  #db;
2277
+ #client;
2095
2278
  constructor(config) {
2096
2279
  super();
2097
- const client = resolveConvexConfig(config);
2098
- this.#db = new ConvexDB(client);
2280
+ this.#client = resolveConvexConfig(config);
2281
+ this.#db = new ConvexDB(this.#client);
2099
2282
  }
2100
2283
  supportsConcurrentUpdates() {
2101
2284
  return true;
2102
2285
  }
2286
+ supportsRunFencing() {
2287
+ return true;
2288
+ }
2103
2289
  async init() {}
2104
2290
  async dangerouslyClearAll() {
2105
2291
  await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT });
2292
+ await this.#db.clearTable({ tableName: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS });
2293
+ }
2294
+ /** The store to write a run through: fenced when the write carries or inherits a fence. */
2295
+ #dbFor(fence, runId, operation) {
2296
+ const resolved = (0, _mastra_core_storage.resolveRunFence)(this, fence, runId);
2297
+ const check = resolved && {
2298
+ claims: _mastra_core_storage.TABLE_WORKFLOW_RUN_OWNERS,
2299
+ fence: resolved,
2300
+ operation
2301
+ };
2302
+ return this.#db.fenced(check);
2106
2303
  }
2107
- async updateWorkflowResults(args) {
2108
- return this.#db.mergeWorkflowStepResult(args);
2304
+ async claimRunOwnership(args) {
2305
+ return claimRunOwnership(this.#client, args);
2109
2306
  }
2110
- async updateWorkflowState(args) {
2111
- return this.#db.mergeWorkflowState(args);
2307
+ async renewRunOwnership(args) {
2308
+ return renewRunOwnership(this.#client, args);
2112
2309
  }
2113
- async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt }) {
2310
+ async releaseRunOwnership(fence) {
2311
+ return releaseRunOwnership(this.#client, fence);
2312
+ }
2313
+ async getRunOwnership({ runId }) {
2314
+ return getRunOwnership(this.#client, runId);
2315
+ }
2316
+ async updateWorkflowResults({ fence, ...args }) {
2317
+ return this.#dbFor(fence, args.runId, "updateWorkflowResults").mergeWorkflowStepResult(args);
2318
+ }
2319
+ async updateWorkflowState({ fence, ...args }) {
2320
+ return this.#dbFor(fence, args.runId, "updateWorkflowState").mergeWorkflowState(args);
2321
+ }
2322
+ async persistWorkflowSnapshot({ workflowName, runId, resourceId, snapshot, createdAt, updatedAt, fence }) {
2114
2323
  const now = /* @__PURE__ */ new Date();
2115
2324
  const existing = await this.#db.load({
2116
2325
  tableName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
@@ -2119,7 +2328,7 @@ var WorkflowsConvex = class extends _mastra_core_storage.WorkflowsStorage {
2119
2328
  run_id: runId
2120
2329
  }
2121
2330
  });
2122
- await this.#db.insert({
2331
+ await this.#dbFor(fence, runId, "persistWorkflowSnapshot").insert({
2123
2332
  tableName: _mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT,
2124
2333
  record: {
2125
2334
  workflow_name: workflowName,
@@ -2201,8 +2410,8 @@ var WorkflowsConvex = class extends _mastra_core_storage.WorkflowsStorage {
2201
2410
  resourceId: match.resourceId
2202
2411
  };
2203
2412
  }
2204
- async deleteWorkflowRunById({ runId, workflowName }) {
2205
- await this.#db.deleteMany(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, [`${workflowName}-${runId}`]);
2413
+ async deleteWorkflowRunById({ runId, workflowName, fence }) {
2414
+ await this.#dbFor(fence, runId, "deleteWorkflowRunById").deleteMany(_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT, [`${workflowName}-${runId}`]);
2206
2415
  }
2207
2416
  async getRun(workflowName, runId) {
2208
2417
  return this.#db.load({