@mastra/cloudflare-d1 1.0.1 → 1.0.2-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.
- package/CHANGELOG.md +13 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/reference-storage-cloudflare-d1.md +8 -8
- package/dist/index.cjs +139 -64
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +139 -64
- package/dist/index.js.map +1 -1
- package/dist/storage/db/index.d.ts +12 -0
- package/dist/storage/db/index.d.ts.map +1 -1
- package/dist/storage/domains/memory/index.d.ts +1 -0
- package/dist/storage/domains/memory/index.d.ts.map +1 -1
- package/package.json +8 -8
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,18 @@
|
|
|
1
1
|
# @mastra/cloudflare-d1
|
|
2
2
|
|
|
3
|
+
## 1.0.2-alpha.0
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- Added resilient column handling to insert and update operations. Unknown columns in records are now silently dropped instead of causing SQL errors, ensuring forward compatibility when newer domain packages add fields that haven't been migrated yet. ([#14021](https://github.com/mastra-ai/mastra/pull/14021))
|
|
8
|
+
|
|
9
|
+
For example, calling `db.insert({ tableName, record: { id: '1', title: 'Hello', futureField: 'value' } })` will silently ignore `futureField` if it doesn't exist in the database table, rather than throwing. The same applies to `update` — unknown fields in the data payload are dropped before building the SQL statement.
|
|
10
|
+
|
|
11
|
+
- Fixed slow semantic recall in the libsql, Cloudflare D1, and ClickHouse storage adapters. Recall performance no longer degrades as threads grow larger. (Fixes #11702) ([#14022](https://github.com/mastra-ai/mastra/pull/14022))
|
|
12
|
+
|
|
13
|
+
- Updated dependencies [[`4f71b43`](https://github.com/mastra-ai/mastra/commit/4f71b436a4a6b8839842d8da47b57b84509af56c), [`a070277`](https://github.com/mastra-ai/mastra/commit/a07027766ce195ba74d0783116d894cbab25d44c), [`b628b91`](https://github.com/mastra-ai/mastra/commit/b628b9128b372c0f54214d902b07279f03443900), [`332c014`](https://github.com/mastra-ai/mastra/commit/332c014e076b81edf7fe45b58205882726415e90), [`6b63153`](https://github.com/mastra-ai/mastra/commit/6b63153878ea841c0f4ce632ba66bb33e57e9c1b), [`4246e34`](https://github.com/mastra-ai/mastra/commit/4246e34cec9c26636d0965942268e6d07c346671), [`b8837ee`](https://github.com/mastra-ai/mastra/commit/b8837ee77e2e84197609762bfabd8b3da326d30c), [`5d950f7`](https://github.com/mastra-ai/mastra/commit/5d950f7bf426a215a1808f0abef7de5c8336ba1c), [`28c85b1`](https://github.com/mastra-ai/mastra/commit/28c85b184fc32b40f7f160483c982da6d388ecbd), [`e9a08fb`](https://github.com/mastra-ai/mastra/commit/e9a08fbef1ada7e50e961e2f54f55e8c10b4a45c), [`631ffd8`](https://github.com/mastra-ai/mastra/commit/631ffd82fed108648b448b28e6a90e38c5f53bf5), [`aae2295`](https://github.com/mastra-ai/mastra/commit/aae2295838a2d329ad6640829e87934790ffe5b8), [`aa61f29`](https://github.com/mastra-ai/mastra/commit/aa61f29ff8095ce46a4ae16e46c4d8c79b2b685b), [`7ff3714`](https://github.com/mastra-ai/mastra/commit/7ff37148515439bb3be009a60e02c3e363299760), [`41d79a1`](https://github.com/mastra-ai/mastra/commit/41d79a14bd8cb6de1e2565fd0a04786bae2f211b), [`e673376`](https://github.com/mastra-ai/mastra/commit/e6733763ad1321aa7e5ae15096b9c2104f93b1f3), [`b2204c9`](https://github.com/mastra-ai/mastra/commit/b2204c98a42848bbfb6f0440f005dc2b6354f1cd), [`a1bf1e3`](https://github.com/mastra-ai/mastra/commit/a1bf1e385ed4c0ef6f11b56c5887442970d127f2), [`b6f647a`](https://github.com/mastra-ai/mastra/commit/b6f647ae2388e091f366581595feb957e37d5b40), [`0c57b8b`](https://github.com/mastra-ai/mastra/commit/0c57b8b0a69a97b5a4ae3f79be6c610f29f3cf7b), [`b081f27`](https://github.com/mastra-ai/mastra/commit/b081f272cf411716e1d6bd72ceac4bcee2657b19), [`0c09eac`](https://github.com/mastra-ai/mastra/commit/0c09eacb1926f64cfdc9ae5c6d63385cf8c9f72c), [`6b9b93d`](https://github.com/mastra-ai/mastra/commit/6b9b93d6f459d1ba6e36f163abf62a085ddb3d64), [`31b6067`](https://github.com/mastra-ai/mastra/commit/31b6067d0cc3ab10e1b29c36147f3b5266bc714a), [`797ac42`](https://github.com/mastra-ai/mastra/commit/797ac4276de231ad2d694d9aeca75980f6cd0419), [`0bc289e`](https://github.com/mastra-ai/mastra/commit/0bc289e2d476bf46c5b91c21969e8d0c6864691c), [`9b75a06`](https://github.com/mastra-ai/mastra/commit/9b75a06e53ebb0b950ba7c1e83a0142047185f46), [`4c3a1b1`](https://github.com/mastra-ai/mastra/commit/4c3a1b122ea083e003d71092f30f3b31680b01c0), [`85cc3b3`](https://github.com/mastra-ai/mastra/commit/85cc3b3b6f32ae4b083c26498f50d5b250ba944b), [`97ea28c`](https://github.com/mastra-ai/mastra/commit/97ea28c746e9e4147d56047bbb1c4a92417a3fec), [`d567299`](https://github.com/mastra-ai/mastra/commit/d567299cf81e02bd9d5221d4bc05967d6c224161), [`716ffe6`](https://github.com/mastra-ai/mastra/commit/716ffe68bed81f7c2690bc8581b9e140f7bf1c3d), [`8296332`](https://github.com/mastra-ai/mastra/commit/8296332de21c16e3dfc3d0b2d615720a6dc88f2f), [`4df2116`](https://github.com/mastra-ai/mastra/commit/4df211619dd922c047d396ca41cd7027c8c4c8e7), [`2219c1a`](https://github.com/mastra-ai/mastra/commit/2219c1acbd21da116da877f0036ffb985a9dd5a3), [`17c4145`](https://github.com/mastra-ai/mastra/commit/17c4145166099354545582335b5252bdfdfd908b)]:
|
|
14
|
+
- @mastra/core@1.11.0-alpha.0
|
|
15
|
+
|
|
3
16
|
## 1.0.1
|
|
4
17
|
|
|
5
18
|
### Patch Changes
|
package/dist/docs/SKILL.md
CHANGED
|
@@ -3,7 +3,7 @@ name: mastra-cloudflare-d1
|
|
|
3
3
|
description: Documentation for @mastra/cloudflare-d1. Use when working with @mastra/cloudflare-d1 APIs, configuration, or implementation.
|
|
4
4
|
metadata:
|
|
5
5
|
package: "@mastra/cloudflare-d1"
|
|
6
|
-
version: "1.0.
|
|
6
|
+
version: "1.0.2-alpha.0"
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## When to use
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
The Cloudflare D1 storage implementation provides a serverless SQL database solution using Cloudflare D1, supporting relational operations and transactional consistency.
|
|
4
4
|
|
|
5
|
-
> **Observability Not Supported:** Cloudflare D1 storage **
|
|
5
|
+
> **Observability Not Supported:** Cloudflare D1 storage **doesn't support the observability domain**. Traces from the `DefaultExporter` can't be persisted to D1, and Mastra Studio's observability features won't work with D1 as your only storage provider. To enable observability, use [composite storage](https://mastra.ai/reference/storage/composite) to route observability data to a supported provider like ClickHouse or PostgreSQL.
|
|
6
6
|
|
|
7
7
|
> **Row Size Limit:** Cloudflare D1 enforces a **1 MiB maximum row size**. This limit can be exceeded when storing messages with base64-encoded attachments such as images. See [Handling large attachments](https://mastra.ai/docs/memory/storage) for workarounds including uploading attachments to external storage.
|
|
8
8
|
|
|
@@ -85,7 +85,7 @@ export default {
|
|
|
85
85
|
> - The **property name** (`D1Database`) must match the `binding` name in your `wrangler.toml`
|
|
86
86
|
> - The **type** (`: D1Database`) is from `@cloudflare/workers-types` for TypeScript type checking
|
|
87
87
|
>
|
|
88
|
-
> At runtime, Cloudflare Workers provides the actual D1 database instance via `env.D1Database`. You
|
|
88
|
+
> At runtime, Cloudflare Workers provides the actual D1 database instance via `env.D1Database`. You can't use `D1Database` directly outside of the worker's context.
|
|
89
89
|
|
|
90
90
|
### Using with REST API
|
|
91
91
|
|
|
@@ -129,15 +129,15 @@ Or in `wrangler.jsonc`:
|
|
|
129
129
|
|
|
130
130
|
## Parameters
|
|
131
131
|
|
|
132
|
-
**binding
|
|
132
|
+
**binding** (`D1Database`): Cloudflare D1 Workers binding (for Workers runtime)
|
|
133
133
|
|
|
134
|
-
**accountId
|
|
134
|
+
**accountId** (`string`): Cloudflare Account ID (for REST API)
|
|
135
135
|
|
|
136
|
-
**databaseId
|
|
136
|
+
**databaseId** (`string`): Cloudflare D1 Database ID (for REST API)
|
|
137
137
|
|
|
138
|
-
**apiToken
|
|
138
|
+
**apiToken** (`string`): Cloudflare API Token (for REST API)
|
|
139
139
|
|
|
140
|
-
**tablePrefix
|
|
140
|
+
**tablePrefix** (`string`): Optional prefix for all table names (useful for environment isolation)
|
|
141
141
|
|
|
142
142
|
## Additional Notes
|
|
143
143
|
|
|
@@ -207,7 +207,7 @@ export default {
|
|
|
207
207
|
}
|
|
208
208
|
```
|
|
209
209
|
|
|
210
|
-
> **Warning:** If `init()`
|
|
210
|
+
> **Warning:** If `init()` isn't called, tables won't be created and storage operations will fail silently or throw errors.
|
|
211
211
|
|
|
212
212
|
### Transactions & Consistency
|
|
213
213
|
|
package/dist/index.cjs
CHANGED
|
@@ -291,6 +291,8 @@ var D1DB = class extends base.MastraBase {
|
|
|
291
291
|
client;
|
|
292
292
|
binding;
|
|
293
293
|
tablePrefix;
|
|
294
|
+
/** Cache of actual table columns: tableName -> Promise<Set<columnName>> (stores in-flight promise to coalesce concurrent calls) */
|
|
295
|
+
tableColumnsCache = /* @__PURE__ */ new Map();
|
|
294
296
|
constructor(config) {
|
|
295
297
|
super({
|
|
296
298
|
component: "STORAGE",
|
|
@@ -399,6 +401,38 @@ var D1DB = class extends base.MastraBase {
|
|
|
399
401
|
throw new Error("Neither binding nor client is configured");
|
|
400
402
|
}
|
|
401
403
|
}
|
|
404
|
+
/**
|
|
405
|
+
* Gets the set of column names that actually exist in the database table.
|
|
406
|
+
* Results are cached; the cache is invalidated when alterTable() adds new columns.
|
|
407
|
+
*/
|
|
408
|
+
async getKnownColumnNames(tableName) {
|
|
409
|
+
const cached = this.tableColumnsCache.get(tableName);
|
|
410
|
+
if (cached) return cached;
|
|
411
|
+
const promise = this.getTableColumns(tableName).then((columns) => {
|
|
412
|
+
const names = new Set(columns.map((c) => c.name));
|
|
413
|
+
if (names.size === 0) {
|
|
414
|
+
this.tableColumnsCache.delete(tableName);
|
|
415
|
+
}
|
|
416
|
+
return names;
|
|
417
|
+
});
|
|
418
|
+
this.tableColumnsCache.set(tableName, promise);
|
|
419
|
+
return promise;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Filters a record to only include columns that exist in the actual database table.
|
|
423
|
+
* Unknown columns are silently dropped to ensure forward compatibility.
|
|
424
|
+
*/
|
|
425
|
+
async filterRecordToKnownColumns(tableName, record) {
|
|
426
|
+
const knownColumns = await this.getKnownColumnNames(tableName);
|
|
427
|
+
if (knownColumns.size === 0) return record;
|
|
428
|
+
const filtered = {};
|
|
429
|
+
for (const [key, value] of Object.entries(record)) {
|
|
430
|
+
if (knownColumns.has(key)) {
|
|
431
|
+
filtered[key] = value;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
return filtered;
|
|
435
|
+
}
|
|
402
436
|
async getTableColumns(tableName) {
|
|
403
437
|
try {
|
|
404
438
|
const sql = `PRAGMA table_info(${tableName})`;
|
|
@@ -465,6 +499,7 @@ var D1DB = class extends base.MastraBase {
|
|
|
465
499
|
const { sql, params } = query.build();
|
|
466
500
|
await this.executeQuery({ sql, params });
|
|
467
501
|
this.logger.debug(`Created table ${fullTableName}`);
|
|
502
|
+
this.tableColumnsCache.delete(fullTableName);
|
|
468
503
|
} catch (error$1) {
|
|
469
504
|
throw new error.MastraError(
|
|
470
505
|
{
|
|
@@ -497,8 +532,8 @@ var D1DB = class extends base.MastraBase {
|
|
|
497
532
|
}
|
|
498
533
|
}
|
|
499
534
|
async dropTable({ tableName }) {
|
|
535
|
+
const fullTableName = this.getTableName(tableName);
|
|
500
536
|
try {
|
|
501
|
-
const fullTableName = this.getTableName(tableName);
|
|
502
537
|
const sql = `DROP TABLE IF EXISTS ${fullTableName}`;
|
|
503
538
|
await this.executeQuery({ sql });
|
|
504
539
|
this.logger.debug(`Dropped table ${fullTableName}`);
|
|
@@ -512,11 +547,13 @@ var D1DB = class extends base.MastraBase {
|
|
|
512
547
|
},
|
|
513
548
|
error$1
|
|
514
549
|
);
|
|
550
|
+
} finally {
|
|
551
|
+
this.tableColumnsCache.delete(fullTableName);
|
|
515
552
|
}
|
|
516
553
|
}
|
|
517
554
|
async alterTable(args) {
|
|
555
|
+
const fullTableName = this.getTableName(args.tableName);
|
|
518
556
|
try {
|
|
519
|
-
const fullTableName = this.getTableName(args.tableName);
|
|
520
557
|
const existingColumns = await this.getTableColumns(fullTableName);
|
|
521
558
|
const existingColumnNames = new Set(existingColumns.map((col) => col.name));
|
|
522
559
|
for (const [columnName, column] of Object.entries(args.schema)) {
|
|
@@ -538,14 +575,18 @@ var D1DB = class extends base.MastraBase {
|
|
|
538
575
|
},
|
|
539
576
|
error$1
|
|
540
577
|
);
|
|
578
|
+
} finally {
|
|
579
|
+
this.tableColumnsCache.delete(fullTableName);
|
|
541
580
|
}
|
|
542
581
|
}
|
|
543
582
|
async insert({ tableName, record }) {
|
|
544
583
|
try {
|
|
545
584
|
const fullTableName = this.getTableName(tableName);
|
|
546
585
|
const processedRecord = await this.processRecord(record);
|
|
547
|
-
const
|
|
548
|
-
const
|
|
586
|
+
const filteredRecord = await this.filterRecordToKnownColumns(fullTableName, processedRecord);
|
|
587
|
+
const columns = Object.keys(filteredRecord);
|
|
588
|
+
if (columns.length === 0) return;
|
|
589
|
+
const values = Object.values(filteredRecord);
|
|
549
590
|
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
550
591
|
const { sql, params } = query.build();
|
|
551
592
|
await this.executeQuery({ sql, params });
|
|
@@ -566,8 +607,12 @@ var D1DB = class extends base.MastraBase {
|
|
|
566
607
|
if (records.length === 0) return;
|
|
567
608
|
const fullTableName = this.getTableName(tableName);
|
|
568
609
|
const processedRecords = await Promise.all(records.map((record) => this.processRecord(record)));
|
|
569
|
-
const
|
|
570
|
-
|
|
610
|
+
const filteredRecords = await Promise.all(
|
|
611
|
+
processedRecords.map((r) => this.filterRecordToKnownColumns(fullTableName, r))
|
|
612
|
+
);
|
|
613
|
+
for (const record of filteredRecords) {
|
|
614
|
+
const columns = Object.keys(record);
|
|
615
|
+
if (columns.length === 0) continue;
|
|
571
616
|
const values = Object.values(record);
|
|
572
617
|
const query = createSqlBuilder().insert(fullTableName, columns, values);
|
|
573
618
|
const { sql, params } = query.build();
|
|
@@ -643,12 +688,14 @@ var D1DB = class extends base.MastraBase {
|
|
|
643
688
|
const batch = records.slice(i, i + batchSize);
|
|
644
689
|
const recordsToInsert = batch;
|
|
645
690
|
if (recordsToInsert.length > 0) {
|
|
646
|
-
const
|
|
647
|
-
|
|
648
|
-
|
|
691
|
+
const filteredRecords = await Promise.all(
|
|
692
|
+
recordsToInsert.map((r) => this.filterRecordToKnownColumns(fullTableName, r || {}))
|
|
693
|
+
);
|
|
694
|
+
for (const record of filteredRecords) {
|
|
695
|
+
const columns = Object.keys(record);
|
|
696
|
+
if (columns.length === 0) continue;
|
|
649
697
|
const values = columns.map((col) => {
|
|
650
|
-
|
|
651
|
-
const value = typeof col === "string" ? record[col] : null;
|
|
698
|
+
const value = record[col];
|
|
652
699
|
return this.serializeValue(value);
|
|
653
700
|
});
|
|
654
701
|
const recordToUpsert = columns.reduce(
|
|
@@ -1134,56 +1181,79 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
|
|
|
1134
1181
|
);
|
|
1135
1182
|
}
|
|
1136
1183
|
}
|
|
1184
|
+
_sortMessages(messages, field, direction) {
|
|
1185
|
+
return messages.sort((a, b) => {
|
|
1186
|
+
const isDateField = field === "createdAt" || field === "updatedAt";
|
|
1187
|
+
const aValue = isDateField ? new Date(a[field]).getTime() : a[field];
|
|
1188
|
+
const bValue = isDateField ? new Date(b[field]).getTime() : b[field];
|
|
1189
|
+
if (aValue === bValue) {
|
|
1190
|
+
return a.id.localeCompare(b.id);
|
|
1191
|
+
}
|
|
1192
|
+
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
1193
|
+
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
1194
|
+
}
|
|
1195
|
+
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1196
|
+
});
|
|
1197
|
+
}
|
|
1137
1198
|
async _getIncludedMessages(include) {
|
|
1138
1199
|
if (!include || include.length === 0) return null;
|
|
1200
|
+
const tableName = this.#db.getTableName(storage.TABLE_MESSAGES);
|
|
1201
|
+
const targetIds = include.map((inc) => inc.id).filter(Boolean);
|
|
1202
|
+
if (targetIds.length === 0) return null;
|
|
1203
|
+
const idPlaceholders = targetIds.map(() => "?").join(", ");
|
|
1204
|
+
const targetResult = await this.#db.executeQuery({
|
|
1205
|
+
sql: `SELECT id, thread_id, createdAt FROM ${tableName} WHERE id IN (${idPlaceholders})`,
|
|
1206
|
+
params: targetIds
|
|
1207
|
+
});
|
|
1208
|
+
if (!Array.isArray(targetResult) || targetResult.length === 0) return null;
|
|
1209
|
+
const targetMap = new Map(
|
|
1210
|
+
targetResult.map((r) => [r.id, { threadId: r.thread_id, createdAt: r.createdAt }])
|
|
1211
|
+
);
|
|
1139
1212
|
const unionQueries = [];
|
|
1140
1213
|
const params = [];
|
|
1141
|
-
let paramIdx = 1;
|
|
1142
|
-
const tableName = this.#db.getTableName(storage.TABLE_MESSAGES);
|
|
1143
1214
|
for (const inc of include) {
|
|
1144
1215
|
const { id, withPreviousMessages = 0, withNextMessages = 0 } = inc;
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
)
|
|
1176
|
-
) AS query_${paramIdx}
|
|
1177
|
-
`);
|
|
1178
|
-
params.push(id, id, id, withNextMessages, withPreviousMessages);
|
|
1179
|
-
paramIdx++;
|
|
1180
|
-
}
|
|
1181
|
-
const finalQuery = unionQueries.join(" UNION ALL ") + " ORDER BY createdAt ASC";
|
|
1216
|
+
const target = targetMap.get(id);
|
|
1217
|
+
if (!target) continue;
|
|
1218
|
+
unionQueries.push(`SELECT * FROM (
|
|
1219
|
+
SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId
|
|
1220
|
+
FROM ${tableName}
|
|
1221
|
+
WHERE thread_id = ?
|
|
1222
|
+
AND createdAt <= ?
|
|
1223
|
+
ORDER BY createdAt DESC, id DESC
|
|
1224
|
+
LIMIT ?
|
|
1225
|
+
)`);
|
|
1226
|
+
params.push(target.threadId, target.createdAt, withPreviousMessages + 1);
|
|
1227
|
+
if (withNextMessages > 0) {
|
|
1228
|
+
unionQueries.push(`SELECT * FROM (
|
|
1229
|
+
SELECT id, content, role, type, createdAt, thread_id AS threadId, resourceId
|
|
1230
|
+
FROM ${tableName}
|
|
1231
|
+
WHERE thread_id = ?
|
|
1232
|
+
AND createdAt > ?
|
|
1233
|
+
ORDER BY createdAt ASC, id ASC
|
|
1234
|
+
LIMIT ?
|
|
1235
|
+
)`);
|
|
1236
|
+
params.push(target.threadId, target.createdAt, withNextMessages);
|
|
1237
|
+
}
|
|
1238
|
+
}
|
|
1239
|
+
if (unionQueries.length === 0) return null;
|
|
1240
|
+
let finalQuery;
|
|
1241
|
+
if (unionQueries.length === 1) {
|
|
1242
|
+
finalQuery = unionQueries[0];
|
|
1243
|
+
} else {
|
|
1244
|
+
finalQuery = `${unionQueries.join(" UNION ALL ")} ORDER BY createdAt ASC, id ASC`;
|
|
1245
|
+
}
|
|
1182
1246
|
const messages = await this.#db.executeQuery({ sql: finalQuery, params });
|
|
1183
1247
|
if (!Array.isArray(messages)) {
|
|
1184
1248
|
return [];
|
|
1185
1249
|
}
|
|
1186
|
-
const
|
|
1250
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1251
|
+
const processedMessages = messages.filter((message) => {
|
|
1252
|
+
const id = message.id;
|
|
1253
|
+
if (seen.has(id)) return false;
|
|
1254
|
+
seen.add(id);
|
|
1255
|
+
return true;
|
|
1256
|
+
}).map((message) => {
|
|
1187
1257
|
const processedMsg = {};
|
|
1188
1258
|
for (const [key, value] of Object.entries(message)) {
|
|
1189
1259
|
if (key === `type` && value === `v2`) continue;
|
|
@@ -1283,6 +1353,23 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
|
|
|
1283
1353
|
queryParams.push(endDate);
|
|
1284
1354
|
}
|
|
1285
1355
|
const { field, direction } = this.parseOrderBy(orderBy, "ASC");
|
|
1356
|
+
if (perPage === 0 && (!include || include.length === 0)) {
|
|
1357
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
1358
|
+
}
|
|
1359
|
+
if (perPage === 0 && include && include.length > 0) {
|
|
1360
|
+
const includeResult = await this._getIncludedMessages(include);
|
|
1361
|
+
if (!Array.isArray(includeResult) || includeResult.length === 0) {
|
|
1362
|
+
return { messages: [], total: 0, page, perPage: perPageForResponse, hasMore: false };
|
|
1363
|
+
}
|
|
1364
|
+
const list2 = new agent.MessageList().add(includeResult, "memory");
|
|
1365
|
+
return {
|
|
1366
|
+
messages: this._sortMessages(list2.get.all.db(), field, direction),
|
|
1367
|
+
total: 0,
|
|
1368
|
+
page,
|
|
1369
|
+
perPage: perPageForResponse,
|
|
1370
|
+
hasMore: false
|
|
1371
|
+
};
|
|
1372
|
+
}
|
|
1286
1373
|
query += ` ORDER BY "${field}" ${direction}`;
|
|
1287
1374
|
if (perPage !== Number.MAX_SAFE_INTEGER) {
|
|
1288
1375
|
query += ` LIMIT ? OFFSET ?`;
|
|
@@ -1342,19 +1429,7 @@ var MemoryStorageD1 = class extends storage.MemoryStorage {
|
|
|
1342
1429
|
}
|
|
1343
1430
|
}
|
|
1344
1431
|
const list = new agent.MessageList().add(paginatedMessages, "memory");
|
|
1345
|
-
|
|
1346
|
-
finalMessages = finalMessages.sort((a, b) => {
|
|
1347
|
-
const isDateField = field === "createdAt" || field === "updatedAt";
|
|
1348
|
-
const aValue = isDateField ? new Date(a[field]).getTime() : a[field];
|
|
1349
|
-
const bValue = isDateField ? new Date(b[field]).getTime() : b[field];
|
|
1350
|
-
if (aValue === bValue) {
|
|
1351
|
-
return a.id.localeCompare(b.id);
|
|
1352
|
-
}
|
|
1353
|
-
if (typeof aValue === "number" && typeof bValue === "number") {
|
|
1354
|
-
return direction === "ASC" ? aValue - bValue : bValue - aValue;
|
|
1355
|
-
}
|
|
1356
|
-
return direction === "ASC" ? String(aValue).localeCompare(String(bValue)) : String(bValue).localeCompare(String(aValue));
|
|
1357
|
-
});
|
|
1432
|
+
const finalMessages = this._sortMessages(list.get.all.db(), field, direction);
|
|
1358
1433
|
const returnedThreadMessageIds = new Set(finalMessages.filter((m) => m.threadId === threadId).map((m) => m.id));
|
|
1359
1434
|
const allThreadMessagesReturned = returnedThreadMessageIds.size >= total;
|
|
1360
1435
|
const hasMore = perPageInput === false ? false : allThreadMessagesReturned ? false : offset + paginatedCount < total;
|