@mastra/factory 0.2.0-alpha.0 → 0.2.1-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 (51) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/dist/capabilities/intake.d.ts +45 -0
  3. package/dist/capabilities/intake.d.ts.map +1 -1
  4. package/dist/factory.js +923 -552
  5. package/dist/factory.js.map +1 -1
  6. package/dist/index.js +923 -552
  7. package/dist/index.js.map +1 -1
  8. package/dist/integrations/github/integration.d.ts.map +1 -1
  9. package/dist/integrations/github/integration.js +127 -12
  10. package/dist/integrations/github/integration.js.map +1 -1
  11. package/dist/integrations/github/project-lock.d.ts +24 -2
  12. package/dist/integrations/github/project-lock.d.ts.map +1 -1
  13. package/dist/integrations/github/project-lock.js +43 -10
  14. package/dist/integrations/github/project-lock.js.map +1 -1
  15. package/dist/integrations/github/routes.js +42 -11
  16. package/dist/integrations/github/routes.js.map +1 -1
  17. package/dist/integrations/linear/agent-tools.js.map +1 -1
  18. package/dist/integrations/linear/integration.d.ts.map +1 -1
  19. package/dist/integrations/linear/integration.js +60 -1
  20. package/dist/integrations/linear/integration.js.map +1 -1
  21. package/dist/integrations/linear/routes.js.map +1 -1
  22. package/dist/integrations/platform/api-client.js +1 -1
  23. package/dist/integrations/platform/api-client.js.map +1 -1
  24. package/dist/integrations/platform/github/event-worker.d.ts.map +1 -1
  25. package/dist/integrations/platform/github/event-worker.js +7 -1
  26. package/dist/integrations/platform/github/event-worker.js.map +1 -1
  27. package/dist/integrations/platform/github/integration.d.ts.map +1 -1
  28. package/dist/integrations/platform/github/integration.js +106 -14
  29. package/dist/integrations/platform/github/integration.js.map +1 -1
  30. package/dist/integrations/platform/linear/integration.d.ts.map +1 -1
  31. package/dist/integrations/platform/linear/integration.js +92 -1
  32. package/dist/integrations/platform/linear/integration.js.map +1 -1
  33. package/dist/routes/fs.d.ts +16 -0
  34. package/dist/routes/fs.d.ts.map +1 -1
  35. package/dist/routes/fs.js +103 -3
  36. package/dist/routes/fs.js.map +1 -1
  37. package/dist/routes/oauth.js +564 -478
  38. package/dist/routes/oauth.js.map +1 -1
  39. package/dist/routes/projects.d.ts.map +1 -1
  40. package/dist/routes/projects.js +1 -0
  41. package/dist/routes/projects.js.map +1 -1
  42. package/dist/routes/surface.d.ts.map +1 -1
  43. package/dist/routes/surface.js +717 -526
  44. package/dist/routes/surface.js.map +1 -1
  45. package/dist/server-error.js +1 -1
  46. package/dist/server-error.js.map +1 -1
  47. package/dist/storage/domains/source-control/base.d.ts +0 -1
  48. package/dist/storage/domains/source-control/base.d.ts.map +1 -1
  49. package/dist/storage/domains/source-control/base.js +6 -7
  50. package/dist/storage/domains/source-control/base.js.map +1 -1
  51. package/package.json +6 -6
@@ -18882,46 +18882,49 @@ Note: This migration may take some time for large tables.
18882
18882
  config: input.config,
18883
18883
  observedTimezone: input.observedTimezone
18884
18884
  };
18885
- await this.#client.execute({
18886
- sql: `INSERT INTO "${OM_TABLE}" (
18887
- id, "lookupKey", scope, "resourceId", "threadId",
18888
- "activeObservations", "activeObservationsPendingUpdate",
18889
- "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
18890
- "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
18891
- "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
18892
- "observedTimezone", "createdAt", "updatedAt"
18893
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
18894
- args: [
18895
- id,
18896
- lookupKey,
18897
- input.scope,
18898
- input.resourceId,
18899
- input.threadId || null,
18900
- "",
18901
- null,
18902
- "initial",
18903
- JSON.stringify(input.config),
18904
- 0,
18905
- null,
18906
- null,
18907
- 0,
18908
- 0,
18909
- 0,
18910
- false,
18911
- false,
18912
- false,
18913
- // isBufferingObservation
18914
- false,
18915
- // isBufferingReflection
18916
- 0,
18917
- // lastBufferedAtTokens
18918
- null,
18919
- // lastBufferedAtTime
18920
- input.observedTimezone || null,
18921
- now.toISOString(),
18922
- now.toISOString()
18923
- ]
18924
- });
18885
+ await withClientWriteLock(
18886
+ this.#client,
18887
+ () => this.#client.execute({
18888
+ sql: `INSERT INTO "${OM_TABLE}" (
18889
+ id, "lookupKey", scope, "resourceId", "threadId",
18890
+ "activeObservations", "activeObservationsPendingUpdate",
18891
+ "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
18892
+ "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
18893
+ "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
18894
+ "observedTimezone", "createdAt", "updatedAt"
18895
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
18896
+ args: [
18897
+ id,
18898
+ lookupKey,
18899
+ input.scope,
18900
+ input.resourceId,
18901
+ input.threadId || null,
18902
+ "",
18903
+ null,
18904
+ "initial",
18905
+ JSON.stringify(input.config),
18906
+ 0,
18907
+ null,
18908
+ null,
18909
+ 0,
18910
+ 0,
18911
+ 0,
18912
+ false,
18913
+ false,
18914
+ false,
18915
+ // isBufferingObservation
18916
+ false,
18917
+ // isBufferingReflection
18918
+ 0,
18919
+ // lastBufferedAtTokens
18920
+ null,
18921
+ // lastBufferedAtTime
18922
+ input.observedTimezone || null,
18923
+ now.toISOString(),
18924
+ now.toISOString()
18925
+ ]
18926
+ })
18927
+ );
18925
18928
  return record;
18926
18929
  } catch (error) {
18927
18930
  throw new MastraError(
@@ -18938,53 +18941,56 @@ Note: This migration may take some time for large tables.
18938
18941
  async insertObservationalMemoryRecord(record) {
18939
18942
  try {
18940
18943
  const lookupKey = this.getOMKey(record.threadId, record.resourceId);
18941
- await this.#client.execute({
18942
- sql: `INSERT INTO "${OM_TABLE}" (
18943
- id, "lookupKey", scope, "resourceId", "threadId",
18944
- "activeObservations", "activeObservationsPendingUpdate",
18945
- "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
18946
- "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
18947
- "observedMessageIds", "bufferedObservationChunks",
18948
- "bufferedReflection", "bufferedReflectionTokens", "bufferedReflectionInputTokens",
18949
- "reflectedObservationLineCount",
18950
- "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection",
18951
- "lastBufferedAtTokens", "lastBufferedAtTime",
18952
- "observedTimezone", metadata, "createdAt", "updatedAt"
18953
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
18954
- args: [
18955
- record.id,
18956
- lookupKey,
18957
- record.scope,
18958
- record.resourceId,
18959
- record.threadId || null,
18960
- record.activeObservations || "",
18961
- null,
18962
- record.originType || "initial",
18963
- record.config ? JSON.stringify(record.config) : null,
18964
- record.generationCount || 0,
18965
- record.lastObservedAt ? record.lastObservedAt.toISOString() : null,
18966
- null,
18967
- record.pendingMessageTokens || 0,
18968
- record.totalTokensObserved || 0,
18969
- record.observationTokenCount || 0,
18970
- record.observedMessageIds ? JSON.stringify(record.observedMessageIds) : null,
18971
- record.bufferedObservationChunks ? JSON.stringify(record.bufferedObservationChunks) : null,
18972
- record.bufferedReflection || null,
18973
- record.bufferedReflectionTokens ?? null,
18974
- record.bufferedReflectionInputTokens ?? null,
18975
- record.reflectedObservationLineCount ?? null,
18976
- record.isObserving || false,
18977
- record.isReflecting || false,
18978
- record.isBufferingObservation || false,
18979
- record.isBufferingReflection || false,
18980
- record.lastBufferedAtTokens || 0,
18981
- record.lastBufferedAtTime ? record.lastBufferedAtTime.toISOString() : null,
18982
- record.observedTimezone || null,
18983
- record.metadata ? JSON.stringify(record.metadata) : null,
18984
- record.createdAt.toISOString(),
18985
- record.updatedAt.toISOString()
18986
- ]
18987
- });
18944
+ await withClientWriteLock(
18945
+ this.#client,
18946
+ () => this.#client.execute({
18947
+ sql: `INSERT INTO "${OM_TABLE}" (
18948
+ id, "lookupKey", scope, "resourceId", "threadId",
18949
+ "activeObservations", "activeObservationsPendingUpdate",
18950
+ "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
18951
+ "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
18952
+ "observedMessageIds", "bufferedObservationChunks",
18953
+ "bufferedReflection", "bufferedReflectionTokens", "bufferedReflectionInputTokens",
18954
+ "reflectedObservationLineCount",
18955
+ "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection",
18956
+ "lastBufferedAtTokens", "lastBufferedAtTime",
18957
+ "observedTimezone", metadata, "createdAt", "updatedAt"
18958
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
18959
+ args: [
18960
+ record.id,
18961
+ lookupKey,
18962
+ record.scope,
18963
+ record.resourceId,
18964
+ record.threadId || null,
18965
+ record.activeObservations || "",
18966
+ null,
18967
+ record.originType || "initial",
18968
+ record.config ? JSON.stringify(record.config) : null,
18969
+ record.generationCount || 0,
18970
+ record.lastObservedAt ? record.lastObservedAt.toISOString() : null,
18971
+ null,
18972
+ record.pendingMessageTokens || 0,
18973
+ record.totalTokensObserved || 0,
18974
+ record.observationTokenCount || 0,
18975
+ record.observedMessageIds ? JSON.stringify(record.observedMessageIds) : null,
18976
+ record.bufferedObservationChunks ? JSON.stringify(record.bufferedObservationChunks) : null,
18977
+ record.bufferedReflection || null,
18978
+ record.bufferedReflectionTokens ?? null,
18979
+ record.bufferedReflectionInputTokens ?? null,
18980
+ record.reflectedObservationLineCount ?? null,
18981
+ record.isObserving || false,
18982
+ record.isReflecting || false,
18983
+ record.isBufferingObservation || false,
18984
+ record.isBufferingReflection || false,
18985
+ record.lastBufferedAtTokens || 0,
18986
+ record.lastBufferedAtTime ? record.lastBufferedAtTime.toISOString() : null,
18987
+ record.observedTimezone || null,
18988
+ record.metadata ? JSON.stringify(record.metadata) : null,
18989
+ record.createdAt.toISOString(),
18990
+ record.updatedAt.toISOString()
18991
+ ]
18992
+ })
18993
+ );
18988
18994
  } catch (error) {
18989
18995
  throw new MastraError(
18990
18996
  {
@@ -19001,26 +19007,29 @@ Note: This migration may take some time for large tables.
19001
19007
  try {
19002
19008
  const now = /* @__PURE__ */ new Date();
19003
19009
  const observedMessageIdsJson = input.observedMessageIds ? JSON.stringify(input.observedMessageIds) : null;
19004
- const result = await this.#client.execute({
19005
- sql: `UPDATE "${OM_TABLE}" SET
19006
- "activeObservations" = ?,
19007
- "lastObservedAt" = ?,
19008
- "pendingMessageTokens" = 0,
19009
- "observationTokenCount" = ?,
19010
- "totalTokensObserved" = "totalTokensObserved" + ?,
19011
- "observedMessageIds" = ?,
19012
- "updatedAt" = ?
19013
- WHERE id = ?`,
19014
- args: [
19015
- input.observations,
19016
- input.lastObservedAt.toISOString(),
19017
- input.tokenCount,
19018
- input.tokenCount,
19019
- observedMessageIdsJson,
19020
- now.toISOString(),
19021
- input.id
19022
- ]
19023
- });
19010
+ const result = await withClientWriteLock(
19011
+ this.#client,
19012
+ () => this.#client.execute({
19013
+ sql: `UPDATE "${OM_TABLE}" SET
19014
+ "activeObservations" = ?,
19015
+ "lastObservedAt" = ?,
19016
+ "pendingMessageTokens" = 0,
19017
+ "observationTokenCount" = ?,
19018
+ "totalTokensObserved" = "totalTokensObserved" + ?,
19019
+ "observedMessageIds" = ?,
19020
+ "updatedAt" = ?
19021
+ WHERE id = ?`,
19022
+ args: [
19023
+ input.observations,
19024
+ input.lastObservedAt.toISOString(),
19025
+ input.tokenCount,
19026
+ input.tokenCount,
19027
+ observedMessageIdsJson,
19028
+ now.toISOString(),
19029
+ input.id
19030
+ ]
19031
+ })
19032
+ );
19024
19033
  if (result.rowsAffected === 0) {
19025
19034
  throw new MastraError({
19026
19035
  id: createStorageErrorId("LIBSQL", "UPDATE_ACTIVE_OBSERVATIONS", "NOT_FOUND"),
@@ -19047,78 +19056,21 @@ Note: This migration may take some time for large tables.
19047
19056
  }
19048
19057
  async createReflectionGeneration(input) {
19049
19058
  try {
19050
- const id = crypto.randomUUID();
19051
- const now = /* @__PURE__ */ new Date();
19052
- const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
19053
- const record = {
19054
- id,
19055
- scope: input.currentRecord.scope,
19056
- threadId: input.currentRecord.threadId,
19057
- resourceId: input.currentRecord.resourceId,
19058
- createdAt: now,
19059
- updatedAt: now,
19060
- lastObservedAt: input.currentRecord.lastObservedAt,
19061
- originType: "reflection",
19062
- generationCount: input.currentRecord.generationCount + 1,
19063
- activeObservations: input.reflection,
19064
- totalTokensObserved: input.currentRecord.totalTokensObserved,
19065
- observationTokenCount: input.tokenCount,
19066
- pendingMessageTokens: 0,
19067
- isReflecting: false,
19068
- isObserving: false,
19069
- isBufferingObservation: false,
19070
- isBufferingReflection: false,
19071
- lastBufferedAtTokens: 0,
19072
- lastBufferedAtTime: null,
19073
- config: input.currentRecord.config,
19074
- metadata: input.currentRecord.metadata,
19075
- observedTimezone: input.currentRecord.observedTimezone
19076
- };
19077
- await this.#client.execute({
19078
- sql: `INSERT INTO "${OM_TABLE}" (
19079
- id, "lookupKey", scope, "resourceId", "threadId",
19080
- "activeObservations", "activeObservationsPendingUpdate",
19081
- "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
19082
- "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
19083
- "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
19084
- "observedTimezone", metadata, "createdAt", "updatedAt"
19085
- ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
19086
- args: [
19087
- id,
19088
- lookupKey,
19089
- record.scope,
19090
- record.resourceId,
19091
- record.threadId || null,
19092
- input.reflection,
19093
- null,
19094
- "reflection",
19095
- JSON.stringify(record.config),
19096
- input.currentRecord.generationCount + 1,
19097
- record.lastObservedAt?.toISOString() || null,
19098
- now.toISOString(),
19099
- record.pendingMessageTokens,
19100
- record.totalTokensObserved,
19101
- record.observationTokenCount,
19102
- false,
19103
- // isObserving
19104
- false,
19105
- // isReflecting
19106
- false,
19107
- // isBufferingObservation
19108
- false,
19109
- // isBufferingReflection
19110
- 0,
19111
- // lastBufferedAtTokens
19112
- null,
19113
- // lastBufferedAtTime
19114
- record.observedTimezone || null,
19115
- record.metadata ? JSON.stringify(record.metadata) : null,
19116
- now.toISOString(),
19117
- now.toISOString()
19118
- ]
19059
+ return await withClientWriteLock(this.#client, async () => {
19060
+ const tx = await this.#client.transaction("write");
19061
+ try {
19062
+ const record = await this.#insertReflectionGeneration(tx, input);
19063
+ await tx.commit();
19064
+ return record;
19065
+ } catch (error) {
19066
+ if (!tx.closed) await tx.rollback();
19067
+ throw error;
19068
+ }
19119
19069
  });
19120
- return record;
19121
19070
  } catch (error) {
19071
+ if (error instanceof MastraError) {
19072
+ throw error;
19073
+ }
19122
19074
  throw new MastraError(
19123
19075
  {
19124
19076
  id: createStorageErrorId("LIBSQL", "CREATE_REFLECTION_GENERATION", "FAILED"),
@@ -19130,12 +19082,94 @@ Note: This migration may take some time for large tables.
19130
19082
  );
19131
19083
  }
19132
19084
  }
19085
+ /**
19086
+ * Inserts a new reflection-generation row. Called inside a locked write
19087
+ * transaction — either from {@link createReflectionGeneration} (standalone)
19088
+ * or from {@link swapBufferedReflectionToActive} (as part of a compound
19089
+ * swap). Must not acquire the write lock itself; the caller owns it.
19090
+ */
19091
+ async #insertReflectionGeneration(tx, input) {
19092
+ const id = crypto.randomUUID();
19093
+ const now = /* @__PURE__ */ new Date();
19094
+ const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
19095
+ const record = {
19096
+ id,
19097
+ scope: input.currentRecord.scope,
19098
+ threadId: input.currentRecord.threadId,
19099
+ resourceId: input.currentRecord.resourceId,
19100
+ createdAt: now,
19101
+ updatedAt: now,
19102
+ lastObservedAt: input.currentRecord.lastObservedAt,
19103
+ originType: "reflection",
19104
+ generationCount: input.currentRecord.generationCount + 1,
19105
+ activeObservations: input.reflection,
19106
+ totalTokensObserved: input.currentRecord.totalTokensObserved,
19107
+ observationTokenCount: input.tokenCount,
19108
+ pendingMessageTokens: 0,
19109
+ isReflecting: false,
19110
+ isObserving: false,
19111
+ isBufferingObservation: false,
19112
+ isBufferingReflection: false,
19113
+ lastBufferedAtTokens: 0,
19114
+ lastBufferedAtTime: null,
19115
+ config: input.currentRecord.config,
19116
+ metadata: input.currentRecord.metadata,
19117
+ observedTimezone: input.currentRecord.observedTimezone
19118
+ };
19119
+ await tx.execute({
19120
+ sql: `INSERT INTO "${OM_TABLE}" (
19121
+ id, "lookupKey", scope, "resourceId", "threadId",
19122
+ "activeObservations", "activeObservationsPendingUpdate",
19123
+ "originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
19124
+ "pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
19125
+ "isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
19126
+ "observedTimezone", metadata, "createdAt", "updatedAt"
19127
+ ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
19128
+ args: [
19129
+ id,
19130
+ lookupKey,
19131
+ record.scope,
19132
+ record.resourceId,
19133
+ record.threadId || null,
19134
+ input.reflection,
19135
+ null,
19136
+ "reflection",
19137
+ JSON.stringify(record.config),
19138
+ input.currentRecord.generationCount + 1,
19139
+ record.lastObservedAt?.toISOString() || null,
19140
+ now.toISOString(),
19141
+ record.pendingMessageTokens,
19142
+ record.totalTokensObserved,
19143
+ record.observationTokenCount,
19144
+ false,
19145
+ // isObserving
19146
+ false,
19147
+ // isReflecting
19148
+ false,
19149
+ // isBufferingObservation
19150
+ false,
19151
+ // isBufferingReflection
19152
+ 0,
19153
+ // lastBufferedAtTokens
19154
+ null,
19155
+ // lastBufferedAtTime
19156
+ record.observedTimezone || null,
19157
+ record.metadata ? JSON.stringify(record.metadata) : null,
19158
+ now.toISOString(),
19159
+ now.toISOString()
19160
+ ]
19161
+ });
19162
+ return record;
19163
+ }
19133
19164
  async setReflectingFlag(id, isReflecting) {
19134
19165
  try {
19135
- const result = await this.#client.execute({
19136
- sql: `UPDATE "${OM_TABLE}" SET "isReflecting" = ?, "updatedAt" = ? WHERE id = ?`,
19137
- args: [isReflecting, (/* @__PURE__ */ new Date()).toISOString(), id]
19138
- });
19166
+ const result = await withClientWriteLock(
19167
+ this.#client,
19168
+ () => this.#client.execute({
19169
+ sql: `UPDATE "${OM_TABLE}" SET "isReflecting" = ?, "updatedAt" = ? WHERE id = ?`,
19170
+ args: [isReflecting, (/* @__PURE__ */ new Date()).toISOString(), id]
19171
+ })
19172
+ );
19139
19173
  if (result.rowsAffected === 0) {
19140
19174
  throw new MastraError({
19141
19175
  id: createStorageErrorId("LIBSQL", "SET_REFLECTING_FLAG", "NOT_FOUND"),
@@ -19162,10 +19196,13 @@ Note: This migration may take some time for large tables.
19162
19196
  }
19163
19197
  async setObservingFlag(id, isObserving) {
19164
19198
  try {
19165
- const result = await this.#client.execute({
19166
- sql: `UPDATE "${OM_TABLE}" SET "isObserving" = ?, "updatedAt" = ? WHERE id = ?`,
19167
- args: [isObserving, (/* @__PURE__ */ new Date()).toISOString(), id]
19168
- });
19199
+ const result = await withClientWriteLock(
19200
+ this.#client,
19201
+ () => this.#client.execute({
19202
+ sql: `UPDATE "${OM_TABLE}" SET "isObserving" = ?, "updatedAt" = ? WHERE id = ?`,
19203
+ args: [isObserving, (/* @__PURE__ */ new Date()).toISOString(), id]
19204
+ })
19205
+ );
19169
19206
  if (result.rowsAffected === 0) {
19170
19207
  throw new MastraError({
19171
19208
  id: createStorageErrorId("LIBSQL", "SET_OBSERVING_FLAG", "NOT_FOUND"),
@@ -19202,7 +19239,7 @@ Note: This migration may take some time for large tables.
19202
19239
  sql = `UPDATE "${OM_TABLE}" SET "isBufferingObservation" = ?, "updatedAt" = ? WHERE id = ?`;
19203
19240
  args = [isBuffering, nowStr, id];
19204
19241
  }
19205
- const result = await this.#client.execute({ sql, args });
19242
+ const result = await withClientWriteLock(this.#client, () => this.#client.execute({ sql, args }));
19206
19243
  if (result.rowsAffected === 0) {
19207
19244
  throw new MastraError({
19208
19245
  id: createStorageErrorId("LIBSQL", "SET_BUFFERING_OBSERVATION_FLAG", "NOT_FOUND"),
@@ -19229,10 +19266,13 @@ Note: This migration may take some time for large tables.
19229
19266
  }
19230
19267
  async setBufferingReflectionFlag(id, isBuffering) {
19231
19268
  try {
19232
- const result = await this.#client.execute({
19233
- sql: `UPDATE "${OM_TABLE}" SET "isBufferingReflection" = ?, "updatedAt" = ? WHERE id = ?`,
19234
- args: [isBuffering, (/* @__PURE__ */ new Date()).toISOString(), id]
19235
- });
19269
+ const result = await withClientWriteLock(
19270
+ this.#client,
19271
+ () => this.#client.execute({
19272
+ sql: `UPDATE "${OM_TABLE}" SET "isBufferingReflection" = ?, "updatedAt" = ? WHERE id = ?`,
19273
+ args: [isBuffering, (/* @__PURE__ */ new Date()).toISOString(), id]
19274
+ })
19275
+ );
19236
19276
  if (result.rowsAffected === 0) {
19237
19277
  throw new MastraError({
19238
19278
  id: createStorageErrorId("LIBSQL", "SET_BUFFERING_REFLECTION_FLAG", "NOT_FOUND"),
@@ -19260,10 +19300,13 @@ Note: This migration may take some time for large tables.
19260
19300
  async clearObservationalMemory(threadId, resourceId) {
19261
19301
  try {
19262
19302
  const lookupKey = this.getOMKey(threadId, resourceId);
19263
- await this.#client.execute({
19264
- sql: `DELETE FROM "${OM_TABLE}" WHERE "lookupKey" = ?`,
19265
- args: [lookupKey]
19266
- });
19303
+ await withClientWriteLock(
19304
+ this.#client,
19305
+ () => this.#client.execute({
19306
+ sql: `DELETE FROM "${OM_TABLE}" WHERE "lookupKey" = ?`,
19307
+ args: [lookupKey]
19308
+ })
19309
+ );
19267
19310
  } catch (error) {
19268
19311
  throw new MastraError(
19269
19312
  {
@@ -19278,13 +19321,16 @@ Note: This migration may take some time for large tables.
19278
19321
  }
19279
19322
  async setPendingMessageTokens(id, tokenCount) {
19280
19323
  try {
19281
- const result = await this.#client.execute({
19282
- sql: `UPDATE "${OM_TABLE}" SET
19283
- "pendingMessageTokens" = ?,
19284
- "updatedAt" = ?
19285
- WHERE id = ?`,
19286
- args: [tokenCount, (/* @__PURE__ */ new Date()).toISOString(), id]
19287
- });
19324
+ const result = await withClientWriteLock(
19325
+ this.#client,
19326
+ () => this.#client.execute({
19327
+ sql: `UPDATE "${OM_TABLE}" SET
19328
+ "pendingMessageTokens" = ?,
19329
+ "updatedAt" = ?
19330
+ WHERE id = ?`,
19331
+ args: [tokenCount, (/* @__PURE__ */ new Date()).toISOString(), id]
19332
+ })
19333
+ );
19288
19334
  if (result.rowsAffected === 0) {
19289
19335
  throw new MastraError({
19290
19336
  id: createStorageErrorId("LIBSQL", "SET_PENDING_MESSAGE_TOKENS", "NOT_FOUND"),
@@ -19311,25 +19357,34 @@ Note: This migration may take some time for large tables.
19311
19357
  }
19312
19358
  async updateObservationalMemoryConfig(input) {
19313
19359
  try {
19314
- const selectResult = await this.#client.execute({
19315
- sql: `SELECT config FROM "${OM_TABLE}" WHERE id = ?`,
19316
- args: [input.id]
19317
- });
19318
- if (selectResult.rows.length === 0) {
19319
- throw new MastraError({
19320
- id: createStorageErrorId("LIBSQL", "UPDATE_OM_CONFIG", "NOT_FOUND"),
19321
- text: `Observational memory record not found: ${input.id}`,
19322
- domain: ErrorDomain.STORAGE,
19323
- category: ErrorCategory.THIRD_PARTY,
19324
- details: { id: input.id }
19325
- });
19326
- }
19327
- const row = selectResult.rows[0];
19328
- const existing = row.config ? JSON.parse(row.config) : {};
19329
- const merged = this.deepMergeConfig(existing, input.config);
19330
- await this.#client.execute({
19331
- sql: `UPDATE "${OM_TABLE}" SET config = ?, "updatedAt" = ? WHERE id = ?`,
19332
- args: [JSON.stringify(merged), (/* @__PURE__ */ new Date()).toISOString(), input.id]
19360
+ await withClientWriteLock(this.#client, async () => {
19361
+ const tx = await this.#client.transaction("write");
19362
+ try {
19363
+ const selectResult = await tx.execute({
19364
+ sql: `SELECT config FROM "${OM_TABLE}" WHERE id = ?`,
19365
+ args: [input.id]
19366
+ });
19367
+ if (selectResult.rows.length === 0) {
19368
+ throw new MastraError({
19369
+ id: createStorageErrorId("LIBSQL", "UPDATE_OM_CONFIG", "NOT_FOUND"),
19370
+ text: `Observational memory record not found: ${input.id}`,
19371
+ domain: ErrorDomain.STORAGE,
19372
+ category: ErrorCategory.THIRD_PARTY,
19373
+ details: { id: input.id }
19374
+ });
19375
+ }
19376
+ const row = selectResult.rows[0];
19377
+ const existing = row.config ? JSON.parse(row.config) : {};
19378
+ const merged = this.deepMergeConfig(existing, input.config);
19379
+ await tx.execute({
19380
+ sql: `UPDATE "${OM_TABLE}" SET config = ?, "updatedAt" = ? WHERE id = ?`,
19381
+ args: [JSON.stringify(merged), (/* @__PURE__ */ new Date()).toISOString(), input.id]
19382
+ });
19383
+ await tx.commit();
19384
+ } catch (error) {
19385
+ if (!tx.closed) await tx.rollback();
19386
+ throw error;
19387
+ }
19333
19388
  });
19334
19389
  } catch (error) {
19335
19390
  if (error instanceof MastraError) {
@@ -19352,63 +19407,72 @@ Note: This migration may take some time for large tables.
19352
19407
  async updateBufferedObservations(input) {
19353
19408
  try {
19354
19409
  const nowStr = (/* @__PURE__ */ new Date()).toISOString();
19355
- const current = await this.#client.execute({
19356
- sql: `SELECT "bufferedObservationChunks" FROM "${OM_TABLE}" WHERE id = ?`,
19357
- args: [input.id]
19358
- });
19359
- if (!current.rows || current.rows.length === 0) {
19360
- throw new MastraError({
19361
- id: createStorageErrorId("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
19362
- text: `Observational memory record not found: ${input.id}`,
19363
- domain: ErrorDomain.STORAGE,
19364
- category: ErrorCategory.THIRD_PARTY,
19365
- details: { id: input.id }
19366
- });
19367
- }
19368
- const row = current.rows[0];
19369
- let existingChunks = [];
19370
- if (row.bufferedObservationChunks) {
19410
+ await withClientWriteLock(this.#client, async () => {
19411
+ const tx = await this.#client.transaction("write");
19371
19412
  try {
19372
- const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
19373
- existingChunks = Array.isArray(parsed) ? parsed : [];
19374
- } catch {
19375
- existingChunks = [];
19413
+ const current = await tx.execute({
19414
+ sql: `SELECT "bufferedObservationChunks" FROM "${OM_TABLE}" WHERE id = ?`,
19415
+ args: [input.id]
19416
+ });
19417
+ if (!current.rows || current.rows.length === 0) {
19418
+ throw new MastraError({
19419
+ id: createStorageErrorId("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
19420
+ text: `Observational memory record not found: ${input.id}`,
19421
+ domain: ErrorDomain.STORAGE,
19422
+ category: ErrorCategory.THIRD_PARTY,
19423
+ details: { id: input.id }
19424
+ });
19425
+ }
19426
+ const row = current.rows[0];
19427
+ let existingChunks = [];
19428
+ if (row.bufferedObservationChunks) {
19429
+ try {
19430
+ const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
19431
+ existingChunks = Array.isArray(parsed) ? parsed : [];
19432
+ } catch {
19433
+ existingChunks = [];
19434
+ }
19435
+ }
19436
+ const newChunk = {
19437
+ id: `ombuf-${randomUUID()}`,
19438
+ cycleId: input.chunk.cycleId,
19439
+ observations: input.chunk.observations,
19440
+ tokenCount: input.chunk.tokenCount,
19441
+ messageIds: input.chunk.messageIds,
19442
+ messageTokens: input.chunk.messageTokens,
19443
+ lastObservedAt: input.chunk.lastObservedAt,
19444
+ createdAt: /* @__PURE__ */ new Date(),
19445
+ suggestedContinuation: input.chunk.suggestedContinuation,
19446
+ currentTask: input.chunk.currentTask,
19447
+ threadTitle: input.chunk.threadTitle,
19448
+ extractedValues: input.chunk.extractedValues,
19449
+ extractionFailures: input.chunk.extractionFailures
19450
+ };
19451
+ const newChunks = [...existingChunks, newChunk];
19452
+ const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
19453
+ const result = await tx.execute({
19454
+ sql: `UPDATE "${OM_TABLE}" SET
19455
+ "bufferedObservationChunks" = ?,
19456
+ "lastBufferedAtTime" = COALESCE(?, "lastBufferedAtTime"),
19457
+ "updatedAt" = ?
19458
+ WHERE id = ?`,
19459
+ args: [JSON.stringify(newChunks), lastBufferedAtTime, nowStr, input.id]
19460
+ });
19461
+ if (result.rowsAffected === 0) {
19462
+ throw new MastraError({
19463
+ id: createStorageErrorId("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
19464
+ text: `Observational memory record not found: ${input.id}`,
19465
+ domain: ErrorDomain.STORAGE,
19466
+ category: ErrorCategory.THIRD_PARTY,
19467
+ details: { id: input.id }
19468
+ });
19469
+ }
19470
+ await tx.commit();
19471
+ } catch (error) {
19472
+ if (!tx.closed) await tx.rollback();
19473
+ throw error;
19376
19474
  }
19377
- }
19378
- const newChunk = {
19379
- id: `ombuf-${randomUUID()}`,
19380
- cycleId: input.chunk.cycleId,
19381
- observations: input.chunk.observations,
19382
- tokenCount: input.chunk.tokenCount,
19383
- messageIds: input.chunk.messageIds,
19384
- messageTokens: input.chunk.messageTokens,
19385
- lastObservedAt: input.chunk.lastObservedAt,
19386
- createdAt: /* @__PURE__ */ new Date(),
19387
- suggestedContinuation: input.chunk.suggestedContinuation,
19388
- currentTask: input.chunk.currentTask,
19389
- threadTitle: input.chunk.threadTitle,
19390
- extractedValues: input.chunk.extractedValues,
19391
- extractionFailures: input.chunk.extractionFailures
19392
- };
19393
- const newChunks = [...existingChunks, newChunk];
19394
- const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
19395
- const result = await this.#client.execute({
19396
- sql: `UPDATE "${OM_TABLE}" SET
19397
- "bufferedObservationChunks" = ?,
19398
- "lastBufferedAtTime" = COALESCE(?, "lastBufferedAtTime"),
19399
- "updatedAt" = ?
19400
- WHERE id = ?`,
19401
- args: [JSON.stringify(newChunks), lastBufferedAtTime, nowStr, input.id]
19402
19475
  });
19403
- if (result.rowsAffected === 0) {
19404
- throw new MastraError({
19405
- id: createStorageErrorId("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
19406
- text: `Observational memory record not found: ${input.id}`,
19407
- domain: ErrorDomain.STORAGE,
19408
- category: ErrorCategory.THIRD_PARTY,
19409
- details: { id: input.id }
19410
- });
19411
- }
19412
19476
  } catch (error) {
19413
19477
  if (error instanceof MastraError) {
19414
19478
  throw error;
@@ -19427,150 +19491,160 @@ Note: This migration may take some time for large tables.
19427
19491
  async swapBufferedToActive(input) {
19428
19492
  try {
19429
19493
  const nowStr = (/* @__PURE__ */ new Date()).toISOString();
19430
- const current = await this.#client.execute({
19431
- sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
19432
- args: [input.id]
19433
- });
19434
- if (!current.rows || current.rows.length === 0) {
19435
- throw new MastraError({
19436
- id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_TO_ACTIVE", "NOT_FOUND"),
19437
- text: `Observational memory record not found: ${input.id}`,
19438
- domain: ErrorDomain.STORAGE,
19439
- category: ErrorCategory.THIRD_PARTY,
19440
- details: { id: input.id }
19441
- });
19442
- }
19443
- const row = current.rows[0];
19444
- let chunks = [];
19445
- if (row.bufferedObservationChunks) {
19494
+ return await withClientWriteLock(this.#client, async () => {
19495
+ const tx = await this.#client.transaction("write");
19446
19496
  try {
19447
- const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
19448
- chunks = Array.isArray(parsed) ? parsed : [];
19449
- } catch {
19450
- chunks = [];
19451
- }
19452
- }
19453
- if (chunks.length === 0) {
19454
- return {
19455
- chunksActivated: 0,
19456
- messageTokensActivated: 0,
19457
- observationTokensActivated: 0,
19458
- messagesActivated: 0,
19459
- activatedCycleIds: [],
19460
- activatedMessageIds: []
19461
- };
19462
- }
19463
- const retentionFloor = input.messageTokensThreshold * (1 - input.activationRatio);
19464
- const targetMessageTokens = Math.max(0, input.currentPendingTokens - retentionFloor);
19465
- let cumulativeMessageTokens = 0;
19466
- let bestOverBoundary = 0;
19467
- let bestOverTokens = 0;
19468
- let bestUnderBoundary = 0;
19469
- let bestUnderTokens = 0;
19470
- for (let i = 0; i < chunks.length; i++) {
19471
- cumulativeMessageTokens += chunks[i].messageTokens ?? 0;
19472
- const boundary2 = i + 1;
19473
- if (cumulativeMessageTokens >= targetMessageTokens) {
19474
- if (bestOverBoundary === 0 || cumulativeMessageTokens < bestOverTokens) {
19475
- bestOverBoundary = boundary2;
19476
- bestOverTokens = cumulativeMessageTokens;
19497
+ const current = await tx.execute({
19498
+ sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
19499
+ args: [input.id]
19500
+ });
19501
+ if (!current.rows || current.rows.length === 0) {
19502
+ throw new MastraError({
19503
+ id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_TO_ACTIVE", "NOT_FOUND"),
19504
+ text: `Observational memory record not found: ${input.id}`,
19505
+ domain: ErrorDomain.STORAGE,
19506
+ category: ErrorCategory.THIRD_PARTY,
19507
+ details: { id: input.id }
19508
+ });
19477
19509
  }
19478
- } else {
19479
- if (cumulativeMessageTokens > bestUnderTokens) {
19480
- bestUnderBoundary = boundary2;
19481
- bestUnderTokens = cumulativeMessageTokens;
19510
+ const row = current.rows[0];
19511
+ let chunks = [];
19512
+ if (row.bufferedObservationChunks) {
19513
+ try {
19514
+ const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
19515
+ chunks = Array.isArray(parsed) ? parsed : [];
19516
+ } catch {
19517
+ chunks = [];
19518
+ }
19482
19519
  }
19483
- }
19484
- }
19485
- const maxOvershoot = retentionFloor * 0.95;
19486
- const overshoot = bestOverTokens - targetMessageTokens;
19487
- const remainingAfterOver = input.currentPendingTokens - bestOverTokens;
19488
- const remainingAfterUnder = input.currentPendingTokens - bestUnderTokens;
19489
- const minRemaining = Math.min(1e3, retentionFloor);
19490
- let chunksToActivate;
19491
- if (input.forceMaxActivation && bestOverBoundary > 0 && remainingAfterOver >= minRemaining) {
19492
- chunksToActivate = bestOverBoundary;
19493
- } else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && remainingAfterOver >= minRemaining) {
19494
- chunksToActivate = bestOverBoundary;
19495
- } else if (bestUnderBoundary > 0 && remainingAfterUnder >= minRemaining) {
19496
- chunksToActivate = bestUnderBoundary;
19497
- } else if (bestOverBoundary > 0) {
19498
- chunksToActivate = bestOverBoundary;
19499
- } else {
19500
- chunksToActivate = 1;
19501
- }
19502
- const activatedChunks = chunks.slice(0, chunksToActivate);
19503
- const remainingChunks = chunks.slice(chunksToActivate);
19504
- const activatedContent = activatedChunks.map((c) => c.observations).join("\n\n");
19505
- const activatedTokens = activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0);
19506
- const activatedMessageTokens = activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0);
19507
- const activatedMessageCount = activatedChunks.reduce((sum, c) => sum + c.messageIds.length, 0);
19508
- const activatedCycleIds = activatedChunks.map((c) => c.cycleId).filter((id) => !!id);
19509
- const activatedMessageIds = activatedChunks.flatMap((c) => c.messageIds ?? []);
19510
- const latestChunk = activatedChunks[activatedChunks.length - 1];
19511
- const lastObservedAt = input.lastObservedAt ?? (latestChunk?.lastObservedAt ? new Date(latestChunk.lastObservedAt) : /* @__PURE__ */ new Date());
19512
- const lastObservedAtStr = lastObservedAt.toISOString();
19513
- const existingActive = row.activeObservations || "";
19514
- const existingTokenCount = Number(row.observationTokenCount || 0);
19515
- const boundary = `
19520
+ if (chunks.length === 0) {
19521
+ await tx.commit();
19522
+ return {
19523
+ chunksActivated: 0,
19524
+ messageTokensActivated: 0,
19525
+ observationTokensActivated: 0,
19526
+ messagesActivated: 0,
19527
+ activatedCycleIds: [],
19528
+ activatedMessageIds: []
19529
+ };
19530
+ }
19531
+ const retentionFloor = input.messageTokensThreshold * (1 - input.activationRatio);
19532
+ const targetMessageTokens = Math.max(0, input.currentPendingTokens - retentionFloor);
19533
+ let cumulativeMessageTokens = 0;
19534
+ let bestOverBoundary = 0;
19535
+ let bestOverTokens = 0;
19536
+ let bestUnderBoundary = 0;
19537
+ let bestUnderTokens = 0;
19538
+ for (let i = 0; i < chunks.length; i++) {
19539
+ cumulativeMessageTokens += chunks[i].messageTokens ?? 0;
19540
+ const boundary2 = i + 1;
19541
+ if (cumulativeMessageTokens >= targetMessageTokens) {
19542
+ if (bestOverBoundary === 0 || cumulativeMessageTokens < bestOverTokens) {
19543
+ bestOverBoundary = boundary2;
19544
+ bestOverTokens = cumulativeMessageTokens;
19545
+ }
19546
+ } else {
19547
+ if (cumulativeMessageTokens > bestUnderTokens) {
19548
+ bestUnderBoundary = boundary2;
19549
+ bestUnderTokens = cumulativeMessageTokens;
19550
+ }
19551
+ }
19552
+ }
19553
+ const maxOvershoot = retentionFloor * 0.95;
19554
+ const overshoot = bestOverTokens - targetMessageTokens;
19555
+ const remainingAfterOver = input.currentPendingTokens - bestOverTokens;
19556
+ const remainingAfterUnder = input.currentPendingTokens - bestUnderTokens;
19557
+ const minRemaining = Math.min(1e3, retentionFloor);
19558
+ let chunksToActivate;
19559
+ if (input.forceMaxActivation && bestOverBoundary > 0 && remainingAfterOver >= minRemaining) {
19560
+ chunksToActivate = bestOverBoundary;
19561
+ } else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && remainingAfterOver >= minRemaining) {
19562
+ chunksToActivate = bestOverBoundary;
19563
+ } else if (bestUnderBoundary > 0 && remainingAfterUnder >= minRemaining) {
19564
+ chunksToActivate = bestUnderBoundary;
19565
+ } else if (bestOverBoundary > 0) {
19566
+ chunksToActivate = bestOverBoundary;
19567
+ } else {
19568
+ chunksToActivate = 1;
19569
+ }
19570
+ const activatedChunks = chunks.slice(0, chunksToActivate);
19571
+ const remainingChunks = chunks.slice(chunksToActivate);
19572
+ const activatedContent = activatedChunks.map((c) => c.observations).join("\n\n");
19573
+ const activatedTokens = activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0);
19574
+ const activatedMessageTokens = activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0);
19575
+ const activatedMessageCount = activatedChunks.reduce((sum, c) => sum + c.messageIds.length, 0);
19576
+ const activatedCycleIds = activatedChunks.map((c) => c.cycleId).filter((id) => !!id);
19577
+ const activatedMessageIds = activatedChunks.flatMap((c) => c.messageIds ?? []);
19578
+ const latestChunk = activatedChunks[activatedChunks.length - 1];
19579
+ const lastObservedAt = input.lastObservedAt ?? (latestChunk?.lastObservedAt ? new Date(latestChunk.lastObservedAt) : /* @__PURE__ */ new Date());
19580
+ const lastObservedAtStr = lastObservedAt.toISOString();
19581
+ const existingActive = row.activeObservations || "";
19582
+ const existingTokenCount = Number(row.observationTokenCount || 0);
19583
+ const boundary = `
19516
19584
 
19517
19585
  --- message boundary (${lastObservedAt.toISOString()}) ---
19518
19586
 
19519
19587
  `;
19520
- const newActive = existingActive ? `${existingActive}${boundary}${activatedContent}` : activatedContent;
19521
- const newTokenCount = existingTokenCount + activatedTokens;
19522
- const existingPending = Number(row.pendingMessageTokens || 0);
19523
- const newPending = Math.max(0, existingPending - activatedMessageTokens);
19524
- const updateResult = await this.#client.execute({
19525
- sql: `UPDATE "${OM_TABLE}" SET
19526
- "activeObservations" = ?,
19527
- "observationTokenCount" = ?,
19528
- "pendingMessageTokens" = ?,
19529
- "bufferedObservationChunks" = ?,
19530
- "lastObservedAt" = ?,
19531
- "updatedAt" = ?
19532
- WHERE id = ?
19533
- AND "bufferedObservationChunks" IS NOT NULL
19534
- AND "bufferedObservationChunks" != '[]'`,
19535
- args: [
19536
- newActive,
19537
- newTokenCount,
19538
- newPending,
19539
- remainingChunks.length > 0 ? JSON.stringify(remainingChunks) : null,
19540
- lastObservedAtStr,
19541
- nowStr,
19542
- input.id
19543
- ]
19588
+ const newActive = existingActive ? `${existingActive}${boundary}${activatedContent}` : activatedContent;
19589
+ const newTokenCount = existingTokenCount + activatedTokens;
19590
+ const existingPending = Number(row.pendingMessageTokens || 0);
19591
+ const newPending = Math.max(0, existingPending - activatedMessageTokens);
19592
+ const updateResult = await tx.execute({
19593
+ sql: `UPDATE "${OM_TABLE}" SET
19594
+ "activeObservations" = ?,
19595
+ "observationTokenCount" = ?,
19596
+ "pendingMessageTokens" = ?,
19597
+ "bufferedObservationChunks" = ?,
19598
+ "lastObservedAt" = ?,
19599
+ "updatedAt" = ?
19600
+ WHERE id = ?
19601
+ AND "bufferedObservationChunks" IS NOT NULL
19602
+ AND "bufferedObservationChunks" != '[]'`,
19603
+ args: [
19604
+ newActive,
19605
+ newTokenCount,
19606
+ newPending,
19607
+ remainingChunks.length > 0 ? JSON.stringify(remainingChunks) : null,
19608
+ lastObservedAtStr,
19609
+ nowStr,
19610
+ input.id
19611
+ ]
19612
+ });
19613
+ await tx.commit();
19614
+ if (updateResult.rowsAffected === 0) {
19615
+ return {
19616
+ chunksActivated: 0,
19617
+ messageTokensActivated: 0,
19618
+ observationTokensActivated: 0,
19619
+ messagesActivated: 0,
19620
+ activatedCycleIds: [],
19621
+ activatedMessageIds: []
19622
+ };
19623
+ }
19624
+ const latestChunkHints = activatedChunks[activatedChunks.length - 1];
19625
+ return {
19626
+ chunksActivated: activatedChunks.length,
19627
+ messageTokensActivated: activatedMessageTokens,
19628
+ observationTokensActivated: activatedTokens,
19629
+ messagesActivated: activatedMessageCount,
19630
+ activatedCycleIds,
19631
+ activatedMessageIds,
19632
+ observations: activatedContent,
19633
+ perChunk: activatedChunks.map((c) => ({
19634
+ cycleId: c.cycleId ?? "",
19635
+ messageTokens: c.messageTokens ?? 0,
19636
+ observationTokens: c.tokenCount,
19637
+ messageCount: c.messageIds.length,
19638
+ observations: c.observations
19639
+ })),
19640
+ suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
19641
+ currentTask: latestChunkHints?.currentTask ?? void 0
19642
+ };
19643
+ } catch (error) {
19644
+ if (!tx.closed) await tx.rollback();
19645
+ throw error;
19646
+ }
19544
19647
  });
19545
- if (updateResult.rowsAffected === 0) {
19546
- return {
19547
- chunksActivated: 0,
19548
- messageTokensActivated: 0,
19549
- observationTokensActivated: 0,
19550
- messagesActivated: 0,
19551
- activatedCycleIds: [],
19552
- activatedMessageIds: []
19553
- };
19554
- }
19555
- const latestChunkHints = activatedChunks[activatedChunks.length - 1];
19556
- return {
19557
- chunksActivated: activatedChunks.length,
19558
- messageTokensActivated: activatedMessageTokens,
19559
- observationTokensActivated: activatedTokens,
19560
- messagesActivated: activatedMessageCount,
19561
- activatedCycleIds,
19562
- activatedMessageIds,
19563
- observations: activatedContent,
19564
- perChunk: activatedChunks.map((c) => ({
19565
- cycleId: c.cycleId ?? "",
19566
- messageTokens: c.messageTokens ?? 0,
19567
- observationTokens: c.tokenCount,
19568
- messageCount: c.messageIds.length,
19569
- observations: c.observations
19570
- })),
19571
- suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
19572
- currentTask: latestChunkHints?.currentTask ?? void 0
19573
- };
19574
19648
  } catch (error) {
19575
19649
  if (error instanceof MastraError) {
19576
19650
  throw error;
@@ -19589,28 +19663,31 @@ Note: This migration may take some time for large tables.
19589
19663
  async updateBufferedReflection(input) {
19590
19664
  try {
19591
19665
  const nowStr = (/* @__PURE__ */ new Date()).toISOString();
19592
- const result = await this.#client.execute({
19593
- sql: `UPDATE "${OM_TABLE}" SET
19594
- "bufferedReflection" = CASE
19595
- WHEN "bufferedReflection" IS NOT NULL AND "bufferedReflection" != ''
19596
- THEN "bufferedReflection" || char(10) || char(10) || ?
19597
- ELSE ?
19598
- END,
19599
- "bufferedReflectionTokens" = COALESCE("bufferedReflectionTokens", 0) + ?,
19600
- "bufferedReflectionInputTokens" = COALESCE("bufferedReflectionInputTokens", 0) + ?,
19601
- "reflectedObservationLineCount" = ?,
19602
- "updatedAt" = ?
19603
- WHERE id = ?`,
19604
- args: [
19605
- input.reflection,
19606
- input.reflection,
19607
- input.tokenCount,
19608
- input.inputTokenCount,
19609
- input.reflectedObservationLineCount,
19610
- nowStr,
19611
- input.id
19612
- ]
19613
- });
19666
+ const result = await withClientWriteLock(
19667
+ this.#client,
19668
+ () => this.#client.execute({
19669
+ sql: `UPDATE "${OM_TABLE}" SET
19670
+ "bufferedReflection" = CASE
19671
+ WHEN "bufferedReflection" IS NOT NULL AND "bufferedReflection" != ''
19672
+ THEN "bufferedReflection" || char(10) || char(10) || ?
19673
+ ELSE ?
19674
+ END,
19675
+ "bufferedReflectionTokens" = COALESCE("bufferedReflectionTokens", 0) + ?,
19676
+ "bufferedReflectionInputTokens" = COALESCE("bufferedReflectionInputTokens", 0) + ?,
19677
+ "reflectedObservationLineCount" = ?,
19678
+ "updatedAt" = ?
19679
+ WHERE id = ?`,
19680
+ args: [
19681
+ input.reflection,
19682
+ input.reflection,
19683
+ input.tokenCount,
19684
+ input.inputTokenCount,
19685
+ input.reflectedObservationLineCount,
19686
+ nowStr,
19687
+ input.id
19688
+ ]
19689
+ })
19690
+ );
19614
19691
  if (result.rowsAffected === 0) {
19615
19692
  throw new MastraError({
19616
19693
  id: createStorageErrorId("LIBSQL", "UPDATE_BUFFERED_REFLECTION", "NOT_FOUND"),
@@ -19637,55 +19714,64 @@ Note: This migration may take some time for large tables.
19637
19714
  }
19638
19715
  async swapBufferedReflectionToActive(input) {
19639
19716
  try {
19640
- const current = await this.#client.execute({
19641
- sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
19642
- args: [input.currentRecord.id]
19643
- });
19644
- if (!current.rows || current.rows.length === 0) {
19645
- throw new MastraError({
19646
- id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NOT_FOUND"),
19647
- text: `Observational memory record not found: ${input.currentRecord.id}`,
19648
- domain: ErrorDomain.STORAGE,
19649
- category: ErrorCategory.THIRD_PARTY,
19650
- details: { id: input.currentRecord.id }
19651
- });
19652
- }
19653
- const row = current.rows[0];
19654
- const bufferedReflection = row.bufferedReflection || "";
19655
- const reflectedLineCount = Number(row.reflectedObservationLineCount || 0);
19656
- if (!bufferedReflection) {
19657
- throw new MastraError({
19658
- id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NO_CONTENT"),
19659
- text: "No buffered reflection to swap",
19660
- domain: ErrorDomain.STORAGE,
19661
- category: ErrorCategory.USER,
19662
- details: { id: input.currentRecord.id }
19663
- });
19664
- }
19665
- const currentObservations = row.activeObservations || "";
19666
- const allLines = currentObservations.split("\n");
19667
- const unreflectedLines = allLines.slice(reflectedLineCount);
19668
- const unreflectedContent = unreflectedLines.join("\n").trim();
19669
- const newObservations = unreflectedContent ? `${bufferedReflection}
19717
+ return await withClientWriteLock(this.#client, async () => {
19718
+ const tx = await this.#client.transaction("write");
19719
+ try {
19720
+ const current = await tx.execute({
19721
+ sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
19722
+ args: [input.currentRecord.id]
19723
+ });
19724
+ if (!current.rows || current.rows.length === 0) {
19725
+ throw new MastraError({
19726
+ id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NOT_FOUND"),
19727
+ text: `Observational memory record not found: ${input.currentRecord.id}`,
19728
+ domain: ErrorDomain.STORAGE,
19729
+ category: ErrorCategory.THIRD_PARTY,
19730
+ details: { id: input.currentRecord.id }
19731
+ });
19732
+ }
19733
+ const row = current.rows[0];
19734
+ const bufferedReflection = row.bufferedReflection || "";
19735
+ const reflectedLineCount = Number(row.reflectedObservationLineCount || 0);
19736
+ if (!bufferedReflection) {
19737
+ throw new MastraError({
19738
+ id: createStorageErrorId("LIBSQL", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NO_CONTENT"),
19739
+ text: "No buffered reflection to swap",
19740
+ domain: ErrorDomain.STORAGE,
19741
+ category: ErrorCategory.USER,
19742
+ details: { id: input.currentRecord.id }
19743
+ });
19744
+ }
19745
+ const currentObservations = row.activeObservations || "";
19746
+ const allLines = currentObservations.split("\n");
19747
+ const unreflectedLines = allLines.slice(reflectedLineCount);
19748
+ const unreflectedContent = unreflectedLines.join("\n").trim();
19749
+ const newObservations = unreflectedContent ? `${bufferedReflection}
19670
19750
 
19671
19751
  ${unreflectedContent}` : bufferedReflection;
19672
- const newRecord = await this.createReflectionGeneration({
19673
- currentRecord: input.currentRecord,
19674
- reflection: newObservations,
19675
- tokenCount: input.tokenCount
19676
- });
19677
- const nowStr = (/* @__PURE__ */ new Date()).toISOString();
19678
- await this.#client.execute({
19679
- sql: `UPDATE "${OM_TABLE}" SET
19680
- "bufferedReflection" = NULL,
19681
- "bufferedReflectionTokens" = NULL,
19682
- "bufferedReflectionInputTokens" = NULL,
19683
- "reflectedObservationLineCount" = NULL,
19684
- "updatedAt" = ?
19685
- WHERE id = ?`,
19686
- args: [nowStr, input.currentRecord.id]
19752
+ const newRecord = await this.#insertReflectionGeneration(tx, {
19753
+ currentRecord: input.currentRecord,
19754
+ reflection: newObservations,
19755
+ tokenCount: input.tokenCount
19756
+ });
19757
+ const nowStr = (/* @__PURE__ */ new Date()).toISOString();
19758
+ await tx.execute({
19759
+ sql: `UPDATE "${OM_TABLE}" SET
19760
+ "bufferedReflection" = NULL,
19761
+ "bufferedReflectionTokens" = NULL,
19762
+ "bufferedReflectionInputTokens" = NULL,
19763
+ "reflectedObservationLineCount" = NULL,
19764
+ "updatedAt" = ?
19765
+ WHERE id = ?`,
19766
+ args: [nowStr, input.currentRecord.id]
19767
+ });
19768
+ await tx.commit();
19769
+ return newRecord;
19770
+ } catch (error) {
19771
+ if (!tx.closed) await tx.rollback();
19772
+ throw error;
19773
+ }
19687
19774
  });
19688
- return newRecord;
19689
19775
  } catch (error) {
19690
19776
  if (error instanceof MastraError) {
19691
19777
  throw error;