@mastra/convex 1.1.0 → 1.2.0-alpha.0

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/CHANGELOG.md +60 -0
  2. package/README.md +31 -13
  3. package/dist/{chunk-FZDLZ4S3.js → chunk-AJFME2ZF.js} +323 -16
  4. package/dist/chunk-AJFME2ZF.js.map +1 -0
  5. package/dist/{chunk-JPWDG4L3.js → chunk-MC75WADX.js} +79 -4
  6. package/dist/chunk-MC75WADX.js.map +1 -0
  7. package/dist/{chunk-EEELVBWO.cjs → chunk-ORSDZTO4.cjs} +322 -15
  8. package/dist/chunk-ORSDZTO4.cjs.map +1 -0
  9. package/dist/{chunk-CV23JOCS.cjs → chunk-SFRHJGSM.cjs} +102 -2
  10. package/dist/chunk-SFRHJGSM.cjs.map +1 -0
  11. package/dist/docs/SKILL.md +1 -1
  12. package/dist/docs/assets/SOURCE_MAP.json +63 -23
  13. package/dist/index.cjs +634 -69
  14. package/dist/index.cjs.map +1 -1
  15. package/dist/index.js +574 -49
  16. package/dist/index.js.map +1 -1
  17. package/dist/schema.cjs +60 -20
  18. package/dist/schema.d.ts +192 -2
  19. package/dist/schema.d.ts.map +1 -1
  20. package/dist/schema.js +1 -1
  21. package/dist/server/index-map.d.ts.map +1 -1
  22. package/dist/server/index.cjs +63 -23
  23. package/dist/server/index.d.ts +1 -1
  24. package/dist/server/index.d.ts.map +1 -1
  25. package/dist/server/index.js +2 -2
  26. package/dist/server/storage.d.ts.map +1 -1
  27. package/dist/storage/db/index.d.ts +28 -1
  28. package/dist/storage/db/index.d.ts.map +1 -1
  29. package/dist/storage/domains/background-tasks/index.d.ts.map +1 -1
  30. package/dist/storage/domains/channels/index.d.ts +19 -0
  31. package/dist/storage/domains/channels/index.d.ts.map +1 -0
  32. package/dist/storage/domains/schedules/index.d.ts +19 -0
  33. package/dist/storage/domains/schedules/index.d.ts.map +1 -0
  34. package/dist/storage/index.d.ts +3 -1
  35. package/dist/storage/index.d.ts.map +1 -1
  36. package/dist/storage/types.d.ts +42 -0
  37. package/dist/storage/types.d.ts.map +1 -1
  38. package/package.json +4 -4
  39. package/dist/chunk-CV23JOCS.cjs.map +0 -1
  40. package/dist/chunk-EEELVBWO.cjs.map +0 -1
  41. package/dist/chunk-FZDLZ4S3.js.map +0 -1
  42. package/dist/chunk-JPWDG4L3.js.map +0 -1
@@ -229,6 +229,41 @@ var TABLE_INDEX_MAP = {
229
229
  { name: "by_created", fields: ["createdAt"] },
230
230
  { name: "by_record_id", fields: ["id"] }
231
231
  ],
232
+ mastra_schedules: [
233
+ { name: "by_workflow_status", fields: ["workflow_id", "status"] },
234
+ { name: "by_workflow_id", fields: ["workflow_id"] },
235
+ { name: "by_owner", fields: ["owner_type", "owner_id"] },
236
+ { name: "by_owner_id", fields: ["owner_id"] },
237
+ { name: "by_status_next_fire_at", fields: ["status", "next_fire_at"] },
238
+ { name: "by_created", fields: ["created_at"] },
239
+ { name: "by_record_id", fields: ["id"] }
240
+ ],
241
+ mastra_schedule_triggers: [
242
+ { name: "by_schedule_actual", fields: ["schedule_id", "actual_fire_at"] },
243
+ { name: "by_parent_trigger", fields: ["parent_trigger_id"] },
244
+ { name: "by_record_id", fields: ["id"] }
245
+ ],
246
+ mastra_channel_installations: [
247
+ { name: "by_platform_agent", fields: ["platform", "agentId"] },
248
+ { name: "by_webhook", fields: ["webhookId"] },
249
+ { name: "by_platform", fields: ["platform"] },
250
+ { name: "by_record_id", fields: ["id"] }
251
+ ],
252
+ mastra_channel_config: [
253
+ { name: "by_platform", fields: ["platform"] },
254
+ { name: "by_record_id", fields: ["id"] }
255
+ ],
256
+ mastra_background_tasks: [
257
+ { name: "by_agent_status", fields: ["agent_id", "status"] },
258
+ { name: "by_status_created", fields: ["status", "createdAt"] },
259
+ { name: "by_run", fields: ["run_id"] },
260
+ { name: "by_tool_call", fields: ["tool_call_id"] },
261
+ { name: "by_thread", fields: ["thread_id"] },
262
+ { name: "by_resource", fields: ["resource_id"] },
263
+ { name: "by_tool", fields: ["tool_name"] },
264
+ { name: "by_created", fields: ["createdAt"] },
265
+ { name: "by_record_id", fields: ["id"] }
266
+ ],
232
267
  mastra_vector_indexes: [
233
268
  { name: "by_name", fields: ["indexName"] },
234
269
  { name: "by_record_id", fields: ["id"] }
@@ -265,7 +300,44 @@ function findBestIndex(convexTable, filters) {
265
300
  var TABLE_VECTOR_INDEXES = "mastra_vector_indexes";
266
301
  var VECTOR_TABLE_PREFIX = "mastra_vector_";
267
302
  var CONVEX_TABLE_WORKFLOW_SNAPSHOTS = "mastra_workflow_snapshots";
303
+ var CONVEX_TABLE_BACKGROUND_TASKS = "mastra_background_tasks";
304
+ var CONVEX_TABLE_DOCUMENTS = "mastra_documents";
268
305
  var STORAGE_MUTATION_BATCH_SIZE = 25;
306
+ var DEFAULT_SCHEDULE_QUERY_LIMIT = 100;
307
+ var BACKGROUND_TASK_FIELD_ALIASES = {
308
+ tool_call_id: "toolCallId",
309
+ toolCallId: "tool_call_id",
310
+ tool_name: "toolName",
311
+ toolName: "tool_name",
312
+ agent_id: "agentId",
313
+ agentId: "agent_id",
314
+ run_id: "runId",
315
+ runId: "run_id",
316
+ thread_id: "threadId",
317
+ threadId: "thread_id",
318
+ resource_id: "resourceId",
319
+ resourceId: "resource_id",
320
+ suspend_payload: "suspendPayload",
321
+ suspendPayload: "suspend_payload",
322
+ retry_count: "retryCount",
323
+ retryCount: "retry_count",
324
+ max_retries: "maxRetries",
325
+ maxRetries: "max_retries",
326
+ timeout_ms: "timeoutMs",
327
+ timeoutMs: "timeout_ms"
328
+ };
329
+ function normalizeScheduleQueryLimit(limit) {
330
+ if (limit == null || !Number.isFinite(limit)) return DEFAULT_SCHEDULE_QUERY_LIMIT;
331
+ return Math.max(0, Math.floor(limit));
332
+ }
333
+ function applyConvexEqualityFilters(query, filters, indexedFields = /* @__PURE__ */ new Set()) {
334
+ const remainingFilters = filters?.filter((filter) => !indexedFields.has(filter.field));
335
+ if (!remainingFilters?.length) return query;
336
+ return query.filter((q) => {
337
+ const predicates = remainingFilters.map((filter) => q.eq(q.field(filter.field), filter.value));
338
+ return predicates.length === 1 ? predicates[0] : q.and(...predicates);
339
+ });
340
+ }
269
341
  async function mapInBatches(inputs, batchSize, mapper) {
270
342
  const results = [];
271
343
  for (let index = 0; index < inputs.length; index += batchSize) {
@@ -280,6 +352,58 @@ async function findExistingDocsByIds(ids, findDoc) {
280
352
  const docs = await mapInBatches([...new Set(ids)], STORAGE_MUTATION_BATCH_SIZE, findDoc);
281
353
  return docs.filter((doc) => Boolean(doc));
282
354
  }
355
+ function isBackgroundTasksTable(convexTable, request) {
356
+ return convexTable === CONVEX_TABLE_BACKGROUND_TASKS && request.tableName === constants.TABLE_BACKGROUND_TASKS;
357
+ }
358
+ function matchesFilters(record, filters) {
359
+ return filters.every((filter) => {
360
+ if (record[filter.field] === filter.value) return true;
361
+ const alternateField = BACKGROUND_TASK_FIELD_ALIASES[filter.field];
362
+ return alternateField ? record[alternateField] === filter.value : false;
363
+ });
364
+ }
365
+ function mergeLegacyRecord(record, patch) {
366
+ const merged = { ...record };
367
+ for (const [field, value] of Object.entries(patch)) {
368
+ const alternateField = BACKGROUND_TASK_FIELD_ALIASES[field];
369
+ if (alternateField) delete merged[alternateField];
370
+ merged[field] = value;
371
+ }
372
+ return merged;
373
+ }
374
+ function stripPatchKeys(record, keys) {
375
+ const stripped = { ...record };
376
+ for (const key of keys) delete stripped[key];
377
+ return stripped;
378
+ }
379
+ function dedupeByRecordId(records) {
380
+ const seen = /* @__PURE__ */ new Set();
381
+ return records.filter((record) => {
382
+ if (record?.id == null) return true;
383
+ const id = String(record.id);
384
+ if (seen.has(id)) return false;
385
+ seen.add(id);
386
+ return true;
387
+ });
388
+ }
389
+ function isMissingBackgroundTaskSchemaError(error) {
390
+ const message = error instanceof Error ? error.message.toLowerCase() : String(error).toLowerCase();
391
+ return message.includes(CONVEX_TABLE_BACKGROUND_TASKS) && (message.includes("does not exist") || message.includes("not found") || message.includes("not defined") || message.includes("no such"));
392
+ }
393
+ async function findGenericDocumentById(ctx, tableName, id) {
394
+ return await ctx.db.query(CONVEX_TABLE_DOCUMENTS).withIndex("by_table_primary", (q) => q.eq("table", tableName).eq("primaryKey", String(id))).unique();
395
+ }
396
+ async function findGenericDocumentsByTable(ctx, tableName, limit) {
397
+ return await ctx.db.query(CONVEX_TABLE_DOCUMENTS).withIndex("by_table", (q) => q.eq("table", tableName)).take(limit);
398
+ }
399
+ async function filterLegacyRecordsWithoutTypedCopy(ctx, convexTable, legacyRecords) {
400
+ const records = await mapInBatches(legacyRecords, STORAGE_MUTATION_BATCH_SIZE, async (record) => {
401
+ if (record.id == null) return record;
402
+ const typedDoc = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", String(record.id))).unique();
403
+ return typedDoc ? null : record;
404
+ });
405
+ return records.filter((record) => Boolean(record));
406
+ }
283
407
  function coalesceTypedRecordsForBatchInsert(records) {
284
408
  const recordsById = /* @__PURE__ */ new Map();
285
409
  for (const record of records) {
@@ -311,6 +435,16 @@ function resolveTable(tableName) {
311
435
  return { convexTable: CONVEX_TABLE_WORKFLOW_SNAPSHOTS, isTyped: true };
312
436
  case constants.TABLE_SCORERS:
313
437
  return { convexTable: "mastra_scorers", isTyped: true };
438
+ case constants.TABLE_SCHEDULES:
439
+ return { convexTable: "mastra_schedules", isTyped: true };
440
+ case constants.TABLE_SCHEDULE_TRIGGERS:
441
+ return { convexTable: "mastra_schedule_triggers", isTyped: true };
442
+ case constants.TABLE_CHANNEL_INSTALLATIONS:
443
+ return { convexTable: "mastra_channel_installations", isTyped: true };
444
+ case constants.TABLE_CHANNEL_CONFIG:
445
+ return { convexTable: "mastra_channel_config", isTyped: true };
446
+ case constants.TABLE_BACKGROUND_TASKS:
447
+ return { convexTable: CONVEX_TABLE_BACKGROUND_TASKS, isTyped: true };
314
448
  case TABLE_VECTOR_INDEXES:
315
449
  return { convexTable: "mastra_vector_indexes", isTyped: true };
316
450
  default:
@@ -327,6 +461,14 @@ var mastraStorage = server.mutationGeneric(async (ctx, request) => {
327
461
  return handleVectorOperation(ctx, request);
328
462
  }
329
463
  if (isTyped) {
464
+ if (isBackgroundTasksTable(convexTable, request)) {
465
+ try {
466
+ return await handleTypedOperation(ctx, convexTable, request);
467
+ } catch (error) {
468
+ if (!isMissingBackgroundTaskSchemaError(error)) throw error;
469
+ return handleGenericOperation(ctx, request);
470
+ }
471
+ }
330
472
  return handleTypedOperation(ctx, convexTable, request);
331
473
  }
332
474
  return handleGenericOperation(ctx, request);
@@ -340,6 +482,100 @@ var mastraStorage = server.mutationGeneric(async (ctx, request) => {
340
482
  });
341
483
  async function handleTypedOperation(ctx, convexTable, request) {
342
484
  switch (request.op) {
485
+ case "createSchedule": {
486
+ if (convexTable !== "mastra_schedules") {
487
+ throw new Error(`createSchedule is only supported for mastra_schedules`);
488
+ }
489
+ const record = request.record;
490
+ const id = record.id;
491
+ if (!id) {
492
+ throw new Error(`Schedule is missing an id`);
493
+ }
494
+ const existing = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", id)).unique();
495
+ if (existing) {
496
+ throw new Error(`Schedule with id "${id}" already exists`);
497
+ }
498
+ await ctx.db.insert(convexTable, record);
499
+ return { ok: true };
500
+ }
501
+ case "recordScheduleTrigger": {
502
+ if (convexTable !== "mastra_schedule_triggers") {
503
+ throw new Error(`recordScheduleTrigger is only supported for mastra_schedule_triggers`);
504
+ }
505
+ const record = request.record;
506
+ const id = record.id;
507
+ if (!id) {
508
+ throw new Error(`Schedule trigger is missing an id`);
509
+ }
510
+ const existing = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", id)).unique();
511
+ if (existing) {
512
+ throw new Error(`Schedule trigger with id "${id}" already exists`);
513
+ }
514
+ await ctx.db.insert(convexTable, record);
515
+ return { ok: true };
516
+ }
517
+ case "listDueSchedules": {
518
+ if (convexTable !== "mastra_schedules") {
519
+ throw new Error(`listDueSchedules is only supported for mastra_schedules`);
520
+ }
521
+ const query = ctx.db.query(convexTable).withIndex("by_status_next_fire_at", (q) => q.eq("status", "active").lte("next_fire_at", request.now));
522
+ const docs = await query.take(normalizeScheduleQueryLimit(request.limit));
523
+ return { ok: true, result: docs };
524
+ }
525
+ case "updateScheduleNextFire": {
526
+ if (convexTable !== "mastra_schedules") {
527
+ throw new Error(`updateScheduleNextFire is only supported for mastra_schedules`);
528
+ }
529
+ const existing = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", request.id)).unique();
530
+ if (!existing || existing.status !== "active" || existing.next_fire_at !== request.expectedNextFireAt) {
531
+ return { ok: true, result: false };
532
+ }
533
+ await ctx.db.patch(existing._id, {
534
+ next_fire_at: request.newNextFireAt,
535
+ last_fire_at: request.lastFireAt,
536
+ last_run_id: request.lastRunId,
537
+ updated_at: Date.now()
538
+ });
539
+ return { ok: true, result: true };
540
+ }
541
+ case "updateSchedule": {
542
+ if (convexTable !== "mastra_schedules") {
543
+ throw new Error(`updateSchedule is only supported for mastra_schedules`);
544
+ }
545
+ const existing = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", request.id)).unique();
546
+ if (!existing) {
547
+ throw new Error(`Schedule ${request.id} not found`);
548
+ }
549
+ await ctx.db.patch(existing._id, request.patch);
550
+ return { ok: true, result: { ...existing, ...request.patch } };
551
+ }
552
+ case "listScheduleTriggers": {
553
+ if (convexTable !== "mastra_schedule_triggers") {
554
+ throw new Error(`listScheduleTriggers is only supported for mastra_schedule_triggers`);
555
+ }
556
+ const query = ctx.db.query(convexTable).withIndex("by_schedule_actual", (q) => {
557
+ let builder = q.eq("schedule_id", request.scheduleId);
558
+ if (request.fromActualFireAt != null) {
559
+ builder = builder.gte("actual_fire_at", request.fromActualFireAt);
560
+ }
561
+ if (request.toActualFireAt != null) {
562
+ builder = builder.lt("actual_fire_at", request.toActualFireAt);
563
+ }
564
+ return builder;
565
+ }).order("desc");
566
+ const docs = await query.take(normalizeScheduleQueryLimit(request.limit));
567
+ return { ok: true, result: docs };
568
+ }
569
+ case "deleteScheduleTriggers": {
570
+ if (convexTable !== "mastra_schedule_triggers") {
571
+ throw new Error(`deleteScheduleTriggers is only supported for mastra_schedule_triggers`);
572
+ }
573
+ const docs = await ctx.db.query(convexTable).withIndex("by_schedule_actual", (q) => q.eq("schedule_id", request.scheduleId)).take(STORAGE_MUTATION_BATCH_SIZE + 1);
574
+ const hasMore = docs.length > STORAGE_MUTATION_BATCH_SIZE;
575
+ const docsToDelete = hasMore ? docs.slice(0, STORAGE_MUTATION_BATCH_SIZE) : docs;
576
+ await deleteDocs(ctx, docsToDelete);
577
+ return { ok: true, hasMore };
578
+ }
343
579
  case "insert": {
344
580
  const record = request.record;
345
581
  const id = record.id;
@@ -369,10 +605,36 @@ async function handleTypedOperation(ctx, convexTable, request) {
369
605
  });
370
606
  return { ok: true };
371
607
  }
608
+ case "patch": {
609
+ const patchRecord = stripPatchKeys(request.record, ["id"]);
610
+ const existing = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", request.id)).unique();
611
+ if (!existing) {
612
+ if (isBackgroundTasksTable(convexTable, request)) {
613
+ const legacy = await findGenericDocumentById(ctx, request.tableName, request.id);
614
+ if (legacy) {
615
+ await ctx.db.patch(legacy._id, { record: mergeLegacyRecord(legacy.record, patchRecord) });
616
+ return { ok: true, result: true };
617
+ }
618
+ }
619
+ return { ok: true, result: false };
620
+ }
621
+ await ctx.db.patch(existing._id, patchRecord);
622
+ if (isBackgroundTasksTable(convexTable, request)) {
623
+ const legacy = await findGenericDocumentById(ctx, request.tableName, request.id);
624
+ if (legacy) {
625
+ await ctx.db.delete(legacy._id);
626
+ }
627
+ }
628
+ return { ok: true, result: true };
629
+ }
372
630
  case "load": {
373
631
  const keys = request.keys;
374
632
  if (keys.id) {
375
633
  const doc = await ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", keys.id)).unique();
634
+ if (!doc && isBackgroundTasksTable(convexTable, request)) {
635
+ const legacy = await findGenericDocumentById(ctx, request.tableName, String(keys.id));
636
+ return { ok: true, result: legacy?.record ?? null };
637
+ }
376
638
  return { ok: true, result: doc || null };
377
639
  }
378
640
  if (convexTable === CONVEX_TABLE_WORKFLOW_SNAPSHOTS && typeof keys.workflow_name === "string" && typeof keys.run_id === "string") {
@@ -385,34 +647,47 @@ async function handleTypedOperation(ctx, convexTable, request) {
385
647
  }
386
648
  case "queryTable": {
387
649
  const maxDocs = request.limit ? Math.min(request.limit * 2, 1e4) : 1e4;
388
- let docs;
650
+ let query;
651
+ let indexedFields = /* @__PURE__ */ new Set();
389
652
  if (request.indexHint) {
390
653
  const hint = request.indexHint;
391
654
  if (hint.index === "by_workflow") {
392
- docs = await ctx.db.query(convexTable).withIndex("by_workflow", (q) => q.eq("workflow_name", hint.workflowName)).take(maxDocs);
655
+ query = ctx.db.query(convexTable).withIndex("by_workflow", (q) => q.eq("workflow_name", hint.workflowName));
393
656
  } else if (hint.index === "by_workflow_run") {
394
- docs = await ctx.db.query(convexTable).withIndex("by_workflow_run", (q) => q.eq("workflow_name", hint.workflowName).eq("run_id", hint.runId)).take(maxDocs);
657
+ query = ctx.db.query(convexTable).withIndex(
658
+ "by_workflow_run",
659
+ (q) => q.eq("workflow_name", hint.workflowName).eq("run_id", hint.runId)
660
+ );
395
661
  } else {
396
- docs = await ctx.db.query(convexTable).take(maxDocs);
662
+ query = ctx.db.query(convexTable);
397
663
  }
398
664
  } else if (request.filters && request.filters.length > 0) {
399
665
  const match = findBestIndex(convexTable, request.filters);
400
666
  if (match) {
401
- docs = await ctx.db.query(convexTable).withIndex(match.indexName, (q) => {
667
+ query = ctx.db.query(convexTable).withIndex(match.indexName, (q) => {
402
668
  let builder = q;
403
669
  for (const filter of match.indexedFilters) {
404
670
  builder = builder.eq(filter.field, filter.value);
405
671
  }
406
672
  return builder;
407
- }).take(maxDocs);
673
+ });
674
+ indexedFields = new Set(match.indexedFilters.map((filter) => filter.field));
408
675
  } else {
409
- docs = await ctx.db.query(convexTable).take(maxDocs);
676
+ query = ctx.db.query(convexTable);
410
677
  }
411
678
  } else {
412
- docs = await ctx.db.query(convexTable).take(maxDocs);
679
+ query = ctx.db.query(convexTable);
413
680
  }
414
- if (request.filters && request.filters.length > 0) {
415
- docs = docs.filter((doc) => request.filters.every((filter) => doc[filter.field] === filter.value));
681
+ let docs = await applyConvexEqualityFilters(query, request.filters, indexedFields).take(maxDocs);
682
+ if (isBackgroundTasksTable(convexTable, request)) {
683
+ const legacyDocs = await findGenericDocumentsByTable(ctx, request.tableName, maxDocs);
684
+ let legacyRecords = legacyDocs.map((doc) => doc.record);
685
+ if (request.filters && request.filters.length > 0) {
686
+ legacyRecords = legacyRecords.filter((record) => matchesFilters(record, request.filters));
687
+ }
688
+ legacyRecords = await filterLegacyRecordsWithoutTypedCopy(ctx, convexTable, legacyRecords);
689
+ docs.push(...legacyRecords);
690
+ docs = dedupeByRecordId(docs);
416
691
  }
417
692
  if (request.limit) {
418
693
  docs = docs.slice(0, request.limit);
@@ -423,15 +698,27 @@ async function handleTypedOperation(ctx, convexTable, request) {
423
698
  case "dropTable": {
424
699
  const docs = await ctx.db.query(convexTable).take(STORAGE_MUTATION_BATCH_SIZE + 1);
425
700
  const hasMore = docs.length > STORAGE_MUTATION_BATCH_SIZE;
426
- const docsToDelete = hasMore ? docs.slice(0, STORAGE_MUTATION_BATCH_SIZE) : docs;
701
+ let docsToDelete = hasMore ? docs.slice(0, STORAGE_MUTATION_BATCH_SIZE) : docs;
702
+ let legacyHasMore = false;
703
+ if (!hasMore && docsToDelete.length < STORAGE_MUTATION_BATCH_SIZE && isBackgroundTasksTable(convexTable, request)) {
704
+ const remainingBatchSize = STORAGE_MUTATION_BATCH_SIZE - docsToDelete.length;
705
+ const legacyDocs = await findGenericDocumentsByTable(ctx, request.tableName, remainingBatchSize + 1);
706
+ legacyHasMore = legacyDocs.length > remainingBatchSize;
707
+ docsToDelete = docsToDelete.concat(legacyHasMore ? legacyDocs.slice(0, remainingBatchSize) : legacyDocs);
708
+ }
427
709
  await deleteDocs(ctx, docsToDelete);
428
- return { ok: true, hasMore };
710
+ return { ok: true, hasMore: hasMore || legacyHasMore };
429
711
  }
430
712
  case "deleteMany": {
431
713
  const docsToDelete = await findExistingDocsByIds(
432
714
  request.ids,
433
715
  (id) => ctx.db.query(convexTable).withIndex("by_record_id", (q) => q.eq("id", id)).unique()
434
716
  );
717
+ if (isBackgroundTasksTable(convexTable, request)) {
718
+ docsToDelete.push(
719
+ ...await findExistingDocsByIds(request.ids, (id) => findGenericDocumentById(ctx, request.tableName, id))
720
+ );
721
+ }
435
722
  await deleteDocs(ctx, docsToDelete);
436
723
  return { ok: true };
437
724
  }
@@ -486,6 +773,15 @@ async function handleVectorOperation(ctx, request) {
486
773
  });
487
774
  return { ok: true };
488
775
  }
776
+ case "patch": {
777
+ const patchRecord = stripPatchKeys(request.record, ["id", "indexName"]);
778
+ const existing = await ctx.db.query(convexTable).withIndex("by_index_id", (q) => q.eq("indexName", indexName).eq("id", request.id)).unique();
779
+ if (!existing) {
780
+ return { ok: true, result: false };
781
+ }
782
+ await ctx.db.patch(existing._id, patchRecord);
783
+ return { ok: true, result: true };
784
+ }
489
785
  case "load": {
490
786
  const keys = request.keys;
491
787
  if (keys.id) {
@@ -567,6 +863,17 @@ async function handleGenericOperation(ctx, request) {
567
863
  });
568
864
  return { ok: true };
569
865
  }
866
+ case "patch": {
867
+ const patchRecord = stripPatchKeys(request.record, ["id"]);
868
+ const existing = await ctx.db.query(convexTable).withIndex("by_table_primary", (q) => q.eq("table", tableName).eq("primaryKey", String(request.id))).unique();
869
+ if (!existing) {
870
+ return { ok: true, result: false };
871
+ }
872
+ await ctx.db.patch(existing._id, {
873
+ record: tableName === constants.TABLE_BACKGROUND_TASKS ? mergeLegacyRecord(existing.record, patchRecord) : { ...existing.record, ...patchRecord }
874
+ });
875
+ return { ok: true, result: true };
876
+ }
570
877
  case "load": {
571
878
  const keys = request.keys;
572
879
  if (keys.id) {
@@ -583,7 +890,7 @@ async function handleGenericOperation(ctx, request) {
583
890
  let records = docs.map((doc) => doc.record);
584
891
  if (request.filters && request.filters.length > 0) {
585
892
  records = records.filter(
586
- (record) => request.filters.every((filter) => record?.[filter.field] === filter.value)
893
+ (record) => tableName === constants.TABLE_BACKGROUND_TASKS ? matchesFilters(record, request.filters) : request.filters.every((filter) => record?.[filter.field] === filter.value)
587
894
  );
588
895
  }
589
896
  if (request.limit) {
@@ -889,5 +1196,5 @@ exports.mastraNativeVectorAction = mastraNativeVectorAction;
889
1196
  exports.mastraNativeVectorMutation = mastraNativeVectorMutation;
890
1197
  exports.mastraNativeVectorQuery = mastraNativeVectorQuery;
891
1198
  exports.mastraStorage = mastraStorage;
892
- //# sourceMappingURL=chunk-EEELVBWO.cjs.map
893
- //# sourceMappingURL=chunk-EEELVBWO.cjs.map
1199
+ //# sourceMappingURL=chunk-ORSDZTO4.cjs.map
1200
+ //# sourceMappingURL=chunk-ORSDZTO4.cjs.map