@mastra/cloudflare-d1 0.10.1 → 0.10.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.
@@ -1,21 +1,21 @@
1
1
  import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
2
2
  import type { EvalRow } from '@mastra/core/storage';
3
3
  import type { MastraMessageV1 } from '@mastra/core/memory';
4
- import type { MastraMessageV2 } from '@mastra/core/memory';
5
- import type { MastraMessageV2 as MastraMessageV2_2 } from '@mastra/core';
4
+ import type { MastraMessageV2 } from '@mastra/core';
6
5
  import { MastraStorage } from '@mastra/core/storage';
6
+ import type { PaginationInfo } from '@mastra/core/storage';
7
7
  import type { StorageColumn } from '@mastra/core/storage';
8
8
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
9
- import type { StorageThreadType } from '@mastra/core/memory';
9
+ import type { StorageThreadType } from '@mastra/core';
10
10
  import type { TABLE_NAMES } from '@mastra/core/storage';
11
+ import type { Trace } from '@mastra/core';
11
12
  import type { WorkflowRun } from '@mastra/core/storage';
12
13
  import type { WorkflowRuns } from '@mastra/core/storage';
13
- import type { WorkflowRunState } from '@mastra/core/workflows';
14
- import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
14
+ import type { WorkflowRunState } from '@mastra/core';
15
15
 
16
- export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState_2 | string, stepId: string, status: string) => void;
16
+ export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState | string, stepId: string, status: string) => void;
17
17
 
18
- export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2_2["content"]["parts"]) => MastraMessageV2_2;
18
+ export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2["content"]["parts"], createdAt?: Date) => MastraMessageV2;
19
19
 
20
20
  export declare const createSampleThread: () => {
21
21
  id: string;
@@ -57,7 +57,7 @@ export declare const createSampleTrace: (name: string, scope?: string, attribute
57
57
  };
58
58
 
59
59
  export declare const createSampleWorkflowSnapshot: (threadId: string, status: string, createdAt?: Date) => {
60
- snapshot: WorkflowRunState_2;
60
+ snapshot: WorkflowRunState;
61
61
  runId: string;
62
62
  stepId: string;
63
63
  };
@@ -125,9 +125,19 @@ declare class D1Store extends MastraStorage {
125
125
  getThreadById({ threadId }: {
126
126
  threadId: string;
127
127
  }): Promise<StorageThreadType | null>;
128
+ /**
129
+ * @deprecated use getThreadsByResourceIdPaginated instead
130
+ */
128
131
  getThreadsByResourceId({ resourceId }: {
129
132
  resourceId: string;
130
133
  }): Promise<StorageThreadType[]>;
134
+ getThreadsByResourceIdPaginated(args: {
135
+ resourceId: string;
136
+ page: number;
137
+ perPage: number;
138
+ }): Promise<PaginationInfo & {
139
+ threads: StorageThreadType[];
140
+ }>;
131
141
  saveThread({ thread }: {
132
142
  thread: StorageThreadType;
133
143
  }): Promise<StorageThreadType>;
@@ -147,12 +157,21 @@ declare class D1Store extends MastraStorage {
147
157
  messages: MastraMessageV2[];
148
158
  format: 'v2';
149
159
  }): Promise<MastraMessageV2[]>;
160
+ private _getIncludedMessages;
161
+ /**
162
+ * @deprecated use getMessagesPaginated instead
163
+ */
150
164
  getMessages(args: StorageGetMessagesArg & {
151
165
  format?: 'v1';
152
166
  }): Promise<MastraMessageV1[]>;
153
167
  getMessages(args: StorageGetMessagesArg & {
154
168
  format: 'v2';
155
169
  }): Promise<MastraMessageV2[]>;
170
+ getMessagesPaginated({ threadId, selectBy, format, }: StorageGetMessagesArg & {
171
+ format?: 'v1' | 'v2';
172
+ }): Promise<PaginationInfo & {
173
+ messages: MastraMessageV1[] | MastraMessageV2[];
174
+ }>;
156
175
  persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
157
176
  workflowName: string;
158
177
  runId: string;
@@ -171,6 +190,9 @@ declare class D1Store extends MastraStorage {
171
190
  tableName: TABLE_NAMES;
172
191
  records: Record<string, any>[];
173
192
  }): Promise<void>;
193
+ /**
194
+ * @deprecated use getTracesPaginated instead
195
+ */
174
196
  getTraces({ name, scope, page, perPage, attributes, fromDate, toDate, }: {
175
197
  name?: string;
176
198
  scope?: string;
@@ -179,8 +201,32 @@ declare class D1Store extends MastraStorage {
179
201
  attributes?: Record<string, string>;
180
202
  fromDate?: Date;
181
203
  toDate?: Date;
182
- }): Promise<Record<string, any>[]>;
204
+ }): Promise<Trace[]>;
205
+ getTracesPaginated(args: {
206
+ name?: string;
207
+ scope?: string;
208
+ attributes?: Record<string, string>;
209
+ page: number;
210
+ perPage: number;
211
+ fromDate?: Date;
212
+ toDate?: Date;
213
+ }): Promise<PaginationInfo & {
214
+ traces: Trace[];
215
+ }>;
216
+ /**
217
+ * @deprecated use getEvals instead
218
+ */
183
219
  getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
220
+ getEvals(options?: {
221
+ agentName?: string;
222
+ type?: 'test' | 'live';
223
+ page?: number;
224
+ perPage?: number;
225
+ fromDate?: Date;
226
+ toDate?: Date;
227
+ }): Promise<PaginationInfo & {
228
+ evals: EvalRow[];
229
+ }>;
184
230
  private parseWorkflowRun;
185
231
  private hasColumn;
186
232
  getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId, }?: {
@@ -1,21 +1,21 @@
1
1
  import type { D1Database as D1Database_2 } from '@cloudflare/workers-types';
2
2
  import type { EvalRow } from '@mastra/core/storage';
3
3
  import type { MastraMessageV1 } from '@mastra/core/memory';
4
- import type { MastraMessageV2 } from '@mastra/core/memory';
5
- import type { MastraMessageV2 as MastraMessageV2_2 } from '@mastra/core';
4
+ import type { MastraMessageV2 } from '@mastra/core';
6
5
  import { MastraStorage } from '@mastra/core/storage';
6
+ import type { PaginationInfo } from '@mastra/core/storage';
7
7
  import type { StorageColumn } from '@mastra/core/storage';
8
8
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
9
- import type { StorageThreadType } from '@mastra/core/memory';
9
+ import type { StorageThreadType } from '@mastra/core';
10
10
  import type { TABLE_NAMES } from '@mastra/core/storage';
11
+ import type { Trace } from '@mastra/core';
11
12
  import type { WorkflowRun } from '@mastra/core/storage';
12
13
  import type { WorkflowRuns } from '@mastra/core/storage';
13
- import type { WorkflowRunState } from '@mastra/core/workflows';
14
- import type { WorkflowRunState as WorkflowRunState_2 } from '@mastra/core';
14
+ import type { WorkflowRunState } from '@mastra/core';
15
15
 
16
- export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState_2 | string, stepId: string, status: string) => void;
16
+ export declare const checkWorkflowSnapshot: (snapshot: WorkflowRunState | string, stepId: string, status: string) => void;
17
17
 
18
- export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2_2["content"]["parts"]) => MastraMessageV2_2;
18
+ export declare const createSampleMessage: (threadId: string, parts?: MastraMessageV2["content"]["parts"], createdAt?: Date) => MastraMessageV2;
19
19
 
20
20
  export declare const createSampleThread: () => {
21
21
  id: string;
@@ -57,7 +57,7 @@ export declare const createSampleTrace: (name: string, scope?: string, attribute
57
57
  };
58
58
 
59
59
  export declare const createSampleWorkflowSnapshot: (threadId: string, status: string, createdAt?: Date) => {
60
- snapshot: WorkflowRunState_2;
60
+ snapshot: WorkflowRunState;
61
61
  runId: string;
62
62
  stepId: string;
63
63
  };
@@ -125,9 +125,19 @@ declare class D1Store extends MastraStorage {
125
125
  getThreadById({ threadId }: {
126
126
  threadId: string;
127
127
  }): Promise<StorageThreadType | null>;
128
+ /**
129
+ * @deprecated use getThreadsByResourceIdPaginated instead
130
+ */
128
131
  getThreadsByResourceId({ resourceId }: {
129
132
  resourceId: string;
130
133
  }): Promise<StorageThreadType[]>;
134
+ getThreadsByResourceIdPaginated(args: {
135
+ resourceId: string;
136
+ page: number;
137
+ perPage: number;
138
+ }): Promise<PaginationInfo & {
139
+ threads: StorageThreadType[];
140
+ }>;
131
141
  saveThread({ thread }: {
132
142
  thread: StorageThreadType;
133
143
  }): Promise<StorageThreadType>;
@@ -147,12 +157,21 @@ declare class D1Store extends MastraStorage {
147
157
  messages: MastraMessageV2[];
148
158
  format: 'v2';
149
159
  }): Promise<MastraMessageV2[]>;
160
+ private _getIncludedMessages;
161
+ /**
162
+ * @deprecated use getMessagesPaginated instead
163
+ */
150
164
  getMessages(args: StorageGetMessagesArg & {
151
165
  format?: 'v1';
152
166
  }): Promise<MastraMessageV1[]>;
153
167
  getMessages(args: StorageGetMessagesArg & {
154
168
  format: 'v2';
155
169
  }): Promise<MastraMessageV2[]>;
170
+ getMessagesPaginated({ threadId, selectBy, format, }: StorageGetMessagesArg & {
171
+ format?: 'v1' | 'v2';
172
+ }): Promise<PaginationInfo & {
173
+ messages: MastraMessageV1[] | MastraMessageV2[];
174
+ }>;
156
175
  persistWorkflowSnapshot({ workflowName, runId, snapshot, }: {
157
176
  workflowName: string;
158
177
  runId: string;
@@ -171,6 +190,9 @@ declare class D1Store extends MastraStorage {
171
190
  tableName: TABLE_NAMES;
172
191
  records: Record<string, any>[];
173
192
  }): Promise<void>;
193
+ /**
194
+ * @deprecated use getTracesPaginated instead
195
+ */
174
196
  getTraces({ name, scope, page, perPage, attributes, fromDate, toDate, }: {
175
197
  name?: string;
176
198
  scope?: string;
@@ -179,8 +201,32 @@ declare class D1Store extends MastraStorage {
179
201
  attributes?: Record<string, string>;
180
202
  fromDate?: Date;
181
203
  toDate?: Date;
182
- }): Promise<Record<string, any>[]>;
204
+ }): Promise<Trace[]>;
205
+ getTracesPaginated(args: {
206
+ name?: string;
207
+ scope?: string;
208
+ attributes?: Record<string, string>;
209
+ page: number;
210
+ perPage: number;
211
+ fromDate?: Date;
212
+ toDate?: Date;
213
+ }): Promise<PaginationInfo & {
214
+ traces: Trace[];
215
+ }>;
216
+ /**
217
+ * @deprecated use getEvals instead
218
+ */
183
219
  getEvalsByAgentName(agentName: string, type?: 'test' | 'live'): Promise<EvalRow[]>;
220
+ getEvals(options?: {
221
+ agentName?: string;
222
+ type?: 'test' | 'live';
223
+ page?: number;
224
+ perPage?: number;
225
+ fromDate?: Date;
226
+ toDate?: Date;
227
+ }): Promise<PaginationInfo & {
228
+ evals: EvalRow[];
229
+ }>;
184
230
  private parseWorkflowRun;
185
231
  private hasColumn;
186
232
  getWorkflowRuns({ workflowName, fromDate, toDate, limit, offset, resourceId, }?: {
package/dist/index.cjs CHANGED
@@ -562,6 +562,9 @@ var D1Store = class extends storage.MastraStorage {
562
562
  return null;
563
563
  }
564
564
  }
565
+ /**
566
+ * @deprecated use getThreadsByResourceIdPaginated instead
567
+ */
565
568
  async getThreadsByResourceId({ resourceId }) {
566
569
  const fullTableName = this.getTableName(storage.TABLE_THREADS);
567
570
  try {
@@ -581,6 +584,29 @@ var D1Store = class extends storage.MastraStorage {
581
584
  return [];
582
585
  }
583
586
  }
587
+ async getThreadsByResourceIdPaginated(args) {
588
+ const { resourceId, page, perPage } = args;
589
+ const fullTableName = this.getTableName(storage.TABLE_THREADS);
590
+ const mapRowToStorageThreadType = (row) => ({
591
+ ...row,
592
+ createdAt: this.ensureDate(row.createdAt),
593
+ updatedAt: this.ensureDate(row.updatedAt),
594
+ metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
595
+ });
596
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
597
+ const countResult = await this.executeQuery(countQuery.build());
598
+ const total = Number(countResult?.[0]?.count ?? 0);
599
+ const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
600
+ const results = await this.executeQuery(selectQuery.build());
601
+ const threads = results.map(mapRowToStorageThreadType);
602
+ return {
603
+ threads,
604
+ total,
605
+ page,
606
+ perPage,
607
+ hasMore: page * perPage + threads.length < total
608
+ };
609
+ }
584
610
  async saveThread({ thread }) {
585
611
  const fullTableName = this.getTableName(storage.TABLE_THREADS);
586
612
  const threadToSave = {
@@ -703,26 +729,18 @@ var D1Store = class extends storage.MastraStorage {
703
729
  throw error;
704
730
  }
705
731
  }
706
- async getMessages({
707
- threadId,
708
- selectBy,
709
- format
710
- }) {
711
- const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
712
- const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
713
- const include = selectBy?.include || [];
714
- const messages = [];
715
- try {
716
- if (include.length) {
717
- const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
718
- const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
719
- const includeIds = include.map((i) => i.id);
720
- const sql2 = `
732
+ async _getIncludedMessages(threadId, selectBy) {
733
+ const include = selectBy?.include;
734
+ if (!include) return null;
735
+ const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
736
+ const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
737
+ const includeIds = include.map((i) => i.id);
738
+ const sql = `
721
739
  WITH ordered_messages AS (
722
740
  SELECT
723
741
  *,
724
742
  ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
725
- FROM ${fullTableName}
743
+ FROM ${this.getTableName(storage.TABLE_MESSAGES)}
726
744
  WHERE thread_id = ?
727
745
  )
728
746
  SELECT
@@ -745,20 +763,38 @@ var D1Store = class extends storage.MastraStorage {
745
763
  )
746
764
  ORDER BY m.createdAt DESC
747
765
  `;
748
- const params2 = [
749
- threadId,
750
- ...includeIds,
751
- // for m.id IN (...)
752
- ...includeIds,
753
- // for target.id IN (...)
754
- prevMax,
755
- nextMax
756
- ];
757
- const includeResult = await this.executeQuery({ sql: sql2, params: params2 });
766
+ const params = [
767
+ threadId,
768
+ ...includeIds,
769
+ // for m.id IN (...)
770
+ ...includeIds,
771
+ // for target.id IN (...)
772
+ prevMax,
773
+ nextMax
774
+ ];
775
+ const messages = await this.executeQuery({ sql, params });
776
+ return messages;
777
+ }
778
+ async getMessages({
779
+ threadId,
780
+ selectBy,
781
+ format
782
+ }) {
783
+ const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
784
+ const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
785
+ const include = selectBy?.include || [];
786
+ const messages = [];
787
+ try {
788
+ if (include.length) {
789
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
758
790
  if (Array.isArray(includeResult)) messages.push(...includeResult);
759
791
  }
760
792
  const excludeIds = messages.map((m) => m.id);
761
- let query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId).andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds).orderBy("createdAt", "DESC").limit(limit);
793
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
794
+ if (excludeIds.length > 0) {
795
+ query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
796
+ }
797
+ query.orderBy("createdAt", "DESC").limit(limit);
762
798
  const { sql, params } = query.build();
763
799
  const result = await this.executeQuery({ sql, params });
764
800
  if (Array.isArray(result)) messages.push(...result);
@@ -789,6 +825,47 @@ var D1Store = class extends storage.MastraStorage {
789
825
  return [];
790
826
  }
791
827
  }
828
+ async getMessagesPaginated({
829
+ threadId,
830
+ selectBy,
831
+ format
832
+ }) {
833
+ const { dateRange, page = 0, perPage = 40 } = selectBy?.pagination || {};
834
+ const { start: fromDate, end: toDate } = dateRange || {};
835
+ const fullTableName = this.getTableName(storage.TABLE_MESSAGES);
836
+ const messages = [];
837
+ if (selectBy?.include?.length) {
838
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
839
+ if (Array.isArray(includeResult)) messages.push(...includeResult);
840
+ }
841
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
842
+ if (fromDate) {
843
+ countQuery.andWhere("createdAt >= ?", this.serializeDate(fromDate));
844
+ }
845
+ if (toDate) {
846
+ countQuery.andWhere("createdAt <= ?", this.serializeDate(toDate));
847
+ }
848
+ const countResult = await this.executeQuery(countQuery.build());
849
+ const total = Number(countResult[0]?.count ?? 0);
850
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
851
+ if (fromDate) {
852
+ query.andWhere("createdAt >= ?", this.serializeDate(fromDate));
853
+ }
854
+ if (toDate) {
855
+ query.andWhere("createdAt <= ?", this.serializeDate(toDate));
856
+ }
857
+ query.orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
858
+ const results = await this.executeQuery(query.build());
859
+ const list = new agent.MessageList().add(results, "memory");
860
+ messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
861
+ return {
862
+ messages,
863
+ total,
864
+ page,
865
+ perPage,
866
+ hasMore: page * perPage + messages.length < total
867
+ };
868
+ }
792
869
  async persistWorkflowSnapshot({
793
870
  workflowName,
794
871
  runId,
@@ -881,6 +958,9 @@ var D1Store = class extends storage.MastraStorage {
881
958
  throw new Error(`Failed to batch insert into ${tableName}: ${error}`);
882
959
  }
883
960
  }
961
+ /**
962
+ * @deprecated use getTracesPaginated instead
963
+ */
884
964
  async getTraces({
885
965
  name,
886
966
  scope,
@@ -910,22 +990,83 @@ var D1Store = class extends storage.MastraStorage {
910
990
  if (toDate) {
911
991
  query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
912
992
  }
913
- query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
993
+ query.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
914
994
  const { sql, params } = query.build();
915
995
  const results = await this.executeQuery({ sql, params });
916
- return isArrayOfRecords(results) ? results.map((trace) => ({
917
- ...trace,
918
- attributes: this.deserializeValue(trace.attributes, "jsonb"),
919
- status: this.deserializeValue(trace.status, "jsonb"),
920
- events: this.deserializeValue(trace.events, "jsonb"),
921
- links: this.deserializeValue(trace.links, "jsonb"),
922
- other: this.deserializeValue(trace.other, "jsonb")
923
- })) : [];
996
+ return isArrayOfRecords(results) ? results.map(
997
+ (trace) => ({
998
+ ...trace,
999
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
1000
+ status: this.deserializeValue(trace.status, "jsonb"),
1001
+ events: this.deserializeValue(trace.events, "jsonb"),
1002
+ links: this.deserializeValue(trace.links, "jsonb"),
1003
+ other: this.deserializeValue(trace.other, "jsonb")
1004
+ })
1005
+ ) : [];
924
1006
  } catch (error) {
925
1007
  this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
926
1008
  return [];
927
1009
  }
928
1010
  }
1011
+ async getTracesPaginated(args) {
1012
+ const { name, scope, page, perPage, attributes, fromDate, toDate } = args;
1013
+ const fullTableName = this.getTableName(storage.TABLE_TRACES);
1014
+ try {
1015
+ const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
1016
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
1017
+ if (name) {
1018
+ dataQuery.andWhere("name LIKE ?", `%${name}%`);
1019
+ countQuery.andWhere("name LIKE ?", `%${name}%`);
1020
+ }
1021
+ if (scope) {
1022
+ dataQuery.andWhere("scope = ?", scope);
1023
+ countQuery.andWhere("scope = ?", scope);
1024
+ }
1025
+ if (attributes && Object.keys(attributes).length > 0) {
1026
+ for (const [key, value] of Object.entries(attributes)) {
1027
+ dataQuery.jsonLike("attributes", key, value);
1028
+ countQuery.jsonLike("attributes", key, value);
1029
+ }
1030
+ }
1031
+ if (fromDate) {
1032
+ const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
1033
+ dataQuery.andWhere("createdAt >= ?", fromDateStr);
1034
+ countQuery.andWhere("createdAt >= ?", fromDateStr);
1035
+ }
1036
+ if (toDate) {
1037
+ const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
1038
+ dataQuery.andWhere("createdAt <= ?", toDateStr);
1039
+ countQuery.andWhere("createdAt <= ?", toDateStr);
1040
+ }
1041
+ const countResult = await this.executeQuery(countQuery.build());
1042
+ const total = Number(countResult?.[0]?.count ?? 0);
1043
+ dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
1044
+ const results = await this.executeQuery(dataQuery.build());
1045
+ const traces = isArrayOfRecords(results) ? results.map(
1046
+ (trace) => ({
1047
+ ...trace,
1048
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
1049
+ status: this.deserializeValue(trace.status, "jsonb"),
1050
+ events: this.deserializeValue(trace.events, "jsonb"),
1051
+ links: this.deserializeValue(trace.links, "jsonb"),
1052
+ other: this.deserializeValue(trace.other, "jsonb")
1053
+ })
1054
+ ) : [];
1055
+ return {
1056
+ traces,
1057
+ total,
1058
+ page,
1059
+ perPage,
1060
+ hasMore: page * perPage + traces.length < total
1061
+ };
1062
+ } catch (error) {
1063
+ this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
1064
+ return { traces: [], total: 0, page, perPage, hasMore: false };
1065
+ }
1066
+ }
1067
+ /**
1068
+ * @deprecated use getEvals instead
1069
+ */
929
1070
  async getEvalsByAgentName(agentName, type) {
930
1071
  const fullTableName = this.getTableName(storage.TABLE_EVALS);
931
1072
  try {
@@ -961,6 +1102,80 @@ var D1Store = class extends storage.MastraStorage {
961
1102
  return [];
962
1103
  }
963
1104
  }
1105
+ async getEvals(options) {
1106
+ const { agentName, type, page = 0, perPage = 40, fromDate, toDate } = options || {};
1107
+ const fullTableName = this.getTableName(storage.TABLE_EVALS);
1108
+ const conditions = [];
1109
+ const queryParams = [];
1110
+ if (agentName) {
1111
+ conditions.push(`agent_name = ?`);
1112
+ queryParams.push(agentName);
1113
+ }
1114
+ if (type === "test") {
1115
+ conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
1116
+ } else if (type === "live") {
1117
+ conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
1118
+ }
1119
+ if (fromDate) {
1120
+ conditions.push(`createdAt >= ?`);
1121
+ queryParams.push(this.serializeDate(fromDate));
1122
+ }
1123
+ if (toDate) {
1124
+ conditions.push(`createdAt <= ?`);
1125
+ queryParams.push(this.serializeDate(toDate));
1126
+ }
1127
+ const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
1128
+ if (conditions.length > 0) {
1129
+ countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1130
+ }
1131
+ const { sql: countSql, params: countParams } = countQueryBuilder.build();
1132
+ const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
1133
+ const total = Number(countResult?.count || 0);
1134
+ const currentOffset = page * perPage;
1135
+ if (total === 0) {
1136
+ return {
1137
+ evals: [],
1138
+ total: 0,
1139
+ page,
1140
+ perPage,
1141
+ hasMore: false
1142
+ };
1143
+ }
1144
+ const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
1145
+ if (conditions.length > 0) {
1146
+ dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1147
+ }
1148
+ dataQueryBuilder.orderBy("createdAt", "DESC").limit(perPage).offset(currentOffset);
1149
+ const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
1150
+ const rows = await this.executeQuery({ sql: dataSql, params: dataParams });
1151
+ const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
1152
+ const result = this.deserializeValue(row.result);
1153
+ const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
1154
+ if (!result || typeof result !== "object" || !("score" in result)) {
1155
+ throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
1156
+ }
1157
+ return {
1158
+ input: row.input,
1159
+ output: row.output,
1160
+ result,
1161
+ agentName: row.agent_name,
1162
+ metricName: row.metric_name,
1163
+ instructions: row.instructions,
1164
+ testInfo,
1165
+ globalRunId: row.global_run_id,
1166
+ runId: row.run_id,
1167
+ createdAt: row.createdAt
1168
+ };
1169
+ });
1170
+ const hasMore = currentOffset + evals.length < total;
1171
+ return {
1172
+ evals,
1173
+ total,
1174
+ page,
1175
+ perPage,
1176
+ hasMore
1177
+ };
1178
+ }
964
1179
  parseWorkflowRun(row) {
965
1180
  let parsedSnapshot = row.snapshot;
966
1181
  if (typeof parsedSnapshot === "string") {
package/dist/index.js CHANGED
@@ -556,6 +556,9 @@ var D1Store = class extends MastraStorage {
556
556
  return null;
557
557
  }
558
558
  }
559
+ /**
560
+ * @deprecated use getThreadsByResourceIdPaginated instead
561
+ */
559
562
  async getThreadsByResourceId({ resourceId }) {
560
563
  const fullTableName = this.getTableName(TABLE_THREADS);
561
564
  try {
@@ -575,6 +578,29 @@ var D1Store = class extends MastraStorage {
575
578
  return [];
576
579
  }
577
580
  }
581
+ async getThreadsByResourceIdPaginated(args) {
582
+ const { resourceId, page, perPage } = args;
583
+ const fullTableName = this.getTableName(TABLE_THREADS);
584
+ const mapRowToStorageThreadType = (row) => ({
585
+ ...row,
586
+ createdAt: this.ensureDate(row.createdAt),
587
+ updatedAt: this.ensureDate(row.updatedAt),
588
+ metadata: typeof row.metadata === "string" ? JSON.parse(row.metadata || "{}") : row.metadata || {}
589
+ });
590
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("resourceId = ?", resourceId);
591
+ const countResult = await this.executeQuery(countQuery.build());
592
+ const total = Number(countResult?.[0]?.count ?? 0);
593
+ const selectQuery = createSqlBuilder().select("*").from(fullTableName).where("resourceId = ?", resourceId).orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
594
+ const results = await this.executeQuery(selectQuery.build());
595
+ const threads = results.map(mapRowToStorageThreadType);
596
+ return {
597
+ threads,
598
+ total,
599
+ page,
600
+ perPage,
601
+ hasMore: page * perPage + threads.length < total
602
+ };
603
+ }
578
604
  async saveThread({ thread }) {
579
605
  const fullTableName = this.getTableName(TABLE_THREADS);
580
606
  const threadToSave = {
@@ -697,26 +723,18 @@ var D1Store = class extends MastraStorage {
697
723
  throw error;
698
724
  }
699
725
  }
700
- async getMessages({
701
- threadId,
702
- selectBy,
703
- format
704
- }) {
705
- const fullTableName = this.getTableName(TABLE_MESSAGES);
706
- const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
707
- const include = selectBy?.include || [];
708
- const messages = [];
709
- try {
710
- if (include.length) {
711
- const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
712
- const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
713
- const includeIds = include.map((i) => i.id);
714
- const sql2 = `
726
+ async _getIncludedMessages(threadId, selectBy) {
727
+ const include = selectBy?.include;
728
+ if (!include) return null;
729
+ const prevMax = Math.max(...include.map((i) => i.withPreviousMessages || 0));
730
+ const nextMax = Math.max(...include.map((i) => i.withNextMessages || 0));
731
+ const includeIds = include.map((i) => i.id);
732
+ const sql = `
715
733
  WITH ordered_messages AS (
716
734
  SELECT
717
735
  *,
718
736
  ROW_NUMBER() OVER (ORDER BY createdAt DESC) AS row_num
719
- FROM ${fullTableName}
737
+ FROM ${this.getTableName(TABLE_MESSAGES)}
720
738
  WHERE thread_id = ?
721
739
  )
722
740
  SELECT
@@ -739,20 +757,38 @@ var D1Store = class extends MastraStorage {
739
757
  )
740
758
  ORDER BY m.createdAt DESC
741
759
  `;
742
- const params2 = [
743
- threadId,
744
- ...includeIds,
745
- // for m.id IN (...)
746
- ...includeIds,
747
- // for target.id IN (...)
748
- prevMax,
749
- nextMax
750
- ];
751
- const includeResult = await this.executeQuery({ sql: sql2, params: params2 });
760
+ const params = [
761
+ threadId,
762
+ ...includeIds,
763
+ // for m.id IN (...)
764
+ ...includeIds,
765
+ // for target.id IN (...)
766
+ prevMax,
767
+ nextMax
768
+ ];
769
+ const messages = await this.executeQuery({ sql, params });
770
+ return messages;
771
+ }
772
+ async getMessages({
773
+ threadId,
774
+ selectBy,
775
+ format
776
+ }) {
777
+ const fullTableName = this.getTableName(TABLE_MESSAGES);
778
+ const limit = typeof selectBy?.last === "number" ? selectBy.last : 40;
779
+ const include = selectBy?.include || [];
780
+ const messages = [];
781
+ try {
782
+ if (include.length) {
783
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
752
784
  if (Array.isArray(includeResult)) messages.push(...includeResult);
753
785
  }
754
786
  const excludeIds = messages.map((m) => m.id);
755
- let query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId).andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds).orderBy("createdAt", "DESC").limit(limit);
787
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
788
+ if (excludeIds.length > 0) {
789
+ query.andWhere(`id NOT IN (${excludeIds.map(() => "?").join(",")})`, ...excludeIds);
790
+ }
791
+ query.orderBy("createdAt", "DESC").limit(limit);
756
792
  const { sql, params } = query.build();
757
793
  const result = await this.executeQuery({ sql, params });
758
794
  if (Array.isArray(result)) messages.push(...result);
@@ -783,6 +819,47 @@ var D1Store = class extends MastraStorage {
783
819
  return [];
784
820
  }
785
821
  }
822
+ async getMessagesPaginated({
823
+ threadId,
824
+ selectBy,
825
+ format
826
+ }) {
827
+ const { dateRange, page = 0, perPage = 40 } = selectBy?.pagination || {};
828
+ const { start: fromDate, end: toDate } = dateRange || {};
829
+ const fullTableName = this.getTableName(TABLE_MESSAGES);
830
+ const messages = [];
831
+ if (selectBy?.include?.length) {
832
+ const includeResult = await this._getIncludedMessages(threadId, selectBy);
833
+ if (Array.isArray(includeResult)) messages.push(...includeResult);
834
+ }
835
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("thread_id = ?", threadId);
836
+ if (fromDate) {
837
+ countQuery.andWhere("createdAt >= ?", this.serializeDate(fromDate));
838
+ }
839
+ if (toDate) {
840
+ countQuery.andWhere("createdAt <= ?", this.serializeDate(toDate));
841
+ }
842
+ const countResult = await this.executeQuery(countQuery.build());
843
+ const total = Number(countResult[0]?.count ?? 0);
844
+ const query = createSqlBuilder().select(["id", "content", "role", "type", "createdAt", "thread_id AS threadId"]).from(fullTableName).where("thread_id = ?", threadId);
845
+ if (fromDate) {
846
+ query.andWhere("createdAt >= ?", this.serializeDate(fromDate));
847
+ }
848
+ if (toDate) {
849
+ query.andWhere("createdAt <= ?", this.serializeDate(toDate));
850
+ }
851
+ query.orderBy("createdAt", "DESC").limit(perPage).offset(page * perPage);
852
+ const results = await this.executeQuery(query.build());
853
+ const list = new MessageList().add(results, "memory");
854
+ messages.push(...format === `v2` ? list.get.all.v2() : list.get.all.v1());
855
+ return {
856
+ messages,
857
+ total,
858
+ page,
859
+ perPage,
860
+ hasMore: page * perPage + messages.length < total
861
+ };
862
+ }
786
863
  async persistWorkflowSnapshot({
787
864
  workflowName,
788
865
  runId,
@@ -875,6 +952,9 @@ var D1Store = class extends MastraStorage {
875
952
  throw new Error(`Failed to batch insert into ${tableName}: ${error}`);
876
953
  }
877
954
  }
955
+ /**
956
+ * @deprecated use getTracesPaginated instead
957
+ */
878
958
  async getTraces({
879
959
  name,
880
960
  scope,
@@ -904,22 +984,83 @@ var D1Store = class extends MastraStorage {
904
984
  if (toDate) {
905
985
  query.andWhere("createdAt <= ?", toDate instanceof Date ? toDate.toISOString() : toDate);
906
986
  }
907
- query.orderBy("startTime", "DESC").limit(perPage).offset((page - 1) * perPage);
987
+ query.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
908
988
  const { sql, params } = query.build();
909
989
  const results = await this.executeQuery({ sql, params });
910
- return isArrayOfRecords(results) ? results.map((trace) => ({
911
- ...trace,
912
- attributes: this.deserializeValue(trace.attributes, "jsonb"),
913
- status: this.deserializeValue(trace.status, "jsonb"),
914
- events: this.deserializeValue(trace.events, "jsonb"),
915
- links: this.deserializeValue(trace.links, "jsonb"),
916
- other: this.deserializeValue(trace.other, "jsonb")
917
- })) : [];
990
+ return isArrayOfRecords(results) ? results.map(
991
+ (trace) => ({
992
+ ...trace,
993
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
994
+ status: this.deserializeValue(trace.status, "jsonb"),
995
+ events: this.deserializeValue(trace.events, "jsonb"),
996
+ links: this.deserializeValue(trace.links, "jsonb"),
997
+ other: this.deserializeValue(trace.other, "jsonb")
998
+ })
999
+ ) : [];
918
1000
  } catch (error) {
919
1001
  this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
920
1002
  return [];
921
1003
  }
922
1004
  }
1005
+ async getTracesPaginated(args) {
1006
+ const { name, scope, page, perPage, attributes, fromDate, toDate } = args;
1007
+ const fullTableName = this.getTableName(TABLE_TRACES);
1008
+ try {
1009
+ const dataQuery = createSqlBuilder().select("*").from(fullTableName).where("1=1");
1010
+ const countQuery = createSqlBuilder().count().from(fullTableName).where("1=1");
1011
+ if (name) {
1012
+ dataQuery.andWhere("name LIKE ?", `%${name}%`);
1013
+ countQuery.andWhere("name LIKE ?", `%${name}%`);
1014
+ }
1015
+ if (scope) {
1016
+ dataQuery.andWhere("scope = ?", scope);
1017
+ countQuery.andWhere("scope = ?", scope);
1018
+ }
1019
+ if (attributes && Object.keys(attributes).length > 0) {
1020
+ for (const [key, value] of Object.entries(attributes)) {
1021
+ dataQuery.jsonLike("attributes", key, value);
1022
+ countQuery.jsonLike("attributes", key, value);
1023
+ }
1024
+ }
1025
+ if (fromDate) {
1026
+ const fromDateStr = fromDate instanceof Date ? fromDate.toISOString() : fromDate;
1027
+ dataQuery.andWhere("createdAt >= ?", fromDateStr);
1028
+ countQuery.andWhere("createdAt >= ?", fromDateStr);
1029
+ }
1030
+ if (toDate) {
1031
+ const toDateStr = toDate instanceof Date ? toDate.toISOString() : toDate;
1032
+ dataQuery.andWhere("createdAt <= ?", toDateStr);
1033
+ countQuery.andWhere("createdAt <= ?", toDateStr);
1034
+ }
1035
+ const countResult = await this.executeQuery(countQuery.build());
1036
+ const total = Number(countResult?.[0]?.count ?? 0);
1037
+ dataQuery.orderBy("startTime", "DESC").limit(perPage).offset(page * perPage);
1038
+ const results = await this.executeQuery(dataQuery.build());
1039
+ const traces = isArrayOfRecords(results) ? results.map(
1040
+ (trace) => ({
1041
+ ...trace,
1042
+ attributes: this.deserializeValue(trace.attributes, "jsonb"),
1043
+ status: this.deserializeValue(trace.status, "jsonb"),
1044
+ events: this.deserializeValue(trace.events, "jsonb"),
1045
+ links: this.deserializeValue(trace.links, "jsonb"),
1046
+ other: this.deserializeValue(trace.other, "jsonb")
1047
+ })
1048
+ ) : [];
1049
+ return {
1050
+ traces,
1051
+ total,
1052
+ page,
1053
+ perPage,
1054
+ hasMore: page * perPage + traces.length < total
1055
+ };
1056
+ } catch (error) {
1057
+ this.logger.error("Error getting traces:", { message: error instanceof Error ? error.message : String(error) });
1058
+ return { traces: [], total: 0, page, perPage, hasMore: false };
1059
+ }
1060
+ }
1061
+ /**
1062
+ * @deprecated use getEvals instead
1063
+ */
923
1064
  async getEvalsByAgentName(agentName, type) {
924
1065
  const fullTableName = this.getTableName(TABLE_EVALS);
925
1066
  try {
@@ -955,6 +1096,80 @@ var D1Store = class extends MastraStorage {
955
1096
  return [];
956
1097
  }
957
1098
  }
1099
+ async getEvals(options) {
1100
+ const { agentName, type, page = 0, perPage = 40, fromDate, toDate } = options || {};
1101
+ const fullTableName = this.getTableName(TABLE_EVALS);
1102
+ const conditions = [];
1103
+ const queryParams = [];
1104
+ if (agentName) {
1105
+ conditions.push(`agent_name = ?`);
1106
+ queryParams.push(agentName);
1107
+ }
1108
+ if (type === "test") {
1109
+ conditions.push(`(test_info IS NOT NULL AND json_extract(test_info, '$.testPath') IS NOT NULL)`);
1110
+ } else if (type === "live") {
1111
+ conditions.push(`(test_info IS NULL OR json_extract(test_info, '$.testPath') IS NULL)`);
1112
+ }
1113
+ if (fromDate) {
1114
+ conditions.push(`createdAt >= ?`);
1115
+ queryParams.push(this.serializeDate(fromDate));
1116
+ }
1117
+ if (toDate) {
1118
+ conditions.push(`createdAt <= ?`);
1119
+ queryParams.push(this.serializeDate(toDate));
1120
+ }
1121
+ const countQueryBuilder = createSqlBuilder().count().from(fullTableName);
1122
+ if (conditions.length > 0) {
1123
+ countQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1124
+ }
1125
+ const { sql: countSql, params: countParams } = countQueryBuilder.build();
1126
+ const countResult = await this.executeQuery({ sql: countSql, params: countParams, first: true });
1127
+ const total = Number(countResult?.count || 0);
1128
+ const currentOffset = page * perPage;
1129
+ if (total === 0) {
1130
+ return {
1131
+ evals: [],
1132
+ total: 0,
1133
+ page,
1134
+ perPage,
1135
+ hasMore: false
1136
+ };
1137
+ }
1138
+ const dataQueryBuilder = createSqlBuilder().select("*").from(fullTableName);
1139
+ if (conditions.length > 0) {
1140
+ dataQueryBuilder.where(conditions.join(" AND "), ...queryParams);
1141
+ }
1142
+ dataQueryBuilder.orderBy("createdAt", "DESC").limit(perPage).offset(currentOffset);
1143
+ const { sql: dataSql, params: dataParams } = dataQueryBuilder.build();
1144
+ const rows = await this.executeQuery({ sql: dataSql, params: dataParams });
1145
+ const evals = (isArrayOfRecords(rows) ? rows : []).map((row) => {
1146
+ const result = this.deserializeValue(row.result);
1147
+ const testInfo = row.test_info ? this.deserializeValue(row.test_info) : void 0;
1148
+ if (!result || typeof result !== "object" || !("score" in result)) {
1149
+ throw new Error(`Invalid MetricResult format: ${JSON.stringify(result)}`);
1150
+ }
1151
+ return {
1152
+ input: row.input,
1153
+ output: row.output,
1154
+ result,
1155
+ agentName: row.agent_name,
1156
+ metricName: row.metric_name,
1157
+ instructions: row.instructions,
1158
+ testInfo,
1159
+ globalRunId: row.global_run_id,
1160
+ runId: row.run_id,
1161
+ createdAt: row.createdAt
1162
+ };
1163
+ });
1164
+ const hasMore = currentOffset + evals.length < total;
1165
+ return {
1166
+ evals,
1167
+ total,
1168
+ page,
1169
+ perPage,
1170
+ hasMore
1171
+ };
1172
+ }
958
1173
  parseWorkflowRun(row) {
959
1174
  let parsedSnapshot = row.snapshot;
960
1175
  if (typeof parsedSnapshot === "string") {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/cloudflare-d1",
3
- "version": "0.10.1",
3
+ "version": "0.10.2-alpha.0",
4
4
  "description": "D1 provider for Mastra - includes db storage capabilities",
5
5
  "type": "module",
6
6
  "files": [
@@ -26,16 +26,17 @@
26
26
  },
27
27
  "devDependencies": {
28
28
  "@cloudflare/workers-types": "^4.20250417.0",
29
- "@microsoft/api-extractor": "^7.52.5",
30
- "@types/node": "^20.17.27",
31
- "dotenv": "^16.4.7",
32
- "eslint": "^9.23.0",
29
+ "@microsoft/api-extractor": "^7.52.8",
30
+ "@types/node": "^20.17.57",
31
+ "dotenv": "^16.5.0",
32
+ "eslint": "^9.28.0",
33
33
  "miniflare": "^4.20250410.1",
34
- "tsup": "^8.4.0",
34
+ "tsup": "^8.5.0",
35
35
  "typescript": "^5.8.2",
36
36
  "vitest": "^3.1.2",
37
- "@internal/lint": "0.0.8",
38
- "@mastra/core": "0.10.2"
37
+ "@internal/lint": "0.0.10",
38
+ "@internal/storage-test-utils": "0.0.6",
39
+ "@mastra/core": "0.10.4-alpha.0"
39
40
  },
40
41
  "peerDependencies": {
41
42
  "@mastra/core": "^0.10.2-alpha.0"