@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.
- package/.turbo/turbo-build.log +2 -2
- package/CHANGELOG.md +20 -0
- package/dist/index.cjs +101 -84
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +103 -86
- package/dist/index.js.map +1 -1
- package/dist/tools/working-memory.d.ts +28 -3
- package/dist/tools/working-memory.d.ts.map +1 -1
- package/package.json +6 -5
- package/src/index.ts +15 -6
- package/src/tools/working-memory.ts +143 -122
|
@@ -1,4 +1,29 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
|
|
3
|
-
export declare const
|
|
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,
|
|
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.
|
|
60
|
-
"@
|
|
61
|
-
"@
|
|
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 {
|
|
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
|
-
|
|
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
|
-
|
|
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,
|
|
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 {
|
|
2
|
-
import {
|
|
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)
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
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
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
|
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
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
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
|
|
83
|
-
|
|
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
|
-
|
|
128
|
-
|
|
129
|
-
|
|
147
|
+
if (result) {
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
130
150
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
});
|
|
151
|
+
return { success: true };
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
};
|