@mastra/memory 0.12.1 → 0.12.2-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,29 @@
1
- import type { CoreTool, MemoryConfig } from '@mastra/core';
2
- export declare const updateWorkingMemoryTool: (memoryConfig?: MemoryConfig) => CoreTool;
3
- export declare const __experimental_updateWorkingMemoryToolVNext: (config: MemoryConfig) => CoreTool;
1
+ import type { MemoryConfig } from '@mastra/core';
2
+ import { z } from 'zod';
3
+ export declare const updateWorkingMemoryTool: (memoryConfig?: MemoryConfig) => import("@mastra/core/tools").Tool<z.ZodTypeAny, undefined, import("@mastra/core").ToolExecutionContext<z.ZodTypeAny>>;
4
+ export declare const __experimental_updateWorkingMemoryToolVNext: (config: MemoryConfig) => import("@mastra/core/tools").Tool<z.ZodObject<{
5
+ newMemory: z.ZodOptional<z.ZodString>;
6
+ searchString: z.ZodOptional<z.ZodString>;
7
+ updateReason: z.ZodOptional<z.ZodEnum<["append-new-memory", "clarify-existing-memory", "replace-irrelevant-memory"]>>;
8
+ }, "strip", z.ZodTypeAny, {
9
+ newMemory?: string | undefined;
10
+ searchString?: string | undefined;
11
+ updateReason?: "append-new-memory" | "clarify-existing-memory" | "replace-irrelevant-memory" | undefined;
12
+ }, {
13
+ newMemory?: string | undefined;
14
+ searchString?: string | undefined;
15
+ updateReason?: "append-new-memory" | "clarify-existing-memory" | "replace-irrelevant-memory" | undefined;
16
+ }>, undefined, import("@mastra/core").ToolExecutionContext<z.ZodObject<{
17
+ newMemory: z.ZodOptional<z.ZodString>;
18
+ searchString: z.ZodOptional<z.ZodString>;
19
+ updateReason: z.ZodOptional<z.ZodEnum<["append-new-memory", "clarify-existing-memory", "replace-irrelevant-memory"]>>;
20
+ }, "strip", z.ZodTypeAny, {
21
+ newMemory?: string | undefined;
22
+ searchString?: string | undefined;
23
+ updateReason?: "append-new-memory" | "clarify-existing-memory" | "replace-irrelevant-memory" | undefined;
24
+ }, {
25
+ newMemory?: string | undefined;
26
+ searchString?: string | undefined;
27
+ updateReason?: "append-new-memory" | "clarify-existing-memory" | "replace-irrelevant-memory" | undefined;
28
+ }>>>;
4
29
  //# sourceMappingURL=working-memory.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"working-memory.d.ts","sourceRoot":"","sources":["../../src/tools/working-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAG3D,eAAO,MAAM,uBAAuB,GAAI,eAAe,YAAY,KAAG,QA0CpE,CAAC;AAEH,eAAO,MAAM,2CAA2C,GAAI,QAAQ,YAAY,KAAG,QAqFjF,CAAC"}
1
+ {"version":3,"file":"working-memory.d.ts","sourceRoot":"","sources":["../../src/tools/working-memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAIjD,OAAO,EAAE,CAAC,EAAa,MAAM,KAAK,CAAC;AAGnC,eAAO,MAAM,uBAAuB,GAAI,eAAe,YAAY,0HAyDlE,CAAC;AAEF,eAAO,MAAM,2CAA2C,GAAI,QAAQ,YAAY;;;;;;;;;;;;;;;;;;;;;;;;IAuF/E,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mastra/memory",
3
- "version": "0.12.1",
3
+ "version": "0.12.2-alpha.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -43,7 +43,8 @@
43
43
  "async-mutex": "^0.5.0",
44
44
  "xxhash-wasm": "^1.1.0",
45
45
  "zod": "^3.25.67",
46
- "zod-to-json-schema": "^3.24.5"
46
+ "zod-to-json-schema": "^3.24.5",
47
+ "@mastra/schema-compat": "0.10.7-alpha.0"
47
48
  },
48
49
  "devDependencies": {
49
50
  "@ai-sdk/openai": "^1.3.22",
@@ -56,9 +57,9 @@
56
57
  "typescript": "^5.8.3",
57
58
  "typescript-eslint": "^8.38.0",
58
59
  "vitest": "^3.2.4",
59
- "@internal/lint": "0.0.27",
60
- "@internal/types-builder": "0.0.2",
61
- "@mastra/core": "0.13.0"
60
+ "@internal/lint": "0.0.28",
61
+ "@mastra/core": "0.13.2-alpha.1",
62
+ "@internal/types-builder": "0.0.3"
62
63
  },
63
64
  "peerDependencies": {
64
65
  "@mastra/core": ">=0.13.0-0 <0.14.0-0"
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';
@@ -871,13 +871,22 @@ Guidelines:
871
871
  2. Update proactively when information changes, no matter how small
872
872
  3. Use ${template.format === 'json' ? 'JSON' : 'Markdown'} format for all data
873
873
  4. Act naturally - don't mention this system to users. Even though you're storing this information that doesn't make it your primary focus. Do not ask them generally for "information about yourself"
874
- 5. IMPORTANT: When calling updateWorkingMemory, the only valid parameter is the memory field.
874
+ ${
875
+ template.format !== 'json'
876
+ ? `5. IMPORTANT: When calling updateWorkingMemory, the only valid parameter is the memory field. DO NOT pass an object.
875
877
  6. IMPORTANT: ALWAYS pass the data you want to store in the memory field as a string. DO NOT pass an object.
876
- 7. IMPORTANT: Data must only be sent as a string no matter which format is used.
878
+ 7. IMPORTANT: Data must only be sent as a string no matter which format is used.`
879
+ : ''
880
+ }
877
881
 
878
- <working_memory_template>
882
+
883
+ ${
884
+ template.format !== 'json'
885
+ ? `<working_memory_template>
879
886
  ${template.content}
880
- </working_memory_template>
887
+ </working_memory_template>`
888
+ : ''
889
+ }
881
890
 
882
891
  ${hasEmptyWorkingMemoryTemplateObject ? 'When working with json data, the object format below represents the template:' : ''}
883
892
  ${hasEmptyWorkingMemoryTemplateObject ? JSON.stringify(emptyWorkingMemoryTemplateObject) : ''}
@@ -948,7 +957,7 @@ ${
948
957
  return Boolean(isMDWorkingMemory && isMDWorkingMemory.version === `vnext`);
949
958
  }
950
959
 
951
- public getTools(config?: MemoryConfig): Record<string, CoreTool> {
960
+ public getTools(config?: MemoryConfig): Record<string, ToolAction<any, any, any>> {
952
961
  const mergedConfig = this.getMergedThreadConfig(config);
953
962
  if (mergedConfig.workingMemory?.enabled) {
954
963
  return {
@@ -1,133 +1,154 @@
1
- import type { CoreTool, MemoryConfig } from '@mastra/core';
2
- import { z } from 'zod';
1
+ import type { MemoryConfig } from '@mastra/core';
2
+ import { createTool } from '@mastra/core';
3
+ import { convertSchemaToZod } from '@mastra/schema-compat';
4
+ import type { Schema } from 'ai';
5
+ import { z, ZodObject } from 'zod';
6
+ import type { ZodTypeAny } from 'zod';
3
7
 
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
+ export const updateWorkingMemoryTool = (memoryConfig?: MemoryConfig) => {
9
+ const schema = memoryConfig?.workingMemory?.schema;
10
+
11
+ let inputSchema: ZodTypeAny = z.object({
8
12
  memory: z
9
13
  .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({
14
+ .describe(`The Markdown formatted working memory content to store. This MUST be a string. Never pass an object.`),
15
+ });
16
+
17
+ if (schema) {
18
+ inputSchema = z.object({
19
+ memory:
20
+ schema instanceof ZodObject
21
+ ? schema
22
+ : convertSchemaToZod({ jsonSchema: schema } as Schema).describe(
23
+ `The JSON formatted working memory content to store.`,
24
+ ),
25
+ });
26
+ }
27
+
28
+ return createTool({
29
+ id: 'update-working-memory',
30
+ description: `Update the working memory with new information. Any data not included will be overwritten.${schema ? ' Always pass data as string to the memory field. Never pass an object.' : ''}`,
31
+ inputSchema,
32
+ execute: async params => {
33
+ const { context, threadId, memory, resourceId } = params;
34
+ if (!threadId || !memory || !resourceId) {
35
+ throw new Error('Thread ID, Memory instance, and resourceId are required for working memory updates');
36
+ }
37
+
38
+ let thread = await memory.getThreadById({ threadId });
39
+
40
+ if (!thread) {
41
+ thread = await memory.createThread({
42
+ threadId,
43
+ resourceId,
44
+ memoryConfig,
45
+ });
46
+ }
47
+
48
+ if (thread.resourceId && thread.resourceId !== resourceId) {
49
+ throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
50
+ }
51
+
52
+ const workingMemory = typeof context.memory === 'string' ? context.memory : JSON.stringify(context.memory);
53
+
54
+ // Use the new updateWorkingMemory method which handles both thread and resource scope
55
+ await memory.updateWorkingMemory({
24
56
  threadId,
25
- resourceId: resourceId || thread.resourceId,
57
+ resourceId,
58
+ workingMemory,
26
59
  memoryConfig,
27
60
  });
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
61
 
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({
62
+ return { success: true };
63
+ },
64
+ });
65
+ };
66
+
67
+ export const __experimental_updateWorkingMemoryToolVNext = (config: MemoryConfig) => {
68
+ return createTool({
69
+ id: 'update-working-memory',
70
+ description: 'Update the working memory with new information.',
71
+ inputSchema: z.object({
72
+ newMemory: z
73
+ .string()
74
+ .optional()
75
+ .describe(
76
+ `The ${config.workingMemory?.schema ? 'JSON' : 'Markdown'} formatted working memory content to store`,
77
+ ),
78
+ searchString: z
79
+ .string()
80
+ .optional()
81
+ .describe(
82
+ "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.",
83
+ ),
84
+ updateReason: z
85
+ .enum(['append-new-memory', 'clarify-existing-memory', 'replace-irrelevant-memory'])
86
+ .optional()
87
+ .describe(
88
+ "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",
89
+ ),
90
+ }),
91
+ execute: async params => {
92
+ const { context, threadId, memory, resourceId } = params;
93
+ if (!threadId || !memory || !resourceId) {
94
+ throw new Error('Thread ID, Memory instance, and resourceId are required for working memory updates');
95
+ }
96
+
97
+ let thread = await memory.getThreadById({ threadId });
98
+
99
+ if (!thread) {
100
+ thread = await memory.createThread({
101
+ threadId,
102
+ resourceId,
103
+ memoryConfig: config,
104
+ });
105
+ }
106
+
107
+ if (thread.resourceId && thread.resourceId !== resourceId) {
108
+ throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
109
+ }
110
+
111
+ const workingMemory = context.newMemory || '';
112
+ if (!context.updateReason) context.updateReason = `append-new-memory`;
113
+
114
+ if (
115
+ context.searchString &&
116
+ config.workingMemory?.scope === `resource` &&
117
+ context.updateReason === `replace-irrelevant-memory`
118
+ ) {
119
+ // don't allow replacements due to something not being relevant to the current conversation
120
+ // if there's no searchString, then we will append.
121
+ context.searchString = undefined;
122
+ }
123
+
124
+ if (context.updateReason === `append-new-memory` && context.searchString) {
125
+ // do not find/replace when append-new-memory is selected
126
+ // some models get confused and pass a search string even when they don't want to replace it.
127
+ // TODO: maybe they're trying to add new info after the search string?
128
+ context.searchString = undefined;
129
+ }
130
+
131
+ if (context.updateReason !== `append-new-memory` && !context.searchString) {
132
+ return {
133
+ success: false,
134
+ reason: `updateReason was ${context.updateReason} but no searchString was provided. Unable to replace undefined with "${context.newMemory}"`,
135
+ };
136
+ }
137
+
138
+ // Use the new updateWorkingMemory method which handles both thread and resource scope
139
+ const result = await memory.__experimental_updateWorkingMemoryVNext({
81
140
  threadId,
82
- resourceId: resourceId || thread.resourceId,
83
- config,
141
+ resourceId,
142
+ workingMemory: workingMemory,
143
+ searchString: context.searchString,
144
+ memoryConfig: config,
84
145
  });
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
146
 
127
- if (result) {
128
- return result;
129
- }
147
+ if (result) {
148
+ return result;
149
+ }
130
150
 
131
- return { success: true };
132
- },
133
- });
151
+ return { success: true };
152
+ },
153
+ });
154
+ };