@mastra/libsql 1.26.0 → 1.26.1-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/_types/@internal_core/dist/memory/index.d.ts +102 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-deployment-workers.md +1 -1
- package/dist/docs/references/docs-memory-multi-user-threads.md +1 -1
- package/dist/docs/references/reference-storage-composite.md +34 -0
- package/dist/docs/references/reference-vectors-libsql.md +1 -1
- package/dist/index.cjs +684 -484
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +684 -484
- package/dist/index.js.map +1 -1
- package/dist/shared/single-connection-client.d.ts +1 -1
- package/dist/shared/single-connection-client.d.ts.map +1 -1
- package/dist/storage/db/client.d.ts +2 -0
- package/dist/storage/db/client.d.ts.map +1 -1
- package/dist/storage/db/index.d.ts +6 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +3 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/dist/storage/domains/workflows/index.d.ts.map +1 -1
- package/dist/storage/factory-storage.d.ts.map +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/package.json +4 -4
package/dist/index.cjs
CHANGED
|
@@ -374,7 +374,7 @@ function isSingleConnectionDatabase({ url, syncUrl }) {
|
|
|
374
374
|
* transactions rather than failing with `TRANSACTION_ACTIVE`.
|
|
375
375
|
*
|
|
376
376
|
* `transaction()` takes the gate and releases it when the transaction commits,
|
|
377
|
-
* rolls back, or closes. `execute`, `batch`, `executeMultiple`, and `
|
|
377
|
+
* rolls back, or closes. `execute`, `batch`, `executeMultiple`, `migrate`, and `sync`
|
|
378
378
|
* wait for the gate to be free before running but do not hold it — the driver
|
|
379
379
|
* executes them synchronously on the connection, so they cannot interleave
|
|
380
380
|
* with each other. Every other member passes through untouched.
|
|
@@ -425,7 +425,8 @@ function gateSingleConnectionClient(client) {
|
|
|
425
425
|
case "execute":
|
|
426
426
|
case "batch":
|
|
427
427
|
case "executeMultiple":
|
|
428
|
-
case "migrate":
|
|
428
|
+
case "migrate":
|
|
429
|
+
case "sync": return (...args) => waitForGate(() => target[prop].apply(target, args));
|
|
429
430
|
default: {
|
|
430
431
|
const value = Reflect.get(target, prop);
|
|
431
432
|
return typeof value === "function" ? value.bind(target) : value;
|
|
@@ -9288,6 +9289,92 @@ var MCPServersLibSQL = class extends _mastra_core_storage.MCPServersStorage {
|
|
|
9288
9289
|
}
|
|
9289
9290
|
};
|
|
9290
9291
|
//#endregion
|
|
9292
|
+
//#region ../../packages/_internal-core/dist/memory/index.js
|
|
9293
|
+
/**
|
|
9294
|
+
* Shared rules for observational memory lifecycle writes. Every storage adapter applies
|
|
9295
|
+
* these inside its own atomic section (lock, transaction, or conditional update), so the
|
|
9296
|
+
* decisions are identical across adapters.
|
|
9297
|
+
*/
|
|
9298
|
+
/**
|
|
9299
|
+
* Observational memory columns that lifecycle writes depend on. Storage adapters merge these
|
|
9300
|
+
* into the table schema they get from `@mastra/core`, so the columns exist even when the
|
|
9301
|
+
* installed core predates them.
|
|
9302
|
+
*/
|
|
9303
|
+
const OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS = { supersededBy: {
|
|
9304
|
+
type: "text",
|
|
9305
|
+
nullable: true
|
|
9306
|
+
} };
|
|
9307
|
+
/** `schema` plus {@link OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS}; `undefined` when `schema` is. */
|
|
9308
|
+
function withObservationalMemoryLifecycleColumns(schema) {
|
|
9309
|
+
return schema ? {
|
|
9310
|
+
...schema,
|
|
9311
|
+
...OBSERVATIONAL_MEMORY_LIFECYCLE_COLUMNS
|
|
9312
|
+
} : void 0;
|
|
9313
|
+
}
|
|
9314
|
+
/**
|
|
9315
|
+
* A buffered chunk stores `lastObservedAt = max message time + 1ms`. It is wholly covered
|
|
9316
|
+
* (every message it observed is already at or before the cursor) iff
|
|
9317
|
+
* `cursor >= chunk.lastObservedAt - 1ms`.
|
|
9318
|
+
*/
|
|
9319
|
+
function isBufferedChunkCoveredByCursor(chunkLastObservedAt, cursor) {
|
|
9320
|
+
if (!cursor) return false;
|
|
9321
|
+
return new Date(cursor).getTime() >= new Date(chunkLastObservedAt).getTime() - 1;
|
|
9322
|
+
}
|
|
9323
|
+
/** The later of two cursors; `undefined` only when both are absent. */
|
|
9324
|
+
function maxObservationCursor(a, b) {
|
|
9325
|
+
if (!a) return b ? new Date(b) : void 0;
|
|
9326
|
+
if (!b) return new Date(a);
|
|
9327
|
+
return new Date(Math.max(new Date(a).getTime(), new Date(b).getTime()));
|
|
9328
|
+
}
|
|
9329
|
+
/**
|
|
9330
|
+
* Decide the new generation's text when a reflection built from `snapshot` commits against
|
|
9331
|
+
* the stored record.
|
|
9332
|
+
*
|
|
9333
|
+
* - Stored text equals the snapshot: the reflection replaces it.
|
|
9334
|
+
* - Stored text extends the snapshot (activation only appends): the appended tail is kept
|
|
9335
|
+
* after the reflection, and its tokens are added.
|
|
9336
|
+
* - Anything else (a non-append rewrite): `null` — the reflection must not be applied.
|
|
9337
|
+
*/
|
|
9338
|
+
function planReflectionGenerationText(input) {
|
|
9339
|
+
const stored = input.storedObservations ?? "";
|
|
9340
|
+
const snapshot = input.snapshotObservations ?? "";
|
|
9341
|
+
if (stored === snapshot) return {
|
|
9342
|
+
mode: "equal",
|
|
9343
|
+
observations: input.reflection,
|
|
9344
|
+
tokenCount: input.tokenCount
|
|
9345
|
+
};
|
|
9346
|
+
if (!stored.startsWith(snapshot)) return null;
|
|
9347
|
+
const tail = stored.slice(snapshot.length).trimStart();
|
|
9348
|
+
if (!tail.trim()) return {
|
|
9349
|
+
mode: "equal",
|
|
9350
|
+
observations: input.reflection,
|
|
9351
|
+
tokenCount: input.tokenCount
|
|
9352
|
+
};
|
|
9353
|
+
return {
|
|
9354
|
+
mode: "append",
|
|
9355
|
+
observations: input.reflection ? `${input.reflection}\n\n${tail}` : tail,
|
|
9356
|
+
tokenCount: input.tokenCount + Math.max(0, (input.storedObservationTokenCount ?? 0) - (input.snapshotObservationTokenCount ?? 0))
|
|
9357
|
+
};
|
|
9358
|
+
}
|
|
9359
|
+
/**
|
|
9360
|
+
* Backs `updateActiveObservations` in adapters that implement `commitActiveObservations`.
|
|
9361
|
+
* Callers of `updateActiveObservations` (which resolves `void`) can't see a commit result, so a
|
|
9362
|
+
* write that was not applied throws instead of resolving as if it had committed.
|
|
9363
|
+
*/
|
|
9364
|
+
function assertActiveObservationsApplied(result, id) {
|
|
9365
|
+
if (result.applied) return;
|
|
9366
|
+
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`);
|
|
9367
|
+
}
|
|
9368
|
+
/**
|
|
9369
|
+
* Whether the stored text can still accept a reflection built from `snapshot`
|
|
9370
|
+
* (equal, or only appended to since).
|
|
9371
|
+
*/
|
|
9372
|
+
function isAppendOnlySince(storedObservations, snapshotObservations) {
|
|
9373
|
+
const stored = storedObservations ?? "";
|
|
9374
|
+
const snapshot = snapshotObservations ?? "";
|
|
9375
|
+
return stored === snapshot || stored.startsWith(snapshot);
|
|
9376
|
+
}
|
|
9377
|
+
//#endregion
|
|
9291
9378
|
//#region src/storage/domains/memory/index.ts
|
|
9292
9379
|
/**
|
|
9293
9380
|
* Local constant for the observational memory table name.
|
|
@@ -9295,6 +9382,13 @@ var MCPServersLibSQL = class extends _mastra_core_storage.MCPServersStorage {
|
|
|
9295
9382
|
* versions that don't export TABLE_OBSERVATIONAL_MEMORY.
|
|
9296
9383
|
*/
|
|
9297
9384
|
const OM_TABLE = "mastra_observational_memory";
|
|
9385
|
+
/** Canonical head order: newest generation, then earliest createdAt, then lowest id. */
|
|
9386
|
+
const OM_HEAD_ORDER = `"generationCount" DESC, "createdAt" ASC, id ASC`;
|
|
9387
|
+
/** Lifecycle writes aimed at a retired record follow `supersededBy` to the head at most this many times. */
|
|
9388
|
+
const OM_MAX_HEAD_HOPS = 3;
|
|
9389
|
+
/** Optimistic lifecycle writes rerun at most this many times when another process changes the row. */
|
|
9390
|
+
const OM_MAX_CAS_ATTEMPTS = 10;
|
|
9391
|
+
const OM_CAS_CONFLICT = Symbol("om-cas-conflict");
|
|
9298
9392
|
function addSqliteMetadataFilter(conditions, params, metadataFilter) {
|
|
9299
9393
|
if (!metadataFilter) return;
|
|
9300
9394
|
for (const [key, value] of Object.entries(metadataFilter)) {
|
|
@@ -9360,11 +9454,13 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
9360
9454
|
}
|
|
9361
9455
|
};
|
|
9362
9456
|
#client;
|
|
9457
|
+
#embeddedReplica;
|
|
9363
9458
|
#db;
|
|
9364
9459
|
constructor(config) {
|
|
9365
9460
|
super();
|
|
9366
9461
|
const client = resolveClient(config);
|
|
9367
9462
|
this.#client = client;
|
|
9463
|
+
this.#embeddedReplica = config.embeddedReplica === true;
|
|
9368
9464
|
this.#db = new LibSQLDB({
|
|
9369
9465
|
client,
|
|
9370
9466
|
maxRetries: config.maxRetries,
|
|
@@ -9403,7 +9499,7 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
9403
9499
|
tableName: _mastra_core_storage.TABLE_MEMORY_RUN_FENCES,
|
|
9404
9500
|
schema: _mastra_core_storage.RUN_FENCING_TABLE_SCHEMAS[_mastra_core_storage.TABLE_MEMORY_RUN_FENCES]
|
|
9405
9501
|
});
|
|
9406
|
-
const omSchema = _mastra_core_storage.OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE];
|
|
9502
|
+
const omSchema = withObservationalMemoryLifecycleColumns(_mastra_core_storage.OBSERVATIONAL_MEMORY_TABLE_SCHEMA?.[OM_TABLE]);
|
|
9407
9503
|
if (omSchema) {
|
|
9408
9504
|
await this.#db.createTable({
|
|
9409
9505
|
tableName: OM_TABLE,
|
|
@@ -9427,7 +9523,8 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
9427
9523
|
"isBufferingReflection",
|
|
9428
9524
|
"lastBufferedAtTokens",
|
|
9429
9525
|
"lastBufferedAtTime",
|
|
9430
|
-
"metadata"
|
|
9526
|
+
"metadata",
|
|
9527
|
+
"supersededBy"
|
|
9431
9528
|
]
|
|
9432
9529
|
});
|
|
9433
9530
|
}
|
|
@@ -9443,10 +9540,13 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
9443
9540
|
sql: `CREATE INDEX IF NOT EXISTS idx_messages_thread_resource_created_at ON ${_mastra_core_storage.TABLE_MESSAGES} (thread_id, "resourceId", "createdAt")`,
|
|
9444
9541
|
args: []
|
|
9445
9542
|
}], "write");
|
|
9446
|
-
if (omSchema)
|
|
9447
|
-
|
|
9448
|
-
|
|
9449
|
-
|
|
9543
|
+
if (omSchema) {
|
|
9544
|
+
await this.#client.execute({
|
|
9545
|
+
sql: `CREATE INDEX IF NOT EXISTS idx_om_lookup_key ON "${OM_TABLE}" ("lookupKey")`,
|
|
9546
|
+
args: []
|
|
9547
|
+
});
|
|
9548
|
+
await this.#backfillSupersededBy();
|
|
9549
|
+
}
|
|
9450
9550
|
}
|
|
9451
9551
|
async dangerouslyClearAll() {
|
|
9452
9552
|
await this.init();
|
|
@@ -10580,18 +10680,218 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10580
10680
|
config: row.config ? JSON.parse(row.config) : {},
|
|
10581
10681
|
metadata: row.metadata ? JSON.parse(row.metadata) : void 0,
|
|
10582
10682
|
observedMessageIds: row.observedMessageIds ? JSON.parse(row.observedMessageIds) : void 0,
|
|
10583
|
-
observedTimezone: row.observedTimezone || void 0
|
|
10683
|
+
observedTimezone: row.observedTimezone || void 0,
|
|
10684
|
+
supersededBy: row.supersededBy ?? null
|
|
10584
10685
|
};
|
|
10585
10686
|
}
|
|
10687
|
+
/**
|
|
10688
|
+
* Runs one optimistic lifecycle write under the client write lock (in-process ordering).
|
|
10689
|
+
* `attempt` reads the rows it needs, then writes with statements guarded by those reads
|
|
10690
|
+
* (`#readOMRow`'s guard); it returns `OM_CAS_CONFLICT` when a guard matched no row because
|
|
10691
|
+
* another process changed the row in between, and the attempt reruns on fresh state.
|
|
10692
|
+
*
|
|
10693
|
+
* No interactive transaction is held across `await`s: the `libsql` driver is synchronous, so
|
|
10694
|
+
* an open write transaction makes any other connection's write in this process block the
|
|
10695
|
+
* event loop until `busy_timeout` (SQLITE_BUSY). Each statement or batch here runs in one call.
|
|
10696
|
+
*
|
|
10697
|
+
* With `fencedOperation`, a write made inside a run fence scope is fenced: each attempt first
|
|
10698
|
+
* checks the run's claim, and the attempt's reads put the claim into their guards, so a claim
|
|
10699
|
+
* taken over between the check and the write turns the write into a conflict and the next
|
|
10700
|
+
* attempt's check rejects it.
|
|
10701
|
+
*/
|
|
10702
|
+
async #withOMCas(operation, attempt, fencedOperation) {
|
|
10703
|
+
const check = fencedOperation ? this.#runFenceCheck(void 0, fencedOperation) : void 0;
|
|
10704
|
+
return this.#write(operation, async () => {
|
|
10705
|
+
for (let i = 0; i < OM_MAX_CAS_ATTEMPTS; i++) {
|
|
10706
|
+
if (check) await assertRunFence(this.#client, check);
|
|
10707
|
+
const result = await attempt(i, check);
|
|
10708
|
+
if (result !== OM_CAS_CONFLICT) return result;
|
|
10709
|
+
if (this.#embeddedReplica) await this.#client.sync?.();
|
|
10710
|
+
}
|
|
10711
|
+
throw new _mastra_core_error.MastraError({
|
|
10712
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", operation, "CONFLICT"),
|
|
10713
|
+
text: `Observational memory write kept conflicting with concurrent writers (${OM_MAX_CAS_ATTEMPTS} attempts)`,
|
|
10714
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
10715
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY
|
|
10716
|
+
});
|
|
10717
|
+
});
|
|
10718
|
+
}
|
|
10719
|
+
/**
|
|
10720
|
+
* Whether a missing row may only be missing from this embedded replica's local copy: the first
|
|
10721
|
+
* attempt reads before any sync, so it returns a conflict to sync and read again instead of
|
|
10722
|
+
* acting on the absence.
|
|
10723
|
+
*/
|
|
10724
|
+
#mayBeUnsynced(attemptIndex) {
|
|
10725
|
+
return this.#embeddedReplica && attemptIndex === 0;
|
|
10726
|
+
}
|
|
10727
|
+
/**
|
|
10728
|
+
* With `check`, the guard also requires the run's claim to still match it, so a guarded write
|
|
10729
|
+
* made after the claim was taken over matches no row.
|
|
10730
|
+
*/
|
|
10731
|
+
#toOMRow(result, check) {
|
|
10732
|
+
const row = result.rows?.[0];
|
|
10733
|
+
if (!row) return null;
|
|
10734
|
+
const columns = result.columns;
|
|
10735
|
+
const guard = {
|
|
10736
|
+
sql: columns.map((c) => `"${c}" IS ?`).join(" AND "),
|
|
10737
|
+
args: columns.map((c) => row[c])
|
|
10738
|
+
};
|
|
10739
|
+
if (check) {
|
|
10740
|
+
guard.sql += ` AND EXISTS (SELECT 1 FROM ${check.claimsTable} WHERE runId = ? AND generation = ? AND ownerId = ?)`;
|
|
10741
|
+
guard.args.push(check.fence.runId, check.fence.generation, check.fence.ownerId);
|
|
10742
|
+
}
|
|
10743
|
+
return {
|
|
10744
|
+
record: this.parseOMRow(row),
|
|
10745
|
+
guard
|
|
10746
|
+
};
|
|
10747
|
+
}
|
|
10748
|
+
async #readOMRow(id, check) {
|
|
10749
|
+
return this.#toOMRow(await this.#client.execute({
|
|
10750
|
+
sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
|
|
10751
|
+
args: [id]
|
|
10752
|
+
}), check);
|
|
10753
|
+
}
|
|
10754
|
+
async #readOMHeadRow(lookupKey, check) {
|
|
10755
|
+
return this.#toOMRow(await this.#client.execute({
|
|
10756
|
+
sql: `SELECT * FROM "${OM_TABLE}" WHERE "lookupKey" = ? ORDER BY ${OM_HEAD_ORDER} LIMIT 1`,
|
|
10757
|
+
args: [lookupKey]
|
|
10758
|
+
}), check);
|
|
10759
|
+
}
|
|
10760
|
+
/** The live row a lifecycle write aimed at `row` lands on: the row itself while live, otherwise the head. */
|
|
10761
|
+
async #resolveLiveOMRow(row, check) {
|
|
10762
|
+
let current = row;
|
|
10763
|
+
for (let hop = 0; current.record.supersededBy; hop++) {
|
|
10764
|
+
const head = hop < OM_MAX_HEAD_HOPS ? await this.#readOMHeadRow(this.getOMKey(current.record.threadId, current.record.resourceId), check) : null;
|
|
10765
|
+
if (!head || head.record.id === current.record.id) throw new _mastra_core_error.MastraError({
|
|
10766
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "RESOLVE_OBSERVATIONAL_MEMORY_HEAD", "FAILED"),
|
|
10767
|
+
text: `Observational memory record ${row.record.id} is superseded but no live head was found`,
|
|
10768
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
10769
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
10770
|
+
details: { id: row.record.id }
|
|
10771
|
+
});
|
|
10772
|
+
current = head;
|
|
10773
|
+
}
|
|
10774
|
+
return current;
|
|
10775
|
+
}
|
|
10776
|
+
/**
|
|
10777
|
+
* Retire every live row of a lookup key that sorts after the canonical head, marking it
|
|
10778
|
+
* superseded by the head. Rows retired by older adapter versions (which never set
|
|
10779
|
+
* `supersededBy`) become frozen. One statement: the head it computes and the rows it retires
|
|
10780
|
+
* are read under the same SQLite write lock, so a concurrent rollover cannot leave a key
|
|
10781
|
+
* without a live row.
|
|
10782
|
+
*/
|
|
10783
|
+
async #backfillSupersededBy() {
|
|
10784
|
+
const headOf = `(SELECT h.id FROM "${OM_TABLE}" h WHERE h."lookupKey" = "${OM_TABLE}"."lookupKey" ORDER BY ${OM_HEAD_ORDER} LIMIT 1)`;
|
|
10785
|
+
const duplicated = `SELECT "lookupKey" FROM "${OM_TABLE}" WHERE "supersededBy" IS NULL GROUP BY "lookupKey" HAVING COUNT(*) > 1`;
|
|
10786
|
+
if (!(await this.#client.execute({
|
|
10787
|
+
sql: duplicated,
|
|
10788
|
+
args: []
|
|
10789
|
+
})).rows?.length) return;
|
|
10790
|
+
await this.#write("backfillSupersededBy", () => this.#client.execute({
|
|
10791
|
+
sql: `UPDATE "${OM_TABLE}" SET "supersededBy" = ${headOf}
|
|
10792
|
+
WHERE "supersededBy" IS NULL AND "lookupKey" IN (${duplicated}) AND id <> ${headOf}`,
|
|
10793
|
+
args: []
|
|
10794
|
+
}));
|
|
10795
|
+
}
|
|
10796
|
+
/**
|
|
10797
|
+
* Create the next generation from the stored (live) row and retire it in one atomic batch,
|
|
10798
|
+
* guarded by the row as read. Buffered chunks move to the new generation (in order); the
|
|
10799
|
+
* cursor, buffering markers, flags, counters, config, and metadata carry over; buffered
|
|
10800
|
+
* reflection state does not (it is cleared on the retired row). Returns `OM_CAS_CONFLICT`
|
|
10801
|
+
* when the row changed since it was read.
|
|
10802
|
+
*/
|
|
10803
|
+
async #rollOverObservationalMemory(storedRow, observations, tokenCount, newRecordId) {
|
|
10804
|
+
const stored = storedRow.record;
|
|
10805
|
+
const id = newRecordId ?? crypto.randomUUID();
|
|
10806
|
+
const now = /* @__PURE__ */ new Date();
|
|
10807
|
+
const chunks = Array.isArray(stored.bufferedObservationChunks) ? stored.bufferedObservationChunks : [];
|
|
10808
|
+
const lookupKey = this.getOMKey(stored.threadId, stored.resourceId);
|
|
10809
|
+
const record = {
|
|
10810
|
+
id,
|
|
10811
|
+
scope: stored.scope,
|
|
10812
|
+
threadId: stored.threadId,
|
|
10813
|
+
resourceId: stored.resourceId,
|
|
10814
|
+
createdAt: now,
|
|
10815
|
+
updatedAt: now,
|
|
10816
|
+
lastObservedAt: stored.lastObservedAt,
|
|
10817
|
+
originType: "reflection",
|
|
10818
|
+
generationCount: stored.generationCount + 1,
|
|
10819
|
+
activeObservations: observations,
|
|
10820
|
+
bufferedObservationChunks: chunks.length > 0 ? chunks : void 0,
|
|
10821
|
+
totalTokensObserved: stored.totalTokensObserved,
|
|
10822
|
+
observationTokenCount: tokenCount,
|
|
10823
|
+
pendingMessageTokens: stored.pendingMessageTokens,
|
|
10824
|
+
isReflecting: false,
|
|
10825
|
+
isObserving: false,
|
|
10826
|
+
isBufferingObservation: stored.isBufferingObservation,
|
|
10827
|
+
isBufferingReflection: false,
|
|
10828
|
+
lastBufferedAtTokens: stored.lastBufferedAtTokens,
|
|
10829
|
+
lastBufferedAtTime: stored.lastBufferedAtTime,
|
|
10830
|
+
config: stored.config,
|
|
10831
|
+
metadata: stored.metadata,
|
|
10832
|
+
observedTimezone: stored.observedTimezone,
|
|
10833
|
+
supersededBy: null
|
|
10834
|
+
};
|
|
10835
|
+
const [retired] = await this.#client.batch([{
|
|
10836
|
+
sql: `UPDATE "${OM_TABLE}" SET "supersededBy" = ?, "bufferedObservationChunks" = NULL,
|
|
10837
|
+
"bufferedReflection" = NULL, "bufferedReflectionTokens" = NULL,
|
|
10838
|
+
"bufferedReflectionInputTokens" = NULL, "reflectedObservationLineCount" = NULL, "updatedAt" = ?
|
|
10839
|
+
WHERE id = ? AND ${storedRow.guard.sql}`,
|
|
10840
|
+
args: [
|
|
10841
|
+
id,
|
|
10842
|
+
now.toISOString(),
|
|
10843
|
+
stored.id,
|
|
10844
|
+
...storedRow.guard.args
|
|
10845
|
+
]
|
|
10846
|
+
}, {
|
|
10847
|
+
sql: `INSERT INTO "${OM_TABLE}" (
|
|
10848
|
+
id, "lookupKey", scope, "resourceId", "threadId",
|
|
10849
|
+
"activeObservations", "activeObservationsPendingUpdate",
|
|
10850
|
+
"originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
|
|
10851
|
+
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
10852
|
+
"bufferedObservationChunks",
|
|
10853
|
+
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
10854
|
+
"observedTimezone", metadata, "supersededBy", "createdAt", "updatedAt"
|
|
10855
|
+
) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
10856
|
+
WHERE EXISTS (SELECT 1 FROM "${OM_TABLE}" WHERE id = ? AND "supersededBy" = ?)`,
|
|
10857
|
+
args: [
|
|
10858
|
+
id,
|
|
10859
|
+
lookupKey,
|
|
10860
|
+
record.scope,
|
|
10861
|
+
record.resourceId,
|
|
10862
|
+
record.threadId || null,
|
|
10863
|
+
observations,
|
|
10864
|
+
null,
|
|
10865
|
+
"reflection",
|
|
10866
|
+
JSON.stringify(record.config),
|
|
10867
|
+
record.generationCount,
|
|
10868
|
+
record.lastObservedAt ? record.lastObservedAt.toISOString() : null,
|
|
10869
|
+
now.toISOString(),
|
|
10870
|
+
record.pendingMessageTokens,
|
|
10871
|
+
record.totalTokensObserved,
|
|
10872
|
+
record.observationTokenCount,
|
|
10873
|
+
chunks.length > 0 ? JSON.stringify(chunks) : null,
|
|
10874
|
+
false,
|
|
10875
|
+
false,
|
|
10876
|
+
record.isBufferingObservation,
|
|
10877
|
+
false,
|
|
10878
|
+
record.lastBufferedAtTokens,
|
|
10879
|
+
record.lastBufferedAtTime ? new Date(record.lastBufferedAtTime).toISOString() : null,
|
|
10880
|
+
record.observedTimezone || null,
|
|
10881
|
+
record.metadata ? JSON.stringify(record.metadata) : null,
|
|
10882
|
+
null,
|
|
10883
|
+
now.toISOString(),
|
|
10884
|
+
now.toISOString(),
|
|
10885
|
+
stored.id,
|
|
10886
|
+
id
|
|
10887
|
+
]
|
|
10888
|
+
}], "write");
|
|
10889
|
+
return retired.rowsAffected === 1 ? record : OM_CAS_CONFLICT;
|
|
10890
|
+
}
|
|
10586
10891
|
async getObservationalMemory(threadId, resourceId) {
|
|
10587
10892
|
try {
|
|
10588
10893
|
const lookupKey = this.getOMKey(threadId, resourceId);
|
|
10589
|
-
|
|
10590
|
-
sql: `SELECT * FROM "${OM_TABLE}" WHERE "lookupKey" = ? ORDER BY "generationCount" DESC LIMIT 1`,
|
|
10591
|
-
args: [lookupKey]
|
|
10592
|
-
});
|
|
10593
|
-
if (!result.rows || result.rows.length === 0) return null;
|
|
10594
|
-
return this.parseOMRow(result.rows[0]);
|
|
10894
|
+
return (await this.#readOMHeadRow(lookupKey))?.record ?? null;
|
|
10595
10895
|
} catch (error) {
|
|
10596
10896
|
throw new _mastra_core_error.MastraError({
|
|
10597
10897
|
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "GET_OBSERVATIONAL_MEMORY", "FAILED"),
|
|
@@ -10665,9 +10965,9 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10665
10965
|
}
|
|
10666
10966
|
async initializeObservationalMemory(input) {
|
|
10667
10967
|
try {
|
|
10968
|
+
const lookupKey = this.getOMKey(input.threadId, input.resourceId);
|
|
10668
10969
|
const id = crypto.randomUUID();
|
|
10669
10970
|
const now = /* @__PURE__ */ new Date();
|
|
10670
|
-
const lookupKey = this.getOMKey(input.threadId, input.resourceId);
|
|
10671
10971
|
const record = {
|
|
10672
10972
|
id,
|
|
10673
10973
|
scope: input.scope,
|
|
@@ -10689,45 +10989,52 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10689
10989
|
lastBufferedAtTokens: 0,
|
|
10690
10990
|
lastBufferedAtTime: null,
|
|
10691
10991
|
config: input.config,
|
|
10692
|
-
observedTimezone: input.observedTimezone
|
|
10992
|
+
observedTimezone: input.observedTimezone,
|
|
10993
|
+
supersededBy: null
|
|
10693
10994
|
};
|
|
10694
|
-
await this.#
|
|
10695
|
-
|
|
10995
|
+
return await this.#withOMCas("INITIALIZE_OBSERVATIONAL_MEMORY", async () => {
|
|
10996
|
+
const existing = (await this.#readOMHeadRow(lookupKey))?.record ?? null;
|
|
10997
|
+
if (existing) return existing;
|
|
10998
|
+
if ((await this.#client.execute({
|
|
10999
|
+
sql: `INSERT INTO "${OM_TABLE}" (
|
|
10696
11000
|
id, "lookupKey", scope, "resourceId", "threadId",
|
|
10697
11001
|
"activeObservations", "activeObservationsPendingUpdate",
|
|
10698
11002
|
"originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
|
|
10699
11003
|
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
10700
11004
|
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
10701
11005
|
"observedTimezone", "createdAt", "updatedAt"
|
|
10702
|
-
)
|
|
10703
|
-
|
|
10704
|
-
|
|
10705
|
-
|
|
10706
|
-
|
|
10707
|
-
|
|
10708
|
-
|
|
10709
|
-
|
|
10710
|
-
|
|
10711
|
-
|
|
10712
|
-
|
|
10713
|
-
|
|
10714
|
-
|
|
10715
|
-
|
|
10716
|
-
|
|
10717
|
-
|
|
10718
|
-
|
|
10719
|
-
|
|
10720
|
-
|
|
10721
|
-
|
|
10722
|
-
|
|
10723
|
-
|
|
10724
|
-
|
|
10725
|
-
|
|
10726
|
-
|
|
10727
|
-
|
|
10728
|
-
|
|
10729
|
-
|
|
10730
|
-
|
|
11006
|
+
) SELECT ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
|
|
11007
|
+
WHERE NOT EXISTS (SELECT 1 FROM "${OM_TABLE}" WHERE "lookupKey" = ? AND "supersededBy" IS NULL)`,
|
|
11008
|
+
args: [
|
|
11009
|
+
id,
|
|
11010
|
+
lookupKey,
|
|
11011
|
+
input.scope,
|
|
11012
|
+
input.resourceId,
|
|
11013
|
+
input.threadId || null,
|
|
11014
|
+
"",
|
|
11015
|
+
null,
|
|
11016
|
+
"initial",
|
|
11017
|
+
JSON.stringify(input.config),
|
|
11018
|
+
0,
|
|
11019
|
+
null,
|
|
11020
|
+
null,
|
|
11021
|
+
0,
|
|
11022
|
+
0,
|
|
11023
|
+
0,
|
|
11024
|
+
false,
|
|
11025
|
+
false,
|
|
11026
|
+
false,
|
|
11027
|
+
false,
|
|
11028
|
+
0,
|
|
11029
|
+
null,
|
|
11030
|
+
input.observedTimezone || null,
|
|
11031
|
+
now.toISOString(),
|
|
11032
|
+
now.toISOString(),
|
|
11033
|
+
lookupKey
|
|
11034
|
+
]
|
|
11035
|
+
})).rowsAffected === 1) return record;
|
|
11036
|
+
return (await this.#readOMHeadRow(lookupKey))?.record ?? OM_CAS_CONFLICT;
|
|
11037
|
+
});
|
|
10731
11038
|
} catch (error) {
|
|
10732
11039
|
throw new _mastra_core_error.MastraError({
|
|
10733
11040
|
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "INITIALIZE_OBSERVATIONAL_MEMORY", "FAILED"),
|
|
@@ -10754,8 +11061,8 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10754
11061
|
"reflectedObservationLineCount",
|
|
10755
11062
|
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection",
|
|
10756
11063
|
"lastBufferedAtTokens", "lastBufferedAtTime",
|
|
10757
|
-
"observedTimezone", metadata, "createdAt", "updatedAt"
|
|
10758
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
11064
|
+
"observedTimezone", metadata, "supersededBy", "createdAt", "updatedAt"
|
|
11065
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
10759
11066
|
args: [
|
|
10760
11067
|
record.id,
|
|
10761
11068
|
lookupKey,
|
|
@@ -10786,6 +11093,7 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10786
11093
|
record.lastBufferedAtTime ? record.lastBufferedAtTime.toISOString() : null,
|
|
10787
11094
|
record.observedTimezone || null,
|
|
10788
11095
|
record.metadata ? JSON.stringify(record.metadata) : null,
|
|
11096
|
+
record.supersededBy ?? null,
|
|
10789
11097
|
record.createdAt.toISOString(),
|
|
10790
11098
|
record.updatedAt.toISOString()
|
|
10791
11099
|
]
|
|
@@ -10804,11 +11112,36 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10804
11112
|
}
|
|
10805
11113
|
}
|
|
10806
11114
|
async updateActiveObservations(input) {
|
|
11115
|
+
assertActiveObservationsApplied(await this.commitActiveObservations(input), input.id);
|
|
11116
|
+
}
|
|
11117
|
+
async commitActiveObservations(input) {
|
|
10807
11118
|
try {
|
|
10808
11119
|
const now = /* @__PURE__ */ new Date();
|
|
10809
11120
|
const observedMessageIdsJson = input.observedMessageIds ? JSON.stringify(input.observedMessageIds) : null;
|
|
10810
|
-
|
|
10811
|
-
|
|
11121
|
+
return await this.#withOMCas("UPDATE_ACTIVE_OBSERVATIONS", async (attemptIndex, check) => {
|
|
11122
|
+
const row = await this.#readOMRow(input.id, check);
|
|
11123
|
+
if (!row) {
|
|
11124
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11125
|
+
throw new _mastra_core_error.MastraError({
|
|
11126
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "UPDATE_ACTIVE_OBSERVATIONS", "NOT_FOUND"),
|
|
11127
|
+
text: `Observational memory record not found: ${input.id}`,
|
|
11128
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11129
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11130
|
+
details: { id: input.id }
|
|
11131
|
+
});
|
|
11132
|
+
}
|
|
11133
|
+
const stored = row.record;
|
|
11134
|
+
if (stored.supersededBy) return {
|
|
11135
|
+
applied: false,
|
|
11136
|
+
reason: "retired"
|
|
11137
|
+
};
|
|
11138
|
+
if (input.expectedActiveObservations !== void 0 && input.expectedActiveObservations !== stored.activeObservations) return {
|
|
11139
|
+
applied: false,
|
|
11140
|
+
reason: "conflict"
|
|
11141
|
+
};
|
|
11142
|
+
const lastObservedAt = maxObservationCursor(stored.lastObservedAt, input.lastObservedAt);
|
|
11143
|
+
return (await this.#client.execute({
|
|
11144
|
+
sql: `UPDATE "${OM_TABLE}" SET
|
|
10812
11145
|
"activeObservations" = ?,
|
|
10813
11146
|
"lastObservedAt" = ?,
|
|
10814
11147
|
"pendingMessageTokens" = 0,
|
|
@@ -10816,23 +11149,19 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10816
11149
|
"totalTokensObserved" = "totalTokensObserved" + ?,
|
|
10817
11150
|
"observedMessageIds" = ?,
|
|
10818
11151
|
"updatedAt" = ?
|
|
10819
|
-
WHERE id =
|
|
10820
|
-
|
|
10821
|
-
|
|
10822
|
-
|
|
10823
|
-
|
|
10824
|
-
|
|
10825
|
-
|
|
10826
|
-
|
|
10827
|
-
|
|
10828
|
-
|
|
10829
|
-
|
|
10830
|
-
|
|
10831
|
-
|
|
10832
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
10833
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
10834
|
-
details: { id: input.id }
|
|
10835
|
-
});
|
|
11152
|
+
WHERE id = ? AND ${row.guard.sql}`,
|
|
11153
|
+
args: [
|
|
11154
|
+
input.observations,
|
|
11155
|
+
lastObservedAt.toISOString(),
|
|
11156
|
+
input.tokenCount,
|
|
11157
|
+
input.tokenCount,
|
|
11158
|
+
observedMessageIdsJson,
|
|
11159
|
+
now.toISOString(),
|
|
11160
|
+
input.id,
|
|
11161
|
+
...row.guard.args
|
|
11162
|
+
]
|
|
11163
|
+
})).rowsAffected === 1 ? { applied: true } : OM_CAS_CONFLICT;
|
|
11164
|
+
}, "commitActiveObservations");
|
|
10836
11165
|
} catch (error) {
|
|
10837
11166
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
10838
11167
|
throw new _mastra_core_error.MastraError({
|
|
@@ -10845,19 +11174,23 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10845
11174
|
}
|
|
10846
11175
|
async createReflectionGeneration(input) {
|
|
10847
11176
|
try {
|
|
10848
|
-
|
|
10849
|
-
|
|
10850
|
-
const
|
|
10851
|
-
|
|
10852
|
-
|
|
10853
|
-
|
|
10854
|
-
|
|
10855
|
-
|
|
10856
|
-
|
|
10857
|
-
|
|
10858
|
-
|
|
10859
|
-
|
|
10860
|
-
|
|
11177
|
+
return await this.#withOMCas("CREATE_REFLECTION_GENERATION", async (attemptIndex, check) => {
|
|
11178
|
+
const { currentRecord } = input;
|
|
11179
|
+
const row = await this.#readOMRow(currentRecord.id, check);
|
|
11180
|
+
if (!row) return this.#mayBeUnsynced(attemptIndex) ? OM_CAS_CONFLICT : currentRecord;
|
|
11181
|
+
const stored = row.record;
|
|
11182
|
+
if (stored.supersededBy) return (await this.#resolveLiveOMRow(row, check)).record;
|
|
11183
|
+
const plan = planReflectionGenerationText({
|
|
11184
|
+
storedObservations: stored.activeObservations,
|
|
11185
|
+
storedObservationTokenCount: stored.observationTokenCount,
|
|
11186
|
+
snapshotObservations: currentRecord.activeObservations,
|
|
11187
|
+
snapshotObservationTokenCount: currentRecord.observationTokenCount,
|
|
11188
|
+
reflection: input.reflection,
|
|
11189
|
+
tokenCount: input.tokenCount
|
|
11190
|
+
});
|
|
11191
|
+
if (!plan) return stored;
|
|
11192
|
+
return this.#rollOverObservationalMemory(row, plan.observations, plan.tokenCount, input.newRecordId);
|
|
11193
|
+
}, "createReflectionGeneration");
|
|
10861
11194
|
} catch (error) {
|
|
10862
11195
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
10863
11196
|
throw new _mastra_core_error.MastraError({
|
|
@@ -10868,79 +11201,6 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
10868
11201
|
}, error);
|
|
10869
11202
|
}
|
|
10870
11203
|
}
|
|
10871
|
-
/**
|
|
10872
|
-
* Inserts a new reflection-generation row. Called inside a locked write
|
|
10873
|
-
* transaction — either from {@link createReflectionGeneration} (standalone)
|
|
10874
|
-
* or from {@link swapBufferedReflectionToActive} (as part of a compound
|
|
10875
|
-
* swap). Must not acquire the write lock itself; the caller owns it.
|
|
10876
|
-
*/
|
|
10877
|
-
async #insertReflectionGeneration(tx, input) {
|
|
10878
|
-
const id = crypto.randomUUID();
|
|
10879
|
-
const now = /* @__PURE__ */ new Date();
|
|
10880
|
-
const lookupKey = this.getOMKey(input.currentRecord.threadId, input.currentRecord.resourceId);
|
|
10881
|
-
const record = {
|
|
10882
|
-
id,
|
|
10883
|
-
scope: input.currentRecord.scope,
|
|
10884
|
-
threadId: input.currentRecord.threadId,
|
|
10885
|
-
resourceId: input.currentRecord.resourceId,
|
|
10886
|
-
createdAt: now,
|
|
10887
|
-
updatedAt: now,
|
|
10888
|
-
lastObservedAt: input.currentRecord.lastObservedAt,
|
|
10889
|
-
originType: "reflection",
|
|
10890
|
-
generationCount: input.currentRecord.generationCount + 1,
|
|
10891
|
-
activeObservations: input.reflection,
|
|
10892
|
-
totalTokensObserved: input.currentRecord.totalTokensObserved,
|
|
10893
|
-
observationTokenCount: input.tokenCount,
|
|
10894
|
-
pendingMessageTokens: 0,
|
|
10895
|
-
isReflecting: false,
|
|
10896
|
-
isObserving: false,
|
|
10897
|
-
isBufferingObservation: false,
|
|
10898
|
-
isBufferingReflection: false,
|
|
10899
|
-
lastBufferedAtTokens: 0,
|
|
10900
|
-
lastBufferedAtTime: null,
|
|
10901
|
-
config: input.currentRecord.config,
|
|
10902
|
-
metadata: input.currentRecord.metadata,
|
|
10903
|
-
observedTimezone: input.currentRecord.observedTimezone
|
|
10904
|
-
};
|
|
10905
|
-
await tx.execute({
|
|
10906
|
-
sql: `INSERT INTO "${OM_TABLE}" (
|
|
10907
|
-
id, "lookupKey", scope, "resourceId", "threadId",
|
|
10908
|
-
"activeObservations", "activeObservationsPendingUpdate",
|
|
10909
|
-
"originType", config, "generationCount", "lastObservedAt", "lastReflectionAt",
|
|
10910
|
-
"pendingMessageTokens", "totalTokensObserved", "observationTokenCount",
|
|
10911
|
-
"isObserving", "isReflecting", "isBufferingObservation", "isBufferingReflection", "lastBufferedAtTokens", "lastBufferedAtTime",
|
|
10912
|
-
"observedTimezone", metadata, "createdAt", "updatedAt"
|
|
10913
|
-
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
10914
|
-
args: [
|
|
10915
|
-
id,
|
|
10916
|
-
lookupKey,
|
|
10917
|
-
record.scope,
|
|
10918
|
-
record.resourceId,
|
|
10919
|
-
record.threadId || null,
|
|
10920
|
-
input.reflection,
|
|
10921
|
-
null,
|
|
10922
|
-
"reflection",
|
|
10923
|
-
JSON.stringify(record.config),
|
|
10924
|
-
input.currentRecord.generationCount + 1,
|
|
10925
|
-
record.lastObservedAt?.toISOString() || null,
|
|
10926
|
-
now.toISOString(),
|
|
10927
|
-
record.pendingMessageTokens,
|
|
10928
|
-
record.totalTokensObserved,
|
|
10929
|
-
record.observationTokenCount,
|
|
10930
|
-
false,
|
|
10931
|
-
false,
|
|
10932
|
-
false,
|
|
10933
|
-
false,
|
|
10934
|
-
0,
|
|
10935
|
-
null,
|
|
10936
|
-
record.observedTimezone || null,
|
|
10937
|
-
record.metadata ? JSON.stringify(record.metadata) : null,
|
|
10938
|
-
now.toISOString(),
|
|
10939
|
-
now.toISOString()
|
|
10940
|
-
]
|
|
10941
|
-
});
|
|
10942
|
-
return record;
|
|
10943
|
-
}
|
|
10944
11204
|
async setReflectingFlag(id, isReflecting) {
|
|
10945
11205
|
try {
|
|
10946
11206
|
if ((await this.#write("setReflectingFlag", () => this.#client.execute({
|
|
@@ -11007,38 +11267,40 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11007
11267
|
}
|
|
11008
11268
|
async setBufferingObservationFlag(id, isBuffering, lastBufferedAtTokens) {
|
|
11009
11269
|
try {
|
|
11010
|
-
|
|
11011
|
-
|
|
11012
|
-
|
|
11013
|
-
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11017
|
-
|
|
11018
|
-
|
|
11019
|
-
|
|
11020
|
-
|
|
11021
|
-
|
|
11022
|
-
|
|
11023
|
-
|
|
11024
|
-
|
|
11025
|
-
nowStr,
|
|
11026
|
-
id
|
|
11027
|
-
];
|
|
11028
|
-
}
|
|
11029
|
-
if ((await this.#write("setBufferingObservationFlag", () => this.#client.execute({
|
|
11030
|
-
sql,
|
|
11031
|
-
args
|
|
11032
|
-
}))).rowsAffected === 0) throw new _mastra_core_error.MastraError({
|
|
11033
|
-
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "SET_BUFFERING_OBSERVATION_FLAG", "NOT_FOUND"),
|
|
11034
|
-
text: `Observational memory record not found: ${id}`,
|
|
11035
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11036
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11037
|
-
details: {
|
|
11038
|
-
id,
|
|
11039
|
-
isBuffering,
|
|
11040
|
-
lastBufferedAtTokens: lastBufferedAtTokens ?? null
|
|
11270
|
+
await this.#withOMCas("SET_BUFFERING_OBSERVATION_FLAG", async (attemptIndex) => {
|
|
11271
|
+
const row = await this.#readOMRow(id);
|
|
11272
|
+
if (!row) {
|
|
11273
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11274
|
+
throw new _mastra_core_error.MastraError({
|
|
11275
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "SET_BUFFERING_OBSERVATION_FLAG", "NOT_FOUND"),
|
|
11276
|
+
text: `Observational memory record not found: ${id}`,
|
|
11277
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11278
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11279
|
+
details: {
|
|
11280
|
+
id,
|
|
11281
|
+
isBuffering,
|
|
11282
|
+
lastBufferedAtTokens: lastBufferedAtTokens ?? null
|
|
11283
|
+
}
|
|
11284
|
+
});
|
|
11041
11285
|
}
|
|
11286
|
+
const target = (await this.#resolveLiveOMRow(row)).record;
|
|
11287
|
+
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
11288
|
+
return (lastBufferedAtTokens !== void 0 ? await this.#client.execute({
|
|
11289
|
+
sql: `UPDATE "${OM_TABLE}" SET "isBufferingObservation" = ?, "lastBufferedAtTokens" = ?, "updatedAt" = ? WHERE id = ? AND "supersededBy" IS NULL`,
|
|
11290
|
+
args: [
|
|
11291
|
+
isBuffering,
|
|
11292
|
+
lastBufferedAtTokens,
|
|
11293
|
+
nowStr,
|
|
11294
|
+
target.id
|
|
11295
|
+
]
|
|
11296
|
+
}) : await this.#client.execute({
|
|
11297
|
+
sql: `UPDATE "${OM_TABLE}" SET "isBufferingObservation" = ?, "updatedAt" = ? WHERE id = ? AND "supersededBy" IS NULL`,
|
|
11298
|
+
args: [
|
|
11299
|
+
isBuffering,
|
|
11300
|
+
nowStr,
|
|
11301
|
+
target.id
|
|
11302
|
+
]
|
|
11303
|
+
})).rowsAffected === 1 ? void 0 : OM_CAS_CONFLICT;
|
|
11042
11304
|
});
|
|
11043
11305
|
} catch (error) {
|
|
11044
11306
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
@@ -11107,25 +11369,30 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11107
11369
|
}
|
|
11108
11370
|
async setPendingMessageTokens(id, tokenCount) {
|
|
11109
11371
|
try {
|
|
11110
|
-
|
|
11111
|
-
|
|
11112
|
-
|
|
11113
|
-
|
|
11114
|
-
|
|
11115
|
-
|
|
11116
|
-
|
|
11117
|
-
|
|
11118
|
-
|
|
11119
|
-
|
|
11120
|
-
|
|
11121
|
-
|
|
11122
|
-
|
|
11123
|
-
|
|
11124
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11125
|
-
details: {
|
|
11126
|
-
id,
|
|
11127
|
-
tokenCount
|
|
11372
|
+
await this.#withOMCas("SET_PENDING_MESSAGE_TOKENS", async (attemptIndex) => {
|
|
11373
|
+
const row = await this.#readOMRow(id);
|
|
11374
|
+
if (!row) {
|
|
11375
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11376
|
+
throw new _mastra_core_error.MastraError({
|
|
11377
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "SET_PENDING_MESSAGE_TOKENS", "NOT_FOUND"),
|
|
11378
|
+
text: `Observational memory record not found: ${id}`,
|
|
11379
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11380
|
+
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11381
|
+
details: {
|
|
11382
|
+
id,
|
|
11383
|
+
tokenCount
|
|
11384
|
+
}
|
|
11385
|
+
});
|
|
11128
11386
|
}
|
|
11387
|
+
const target = (await this.#resolveLiveOMRow(row)).record;
|
|
11388
|
+
return (await this.#client.execute({
|
|
11389
|
+
sql: `UPDATE "${OM_TABLE}" SET "pendingMessageTokens" = ?, "updatedAt" = ? WHERE id = ? AND "supersededBy" IS NULL`,
|
|
11390
|
+
args: [
|
|
11391
|
+
tokenCount,
|
|
11392
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
11393
|
+
target.id
|
|
11394
|
+
]
|
|
11395
|
+
})).rowsAffected === 1 ? void 0 : OM_CAS_CONFLICT;
|
|
11129
11396
|
});
|
|
11130
11397
|
} catch (error) {
|
|
11131
11398
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
@@ -11142,36 +11409,33 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11142
11409
|
}
|
|
11143
11410
|
async updateObservationalMemoryConfig(input) {
|
|
11144
11411
|
try {
|
|
11145
|
-
await this.#
|
|
11146
|
-
const
|
|
11147
|
-
|
|
11148
|
-
|
|
11149
|
-
|
|
11150
|
-
|
|
11151
|
-
|
|
11152
|
-
|
|
11412
|
+
await this.#withOMCas("UPDATE_OM_CONFIG", async (attemptIndex) => {
|
|
11413
|
+
const selectResult = await this.#client.execute({
|
|
11414
|
+
sql: `SELECT config FROM "${OM_TABLE}" WHERE id = ?`,
|
|
11415
|
+
args: [input.id]
|
|
11416
|
+
});
|
|
11417
|
+
if (selectResult.rows.length === 0) {
|
|
11418
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11419
|
+
throw new _mastra_core_error.MastraError({
|
|
11153
11420
|
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "UPDATE_OM_CONFIG", "NOT_FOUND"),
|
|
11154
11421
|
text: `Observational memory record not found: ${input.id}`,
|
|
11155
11422
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11156
11423
|
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11157
11424
|
details: { id: input.id }
|
|
11158
11425
|
});
|
|
11159
|
-
const row = selectResult.rows[0];
|
|
11160
|
-
const existing = row.config ? JSON.parse(row.config) : {};
|
|
11161
|
-
const merged = this.deepMergeConfig(existing, input.config);
|
|
11162
|
-
await tx.execute({
|
|
11163
|
-
sql: `UPDATE "${OM_TABLE}" SET config = ?, "updatedAt" = ? WHERE id = ?`,
|
|
11164
|
-
args: [
|
|
11165
|
-
JSON.stringify(merged),
|
|
11166
|
-
(/* @__PURE__ */ new Date()).toISOString(),
|
|
11167
|
-
input.id
|
|
11168
|
-
]
|
|
11169
|
-
});
|
|
11170
|
-
await tx.commit();
|
|
11171
|
-
} catch (error) {
|
|
11172
|
-
if (!tx.closed) await tx.rollback();
|
|
11173
|
-
throw error;
|
|
11174
11426
|
}
|
|
11427
|
+
const row = selectResult.rows[0];
|
|
11428
|
+
const existing = row.config ? JSON.parse(row.config) : {};
|
|
11429
|
+
const merged = this.deepMergeConfig(existing, input.config);
|
|
11430
|
+
return (await this.#client.execute({
|
|
11431
|
+
sql: `UPDATE "${OM_TABLE}" SET config = ?, "updatedAt" = ? WHERE id = ? AND config IS ?`,
|
|
11432
|
+
args: [
|
|
11433
|
+
JSON.stringify(merged),
|
|
11434
|
+
(/* @__PURE__ */ new Date()).toISOString(),
|
|
11435
|
+
input.id,
|
|
11436
|
+
row.config ?? null
|
|
11437
|
+
]
|
|
11438
|
+
})).rowsAffected === 1 ? void 0 : OM_CAS_CONFLICT;
|
|
11175
11439
|
});
|
|
11176
11440
|
} catch (error) {
|
|
11177
11441
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
@@ -11184,78 +11448,64 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11184
11448
|
}
|
|
11185
11449
|
}
|
|
11186
11450
|
async updateBufferedObservations(input) {
|
|
11451
|
+
await this.appendBufferedObservations(input);
|
|
11452
|
+
}
|
|
11453
|
+
async appendBufferedObservations(input) {
|
|
11187
11454
|
try {
|
|
11188
11455
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
11189
|
-
|
|
11190
|
-
|
|
11191
|
-
|
|
11192
|
-
|
|
11193
|
-
|
|
11194
|
-
const current = await tx.execute({
|
|
11195
|
-
sql: `SELECT "bufferedObservationChunks" FROM "${OM_TABLE}" WHERE id = ?`,
|
|
11196
|
-
args: [input.id]
|
|
11197
|
-
});
|
|
11198
|
-
if (!current.rows || current.rows.length === 0) throw new _mastra_core_error.MastraError({
|
|
11199
|
-
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
|
|
11200
|
-
text: `Observational memory record not found: ${input.id}`,
|
|
11201
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11202
|
-
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11203
|
-
details: { id: input.id }
|
|
11204
|
-
});
|
|
11205
|
-
const row = current.rows[0];
|
|
11206
|
-
let existingChunks = [];
|
|
11207
|
-
if (row.bufferedObservationChunks) try {
|
|
11208
|
-
const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
|
|
11209
|
-
existingChunks = Array.isArray(parsed) ? parsed : [];
|
|
11210
|
-
} catch {
|
|
11211
|
-
existingChunks = [];
|
|
11212
|
-
}
|
|
11213
|
-
if (existingChunks.some((existing) => existing.cycleId === input.chunk.cycleId)) {
|
|
11214
|
-
await tx.commit();
|
|
11215
|
-
return;
|
|
11216
|
-
}
|
|
11217
|
-
const newChunk = {
|
|
11218
|
-
id: `ombuf-${globalThis.crypto.randomUUID()}`,
|
|
11219
|
-
cycleId: input.chunk.cycleId,
|
|
11220
|
-
observations: input.chunk.observations,
|
|
11221
|
-
tokenCount: input.chunk.tokenCount,
|
|
11222
|
-
messageIds: input.chunk.messageIds,
|
|
11223
|
-
messageTokens: input.chunk.messageTokens,
|
|
11224
|
-
lastObservedAt: input.chunk.lastObservedAt,
|
|
11225
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
11226
|
-
suggestedContinuation: input.chunk.suggestedContinuation,
|
|
11227
|
-
currentTask: input.chunk.currentTask,
|
|
11228
|
-
threadTitle: input.chunk.threadTitle,
|
|
11229
|
-
extractedValues: input.chunk.extractedValues,
|
|
11230
|
-
extractionFailures: input.chunk.extractionFailures
|
|
11231
|
-
};
|
|
11232
|
-
const newChunks = [...existingChunks, newChunk];
|
|
11233
|
-
const lastBufferedAtTime = input.lastBufferedAtTime ? input.lastBufferedAtTime.toISOString() : null;
|
|
11234
|
-
if ((await tx.execute({
|
|
11235
|
-
sql: `UPDATE "${OM_TABLE}" SET
|
|
11236
|
-
"bufferedObservationChunks" = ?,
|
|
11237
|
-
"lastBufferedAtTime" = COALESCE(?, "lastBufferedAtTime"),
|
|
11238
|
-
"updatedAt" = ?
|
|
11239
|
-
WHERE id = ?`,
|
|
11240
|
-
args: [
|
|
11241
|
-
JSON.stringify(newChunks),
|
|
11242
|
-
lastBufferedAtTime,
|
|
11243
|
-
nowStr,
|
|
11244
|
-
input.id
|
|
11245
|
-
]
|
|
11246
|
-
})).rowsAffected === 0) throw new _mastra_core_error.MastraError({
|
|
11456
|
+
return await this.#withOMCas("UPDATE_BUFFERED_OBSERVATIONS", async (attemptIndex, check) => {
|
|
11457
|
+
const row = await this.#readOMRow(input.id, check);
|
|
11458
|
+
if (!row) {
|
|
11459
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11460
|
+
throw new _mastra_core_error.MastraError({
|
|
11247
11461
|
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "UPDATE_BUFFERED_OBSERVATIONS", "NOT_FOUND"),
|
|
11248
11462
|
text: `Observational memory record not found: ${input.id}`,
|
|
11249
11463
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11250
11464
|
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11251
11465
|
details: { id: input.id }
|
|
11252
11466
|
});
|
|
11253
|
-
await tx.commit();
|
|
11254
|
-
} catch (error) {
|
|
11255
|
-
if (!tx.closed) await tx.rollback();
|
|
11256
|
-
throw error;
|
|
11257
11467
|
}
|
|
11258
|
-
|
|
11468
|
+
const targetRow = await this.#resolveLiveOMRow(row, check);
|
|
11469
|
+
const target = targetRow.record;
|
|
11470
|
+
const existingChunks = Array.isArray(target.bufferedObservationChunks) ? target.bufferedObservationChunks : [];
|
|
11471
|
+
if (existingChunks.some((existing) => existing.cycleId === input.chunk.cycleId) || isBufferedChunkCoveredByCursor(input.chunk.lastObservedAt, target.lastObservedAt)) return {
|
|
11472
|
+
persisted: false,
|
|
11473
|
+
recordId: target.id
|
|
11474
|
+
};
|
|
11475
|
+
const newChunk = {
|
|
11476
|
+
id: `ombuf-${globalThis.crypto.randomUUID()}`,
|
|
11477
|
+
cycleId: input.chunk.cycleId,
|
|
11478
|
+
observations: input.chunk.observations,
|
|
11479
|
+
tokenCount: input.chunk.tokenCount,
|
|
11480
|
+
messageIds: input.chunk.messageIds,
|
|
11481
|
+
messageTokens: input.chunk.messageTokens,
|
|
11482
|
+
lastObservedAt: input.chunk.lastObservedAt,
|
|
11483
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
11484
|
+
suggestedContinuation: input.chunk.suggestedContinuation,
|
|
11485
|
+
currentTask: input.chunk.currentTask,
|
|
11486
|
+
threadTitle: input.chunk.threadTitle,
|
|
11487
|
+
extractedValues: input.chunk.extractedValues,
|
|
11488
|
+
extractionFailures: input.chunk.extractionFailures
|
|
11489
|
+
};
|
|
11490
|
+
const lastBufferedAtTime = maxObservationCursor(target.lastBufferedAtTime, input.lastBufferedAtTime);
|
|
11491
|
+
return (await this.#client.execute({
|
|
11492
|
+
sql: `UPDATE "${OM_TABLE}" SET
|
|
11493
|
+
"bufferedObservationChunks" = ?,
|
|
11494
|
+
"lastBufferedAtTime" = ?,
|
|
11495
|
+
"updatedAt" = ?
|
|
11496
|
+
WHERE id = ? AND ${targetRow.guard.sql}`,
|
|
11497
|
+
args: [
|
|
11498
|
+
JSON.stringify([...existingChunks, newChunk]),
|
|
11499
|
+
lastBufferedAtTime ? lastBufferedAtTime.toISOString() : null,
|
|
11500
|
+
nowStr,
|
|
11501
|
+
target.id,
|
|
11502
|
+
...targetRow.guard.args
|
|
11503
|
+
]
|
|
11504
|
+
})).rowsAffected === 1 ? {
|
|
11505
|
+
persisted: true,
|
|
11506
|
+
recordId: target.id
|
|
11507
|
+
} : OM_CAS_CONFLICT;
|
|
11508
|
+
}, "appendBufferedObservations");
|
|
11259
11509
|
} catch (error) {
|
|
11260
11510
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
11261
11511
|
throw new _mastra_core_error.MastraError({
|
|
@@ -11269,144 +11519,137 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11269
11519
|
async swapBufferedToActive(input) {
|
|
11270
11520
|
try {
|
|
11271
11521
|
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
11272
|
-
|
|
11273
|
-
|
|
11274
|
-
|
|
11275
|
-
|
|
11276
|
-
|
|
11277
|
-
|
|
11278
|
-
|
|
11279
|
-
|
|
11280
|
-
});
|
|
11281
|
-
if (!current.rows || current.rows.length === 0) throw new _mastra_core_error.MastraError({
|
|
11522
|
+
return await this.#withOMCas("SWAP_BUFFERED_TO_ACTIVE", async (attemptIndex, check) => {
|
|
11523
|
+
const current = await this.#client.execute({
|
|
11524
|
+
sql: `SELECT * FROM "${OM_TABLE}" WHERE id = ?`,
|
|
11525
|
+
args: [input.id]
|
|
11526
|
+
});
|
|
11527
|
+
if (!current.rows || current.rows.length === 0) {
|
|
11528
|
+
if (this.#mayBeUnsynced(attemptIndex)) return OM_CAS_CONFLICT;
|
|
11529
|
+
throw new _mastra_core_error.MastraError({
|
|
11282
11530
|
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "SWAP_BUFFERED_TO_ACTIVE", "NOT_FOUND"),
|
|
11283
11531
|
text: `Observational memory record not found: ${input.id}`,
|
|
11284
11532
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11285
11533
|
category: _mastra_core_error.ErrorCategory.THIRD_PARTY,
|
|
11286
11534
|
details: { id: input.id }
|
|
11287
11535
|
});
|
|
11288
|
-
|
|
11289
|
-
|
|
11290
|
-
|
|
11291
|
-
|
|
11292
|
-
|
|
11293
|
-
|
|
11294
|
-
|
|
11295
|
-
|
|
11296
|
-
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11308
|
-
|
|
11309
|
-
|
|
11310
|
-
|
|
11311
|
-
|
|
11312
|
-
|
|
11313
|
-
|
|
11314
|
-
|
|
11315
|
-
|
|
11316
|
-
|
|
11317
|
-
|
|
11318
|
-
|
|
11319
|
-
|
|
11320
|
-
|
|
11321
|
-
|
|
11322
|
-
|
|
11323
|
-
|
|
11324
|
-
|
|
11536
|
+
}
|
|
11537
|
+
const row = current.rows[0];
|
|
11538
|
+
const guard = this.#toOMRow(current, check).guard;
|
|
11539
|
+
const emptyResult = {
|
|
11540
|
+
chunksActivated: 0,
|
|
11541
|
+
messageTokensActivated: 0,
|
|
11542
|
+
observationTokensActivated: 0,
|
|
11543
|
+
messagesActivated: 0,
|
|
11544
|
+
activatedCycleIds: [],
|
|
11545
|
+
activatedMessageIds: []
|
|
11546
|
+
};
|
|
11547
|
+
if (row.supersededBy) return {
|
|
11548
|
+
...emptyResult,
|
|
11549
|
+
retired: true
|
|
11550
|
+
};
|
|
11551
|
+
let persistedChunks = [];
|
|
11552
|
+
if (row.bufferedObservationChunks) try {
|
|
11553
|
+
const parsed = typeof row.bufferedObservationChunks === "string" ? JSON.parse(row.bufferedObservationChunks) : row.bufferedObservationChunks;
|
|
11554
|
+
persistedChunks = Array.isArray(parsed) ? parsed : [];
|
|
11555
|
+
} catch {
|
|
11556
|
+
persistedChunks = [];
|
|
11557
|
+
}
|
|
11558
|
+
const refreshedWeights = new Map((Array.isArray(input.bufferedChunks) ? input.bufferedChunks : []).map((c) => [c.id, c.messageTokens]));
|
|
11559
|
+
const chunks = persistedChunks.map((c) => refreshedWeights.has(c.id) ? {
|
|
11560
|
+
...c,
|
|
11561
|
+
messageTokens: refreshedWeights.get(c.id)
|
|
11562
|
+
} : c);
|
|
11563
|
+
if (chunks.length === 0) return emptyResult;
|
|
11564
|
+
const retentionFloor = input.messageTokensThreshold * (1 - input.activationRatio);
|
|
11565
|
+
const targetMessageTokens = Math.max(0, input.currentPendingTokens - retentionFloor);
|
|
11566
|
+
let cumulativeMessageTokens = 0;
|
|
11567
|
+
let bestOverBoundary = 0;
|
|
11568
|
+
let bestOverTokens = 0;
|
|
11569
|
+
let bestUnderBoundary = 0;
|
|
11570
|
+
let bestUnderTokens = 0;
|
|
11571
|
+
for (let i = 0; i < chunks.length; i++) {
|
|
11572
|
+
cumulativeMessageTokens += chunks[i].messageTokens ?? 0;
|
|
11573
|
+
const boundary = i + 1;
|
|
11574
|
+
if (cumulativeMessageTokens >= targetMessageTokens) {
|
|
11575
|
+
if (bestOverBoundary === 0 || cumulativeMessageTokens < bestOverTokens) {
|
|
11576
|
+
bestOverBoundary = boundary;
|
|
11577
|
+
bestOverTokens = cumulativeMessageTokens;
|
|
11325
11578
|
}
|
|
11579
|
+
} else if (cumulativeMessageTokens > bestUnderTokens) {
|
|
11580
|
+
bestUnderBoundary = boundary;
|
|
11581
|
+
bestUnderTokens = cumulativeMessageTokens;
|
|
11326
11582
|
}
|
|
11327
|
-
|
|
11328
|
-
|
|
11329
|
-
|
|
11330
|
-
|
|
11331
|
-
|
|
11332
|
-
|
|
11333
|
-
|
|
11334
|
-
|
|
11335
|
-
|
|
11336
|
-
|
|
11337
|
-
|
|
11338
|
-
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11345
|
-
|
|
11346
|
-
|
|
11347
|
-
|
|
11348
|
-
|
|
11349
|
-
|
|
11350
|
-
|
|
11351
|
-
|
|
11352
|
-
|
|
11353
|
-
|
|
11354
|
-
|
|
11355
|
-
|
|
11356
|
-
|
|
11357
|
-
|
|
11583
|
+
}
|
|
11584
|
+
const maxOvershoot = retentionFloor * .95;
|
|
11585
|
+
const overshoot = bestOverTokens - targetMessageTokens;
|
|
11586
|
+
const remainingAfterOver = input.currentPendingTokens - bestOverTokens;
|
|
11587
|
+
const remainingAfterUnder = input.currentPendingTokens - bestUnderTokens;
|
|
11588
|
+
const minRemaining = Math.min(1e3, retentionFloor);
|
|
11589
|
+
let chunksToActivate;
|
|
11590
|
+
if (input.forceMaxActivation && bestOverBoundary > 0 && remainingAfterOver >= minRemaining) chunksToActivate = bestOverBoundary;
|
|
11591
|
+
else if (bestOverBoundary > 0 && overshoot <= maxOvershoot && remainingAfterOver >= minRemaining) chunksToActivate = bestOverBoundary;
|
|
11592
|
+
else if (bestUnderBoundary > 0 && remainingAfterUnder >= minRemaining) chunksToActivate = bestUnderBoundary;
|
|
11593
|
+
else if (bestOverBoundary > 0) chunksToActivate = bestOverBoundary;
|
|
11594
|
+
else chunksToActivate = 1;
|
|
11595
|
+
const activatedChunks = chunks.slice(0, chunksToActivate);
|
|
11596
|
+
const remainingChunks = persistedChunks.slice(chunksToActivate);
|
|
11597
|
+
const activatedContent = activatedChunks.map((c) => c.observations).join("\n\n");
|
|
11598
|
+
const activatedTokens = activatedChunks.reduce((sum, c) => sum + c.tokenCount, 0);
|
|
11599
|
+
const activatedMessageTokens = activatedChunks.reduce((sum, c) => sum + (c.messageTokens ?? 0), 0);
|
|
11600
|
+
const activatedMessageCount = activatedChunks.reduce((sum, c) => sum + c.messageIds.length, 0);
|
|
11601
|
+
const activatedCycleIds = activatedChunks.map((c) => c.cycleId).filter((id) => !!id);
|
|
11602
|
+
const activatedMessageIds = activatedChunks.flatMap((c) => c.messageIds ?? []);
|
|
11603
|
+
const latestChunk = activatedChunks[activatedChunks.length - 1];
|
|
11604
|
+
const lastObservedAt = input.lastObservedAt ?? (latestChunk?.lastObservedAt ? new Date(latestChunk.lastObservedAt) : /* @__PURE__ */ new Date());
|
|
11605
|
+
const lastObservedAtStr = maxObservationCursor(row.lastObservedAt, lastObservedAt).toISOString();
|
|
11606
|
+
const existingActive = row.activeObservations || "";
|
|
11607
|
+
const existingTokenCount = Number(row.observationTokenCount || 0);
|
|
11608
|
+
const boundary = `\n\n--- message boundary (${lastObservedAt.toISOString()}) ---\n\n`;
|
|
11609
|
+
const newActive = existingActive ? `${existingActive}${boundary}${activatedContent}` : activatedContent;
|
|
11610
|
+
const newTokenCount = existingTokenCount + activatedTokens;
|
|
11611
|
+
const existingPending = Number(row.pendingMessageTokens || 0);
|
|
11612
|
+
const newPending = Math.max(0, existingPending - activatedMessageTokens);
|
|
11613
|
+
if ((await this.#client.execute({
|
|
11614
|
+
sql: `UPDATE "${OM_TABLE}" SET
|
|
11358
11615
|
"activeObservations" = ?,
|
|
11359
11616
|
"observationTokenCount" = ?,
|
|
11360
11617
|
"pendingMessageTokens" = ?,
|
|
11361
11618
|
"bufferedObservationChunks" = ?,
|
|
11362
11619
|
"lastObservedAt" = ?,
|
|
11363
11620
|
"updatedAt" = ?
|
|
11364
|
-
WHERE id = ?
|
|
11365
|
-
|
|
11366
|
-
|
|
11367
|
-
|
|
11368
|
-
|
|
11369
|
-
|
|
11370
|
-
|
|
11371
|
-
|
|
11372
|
-
|
|
11373
|
-
|
|
11374
|
-
|
|
11375
|
-
|
|
11376
|
-
|
|
11377
|
-
|
|
11378
|
-
|
|
11379
|
-
|
|
11380
|
-
|
|
11381
|
-
|
|
11382
|
-
|
|
11383
|
-
|
|
11384
|
-
|
|
11385
|
-
|
|
11386
|
-
|
|
11387
|
-
|
|
11388
|
-
|
|
11389
|
-
|
|
11390
|
-
|
|
11391
|
-
|
|
11392
|
-
|
|
11393
|
-
|
|
11394
|
-
|
|
11395
|
-
|
|
11396
|
-
cycleId: c.cycleId ?? "",
|
|
11397
|
-
messageTokens: c.messageTokens ?? 0,
|
|
11398
|
-
observationTokens: c.tokenCount,
|
|
11399
|
-
messageCount: c.messageIds.length,
|
|
11400
|
-
observations: c.observations
|
|
11401
|
-
})),
|
|
11402
|
-
suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
|
|
11403
|
-
currentTask: latestChunkHints?.currentTask ?? void 0
|
|
11404
|
-
};
|
|
11405
|
-
} catch (error) {
|
|
11406
|
-
if (!tx.closed) await tx.rollback();
|
|
11407
|
-
throw error;
|
|
11408
|
-
}
|
|
11409
|
-
});
|
|
11621
|
+
WHERE id = ? AND ${guard.sql}`,
|
|
11622
|
+
args: [
|
|
11623
|
+
newActive,
|
|
11624
|
+
newTokenCount,
|
|
11625
|
+
newPending,
|
|
11626
|
+
remainingChunks.length > 0 ? JSON.stringify(remainingChunks) : null,
|
|
11627
|
+
lastObservedAtStr,
|
|
11628
|
+
nowStr,
|
|
11629
|
+
input.id,
|
|
11630
|
+
...guard.args
|
|
11631
|
+
]
|
|
11632
|
+
})).rowsAffected === 0) return OM_CAS_CONFLICT;
|
|
11633
|
+
const latestChunkHints = activatedChunks[activatedChunks.length - 1];
|
|
11634
|
+
return {
|
|
11635
|
+
chunksActivated: activatedChunks.length,
|
|
11636
|
+
messageTokensActivated: activatedMessageTokens,
|
|
11637
|
+
observationTokensActivated: activatedTokens,
|
|
11638
|
+
messagesActivated: activatedMessageCount,
|
|
11639
|
+
activatedCycleIds,
|
|
11640
|
+
activatedMessageIds,
|
|
11641
|
+
observations: activatedContent,
|
|
11642
|
+
perChunk: activatedChunks.map((c) => ({
|
|
11643
|
+
cycleId: c.cycleId ?? "",
|
|
11644
|
+
messageTokens: c.messageTokens ?? 0,
|
|
11645
|
+
observationTokens: c.tokenCount,
|
|
11646
|
+
messageCount: c.messageIds.length,
|
|
11647
|
+
observations: c.observations
|
|
11648
|
+
})),
|
|
11649
|
+
suggestedContinuation: latestChunkHints?.suggestedContinuation ?? void 0,
|
|
11650
|
+
currentTask: latestChunkHints?.currentTask ?? void 0
|
|
11651
|
+
};
|
|
11652
|
+
}, "swapBufferedToActive");
|
|
11410
11653
|
} catch (error) {
|
|
11411
11654
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
11412
11655
|
throw new _mastra_core_error.MastraError({
|
|
@@ -11460,57 +11703,27 @@ var MemoryLibSQL = class MemoryLibSQL extends _mastra_core_storage.MemoryStorage
|
|
|
11460
11703
|
}
|
|
11461
11704
|
async swapBufferedReflectionToActive(input) {
|
|
11462
11705
|
try {
|
|
11463
|
-
|
|
11464
|
-
|
|
11465
|
-
const
|
|
11466
|
-
|
|
11467
|
-
|
|
11468
|
-
|
|
11469
|
-
|
|
11470
|
-
|
|
11471
|
-
|
|
11472
|
-
|
|
11473
|
-
|
|
11474
|
-
|
|
11475
|
-
|
|
11476
|
-
|
|
11477
|
-
|
|
11478
|
-
|
|
11479
|
-
|
|
11480
|
-
|
|
11481
|
-
|
|
11482
|
-
|
|
11483
|
-
|
|
11484
|
-
text: "No buffered reflection to swap",
|
|
11485
|
-
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11486
|
-
category: _mastra_core_error.ErrorCategory.USER,
|
|
11487
|
-
details: { id: input.currentRecord.id }
|
|
11488
|
-
});
|
|
11489
|
-
const unreflectedContent = (row.activeObservations || "").split("\n").slice(reflectedLineCount).join("\n").trim();
|
|
11490
|
-
const newObservations = unreflectedContent ? `${bufferedReflection}\n\n${unreflectedContent}` : bufferedReflection;
|
|
11491
|
-
const newRecord = await this.#insertReflectionGeneration(tx, {
|
|
11492
|
-
currentRecord: input.currentRecord,
|
|
11493
|
-
reflection: newObservations,
|
|
11494
|
-
tokenCount: input.tokenCount
|
|
11495
|
-
});
|
|
11496
|
-
const nowStr = (/* @__PURE__ */ new Date()).toISOString();
|
|
11497
|
-
await tx.execute({
|
|
11498
|
-
sql: `UPDATE "${OM_TABLE}" SET
|
|
11499
|
-
"bufferedReflection" = NULL,
|
|
11500
|
-
"bufferedReflectionTokens" = NULL,
|
|
11501
|
-
"bufferedReflectionInputTokens" = NULL,
|
|
11502
|
-
"reflectedObservationLineCount" = NULL,
|
|
11503
|
-
"updatedAt" = ?
|
|
11504
|
-
WHERE id = ?`,
|
|
11505
|
-
args: [nowStr, input.currentRecord.id]
|
|
11506
|
-
});
|
|
11507
|
-
await tx.commit();
|
|
11508
|
-
return newRecord;
|
|
11509
|
-
} catch (error) {
|
|
11510
|
-
if (!tx.closed) await tx.rollback();
|
|
11511
|
-
throw error;
|
|
11512
|
-
}
|
|
11513
|
-
});
|
|
11706
|
+
return await this.#withOMCas("SWAP_BUFFERED_REFLECTION_TO_ACTIVE", async (attemptIndex, check) => {
|
|
11707
|
+
const { currentRecord } = input;
|
|
11708
|
+
const row = await this.#readOMRow(currentRecord.id, check);
|
|
11709
|
+
if (!row) return this.#mayBeUnsynced(attemptIndex) ? OM_CAS_CONFLICT : currentRecord;
|
|
11710
|
+
const stored = row.record;
|
|
11711
|
+
if (stored.supersededBy) return (await this.#resolveLiveOMRow(row, check)).record;
|
|
11712
|
+
const bufferedReflection = stored.bufferedReflection || "";
|
|
11713
|
+
if (!bufferedReflection) throw new _mastra_core_error.MastraError({
|
|
11714
|
+
id: (0, _mastra_core_storage.createStorageErrorId)("LIBSQL", "SWAP_BUFFERED_REFLECTION_TO_ACTIVE", "NO_CONTENT"),
|
|
11715
|
+
text: "No buffered reflection to swap",
|
|
11716
|
+
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
11717
|
+
category: _mastra_core_error.ErrorCategory.USER,
|
|
11718
|
+
details: { id: currentRecord.id }
|
|
11719
|
+
});
|
|
11720
|
+
if (!isAppendOnlySince(stored.activeObservations, currentRecord.activeObservations)) return stored;
|
|
11721
|
+
const reflectedLineCount = stored.reflectedObservationLineCount ?? 0;
|
|
11722
|
+
const unreflectedContent = (stored.activeObservations || "").split("\n").slice(reflectedLineCount).join("\n").trim();
|
|
11723
|
+
const newObservations = unreflectedContent ? `${bufferedReflection}\n\n${unreflectedContent}` : bufferedReflection;
|
|
11724
|
+
const tokenCount = input.tokenCount + Math.max(0, (stored.observationTokenCount ?? 0) - (currentRecord.observationTokenCount ?? 0));
|
|
11725
|
+
return this.#rollOverObservationalMemory(row, newObservations, tokenCount, input.newRecordId);
|
|
11726
|
+
}, "swapBufferedReflectionToActive");
|
|
11514
11727
|
} catch (error) {
|
|
11515
11728
|
if (error instanceof _mastra_core_error.MastraError) throw error;
|
|
11516
11729
|
throw new _mastra_core_error.MastraError({
|
|
@@ -15213,25 +15426,12 @@ var WorkflowsLibSQL = class WorkflowsLibSQL extends _mastra_core_storage.Workflo
|
|
|
15213
15426
|
sql: `SELECT json(snapshot) as snapshot FROM ${_mastra_core_storage.TABLE_WORKFLOW_SNAPSHOT} WHERE workflow_name = ? AND run_id = ?`,
|
|
15214
15427
|
args: [workflowName, runId]
|
|
15215
15428
|
});
|
|
15216
|
-
|
|
15217
|
-
|
|
15218
|
-
|
|
15219
|
-
activePaths: [],
|
|
15220
|
-
timestamp: Date.now(),
|
|
15221
|
-
suspendedPaths: {},
|
|
15222
|
-
activeStepsPath: {},
|
|
15223
|
-
resumeLabels: {},
|
|
15224
|
-
serializedStepGraph: [],
|
|
15225
|
-
status: "pending",
|
|
15226
|
-
value: {},
|
|
15227
|
-
waitingPaths: {},
|
|
15228
|
-
runId,
|
|
15229
|
-
requestContext: {}
|
|
15230
|
-
};
|
|
15231
|
-
else {
|
|
15232
|
-
const existingSnapshot = existingSnapshotResult.rows[0].snapshot;
|
|
15233
|
-
snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
15429
|
+
if (!existingSnapshotResult.rows?.[0]) {
|
|
15430
|
+
await tx.rollback();
|
|
15431
|
+
return {};
|
|
15234
15432
|
}
|
|
15433
|
+
const existingSnapshot = existingSnapshotResult.rows[0].snapshot;
|
|
15434
|
+
const snapshot = typeof existingSnapshot === "string" ? JSON.parse(existingSnapshot) : existingSnapshot;
|
|
15235
15435
|
(0, _mastra_core_storage.mergeWorkflowStepResult)({
|
|
15236
15436
|
snapshot,
|
|
15237
15437
|
stepId,
|
|
@@ -16267,7 +16467,6 @@ var LibSQLFactoryStorage = class extends _mastra_core_storage.FactoryStorage {
|
|
|
16267
16467
|
}
|
|
16268
16468
|
async withTransaction(fn) {
|
|
16269
16469
|
return withClientWriteLock(this.#client, async () => {
|
|
16270
|
-
if (this.#config.url.includes(":memory:")) return fn(new LibSQLFactoryStorageOps(this.#client, this.#schemas, runWithoutWriteLock));
|
|
16271
16470
|
const transaction = await this.#client.transaction("write");
|
|
16272
16471
|
try {
|
|
16273
16472
|
const result = await fn(new LibSQLFactoryStorageOps(transaction, this.#schemas, runWithoutWriteLock));
|
|
@@ -16429,6 +16628,7 @@ var LibSQLStore = class extends _mastra_core_storage.MastraCompositeStore {
|
|
|
16429
16628
|
}
|
|
16430
16629
|
const domainConfig = {
|
|
16431
16630
|
client: this.client,
|
|
16631
|
+
embeddedReplica: "url" in config && !!config.syncUrl,
|
|
16432
16632
|
maxRetries: this.maxRetries,
|
|
16433
16633
|
initialBackoffMs: this.initialBackoffMs
|
|
16434
16634
|
};
|