@mastra/memory 0.12.1-alpha.2 → 0.12.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/src/index.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import { generateEmptyFromSchema } from '@mastra/core';
2
- import type { CoreTool, MastraMessageV1 } from '@mastra/core';
2
+ import type { MastraMessageV1, ToolAction } from '@mastra/core';
3
3
  import { MessageList } from '@mastra/core/agent';
4
4
  import type { MastraMessageV2, UIMessageWithMetadata } from '@mastra/core/agent';
5
5
  import { MastraMemory } from '@mastra/core/memory';
@@ -948,7 +948,7 @@ ${
948
948
  return Boolean(isMDWorkingMemory && isMDWorkingMemory.version === `vnext`);
949
949
  }
950
950
 
951
- public getTools(config?: MemoryConfig): Record<string, CoreTool> {
951
+ public getTools(config?: MemoryConfig): Record<string, ToolAction<any, any, any>> {
952
952
  const mergedConfig = this.getMergedThreadConfig(config);
953
953
  if (mergedConfig.workingMemory?.enabled) {
954
954
  return {
@@ -1,133 +1,139 @@
1
- import type { CoreTool, MemoryConfig } from '@mastra/core';
1
+ import type { MemoryConfig } from '@mastra/core';
2
+ import { createTool } from '@mastra/core';
2
3
  import { z } from 'zod';
3
4
 
4
- export const updateWorkingMemoryTool = (memoryConfig?: MemoryConfig): CoreTool => ({
5
- description:
6
- 'Update the working memory with new information. Always pass data as string to the memory field. Never pass an object.',
7
- parameters: z.object({
8
- memory: z
9
- .string()
10
- .describe(
11
- `The ${!!memoryConfig?.workingMemory?.schema ? 'JSON' : 'Markdown'} formatted working memory content to store. This MUST be a string. Never pass an object.`,
12
- ),
13
- }),
14
- execute: async (params: any) => {
15
- const { context, threadId, memory, resourceId } = params;
16
- if (!threadId || !memory) {
17
- throw new Error('Thread ID and Memory instance are required for working memory updates');
18
- }
19
-
20
- let thread = await memory.getThreadById({ threadId });
21
-
22
- if (!thread) {
23
- thread = await memory.createThread({
5
+ export const updateWorkingMemoryTool = (memoryConfig?: MemoryConfig) => {
6
+ return createTool({
7
+ id: 'update-working-memory',
8
+ description:
9
+ 'Update the working memory with new information. Always pass data as string to the memory field. Never pass an object.',
10
+ inputSchema: z.object({
11
+ memory: z
12
+ .string()
13
+ .describe(
14
+ `The ${!!memoryConfig?.workingMemory?.schema ? 'JSON' : 'Markdown'} formatted working memory content to store. This MUST be a string. Never pass an object.`,
15
+ ),
16
+ }),
17
+ execute: async params => {
18
+ const { context, threadId, memory, resourceId } = params;
19
+ if (!threadId || !memory || !resourceId) {
20
+ throw new Error('Thread ID, Memory instance, and resourceId are required for working memory updates');
21
+ }
22
+
23
+ let thread = await memory.getThreadById({ threadId });
24
+
25
+ if (!thread) {
26
+ thread = await memory.createThread({
27
+ threadId,
28
+ resourceId,
29
+ memoryConfig,
30
+ });
31
+ }
32
+
33
+ if (thread.resourceId && thread.resourceId !== resourceId) {
34
+ throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
35
+ }
36
+
37
+ const workingMemory = context.memory;
38
+
39
+ // Use the new updateWorkingMemory method which handles both thread and resource scope
40
+ await memory.updateWorkingMemory({
24
41
  threadId,
25
- resourceId: resourceId || thread.resourceId,
42
+ resourceId,
43
+ workingMemory: workingMemory,
26
44
  memoryConfig,
27
45
  });
28
- }
29
-
30
- if (thread.resourceId && thread.resourceId !== resourceId) {
31
- throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
32
- }
33
-
34
- const workingMemory = context.memory;
35
-
36
- // Use the new updateWorkingMemory method which handles both thread and resource scope
37
- await memory.updateWorkingMemory({
38
- threadId,
39
- resourceId: resourceId || thread.resourceId,
40
- workingMemory: workingMemory,
41
- memoryConfig,
42
- });
43
-
44
- return { success: true };
45
- },
46
- });
47
-
48
- export const __experimental_updateWorkingMemoryToolVNext = (config: MemoryConfig): CoreTool => ({
49
- description: 'Update the working memory with new information.',
50
- parameters: z.object({
51
- newMemory: z
52
- .string()
53
- .optional()
54
- .nullable()
55
- .describe(`The ${config.workingMemory?.schema ? 'JSON' : 'Markdown'} formatted working memory content to store`),
56
- searchString: z
57
- .string()
58
- .optional()
59
- .nullable()
60
- .describe(
61
- "The working memory string to find. Will be replaced with the newMemory string. If this is omitted or doesn't exist, the newMemory string will be appended to the end of your working memory. Replacing single lines at a time is encouraged for greater accuracy. If updateReason is not 'append-new-memory', this search string must be provided or the tool call will be rejected.",
62
- ),
63
- updateReason: z
64
- .enum(['append-new-memory', 'clarify-existing-memory', 'replace-irrelevant-memory'])
65
- .optional()
66
- .nullable()
67
- .describe(
68
- "The reason you're updating working memory. Passing any value other than 'append-new-memory' requires a searchString to be provided. Defaults to append-new-memory",
69
- ),
70
- }),
71
- execute: async (params: any) => {
72
- const { context, threadId, memory, resourceId } = params;
73
- if (!threadId || !memory) {
74
- throw new Error('Thread ID and Memory instance are required for working memory updates');
75
- }
76
-
77
- let thread = await memory.getThreadById({ threadId });
78
-
79
- if (!thread) {
80
- thread = await memory.createThread({
46
+
47
+ return { success: true };
48
+ },
49
+ });
50
+ };
51
+
52
+ export const __experimental_updateWorkingMemoryToolVNext = (config: MemoryConfig) => {
53
+ return createTool({
54
+ id: 'update-working-memory',
55
+ description: 'Update the working memory with new information.',
56
+ inputSchema: z.object({
57
+ newMemory: z
58
+ .string()
59
+ .optional()
60
+ .describe(
61
+ `The ${config.workingMemory?.schema ? 'JSON' : 'Markdown'} formatted working memory content to store`,
62
+ ),
63
+ searchString: z
64
+ .string()
65
+ .optional()
66
+ .describe(
67
+ "The working memory string to find. Will be replaced with the newMemory string. If this is omitted or doesn't exist, the newMemory string will be appended to the end of your working memory. Replacing single lines at a time is encouraged for greater accuracy. If updateReason is not 'append-new-memory', this search string must be provided or the tool call will be rejected.",
68
+ ),
69
+ updateReason: z
70
+ .enum(['append-new-memory', 'clarify-existing-memory', 'replace-irrelevant-memory'])
71
+ .optional()
72
+ .describe(
73
+ "The reason you're updating working memory. Passing any value other than 'append-new-memory' requires a searchString to be provided. Defaults to append-new-memory",
74
+ ),
75
+ }),
76
+ execute: async params => {
77
+ const { context, threadId, memory, resourceId } = params;
78
+ if (!threadId || !memory || !resourceId) {
79
+ throw new Error('Thread ID, Memory instance, and resourceId are required for working memory updates');
80
+ }
81
+
82
+ let thread = await memory.getThreadById({ threadId });
83
+
84
+ if (!thread) {
85
+ thread = await memory.createThread({
86
+ threadId,
87
+ resourceId,
88
+ memoryConfig: config,
89
+ });
90
+ }
91
+
92
+ if (thread.resourceId && thread.resourceId !== resourceId) {
93
+ throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
94
+ }
95
+
96
+ const workingMemory = context.newMemory || '';
97
+ if (!context.updateReason) context.updateReason = `append-new-memory`;
98
+
99
+ if (
100
+ context.searchString &&
101
+ config.workingMemory?.scope === `resource` &&
102
+ context.updateReason === `replace-irrelevant-memory`
103
+ ) {
104
+ // don't allow replacements due to something not being relevant to the current conversation
105
+ // if there's no searchString, then we will append.
106
+ context.searchString = undefined;
107
+ }
108
+
109
+ if (context.updateReason === `append-new-memory` && context.searchString) {
110
+ // do not find/replace when append-new-memory is selected
111
+ // some models get confused and pass a search string even when they don't want to replace it.
112
+ // TODO: maybe they're trying to add new info after the search string?
113
+ context.searchString = undefined;
114
+ }
115
+
116
+ if (context.updateReason !== `append-new-memory` && !context.searchString) {
117
+ return {
118
+ success: false,
119
+ reason: `updateReason was ${context.updateReason} but no searchString was provided. Unable to replace undefined with "${context.newMemory}"`,
120
+ };
121
+ }
122
+
123
+ // Use the new updateWorkingMemory method which handles both thread and resource scope
124
+ const result = await memory.__experimental_updateWorkingMemoryVNext({
81
125
  threadId,
82
- resourceId: resourceId || thread.resourceId,
83
- config,
126
+ resourceId,
127
+ workingMemory: workingMemory,
128
+ searchString: context.searchString,
129
+ memoryConfig: config,
84
130
  });
85
- }
86
-
87
- if (thread.resourceId && thread.resourceId !== resourceId) {
88
- throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
89
- }
90
-
91
- const workingMemory = context.newMemory || '';
92
- if (!context.updateReason) context.updateReason = `append-new-memory`;
93
-
94
- if (
95
- context.searchString &&
96
- config.workingMemory?.scope === `resource` &&
97
- context.updateReason === `replace-irrelevant-memory`
98
- ) {
99
- // don't allow replacements due to something not being relevant to the current conversation
100
- // if there's no searchString, then we will append.
101
- context.searchString = undefined;
102
- }
103
-
104
- if (context.updateReason === `append-new-memory` && context.searchString) {
105
- // do not find/replace when append-new-memory is selected
106
- // some models get confused and pass a search string even when they don't want to replace it.
107
- // TODO: maybe they're trying to add new info after the search string?
108
- context.searchString = undefined;
109
- }
110
-
111
- if (context.updateReason !== `append-new-memory` && !context.searchString) {
112
- return {
113
- success: false,
114
- reason: `updateReason was ${context.updateReason} but no searchString was provided. Unable to replace undefined with "${context.newMemory}"`,
115
- };
116
- }
117
-
118
- // Use the new updateWorkingMemory method which handles both thread and resource scope
119
- const result = await memory.__experimental_updateWorkingMemoryVNext({
120
- threadId,
121
- resourceId: resourceId || thread.resourceId,
122
- workingMemory: workingMemory,
123
- searchString: context.searchString,
124
- memoryConfig: config,
125
- });
126
-
127
- if (result) {
128
- return result;
129
- }
130
-
131
- return { success: true };
132
- },
133
- });
131
+
132
+ if (result) {
133
+ return result;
134
+ }
135
+
136
+ return { success: true };
137
+ },
138
+ });
139
+ };