@mastra/pg 1.24.1-alpha.0 → 1.25.0-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.
package/dist/index.js CHANGED
@@ -10668,6 +10668,57 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
10668
10668
  }, error);
10669
10669
  }
10670
10670
  }
10671
+ /**
10672
+ * Atomically reassign a thread and all of its messages to a different resource.
10673
+ *
10674
+ * Runs inside a single transaction and takes a `SELECT ... FOR UPDATE` row lock on the
10675
+ * thread, so overlapping transfers of the same thread serialize and can never interleave
10676
+ * the thread update with the message update. Either both the thread and every message move
10677
+ * to the new resource, or neither does — there is no split-ownership window. The thread's
10678
+ * `createdAt` is preserved. Callers are responsible for authorizing the reassignment.
10679
+ */
10680
+ async updateThreadResourceId({ threadId, resourceId }) {
10681
+ const threadsTable = getTableName$3({
10682
+ indexName: TABLE_THREADS,
10683
+ schemaName: getSchemaName$3(this.#schema)
10684
+ });
10685
+ const messagesTable = getTableName$3({
10686
+ indexName: TABLE_MESSAGES,
10687
+ schemaName: getSchemaName$3(this.#schema)
10688
+ });
10689
+ try {
10690
+ return await this.#db.client.tx(async (t) => {
10691
+ const thread = await t.oneOrNone(`SELECT * FROM ${threadsTable} WHERE id = $1 FOR UPDATE`, [threadId]);
10692
+ if (!thread) throw new Error(`Thread "${threadId}" not found`);
10693
+ const normalized = {
10694
+ id: thread.id,
10695
+ resourceId: thread.resourceId,
10696
+ title: thread.title,
10697
+ metadata: typeof thread.metadata === "string" ? JSON.parse(thread.metadata) : thread.metadata,
10698
+ createdAt: thread.createdAtZ || thread.createdAt,
10699
+ updatedAt: thread.updatedAtZ || thread.updatedAt
10700
+ };
10701
+ if (thread.resourceId === resourceId) return normalized;
10702
+ await t.none(`UPDATE ${threadsTable} SET "resourceId" = $1, "updatedAt" = NOW(), "updatedAtZ" = NOW() WHERE id = $2`, [resourceId, threadId]);
10703
+ await t.none(`UPDATE ${messagesTable} SET "resourceId" = $1 WHERE thread_id = $2`, [resourceId, threadId]);
10704
+ return {
10705
+ ...normalized,
10706
+ resourceId,
10707
+ updatedAt: /* @__PURE__ */ new Date()
10708
+ };
10709
+ });
10710
+ } catch (error) {
10711
+ throw new MastraError({
10712
+ id: createStorageErrorId("PG", "UPDATE_THREAD_RESOURCE_ID", "FAILED"),
10713
+ domain: ErrorDomain.STORAGE,
10714
+ category: ErrorCategory.THIRD_PARTY,
10715
+ details: {
10716
+ threadId,
10717
+ resourceId
10718
+ }
10719
+ }, error);
10720
+ }
10721
+ }
10671
10722
  async listThreads(args) {
10672
10723
  const { page = 0, perPage: perPageInput, orderBy, filter } = args;
10673
10724
  try {
@@ -11672,7 +11723,7 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
11672
11723
  await this.#db.client.none(`UPDATE ${tableName} SET ${updates.join(", ")} WHERE id = $${paramIndex}`, values);
11673
11724
  return updatedResource;
11674
11725
  }
11675
- async cloneThread(args) {
11726
+ async copyThread(args) {
11676
11727
  const { sourceThreadId, newThreadId: providedThreadId, resourceId, title, metadata, options } = args;
11677
11728
  const sourceThread = await this.#getThreadById(this.#db.client, { threadId: sourceThreadId });
11678
11729
  if (!sourceThread) throw new MastraError({
@@ -11698,10 +11749,9 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
11698
11749
  indexName: TABLE_MESSAGES,
11699
11750
  schemaName: getSchemaName$3(this.#schema)
11700
11751
  });
11701
- const hydrateMessages = options?.hydrateMessages ?? true;
11702
11752
  try {
11703
11753
  return await this.#db.client.tx(async (t) => {
11704
- let messageQuery = `SELECT ${hydrateMessages ? `id, content, role, type, "createdAt", "createdAtZ", thread_id AS "threadId", "resourceId"` : `id, "createdAt"`}
11754
+ let messageQuery = `SELECT id, "createdAt"
11705
11755
  FROM ${messageTableName} WHERE thread_id = $1`;
11706
11756
  const messageParams = [sourceThreadId];
11707
11757
  let paramIndex = 2;
@@ -11762,54 +11812,23 @@ var MemoryPG = class MemoryPG extends MemoryStorage {
11762
11812
  nowStr,
11763
11813
  nowStr
11764
11814
  ]);
11765
- const clonedMessages = [];
11766
11815
  const messageIdMap = {};
11767
11816
  const targetResourceId = resourceId || sourceThread.resourceId;
11768
11817
  for (const sourceMsg of sourceMessages) {
11769
11818
  const newMessageId = crypto.randomUUID();
11770
11819
  messageIdMap[sourceMsg.id] = newMessageId;
11771
- if (!hydrateMessages) {
11772
- const insertResult = await t.query(`INSERT INTO ${messageTableName} (id, thread_id, content, "createdAt", "createdAtZ", role, type, "resourceId")
11773
- SELECT $1, $2, content, "createdAt", "createdAtZ", role, type, $3
11774
- FROM ${messageTableName} WHERE id = $4`, [
11775
- newMessageId,
11776
- newThreadId,
11777
- targetResourceId,
11778
- sourceMsg.id
11779
- ]);
11780
- if (insertResult.rowCount !== 1) throw new Error(`Failed to clone message ${sourceMsg.id}: expected 1 row copied but got ${insertResult.rowCount}`);
11781
- continue;
11782
- }
11783
- const normalizedMsg = this.normalizeMessageRow(sourceMsg);
11784
- let parsedContent = normalizedMsg.content;
11785
- try {
11786
- parsedContent = JSON.parse(normalizedMsg.content);
11787
- } catch {}
11788
- const createdAt = toUtcISOString(new Date(normalizedMsg.createdAt));
11789
- await t.none(`INSERT INTO ${messageTableName} (id, thread_id, content, "createdAt", "createdAtZ", role, type, "resourceId")
11790
- VALUES ($1, $2, $3, $4, $5, $6, $7, $8)`, [
11820
+ const insertResult = await t.query(`INSERT INTO ${messageTableName} (id, thread_id, content, "createdAt", "createdAtZ", role, type, "resourceId")
11821
+ SELECT $1, $2, content, "createdAt", "createdAtZ", role, type, $3
11822
+ FROM ${messageTableName} WHERE id = $4`, [
11791
11823
  newMessageId,
11792
11824
  newThreadId,
11793
- typeof normalizedMsg.content === "string" ? normalizedMsg.content : JSON.stringify(normalizedMsg.content),
11794
- createdAt,
11795
- createdAt,
11796
- normalizedMsg.role,
11797
- normalizedMsg.type || "v2",
11798
- targetResourceId
11825
+ targetResourceId,
11826
+ sourceMsg.id
11799
11827
  ]);
11800
- clonedMessages.push({
11801
- id: newMessageId,
11802
- threadId: newThreadId,
11803
- content: parsedContent,
11804
- role: normalizedMsg.role,
11805
- type: normalizedMsg.type,
11806
- createdAt: new Date(normalizedMsg.createdAt),
11807
- resourceId: targetResourceId
11808
- });
11828
+ if (insertResult.rowCount !== 1) throw new Error(`Failed to copy message ${sourceMsg.id}: expected 1 row copied but got ${insertResult.rowCount}`);
11809
11829
  }
11810
11830
  return {
11811
11831
  thread: newThread,
11812
- clonedMessages,
11813
11832
  messageIdMap
11814
11833
  };
11815
11834
  });