@mastra/dsql 1.2.2 → 1.3.0-alpha.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +41 -0
- package/dist/index.cjs +103 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +103 -49
- package/dist/index.js.map +1 -1
- package/dist/storage/client.d.ts +5 -1
- package/dist/storage/client.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +7 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +6 -6
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,46 @@
|
|
|
1
1
|
# @mastra/dsql
|
|
2
2
|
|
|
3
|
+
## 1.3.0-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Fixed resource-scoped message includes across storage adapters so included context cannot cross resource boundaries. ([#20984](https://github.com/mastra-ai/mastra/pull/20984))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`6445eba`](https://github.com/mastra-ai/mastra/commit/6445eba6020abac681aba1cc9289f446cb400cbe), [`df31eb0`](https://github.com/mastra-ai/mastra/commit/df31eb0c7087d782a0d9346e467f9a4af4b0eef6), [`fcd0667`](https://github.com/mastra-ai/mastra/commit/fcd0667a4e378be35c9a1b1eb19cce78fbfd7282), [`bab06b1`](https://github.com/mastra-ai/mastra/commit/bab06b18923873a584bdfc71a6b4ec7fb4727fb7)]:
|
|
10
|
+
- @mastra/core@1.58.0-alpha.5
|
|
11
|
+
|
|
12
|
+
## 1.3.0-alpha.0
|
|
13
|
+
|
|
14
|
+
### Minor Changes
|
|
15
|
+
|
|
16
|
+
- Memory list reads now surface database errors instead of silently returning empty results. ([#17910](https://github.com/mastra-ai/mastra/pull/17910))
|
|
17
|
+
|
|
18
|
+
Previously, the paginated memory reads (`listThreads`, `listMessages`, `listMessagesByResourceId`, and `listMessagesById`) caught backend failures, logged them, and returned an empty payload like `{ threads: [], total: 0, hasMore: false }`. A transient outage (locked table, dropped connection) was therefore indistinguishable from a genuinely empty result, so an agent reading conversation history during a brief failure would treat it as "no history" and could overwrite real state. These methods now re-throw the failure as a `MastraError`. Validation (USER) errors and genuinely empty results are unchanged.
|
|
19
|
+
|
|
20
|
+
**Behavior change**
|
|
21
|
+
|
|
22
|
+
Callers that previously received an empty result on a backend failure will now receive a thrown `MastraError`. If you call these read methods directly (rather than through an agent, which already surfaces errors), wrap them so a transient outage doesn't crash the caller:
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
try {
|
|
26
|
+
const { threads } = await storage.listThreads({ resourceId });
|
|
27
|
+
// ...use threads
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// a real backend failure. Decide whether to retry, surface, or degrade.
|
|
30
|
+
// An empty thread list no longer hides here; it only means "no threads".
|
|
31
|
+
}
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### Patch Changes
|
|
35
|
+
|
|
36
|
+
- dependencies updates: ([#20406](https://github.com/mastra-ai/mastra/pull/20406))
|
|
37
|
+
- Updated dependency [`@aws-sdk/types@^3.974.2` ↗︎](https://www.npmjs.com/package/@aws-sdk/types/v/3.974.2) (from `^3.973.9`, in `dependencies`)
|
|
38
|
+
|
|
39
|
+
- Fixed transaction completion when applications start several database operations at the same time. Pending operations now finish before the transaction completes or is cancelled, preventing query conflicts after batch failures and operations that application code does not await. ([#20869](https://github.com/mastra-ai/mastra/pull/20869))
|
|
40
|
+
|
|
41
|
+
- Updated dependencies [[`e7109ee`](https://github.com/mastra-ai/mastra/commit/e7109ee6f731bacc79c885906f3c7dca8d8f013a), [`772c0c8`](https://github.com/mastra-ai/mastra/commit/772c0c897cec383258de2e6178147f8014767c7b), [`578bf2e`](https://github.com/mastra-ai/mastra/commit/578bf2e6a88e9d5b8bf502204e15a95dfbb679ae), [`06b2d87`](https://github.com/mastra-ai/mastra/commit/06b2d87e63bcdd0ed59215c6789692b9b12de376), [`ac01d63`](https://github.com/mastra-ai/mastra/commit/ac01d6355974aec73fdb8781449ed12bac582094), [`a810a05`](https://github.com/mastra-ai/mastra/commit/a810a058f62ad407cfc1701e0be36ae91145d7cf), [`f8da216`](https://github.com/mastra-ai/mastra/commit/f8da21633e7eb0e31c9ce0fc30567870d19416d3), [`6104347`](https://github.com/mastra-ai/mastra/commit/61043473ba6bfd0a25156824e853e13165562e6c), [`45bfb88`](https://github.com/mastra-ai/mastra/commit/45bfb88fd52f1dd3be20e2a38905777c96499c90), [`e3b9307`](https://github.com/mastra-ai/mastra/commit/e3b9307098daefbfae2a52ae2ef51bc9fc701190), [`d6834c5`](https://github.com/mastra-ai/mastra/commit/d6834c5a7866b16734d23900163c2414ed70d791), [`c52d346`](https://github.com/mastra-ai/mastra/commit/c52d3462ec831a5d95926ecd3d3373f5928ad2e5), [`0023e79`](https://github.com/mastra-ai/mastra/commit/0023e7919431078280abd11c89d1edeae35fcc69), [`c2ad51e`](https://github.com/mastra-ai/mastra/commit/c2ad51e2467f901eecba8c9f4a45e22a50bd7c18), [`3dc97ea`](https://github.com/mastra-ai/mastra/commit/3dc97ea415fad353b48a13095fad1835933cc12a), [`3d01cd3`](https://github.com/mastra-ai/mastra/commit/3d01cd387321b6f9c5cac31d487c84bf51b19c78), [`7bf3086`](https://github.com/mastra-ai/mastra/commit/7bf308663f0115ca74ad20554ade740f06640859), [`a8dd139`](https://github.com/mastra-ai/mastra/commit/a8dd1391a9fe9a6632c25809ef236980afa9a020), [`e5786be`](https://github.com/mastra-ai/mastra/commit/e5786be02bb903073082bd9d6da880ebaacc343f), [`2093fbd`](https://github.com/mastra-ai/mastra/commit/2093fbd53bb744bae19ec89f6d73db9a66fbe8a7), [`e7a5da4`](https://github.com/mastra-ai/mastra/commit/e7a5da4ef8e4dd452d2f232961b4e682a85ffe43), [`7b4393d`](https://github.com/mastra-ai/mastra/commit/7b4393d557411fdcf07b0e30e5acaf7cc85154ae)]:
|
|
42
|
+
- @mastra/core@1.58.0-alpha.1
|
|
43
|
+
|
|
3
44
|
## 1.2.2
|
|
4
45
|
|
|
5
46
|
### Patch Changes
|
package/dist/index.cjs
CHANGED
|
@@ -126,16 +126,21 @@ var PoolAdapter = class {
|
|
|
126
126
|
const client = await this.$pool.connect();
|
|
127
127
|
try {
|
|
128
128
|
await client.query("BEGIN");
|
|
129
|
-
const
|
|
130
|
-
await client.query("COMMIT");
|
|
131
|
-
return result;
|
|
132
|
-
} catch (error) {
|
|
129
|
+
const txClient = new TransactionClient(client);
|
|
133
130
|
try {
|
|
134
|
-
await
|
|
135
|
-
|
|
136
|
-
|
|
131
|
+
const result = await callback(txClient);
|
|
132
|
+
await txClient.drain();
|
|
133
|
+
await client.query("COMMIT");
|
|
134
|
+
return result;
|
|
135
|
+
} catch (error) {
|
|
136
|
+
await txClient.drain().catch(() => void 0);
|
|
137
|
+
try {
|
|
138
|
+
await client.query("ROLLBACK");
|
|
139
|
+
} catch (rollbackError) {
|
|
140
|
+
console.error("Transaction rollback failed:", rollbackError);
|
|
141
|
+
}
|
|
142
|
+
throw error;
|
|
137
143
|
}
|
|
138
|
-
throw error;
|
|
139
144
|
} finally {
|
|
140
145
|
client.release();
|
|
141
146
|
}
|
|
@@ -143,41 +148,85 @@ var PoolAdapter = class {
|
|
|
143
148
|
};
|
|
144
149
|
/**
|
|
145
150
|
* Transaction client that wraps a PoolClient for executing queries within a transaction.
|
|
151
|
+
*
|
|
152
|
+
* Query methods are serialized through a tail promise (same pattern as
|
|
153
|
+
* PinnedClientAdapter). Callers such as memory.updateMessages historically
|
|
154
|
+
* did `queries.push(t.none(...))` then `await t.batch(queries)` — each
|
|
155
|
+
* `t.none()` is async and starts `client.query` immediately, so by the time
|
|
156
|
+
* batch runs, N queries are already in flight on one PoolClient. pg@8 queues
|
|
157
|
+
* those internally and emits a DeprecationWarning; pg@9 will throw.
|
|
158
|
+
* (#20820)
|
|
146
159
|
*/
|
|
147
160
|
var TransactionClient = class {
|
|
148
161
|
client;
|
|
162
|
+
/**
|
|
163
|
+
* Serialization tail. Without this gate, concurrent t.none()/t.query()
|
|
164
|
+
* from Promise.all / batch land on the same PoolClient at once.
|
|
165
|
+
*/
|
|
166
|
+
#tail = Promise.resolve();
|
|
167
|
+
#error;
|
|
149
168
|
constructor(client) {
|
|
150
169
|
this.client = client;
|
|
151
170
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
171
|
+
#enqueue(fn) {
|
|
172
|
+
const next = this.#tail.then(fn);
|
|
173
|
+
this.#tail = next.then(() => void 0, (error) => {
|
|
174
|
+
this.#error ??= { value: error };
|
|
175
|
+
});
|
|
176
|
+
return next;
|
|
155
177
|
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
178
|
+
/**
|
|
179
|
+
* Wait until every enqueued query has settled and surface the first failure.
|
|
180
|
+
* PoolAdapter calls this before COMMIT/ROLLBACK so those control
|
|
181
|
+
* statements never overlap in-flight work on the same client.
|
|
182
|
+
*/
|
|
183
|
+
async drain() {
|
|
184
|
+
await this.#tail;
|
|
185
|
+
if (this.#error) {
|
|
186
|
+
const { value } = this.#error;
|
|
187
|
+
this.#error = void 0;
|
|
188
|
+
throw value;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
none(query, values) {
|
|
192
|
+
return this.#enqueue(async () => {
|
|
193
|
+
await this.client.query(query, values);
|
|
194
|
+
return null;
|
|
195
|
+
});
|
|
161
196
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
197
|
+
one(query, values) {
|
|
198
|
+
return this.#enqueue(async () => {
|
|
199
|
+
const result = await this.client.query(query, values);
|
|
200
|
+
if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
|
|
201
|
+
if (result.rows.length > 1) throw new Error(`Multiple rows returned when one was expected: ${truncateQuery(query)}`);
|
|
202
|
+
return result.rows[0];
|
|
203
|
+
});
|
|
167
204
|
}
|
|
168
|
-
|
|
169
|
-
return (
|
|
205
|
+
oneOrNone(query, values) {
|
|
206
|
+
return this.#enqueue(async () => {
|
|
207
|
+
const result = await this.client.query(query, values);
|
|
208
|
+
if (result.rows.length === 0) return null;
|
|
209
|
+
if (result.rows.length > 1) throw new Error(`Multiple rows returned when one or none was expected: ${truncateQuery(query)}`);
|
|
210
|
+
return result.rows[0];
|
|
211
|
+
});
|
|
170
212
|
}
|
|
171
|
-
|
|
213
|
+
any(query, values) {
|
|
214
|
+
return this.#enqueue(async () => {
|
|
215
|
+
return (await this.client.query(query, values)).rows;
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
manyOrNone(query, values) {
|
|
172
219
|
return this.any(query, values);
|
|
173
220
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
221
|
+
many(query, values) {
|
|
222
|
+
return this.#enqueue(async () => {
|
|
223
|
+
const result = await this.client.query(query, values);
|
|
224
|
+
if (result.rows.length === 0) throw new Error(`No data returned from query: ${truncateQuery(query)}`);
|
|
225
|
+
return result.rows;
|
|
226
|
+
});
|
|
178
227
|
}
|
|
179
|
-
|
|
180
|
-
return this.client.query(query, values);
|
|
228
|
+
query(query, values) {
|
|
229
|
+
return this.#enqueue(() => this.client.query(query, values));
|
|
181
230
|
}
|
|
182
231
|
async batch(promises) {
|
|
183
232
|
return Promise.all(promises);
|
|
@@ -1977,6 +2026,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
1977
2026
|
hasMore: perPageInput === false ? false : offset + perPage < total
|
|
1978
2027
|
};
|
|
1979
2028
|
} catch (error) {
|
|
2029
|
+
if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
|
|
1980
2030
|
const mastraError = new _mastra_core_error.MastraError({
|
|
1981
2031
|
id: (0, _mastra_core_storage.createStorageErrorId)("DSQL", "LIST_THREADS", "FAILED"),
|
|
1982
2032
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -1989,13 +2039,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
1989
2039
|
}, error);
|
|
1990
2040
|
this.logger?.error?.(mastraError.toString());
|
|
1991
2041
|
this.logger?.trackException(mastraError);
|
|
1992
|
-
|
|
1993
|
-
threads: [],
|
|
1994
|
-
total: 0,
|
|
1995
|
-
page,
|
|
1996
|
-
perPage: perPageForResponse,
|
|
1997
|
-
hasMore: false
|
|
1998
|
-
};
|
|
2042
|
+
throw mastraError;
|
|
1999
2043
|
}
|
|
2000
2044
|
}
|
|
2001
2045
|
async saveThread({ thread }) {
|
|
@@ -2129,7 +2173,14 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2129
2173
|
}, error);
|
|
2130
2174
|
});
|
|
2131
2175
|
}
|
|
2132
|
-
|
|
2176
|
+
/**
|
|
2177
|
+
* Fetches the messages named by `include` together with their surrounding context.
|
|
2178
|
+
*
|
|
2179
|
+
* @param include - Message ids to pin, each with an optional before/after window.
|
|
2180
|
+
* @param resourceId - When set, restricts both the pinned messages and their context
|
|
2181
|
+
* to that resource so an id from another resource returns nothing.
|
|
2182
|
+
*/
|
|
2183
|
+
async _getIncludedMessages({ include, resourceId }) {
|
|
2133
2184
|
if (!include || include.length === 0) return null;
|
|
2134
2185
|
const unionQueries = [];
|
|
2135
2186
|
const params = [];
|
|
@@ -2140,17 +2191,18 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2140
2191
|
});
|
|
2141
2192
|
for (const inc of include) {
|
|
2142
2193
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
2194
|
+
const resourceCondition = resourceId ? ` AND "resourceId" = $${paramIdx + 3}` : "";
|
|
2143
2195
|
unionQueries.push(`
|
|
2144
2196
|
SELECT * FROM (
|
|
2145
2197
|
WITH target_thread AS (
|
|
2146
|
-
SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx}
|
|
2198
|
+
SELECT thread_id FROM ${tableName} WHERE id = $${paramIdx}${resourceCondition}
|
|
2147
2199
|
),
|
|
2148
2200
|
ordered_messages AS (
|
|
2149
2201
|
SELECT
|
|
2150
2202
|
*,
|
|
2151
2203
|
ROW_NUMBER() OVER (ORDER BY "createdAt" ASC) as row_num
|
|
2152
2204
|
FROM ${tableName}
|
|
2153
|
-
WHERE thread_id = (SELECT thread_id FROM target_thread)
|
|
2205
|
+
WHERE thread_id = (SELECT thread_id FROM target_thread)${resourceCondition}
|
|
2154
2206
|
)
|
|
2155
2207
|
SELECT
|
|
2156
2208
|
m.id,
|
|
@@ -2176,6 +2228,10 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2176
2228
|
`);
|
|
2177
2229
|
params.push(id, withPreviousMessages, withNextMessages);
|
|
2178
2230
|
paramIdx += 3;
|
|
2231
|
+
if (resourceId) {
|
|
2232
|
+
params.push(resourceId);
|
|
2233
|
+
paramIdx += 1;
|
|
2234
|
+
}
|
|
2179
2235
|
}
|
|
2180
2236
|
const finalQuery = unionQueries.join(" UNION ALL ") + " ORDER BY \"createdAt\" ASC";
|
|
2181
2237
|
const includedRows = await this.#db.client.manyOrNone(finalQuery, params);
|
|
@@ -2225,7 +2281,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2225
2281
|
}, error);
|
|
2226
2282
|
this.logger?.error?.(mastraError.toString());
|
|
2227
2283
|
this.logger?.trackException(mastraError);
|
|
2228
|
-
|
|
2284
|
+
throw mastraError;
|
|
2229
2285
|
}
|
|
2230
2286
|
}
|
|
2231
2287
|
async listMessages(args) {
|
|
@@ -2301,7 +2357,10 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2301
2357
|
};
|
|
2302
2358
|
const messageIds = new Set(messages.map((m) => m.id));
|
|
2303
2359
|
if (include && include.length > 0) {
|
|
2304
|
-
const includeMessages = await this._getIncludedMessages({
|
|
2360
|
+
const includeMessages = await this._getIncludedMessages({
|
|
2361
|
+
include,
|
|
2362
|
+
resourceId
|
|
2363
|
+
});
|
|
2305
2364
|
if (includeMessages) {
|
|
2306
2365
|
for (const includeMsg of includeMessages) if (!messageIds.has(includeMsg.id)) {
|
|
2307
2366
|
messages.push(includeMsg);
|
|
@@ -2332,6 +2391,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2332
2391
|
hasMore
|
|
2333
2392
|
};
|
|
2334
2393
|
} catch (error) {
|
|
2394
|
+
if (error instanceof _mastra_core_error.MastraError && error.category === _mastra_core_error.ErrorCategory.USER) throw error;
|
|
2335
2395
|
const mastraError = new _mastra_core_error.MastraError({
|
|
2336
2396
|
id: (0, _mastra_core_storage.createStorageErrorId)("DSQL", "LIST_MESSAGES", "FAILED"),
|
|
2337
2397
|
domain: _mastra_core_error.ErrorDomain.STORAGE,
|
|
@@ -2343,13 +2403,7 @@ var MemoryDSQL = class MemoryDSQL extends _mastra_core_storage.MemoryStorage {
|
|
|
2343
2403
|
}, error);
|
|
2344
2404
|
this.logger?.error?.(mastraError.toString());
|
|
2345
2405
|
this.logger?.trackException(mastraError);
|
|
2346
|
-
|
|
2347
|
-
messages: [],
|
|
2348
|
-
total: 0,
|
|
2349
|
-
page,
|
|
2350
|
-
perPage: perPageForResponse,
|
|
2351
|
-
hasMore: false
|
|
2352
|
-
};
|
|
2406
|
+
throw mastraError;
|
|
2353
2407
|
}
|
|
2354
2408
|
}
|
|
2355
2409
|
async saveMessages({ messages }) {
|