@mastra/memory 0.11.6-alpha.1 → 0.11.6-alpha.2

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,9 +1,9 @@
1
1
 
2
- > @mastra/memory@0.11.6-alpha.1 build /home/runner/work/mastra/mastra/packages/memory
2
+ > @mastra/memory@0.11.6-alpha.2 build /home/runner/work/mastra/mastra/packages/memory
3
3
  > pnpm run check && tsup --silent src/index.ts src/processors/index.ts --format esm,cjs --experimental-dts --clean --treeshake=smallest --splitting
4
4
 
5
5
 
6
- > @mastra/memory@0.11.6-alpha.1 check /home/runner/work/mastra/mastra/packages/memory
6
+ > @mastra/memory@0.11.6-alpha.2 check /home/runner/work/mastra/mastra/packages/memory
7
7
  > tsc --noEmit
8
8
 
9
9
  Analysis will use the bundled TypeScript version 5.8.3
package/CHANGELOG.md CHANGED
@@ -1,5 +1,33 @@
1
1
  # @mastra/memory
2
2
 
3
+ ## 0.11.6-alpha.2
4
+
5
+ ### Patch Changes
6
+
7
+ - ff9c125: enhance thread retrieval with sorting options in libsql and pg
8
+ - b8efbb9: feat: add flexible deleteMessages method to memory API
9
+ - Added `memory.deleteMessages(input)` method that accepts multiple input types:
10
+ - Single message ID as string: `deleteMessages('msg-123')`
11
+ - Array of message IDs: `deleteMessages(['msg-1', 'msg-2'])`
12
+ - Message object with id property: `deleteMessages({ id: 'msg-123' })`
13
+ - Array of message objects: `deleteMessages([{ id: 'msg-1' }, { id: 'msg-2' }])`
14
+ - Implemented in all storage adapters (LibSQL, PostgreSQL, Upstash, InMemory)
15
+ - Added REST API endpoint: `POST /api/memory/messages/delete`
16
+ - Updated client SDK: `thread.deleteMessages()` accepts all input types
17
+ - Updates thread timestamps when messages are deleted
18
+ - Added comprehensive test coverage and documentation
19
+
20
+ - Updated dependencies [27cc97a]
21
+ - Updated dependencies [41daa63]
22
+ - Updated dependencies [254a36b]
23
+ - Updated dependencies [0b89602]
24
+ - Updated dependencies [4d37822]
25
+ - Updated dependencies [ff9c125]
26
+ - Updated dependencies [b8efbb9]
27
+ - Updated dependencies [71466e7]
28
+ - Updated dependencies [0c99fbe]
29
+ - @mastra/core@0.12.0-alpha.2
30
+
3
31
  ## 0.11.6-alpha.1
4
32
 
5
33
  ### Patch Changes
@@ -13,6 +13,7 @@ import type { MemoryProcessorOpts } from '@mastra/core';
13
13
  import type { SharedMemoryConfig } from '@mastra/core/memory';
14
14
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
15
15
  import type { StorageThreadType } from '@mastra/core/memory';
16
+ import type { ThreadSortOptions } from '@mastra/core/storage';
16
17
  import type { TiktokenBPE } from 'js-tiktoken/lite';
17
18
  import type { UIMessageWithMetadata } from '@mastra/core/agent';
18
19
  import type { WorkingMemoryTemplate } from '@mastra/core/memory';
@@ -46,9 +47,9 @@ export declare class Memory extends MastraMemory {
46
47
  getThreadById({ threadId }: {
47
48
  threadId: string;
48
49
  }): Promise<StorageThreadType | null>;
49
- getThreadsByResourceId({ resourceId }: {
50
+ getThreadsByResourceId({ resourceId, orderBy, sortDirection, }: {
50
51
  resourceId: string;
51
- }): Promise<StorageThreadType[]>;
52
+ } & ThreadSortOptions): Promise<StorageThreadType[]>;
52
53
  saveThread({ thread }: {
53
54
  thread: StorageThreadType;
54
55
  memoryConfig?: MemoryConfig;
@@ -142,8 +143,20 @@ export declare class Memory extends MastraMemory {
142
143
  id: string;
143
144
  }[];
144
145
  }): Promise<MastraMessageV2[]>;
146
+ /**
147
+ * Deletes one or more messages
148
+ * @param input - Must be an array containing either:
149
+ * - Message ID strings
150
+ * - Message objects with 'id' properties
151
+ * @returns Promise that resolves when all messages are deleted
152
+ */
153
+ deleteMessages(input: MessageDeleteInput): Promise<void>;
145
154
  }
146
155
 
156
+ export declare type MessageDeleteInput = string[] | {
157
+ id: string;
158
+ }[];
159
+
147
160
  /**
148
161
  * Limits the total number of tokens in the messages.
149
162
  * Uses js-tiktoken with o200k_base encoding by default for accurate token counting with modern models.
@@ -13,6 +13,7 @@ import type { MemoryProcessorOpts } from '@mastra/core';
13
13
  import type { SharedMemoryConfig } from '@mastra/core/memory';
14
14
  import type { StorageGetMessagesArg } from '@mastra/core/storage';
15
15
  import type { StorageThreadType } from '@mastra/core/memory';
16
+ import type { ThreadSortOptions } from '@mastra/core/storage';
16
17
  import type { TiktokenBPE } from 'js-tiktoken/lite';
17
18
  import type { UIMessageWithMetadata } from '@mastra/core/agent';
18
19
  import type { WorkingMemoryTemplate } from '@mastra/core/memory';
@@ -46,9 +47,9 @@ export declare class Memory extends MastraMemory {
46
47
  getThreadById({ threadId }: {
47
48
  threadId: string;
48
49
  }): Promise<StorageThreadType | null>;
49
- getThreadsByResourceId({ resourceId }: {
50
+ getThreadsByResourceId({ resourceId, orderBy, sortDirection, }: {
50
51
  resourceId: string;
51
- }): Promise<StorageThreadType[]>;
52
+ } & ThreadSortOptions): Promise<StorageThreadType[]>;
52
53
  saveThread({ thread }: {
53
54
  thread: StorageThreadType;
54
55
  memoryConfig?: MemoryConfig;
@@ -142,8 +143,20 @@ export declare class Memory extends MastraMemory {
142
143
  id: string;
143
144
  }[];
144
145
  }): Promise<MastraMessageV2[]>;
146
+ /**
147
+ * Deletes one or more messages
148
+ * @param input - Must be an array containing either:
149
+ * - Message ID strings
150
+ * - Message objects with 'id' properties
151
+ * @returns Promise that resolves when all messages are deleted
152
+ */
153
+ deleteMessages(input: MessageDeleteInput): Promise<void>;
145
154
  }
146
155
 
156
+ export declare type MessageDeleteInput = string[] | {
157
+ id: string;
158
+ }[];
159
+
147
160
  /**
148
161
  * Limits the total number of tokens in the messages.
149
162
  * Uses js-tiktoken with o200k_base encoding by default for accurate token counting with modern models.
package/dist/index.cjs CHANGED
@@ -27,9 +27,13 @@ var updateWorkingMemoryTool = (memoryConfig) => ({
27
27
  if (!threadId || !memory) {
28
28
  throw new Error("Thread ID and Memory instance are required for working memory updates");
29
29
  }
30
- const thread = await memory.getThreadById({ threadId });
30
+ let thread = await memory.getThreadById({ threadId });
31
31
  if (!thread) {
32
- throw new Error(`Thread ${threadId} not found`);
32
+ thread = await memory.createThread({
33
+ threadId,
34
+ resourceId: resourceId || thread.resourceId,
35
+ memoryConfig
36
+ });
33
37
  }
34
38
  if (thread.resourceId && thread.resourceId !== resourceId) {
35
39
  throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
@@ -60,9 +64,13 @@ var __experimental_updateWorkingMemoryToolVNext = (config) => ({
60
64
  if (!threadId || !memory) {
61
65
  throw new Error("Thread ID and Memory instance are required for working memory updates");
62
66
  }
63
- const thread = await memory.getThreadById({ threadId });
67
+ let thread = await memory.getThreadById({ threadId });
64
68
  if (!thread) {
65
- throw new Error(`Thread ${threadId} not found`);
69
+ thread = await memory.createThread({
70
+ threadId,
71
+ resourceId: resourceId || thread.resourceId,
72
+ config
73
+ });
66
74
  }
67
75
  if (thread.resourceId && thread.resourceId !== resourceId) {
68
76
  throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
@@ -252,8 +260,12 @@ var Memory = class extends memory.MastraMemory {
252
260
  async getThreadById({ threadId }) {
253
261
  return this.storage.getThreadById({ threadId });
254
262
  }
255
- async getThreadsByResourceId({ resourceId }) {
256
- return this.storage.getThreadsByResourceId({ resourceId });
263
+ async getThreadsByResourceId({
264
+ resourceId,
265
+ orderBy,
266
+ sortDirection
267
+ }) {
268
+ return this.storage.getThreadsByResourceId({ resourceId, orderBy, sortDirection });
257
269
  }
258
270
  async saveThread({ thread }) {
259
271
  return this.storage.saveThread({ thread });
@@ -752,6 +764,36 @@ ${template.content !== this.defaultWorkingMemoryTemplate ? `- Only store informa
752
764
  if (messages.length === 0) return [];
753
765
  return this.storage.updateMessages({ messages });
754
766
  }
767
+ /**
768
+ * Deletes one or more messages
769
+ * @param input - Must be an array containing either:
770
+ * - Message ID strings
771
+ * - Message objects with 'id' properties
772
+ * @returns Promise that resolves when all messages are deleted
773
+ */
774
+ async deleteMessages(input) {
775
+ let messageIds;
776
+ if (!Array.isArray(input)) {
777
+ throw new Error("Invalid input: must be an array of message IDs or message objects");
778
+ }
779
+ if (input.length === 0) {
780
+ return;
781
+ }
782
+ messageIds = input.map((item) => {
783
+ if (typeof item === "string") {
784
+ return item;
785
+ } else if (item && typeof item === "object" && "id" in item) {
786
+ return item.id;
787
+ } else {
788
+ throw new Error("Invalid input: array items must be strings or objects with an id property");
789
+ }
790
+ });
791
+ const invalidIds = messageIds.filter((id) => !id || typeof id !== "string");
792
+ if (invalidIds.length > 0) {
793
+ throw new Error("All message IDs must be non-empty strings");
794
+ }
795
+ await this.storage.deleteMessages(messageIds);
796
+ }
755
797
  };
756
798
 
757
799
  exports.Memory = Memory;
package/dist/index.d.cts CHANGED
@@ -1 +1,2 @@
1
+ export { MessageDeleteInput } from './_tsup-dts-rollup.cjs';
1
2
  export { Memory } from './_tsup-dts-rollup.cjs';
package/dist/index.d.ts CHANGED
@@ -1 +1,2 @@
1
+ export { MessageDeleteInput } from './_tsup-dts-rollup.js';
1
2
  export { Memory } from './_tsup-dts-rollup.js';
package/dist/index.js CHANGED
@@ -20,9 +20,13 @@ var updateWorkingMemoryTool = (memoryConfig) => ({
20
20
  if (!threadId || !memory) {
21
21
  throw new Error("Thread ID and Memory instance are required for working memory updates");
22
22
  }
23
- const thread = await memory.getThreadById({ threadId });
23
+ let thread = await memory.getThreadById({ threadId });
24
24
  if (!thread) {
25
- throw new Error(`Thread ${threadId} not found`);
25
+ thread = await memory.createThread({
26
+ threadId,
27
+ resourceId: resourceId || thread.resourceId,
28
+ memoryConfig
29
+ });
26
30
  }
27
31
  if (thread.resourceId && thread.resourceId !== resourceId) {
28
32
  throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
@@ -53,9 +57,13 @@ var __experimental_updateWorkingMemoryToolVNext = (config) => ({
53
57
  if (!threadId || !memory) {
54
58
  throw new Error("Thread ID and Memory instance are required for working memory updates");
55
59
  }
56
- const thread = await memory.getThreadById({ threadId });
60
+ let thread = await memory.getThreadById({ threadId });
57
61
  if (!thread) {
58
- throw new Error(`Thread ${threadId} not found`);
62
+ thread = await memory.createThread({
63
+ threadId,
64
+ resourceId: resourceId || thread.resourceId,
65
+ config
66
+ });
59
67
  }
60
68
  if (thread.resourceId && thread.resourceId !== resourceId) {
61
69
  throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
@@ -245,8 +253,12 @@ var Memory = class extends MastraMemory {
245
253
  async getThreadById({ threadId }) {
246
254
  return this.storage.getThreadById({ threadId });
247
255
  }
248
- async getThreadsByResourceId({ resourceId }) {
249
- return this.storage.getThreadsByResourceId({ resourceId });
256
+ async getThreadsByResourceId({
257
+ resourceId,
258
+ orderBy,
259
+ sortDirection
260
+ }) {
261
+ return this.storage.getThreadsByResourceId({ resourceId, orderBy, sortDirection });
250
262
  }
251
263
  async saveThread({ thread }) {
252
264
  return this.storage.saveThread({ thread });
@@ -745,6 +757,36 @@ ${template.content !== this.defaultWorkingMemoryTemplate ? `- Only store informa
745
757
  if (messages.length === 0) return [];
746
758
  return this.storage.updateMessages({ messages });
747
759
  }
760
+ /**
761
+ * Deletes one or more messages
762
+ * @param input - Must be an array containing either:
763
+ * - Message ID strings
764
+ * - Message objects with 'id' properties
765
+ * @returns Promise that resolves when all messages are deleted
766
+ */
767
+ async deleteMessages(input) {
768
+ let messageIds;
769
+ if (!Array.isArray(input)) {
770
+ throw new Error("Invalid input: must be an array of message IDs or message objects");
771
+ }
772
+ if (input.length === 0) {
773
+ return;
774
+ }
775
+ messageIds = input.map((item) => {
776
+ if (typeof item === "string") {
777
+ return item;
778
+ } else if (item && typeof item === "object" && "id" in item) {
779
+ return item.id;
780
+ } else {
781
+ throw new Error("Invalid input: array items must be strings or objects with an id property");
782
+ }
783
+ });
784
+ const invalidIds = messageIds.filter((id) => !id || typeof id !== "string");
785
+ if (invalidIds.length > 0) {
786
+ throw new Error("All message IDs must be non-empty strings");
787
+ }
788
+ await this.storage.deleteMessages(messageIds);
789
+ }
748
790
  };
749
791
 
750
792
  export { Memory };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/memory",
3
- "version": "0.11.6-alpha.1",
3
+ "version": "0.11.6-alpha.2",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -57,7 +57,7 @@
57
57
  "typescript-eslint": "^8.38.0",
58
58
  "vitest": "^3.2.4",
59
59
  "@internal/lint": "0.0.23",
60
- "@mastra/core": "0.12.0-alpha.1"
60
+ "@mastra/core": "0.12.0-alpha.2"
61
61
  },
62
62
  "peerDependencies": {
63
63
  "@mastra/core": ">=0.10.9-0 <0.12.0-0"
package/src/index.ts CHANGED
@@ -4,7 +4,7 @@ import { MessageList } from '@mastra/core/agent';
4
4
  import type { MastraMessageV2, UIMessageWithMetadata } from '@mastra/core/agent';
5
5
  import { MastraMemory } from '@mastra/core/memory';
6
6
  import type { MemoryConfig, SharedMemoryConfig, StorageThreadType, WorkingMemoryTemplate } from '@mastra/core/memory';
7
- import type { StorageGetMessagesArg } from '@mastra/core/storage';
7
+ import type { StorageGetMessagesArg, ThreadSortOptions } from '@mastra/core/storage';
8
8
  import { embedMany } from 'ai';
9
9
  import type { CoreMessage, TextPart } from 'ai';
10
10
  import { Mutex } from 'async-mutex';
@@ -16,6 +16,9 @@ import type { ZodTypeAny } from 'zod';
16
16
  import zodToJsonSchema from 'zod-to-json-schema';
17
17
  import { updateWorkingMemoryTool, __experimental_updateWorkingMemoryToolVNext } from './tools/working-memory';
18
18
 
19
+ // Type for flexible message deletion input
20
+ export type MessageDeleteInput = string[] | { id: string }[];
21
+
19
22
  // Average characters per token based on OpenAI's tokenization
20
23
  const CHARS_PER_TOKEN = 4;
21
24
 
@@ -247,8 +250,12 @@ export class Memory extends MastraMemory {
247
250
  return this.storage.getThreadById({ threadId });
248
251
  }
249
252
 
250
- async getThreadsByResourceId({ resourceId }: { resourceId: string }): Promise<StorageThreadType[]> {
251
- return this.storage.getThreadsByResourceId({ resourceId });
253
+ async getThreadsByResourceId({
254
+ resourceId,
255
+ orderBy,
256
+ sortDirection,
257
+ }: { resourceId: string } & ThreadSortOptions): Promise<StorageThreadType[]> {
258
+ return this.storage.getThreadsByResourceId({ resourceId, orderBy, sortDirection });
252
259
  }
253
260
 
254
261
  async saveThread({ thread }: { thread: StorageThreadType; memoryConfig?: MemoryConfig }): Promise<StorageThreadType> {
@@ -946,4 +953,47 @@ ${
946
953
 
947
954
  return this.storage.updateMessages({ messages });
948
955
  }
956
+
957
+ /**
958
+ * Deletes one or more messages
959
+ * @param input - Must be an array containing either:
960
+ * - Message ID strings
961
+ * - Message objects with 'id' properties
962
+ * @returns Promise that resolves when all messages are deleted
963
+ */
964
+ public async deleteMessages(input: MessageDeleteInput): Promise<void> {
965
+ // Normalize input to array of IDs
966
+ let messageIds: string[];
967
+
968
+ if (!Array.isArray(input)) {
969
+ throw new Error('Invalid input: must be an array of message IDs or message objects');
970
+ }
971
+
972
+ if (input.length === 0) {
973
+ return; // No-op for empty array
974
+ }
975
+
976
+ messageIds = input.map(item => {
977
+ if (typeof item === 'string') {
978
+ return item;
979
+ } else if (item && typeof item === 'object' && 'id' in item) {
980
+ return item.id;
981
+ } else {
982
+ throw new Error('Invalid input: array items must be strings or objects with an id property');
983
+ }
984
+ });
985
+
986
+ // Validate all IDs are non-empty strings
987
+ const invalidIds = messageIds.filter(id => !id || typeof id !== 'string');
988
+ if (invalidIds.length > 0) {
989
+ throw new Error('All message IDs must be non-empty strings');
990
+ }
991
+
992
+ // Delete from storage
993
+ await this.storage.deleteMessages(messageIds);
994
+
995
+ // TODO: Delete from vector store if semantic recall is enabled
996
+ // This would require getting the messages first to know their threadId/resourceId
997
+ // and then querying the vector store to delete associated embeddings
998
+ }
949
999
  }
@@ -17,10 +17,14 @@ export const updateWorkingMemoryTool = (memoryConfig?: MemoryConfig): CoreTool =
17
17
  throw new Error('Thread ID and Memory instance are required for working memory updates');
18
18
  }
19
19
 
20
- const thread = await memory.getThreadById({ threadId });
20
+ let thread = await memory.getThreadById({ threadId });
21
21
 
22
22
  if (!thread) {
23
- throw new Error(`Thread ${threadId} not found`);
23
+ thread = await memory.createThread({
24
+ threadId,
25
+ resourceId: resourceId || thread.resourceId,
26
+ memoryConfig,
27
+ });
24
28
  }
25
29
 
26
30
  if (thread.resourceId && thread.resourceId !== resourceId) {
@@ -70,10 +74,14 @@ export const __experimental_updateWorkingMemoryToolVNext = (config: MemoryConfig
70
74
  throw new Error('Thread ID and Memory instance are required for working memory updates');
71
75
  }
72
76
 
73
- const thread = await memory.getThreadById({ threadId });
77
+ let thread = await memory.getThreadById({ threadId });
74
78
 
75
79
  if (!thread) {
76
- throw new Error(`Thread ${threadId} not found`);
80
+ thread = await memory.createThread({
81
+ threadId,
82
+ resourceId: resourceId || thread.resourceId,
83
+ config,
84
+ });
77
85
  }
78
86
 
79
87
  if (thread.resourceId && thread.resourceId !== resourceId) {