@mastra/memory 0.11.2 → 0.11.3-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 +30 -0
- package/dist/_tsup-dts-rollup.d.cts +34 -6
- package/dist/_tsup-dts-rollup.d.ts +34 -6
- package/dist/index.cjs +224 -56
- package/dist/index.js +225 -57
- package/package.json +7 -4
- package/src/index.ts +229 -71
- package/src/tools/working-memory.ts +91 -5
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
|
|
2
|
-
> @mastra/memory@0.11.
|
|
2
|
+
> @mastra/memory@0.11.3-alpha.1 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
|
+
> @mastra/memory@0.11.3-alpha.1 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,35 @@
|
|
|
1
1
|
# @mastra/memory
|
|
2
2
|
|
|
3
|
+
## 0.11.3-alpha.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- 2ba5b76: Allow passing jsonSchema into workingMemory schema
|
|
8
|
+
- c3a30de: added new experimental vnext working memory
|
|
9
|
+
- Updated dependencies [0b56518]
|
|
10
|
+
- Updated dependencies [2ba5b76]
|
|
11
|
+
- Updated dependencies [c3a30de]
|
|
12
|
+
- Updated dependencies [cf3a184]
|
|
13
|
+
- Updated dependencies [d6bfd60]
|
|
14
|
+
- @mastra/core@0.10.15-alpha.1
|
|
15
|
+
|
|
16
|
+
## 0.11.3-alpha.0
|
|
17
|
+
|
|
18
|
+
### Patch Changes
|
|
19
|
+
|
|
20
|
+
- 4b20131: Fixed an issue where per-resource semantic recall wouldn't always be enabled properly in agent tool calls
|
|
21
|
+
- 626b0f4: [Cloud-126] Working Memory Playground - Added working memory to playground to allow users to view/edit working memory
|
|
22
|
+
- Updated dependencies [db5cc15]
|
|
23
|
+
- Updated dependencies [5237998]
|
|
24
|
+
- Updated dependencies [37c1acd]
|
|
25
|
+
- Updated dependencies [1aa60b1]
|
|
26
|
+
- Updated dependencies [89ec9d4]
|
|
27
|
+
- Updated dependencies [626b0f4]
|
|
28
|
+
- Updated dependencies [c22a91f]
|
|
29
|
+
- Updated dependencies [f7403ab]
|
|
30
|
+
- Updated dependencies [6c89d7f]
|
|
31
|
+
- @mastra/core@0.10.15-alpha.0
|
|
32
|
+
|
|
3
33
|
## 0.11.2
|
|
4
34
|
|
|
5
35
|
### Patch Changes
|
|
@@ -6,6 +6,7 @@ import { MastraMemory } from '@mastra/core/memory';
|
|
|
6
6
|
import type { MastraMessageV1 } from '@mastra/core';
|
|
7
7
|
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
8
8
|
import type { MemoryConfig } from '@mastra/core/memory';
|
|
9
|
+
import type { MemoryConfig as MemoryConfig_2 } from '@mastra/core';
|
|
9
10
|
import { MemoryProcessor } from '@mastra/core/memory';
|
|
10
11
|
import { MemoryProcessor as MemoryProcessor_2 } from '@mastra/core';
|
|
11
12
|
import type { MemoryProcessorOpts } from '@mastra/core';
|
|
@@ -14,9 +15,10 @@ import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
|
14
15
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
15
16
|
import type { TiktokenBPE } from 'js-tiktoken/lite';
|
|
16
17
|
import type { UIMessage } from 'ai';
|
|
17
|
-
import type { WorkingMemoryFormat } from '@mastra/core/memory';
|
|
18
18
|
import type { WorkingMemoryTemplate } from '@mastra/core/memory';
|
|
19
19
|
|
|
20
|
+
export declare const __experimental_updateWorkingMemoryToolVNext: (config: MemoryConfig_2) => CoreTool;
|
|
21
|
+
|
|
20
22
|
/**
|
|
21
23
|
* Concrete implementation of MastraMemory that adds support for thread configuration
|
|
22
24
|
* and message injection.
|
|
@@ -47,7 +49,7 @@ export declare class Memory extends MastraMemory {
|
|
|
47
49
|
getThreadsByResourceId({ resourceId }: {
|
|
48
50
|
resourceId: string;
|
|
49
51
|
}): Promise<StorageThreadType[]>;
|
|
50
|
-
saveThread({ thread
|
|
52
|
+
saveThread({ thread }: {
|
|
51
53
|
thread: StorageThreadType;
|
|
52
54
|
memoryConfig?: MemoryConfig;
|
|
53
55
|
}): Promise<StorageThreadType>;
|
|
@@ -63,6 +65,20 @@ export declare class Memory extends MastraMemory {
|
|
|
63
65
|
workingMemory: string;
|
|
64
66
|
memoryConfig?: MemoryConfig;
|
|
65
67
|
}): Promise<void>;
|
|
68
|
+
private updateWorkingMemoryMutexes;
|
|
69
|
+
/**
|
|
70
|
+
* @warning experimental! can be removed or changed at any time
|
|
71
|
+
*/
|
|
72
|
+
__experimental_updateWorkingMemoryVNext({ threadId, resourceId, workingMemory, searchString, memoryConfig, }: {
|
|
73
|
+
threadId: string;
|
|
74
|
+
resourceId?: string;
|
|
75
|
+
workingMemory: string;
|
|
76
|
+
searchString?: string;
|
|
77
|
+
memoryConfig?: MemoryConfig;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
success: boolean;
|
|
80
|
+
reason: string;
|
|
81
|
+
}>;
|
|
66
82
|
protected chunkText(text: string, tokenSize?: number): string[];
|
|
67
83
|
private hasher;
|
|
68
84
|
private embeddingCache;
|
|
@@ -90,7 +106,16 @@ export declare class Memory extends MastraMemory {
|
|
|
90
106
|
resourceId?: string;
|
|
91
107
|
memoryConfig?: MemoryConfig;
|
|
92
108
|
}): Promise<string | null>;
|
|
93
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Gets the working memory template for the current memory configuration.
|
|
111
|
+
* Supports both ZodObject and JSONSchema7 schemas.
|
|
112
|
+
*
|
|
113
|
+
* @param memoryConfig - The memory configuration containing the working memory settings
|
|
114
|
+
* @returns The working memory template with format and content, or null if working memory is disabled
|
|
115
|
+
*/
|
|
116
|
+
getWorkingMemoryTemplate({ memoryConfig, }: {
|
|
117
|
+
memoryConfig?: MemoryConfig;
|
|
118
|
+
}): Promise<WorkingMemoryTemplate | null>;
|
|
94
119
|
getSystemMessage({ threadId, resourceId, memoryConfig, }: {
|
|
95
120
|
threadId: string;
|
|
96
121
|
resourceId?: string;
|
|
@@ -101,6 +126,11 @@ export declare class Memory extends MastraMemory {
|
|
|
101
126
|
template: WorkingMemoryTemplate;
|
|
102
127
|
data: string | null;
|
|
103
128
|
}): string;
|
|
129
|
+
protected __experimental_getWorkingMemoryToolInstructionVNext({ template, data, }: {
|
|
130
|
+
template: WorkingMemoryTemplate;
|
|
131
|
+
data: string | null;
|
|
132
|
+
}): string;
|
|
133
|
+
private isVNextWorkingMemoryConfig;
|
|
104
134
|
getTools(config?: MemoryConfig): Record<string, CoreTool>;
|
|
105
135
|
/**
|
|
106
136
|
* Updates the metadata of a list of messages
|
|
@@ -164,8 +194,6 @@ declare class ToolCallFilter extends MemoryProcessor_2 {
|
|
|
164
194
|
export { ToolCallFilter }
|
|
165
195
|
export { ToolCallFilter as ToolCallFilter_alias_1 }
|
|
166
196
|
|
|
167
|
-
export declare const updateWorkingMemoryTool: (
|
|
168
|
-
format: WorkingMemoryFormat;
|
|
169
|
-
}) => CoreTool;
|
|
197
|
+
export declare const updateWorkingMemoryTool: (memoryConfig?: MemoryConfig_2) => CoreTool;
|
|
170
198
|
|
|
171
199
|
export { }
|
|
@@ -6,6 +6,7 @@ import { MastraMemory } from '@mastra/core/memory';
|
|
|
6
6
|
import type { MastraMessageV1 } from '@mastra/core';
|
|
7
7
|
import type { MastraMessageV2 } from '@mastra/core/agent';
|
|
8
8
|
import type { MemoryConfig } from '@mastra/core/memory';
|
|
9
|
+
import type { MemoryConfig as MemoryConfig_2 } from '@mastra/core';
|
|
9
10
|
import { MemoryProcessor } from '@mastra/core/memory';
|
|
10
11
|
import { MemoryProcessor as MemoryProcessor_2 } from '@mastra/core';
|
|
11
12
|
import type { MemoryProcessorOpts } from '@mastra/core';
|
|
@@ -14,9 +15,10 @@ import type { StorageGetMessagesArg } from '@mastra/core/storage';
|
|
|
14
15
|
import type { StorageThreadType } from '@mastra/core/memory';
|
|
15
16
|
import type { TiktokenBPE } from 'js-tiktoken/lite';
|
|
16
17
|
import type { UIMessage } from 'ai';
|
|
17
|
-
import type { WorkingMemoryFormat } from '@mastra/core/memory';
|
|
18
18
|
import type { WorkingMemoryTemplate } from '@mastra/core/memory';
|
|
19
19
|
|
|
20
|
+
export declare const __experimental_updateWorkingMemoryToolVNext: (config: MemoryConfig_2) => CoreTool;
|
|
21
|
+
|
|
20
22
|
/**
|
|
21
23
|
* Concrete implementation of MastraMemory that adds support for thread configuration
|
|
22
24
|
* and message injection.
|
|
@@ -47,7 +49,7 @@ export declare class Memory extends MastraMemory {
|
|
|
47
49
|
getThreadsByResourceId({ resourceId }: {
|
|
48
50
|
resourceId: string;
|
|
49
51
|
}): Promise<StorageThreadType[]>;
|
|
50
|
-
saveThread({ thread
|
|
52
|
+
saveThread({ thread }: {
|
|
51
53
|
thread: StorageThreadType;
|
|
52
54
|
memoryConfig?: MemoryConfig;
|
|
53
55
|
}): Promise<StorageThreadType>;
|
|
@@ -63,6 +65,20 @@ export declare class Memory extends MastraMemory {
|
|
|
63
65
|
workingMemory: string;
|
|
64
66
|
memoryConfig?: MemoryConfig;
|
|
65
67
|
}): Promise<void>;
|
|
68
|
+
private updateWorkingMemoryMutexes;
|
|
69
|
+
/**
|
|
70
|
+
* @warning experimental! can be removed or changed at any time
|
|
71
|
+
*/
|
|
72
|
+
__experimental_updateWorkingMemoryVNext({ threadId, resourceId, workingMemory, searchString, memoryConfig, }: {
|
|
73
|
+
threadId: string;
|
|
74
|
+
resourceId?: string;
|
|
75
|
+
workingMemory: string;
|
|
76
|
+
searchString?: string;
|
|
77
|
+
memoryConfig?: MemoryConfig;
|
|
78
|
+
}): Promise<{
|
|
79
|
+
success: boolean;
|
|
80
|
+
reason: string;
|
|
81
|
+
}>;
|
|
66
82
|
protected chunkText(text: string, tokenSize?: number): string[];
|
|
67
83
|
private hasher;
|
|
68
84
|
private embeddingCache;
|
|
@@ -90,7 +106,16 @@ export declare class Memory extends MastraMemory {
|
|
|
90
106
|
resourceId?: string;
|
|
91
107
|
memoryConfig?: MemoryConfig;
|
|
92
108
|
}): Promise<string | null>;
|
|
93
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Gets the working memory template for the current memory configuration.
|
|
111
|
+
* Supports both ZodObject and JSONSchema7 schemas.
|
|
112
|
+
*
|
|
113
|
+
* @param memoryConfig - The memory configuration containing the working memory settings
|
|
114
|
+
* @returns The working memory template with format and content, or null if working memory is disabled
|
|
115
|
+
*/
|
|
116
|
+
getWorkingMemoryTemplate({ memoryConfig, }: {
|
|
117
|
+
memoryConfig?: MemoryConfig;
|
|
118
|
+
}): Promise<WorkingMemoryTemplate | null>;
|
|
94
119
|
getSystemMessage({ threadId, resourceId, memoryConfig, }: {
|
|
95
120
|
threadId: string;
|
|
96
121
|
resourceId?: string;
|
|
@@ -101,6 +126,11 @@ export declare class Memory extends MastraMemory {
|
|
|
101
126
|
template: WorkingMemoryTemplate;
|
|
102
127
|
data: string | null;
|
|
103
128
|
}): string;
|
|
129
|
+
protected __experimental_getWorkingMemoryToolInstructionVNext({ template, data, }: {
|
|
130
|
+
template: WorkingMemoryTemplate;
|
|
131
|
+
data: string | null;
|
|
132
|
+
}): string;
|
|
133
|
+
private isVNextWorkingMemoryConfig;
|
|
104
134
|
getTools(config?: MemoryConfig): Record<string, CoreTool>;
|
|
105
135
|
/**
|
|
106
136
|
* Updates the metadata of a list of messages
|
|
@@ -164,8 +194,6 @@ declare class ToolCallFilter extends MemoryProcessor_2 {
|
|
|
164
194
|
export { ToolCallFilter }
|
|
165
195
|
export { ToolCallFilter as ToolCallFilter_alias_1 }
|
|
166
196
|
|
|
167
|
-
export declare const updateWorkingMemoryTool: (
|
|
168
|
-
format: WorkingMemoryFormat;
|
|
169
|
-
}) => CoreTool;
|
|
197
|
+
export declare const updateWorkingMemoryTool: (memoryConfig?: MemoryConfig_2) => CoreTool;
|
|
170
198
|
|
|
171
199
|
export { }
|
package/dist/index.cjs
CHANGED
|
@@ -4,9 +4,10 @@ var core = require('@mastra/core');
|
|
|
4
4
|
var agent = require('@mastra/core/agent');
|
|
5
5
|
var memory = require('@mastra/core/memory');
|
|
6
6
|
var ai = require('ai');
|
|
7
|
+
var asyncMutex = require('async-mutex');
|
|
7
8
|
var xxhash = require('xxhash-wasm');
|
|
8
|
-
var zodToJsonSchema = require('zod-to-json-schema');
|
|
9
9
|
var zod = require('zod');
|
|
10
|
+
var zodToJsonSchema = require('zod-to-json-schema');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -14,10 +15,12 @@ var xxhash__default = /*#__PURE__*/_interopDefault(xxhash);
|
|
|
14
15
|
var zodToJsonSchema__default = /*#__PURE__*/_interopDefault(zodToJsonSchema);
|
|
15
16
|
|
|
16
17
|
// src/index.ts
|
|
17
|
-
var updateWorkingMemoryTool = (
|
|
18
|
-
description: "Update the working memory with new information",
|
|
18
|
+
var updateWorkingMemoryTool = (memoryConfig) => ({
|
|
19
|
+
description: "Update the working memory with new information. Always pass data as string to the memory field. Never pass an object.",
|
|
19
20
|
parameters: zod.z.object({
|
|
20
|
-
memory: zod.z.string().describe(
|
|
21
|
+
memory: zod.z.string().describe(
|
|
22
|
+
`The ${!!memoryConfig?.workingMemory?.schema ? "JSON" : "Markdown"} formatted working memory content to store. This MUST be a string. Never pass an object.`
|
|
23
|
+
)
|
|
21
24
|
}),
|
|
22
25
|
execute: async (params) => {
|
|
23
26
|
const { context, threadId, memory, resourceId } = params;
|
|
@@ -35,8 +38,59 @@ var updateWorkingMemoryTool = ({ format }) => ({
|
|
|
35
38
|
await memory.updateWorkingMemory({
|
|
36
39
|
threadId,
|
|
37
40
|
resourceId: resourceId || thread.resourceId,
|
|
38
|
-
workingMemory
|
|
41
|
+
workingMemory,
|
|
42
|
+
memoryConfig
|
|
43
|
+
});
|
|
44
|
+
return { success: true };
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
var __experimental_updateWorkingMemoryToolVNext = (config) => ({
|
|
48
|
+
description: "Update the working memory with new information.",
|
|
49
|
+
parameters: zod.z.object({
|
|
50
|
+
newMemory: zod.z.string().optional().nullable().describe(`The ${config.workingMemory?.schema ? "JSON" : "Markdown"} formatted working memory content to store`),
|
|
51
|
+
searchString: zod.z.string().optional().nullable().describe(
|
|
52
|
+
"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."
|
|
53
|
+
),
|
|
54
|
+
updateReason: zod.z.enum(["append-new-memory", "clarify-existing-memory", "replace-irrelevant-memory"]).optional().nullable().describe(
|
|
55
|
+
"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"
|
|
56
|
+
)
|
|
57
|
+
}),
|
|
58
|
+
execute: async (params) => {
|
|
59
|
+
const { context, threadId, memory, resourceId } = params;
|
|
60
|
+
if (!threadId || !memory) {
|
|
61
|
+
throw new Error("Thread ID and Memory instance are required for working memory updates");
|
|
62
|
+
}
|
|
63
|
+
const thread = await memory.getThreadById({ threadId });
|
|
64
|
+
if (!thread) {
|
|
65
|
+
throw new Error(`Thread ${threadId} not found`);
|
|
66
|
+
}
|
|
67
|
+
if (thread.resourceId && thread.resourceId !== resourceId) {
|
|
68
|
+
throw new Error(`Thread with id ${threadId} resourceId does not match the current resourceId ${resourceId}`);
|
|
69
|
+
}
|
|
70
|
+
const workingMemory = context.newMemory || "";
|
|
71
|
+
if (!context.updateReason) context.updateReason = `append-new-memory`;
|
|
72
|
+
if (context.searchString && config.workingMemory?.scope === `resource` && context.updateReason === `replace-irrelevant-memory`) {
|
|
73
|
+
context.searchString = void 0;
|
|
74
|
+
}
|
|
75
|
+
if (context.updateReason === `append-new-memory` && context.searchString) {
|
|
76
|
+
context.searchString = void 0;
|
|
77
|
+
}
|
|
78
|
+
if (context.updateReason !== `append-new-memory` && !context.searchString) {
|
|
79
|
+
return {
|
|
80
|
+
success: false,
|
|
81
|
+
reason: `updateReason was ${context.updateReason} but no searchString was provided. Unable to replace undefined with "${context.newMemory}"`
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
const result = await memory.__experimental_updateWorkingMemoryVNext({
|
|
85
|
+
threadId,
|
|
86
|
+
resourceId: resourceId || thread.resourceId,
|
|
87
|
+
workingMemory,
|
|
88
|
+
searchString: context.searchString,
|
|
89
|
+
memoryConfig: config
|
|
39
90
|
});
|
|
91
|
+
if (result) {
|
|
92
|
+
return result;
|
|
93
|
+
}
|
|
40
94
|
return { success: true };
|
|
41
95
|
}
|
|
42
96
|
});
|
|
@@ -45,6 +99,7 @@ var updateWorkingMemoryTool = ({ format }) => ({
|
|
|
45
99
|
var CHARS_PER_TOKEN = 4;
|
|
46
100
|
var DEFAULT_MESSAGE_RANGE = { before: 2, after: 2 };
|
|
47
101
|
var DEFAULT_TOP_K = 2;
|
|
102
|
+
var isZodObject = (v) => v instanceof zod.ZodObject;
|
|
48
103
|
var Memory = class extends memory.MastraMemory {
|
|
49
104
|
constructor(config = {}) {
|
|
50
105
|
super({ name: "Memory", ...config });
|
|
@@ -201,39 +256,7 @@ var Memory = class extends memory.MastraMemory {
|
|
|
201
256
|
async getThreadsByResourceId({ resourceId }) {
|
|
202
257
|
return this.storage.getThreadsByResourceId({ resourceId });
|
|
203
258
|
}
|
|
204
|
-
async saveThread({
|
|
205
|
-
thread,
|
|
206
|
-
memoryConfig
|
|
207
|
-
}) {
|
|
208
|
-
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
209
|
-
if (config.workingMemory?.enabled) {
|
|
210
|
-
const scope = config.workingMemory.scope || "thread";
|
|
211
|
-
if (scope === "resource" && thread.resourceId) {
|
|
212
|
-
const existingResource = await this.storage.getResourceById({ resourceId: thread.resourceId });
|
|
213
|
-
if (!existingResource?.workingMemory) {
|
|
214
|
-
let workingMemory = config.workingMemory.template || this.defaultWorkingMemoryTemplate;
|
|
215
|
-
if (config.workingMemory.schema) {
|
|
216
|
-
workingMemory = JSON.stringify(zodToJsonSchema__default.default(config.workingMemory.schema));
|
|
217
|
-
}
|
|
218
|
-
await this.storage.updateResource({
|
|
219
|
-
resourceId: thread.resourceId,
|
|
220
|
-
workingMemory
|
|
221
|
-
});
|
|
222
|
-
}
|
|
223
|
-
} else if (scope === "thread" && !thread?.metadata?.workingMemory) {
|
|
224
|
-
let workingMemory = config.workingMemory.template || this.defaultWorkingMemoryTemplate;
|
|
225
|
-
if (config.workingMemory.schema) {
|
|
226
|
-
workingMemory = JSON.stringify(zodToJsonSchema__default.default(config.workingMemory.schema));
|
|
227
|
-
}
|
|
228
|
-
return this.storage.saveThread({
|
|
229
|
-
thread: core.deepMerge(thread, {
|
|
230
|
-
metadata: {
|
|
231
|
-
workingMemory
|
|
232
|
-
}
|
|
233
|
-
})
|
|
234
|
-
});
|
|
235
|
-
}
|
|
236
|
-
}
|
|
259
|
+
async saveThread({ thread }) {
|
|
237
260
|
return this.storage.saveThread({ thread });
|
|
238
261
|
}
|
|
239
262
|
async updateThread({
|
|
@@ -281,6 +304,87 @@ var Memory = class extends memory.MastraMemory {
|
|
|
281
304
|
});
|
|
282
305
|
}
|
|
283
306
|
}
|
|
307
|
+
updateWorkingMemoryMutexes = /* @__PURE__ */ new Map();
|
|
308
|
+
/**
|
|
309
|
+
* @warning experimental! can be removed or changed at any time
|
|
310
|
+
*/
|
|
311
|
+
async __experimental_updateWorkingMemoryVNext({
|
|
312
|
+
threadId,
|
|
313
|
+
resourceId,
|
|
314
|
+
workingMemory,
|
|
315
|
+
searchString,
|
|
316
|
+
memoryConfig
|
|
317
|
+
}) {
|
|
318
|
+
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
319
|
+
if (!config.workingMemory?.enabled) {
|
|
320
|
+
throw new Error("Working memory is not enabled for this memory instance");
|
|
321
|
+
}
|
|
322
|
+
const mutexKey = memoryConfig?.workingMemory?.scope === `resource` ? `resource-${resourceId}` : `thread-${threadId}`;
|
|
323
|
+
const mutex = this.updateWorkingMemoryMutexes.has(mutexKey) ? this.updateWorkingMemoryMutexes.get(mutexKey) : new asyncMutex.Mutex();
|
|
324
|
+
this.updateWorkingMemoryMutexes.set(mutexKey, mutex);
|
|
325
|
+
const release = await mutex.acquire();
|
|
326
|
+
try {
|
|
327
|
+
const existingWorkingMemory = await this.getWorkingMemory({ threadId, resourceId, memoryConfig }) || "";
|
|
328
|
+
const template = await this.getWorkingMemoryTemplate({ memoryConfig });
|
|
329
|
+
let reason = "";
|
|
330
|
+
if (existingWorkingMemory) {
|
|
331
|
+
if (searchString && existingWorkingMemory?.includes(searchString)) {
|
|
332
|
+
workingMemory = existingWorkingMemory.replace(searchString, workingMemory);
|
|
333
|
+
reason = `found and replaced searchString with newMemory`;
|
|
334
|
+
} else if (existingWorkingMemory.includes(workingMemory) || template?.content?.trim() === workingMemory.trim()) {
|
|
335
|
+
return {
|
|
336
|
+
success: false,
|
|
337
|
+
reason: `attempted to insert duplicate data into working memory. this entry was skipped`
|
|
338
|
+
};
|
|
339
|
+
} else {
|
|
340
|
+
if (searchString) {
|
|
341
|
+
reason = `attempted to replace working memory string that doesn't exist. Appending to working memory instead.`;
|
|
342
|
+
} else {
|
|
343
|
+
reason = `appended newMemory to end of working memory`;
|
|
344
|
+
}
|
|
345
|
+
workingMemory = existingWorkingMemory + `
|
|
346
|
+
${workingMemory}`;
|
|
347
|
+
}
|
|
348
|
+
} else if (workingMemory === template?.content) {
|
|
349
|
+
return {
|
|
350
|
+
success: false,
|
|
351
|
+
reason: `try again when you have data to add. newMemory was equal to the working memory template`
|
|
352
|
+
};
|
|
353
|
+
} else {
|
|
354
|
+
reason = `started new working memory`;
|
|
355
|
+
}
|
|
356
|
+
workingMemory = template?.content ? workingMemory.replaceAll(template?.content, "") : workingMemory;
|
|
357
|
+
const scope = config.workingMemory.scope || "thread";
|
|
358
|
+
if (scope === "resource" && resourceId) {
|
|
359
|
+
await this.storage.updateResource({
|
|
360
|
+
resourceId,
|
|
361
|
+
workingMemory
|
|
362
|
+
});
|
|
363
|
+
if (reason) {
|
|
364
|
+
return { success: true, reason };
|
|
365
|
+
}
|
|
366
|
+
} else {
|
|
367
|
+
const thread = await this.storage.getThreadById({ threadId });
|
|
368
|
+
if (!thread) {
|
|
369
|
+
throw new Error(`Thread ${threadId} not found`);
|
|
370
|
+
}
|
|
371
|
+
await this.storage.updateThread({
|
|
372
|
+
id: threadId,
|
|
373
|
+
title: thread.title || "Untitled Thread",
|
|
374
|
+
metadata: {
|
|
375
|
+
...thread.metadata,
|
|
376
|
+
workingMemory
|
|
377
|
+
}
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
return { success: true, reason };
|
|
381
|
+
} catch (e) {
|
|
382
|
+
this.logger.error(e instanceof Error ? e.stack || e.message : JSON.stringify(e));
|
|
383
|
+
return { success: false, reason: "Tool error." };
|
|
384
|
+
} finally {
|
|
385
|
+
release();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
284
388
|
chunkText(text, tokenSize = 4096) {
|
|
285
389
|
const charSize = tokenSize * CHARS_PER_TOKEN;
|
|
286
390
|
const chunks = [];
|
|
@@ -479,23 +583,38 @@ var Memory = class extends memory.MastraMemory {
|
|
|
479
583
|
}
|
|
480
584
|
return workingMemoryData;
|
|
481
585
|
}
|
|
482
|
-
|
|
483
|
-
|
|
586
|
+
/**
|
|
587
|
+
* Gets the working memory template for the current memory configuration.
|
|
588
|
+
* Supports both ZodObject and JSONSchema7 schemas.
|
|
589
|
+
*
|
|
590
|
+
* @param memoryConfig - The memory configuration containing the working memory settings
|
|
591
|
+
* @returns The working memory template with format and content, or null if working memory is disabled
|
|
592
|
+
*/
|
|
593
|
+
async getWorkingMemoryTemplate({
|
|
594
|
+
memoryConfig
|
|
595
|
+
}) {
|
|
596
|
+
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
597
|
+
if (!config.workingMemory?.enabled) {
|
|
484
598
|
return null;
|
|
485
599
|
}
|
|
486
|
-
if (
|
|
600
|
+
if (config.workingMemory?.schema) {
|
|
487
601
|
try {
|
|
488
|
-
const schema =
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
602
|
+
const schema = config.workingMemory.schema;
|
|
603
|
+
let convertedSchema;
|
|
604
|
+
if (isZodObject(schema)) {
|
|
605
|
+
convertedSchema = zodToJsonSchema__default.default(schema, {
|
|
606
|
+
$refStrategy: "none"
|
|
607
|
+
});
|
|
608
|
+
} else {
|
|
609
|
+
convertedSchema = schema;
|
|
610
|
+
}
|
|
492
611
|
return { format: "json", content: JSON.stringify(convertedSchema) };
|
|
493
612
|
} catch (error) {
|
|
494
613
|
this.logger.error("Error converting schema", error);
|
|
495
614
|
throw error;
|
|
496
615
|
}
|
|
497
616
|
}
|
|
498
|
-
const memory =
|
|
617
|
+
const memory = config.workingMemory.template || this.defaultWorkingMemoryTemplate;
|
|
499
618
|
return { format: "markdown", content: memory.trim() };
|
|
500
619
|
}
|
|
501
620
|
async getSystemMessage({
|
|
@@ -507,12 +626,15 @@ var Memory = class extends memory.MastraMemory {
|
|
|
507
626
|
if (!config.workingMemory?.enabled) {
|
|
508
627
|
return null;
|
|
509
628
|
}
|
|
510
|
-
const workingMemoryTemplate = await this.getWorkingMemoryTemplate();
|
|
629
|
+
const workingMemoryTemplate = await this.getWorkingMemoryTemplate({ memoryConfig: config });
|
|
511
630
|
const workingMemoryData = await this.getWorkingMemory({ threadId, resourceId, memoryConfig: config });
|
|
512
631
|
if (!workingMemoryTemplate) {
|
|
513
632
|
return null;
|
|
514
633
|
}
|
|
515
|
-
return this.
|
|
634
|
+
return this.isVNextWorkingMemoryConfig(memoryConfig) ? this.__experimental_getWorkingMemoryToolInstructionVNext({
|
|
635
|
+
template: workingMemoryTemplate,
|
|
636
|
+
data: workingMemoryData
|
|
637
|
+
}) : this.getWorkingMemoryToolInstruction({
|
|
516
638
|
template: workingMemoryTemplate,
|
|
517
639
|
data: workingMemoryData
|
|
518
640
|
});
|
|
@@ -533,6 +655,8 @@ var Memory = class extends memory.MastraMemory {
|
|
|
533
655
|
template,
|
|
534
656
|
data
|
|
535
657
|
}) {
|
|
658
|
+
const emptyWorkingMemoryTemplateObject = template.format === "json" ? core.generateEmptyFromSchema(template.content) : null;
|
|
659
|
+
const hasEmptyWorkingMemoryTemplateObject = emptyWorkingMemoryTemplateObject && Object.keys(emptyWorkingMemoryTemplateObject).length > 0;
|
|
536
660
|
return `WORKING_MEMORY_SYSTEM_INSTRUCTION:
|
|
537
661
|
Store and update any conversation-relevant information by calling the updateWorkingMemory tool. If information might be referenced again - store it!
|
|
538
662
|
|
|
@@ -541,12 +665,20 @@ Guidelines:
|
|
|
541
665
|
2. Update proactively when information changes, no matter how small
|
|
542
666
|
3. Use ${template.format === "json" ? "JSON" : "Markdown"} format for all data
|
|
543
667
|
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"
|
|
668
|
+
5. IMPORTANT: When calling updateWorkingMemory, the only valid parameter is the memory field.
|
|
669
|
+
6. IMPORTANT: ALWAYS pass the data you want to store in the memory field as a string. DO NOT pass an object.
|
|
670
|
+
7. IMPORTANT: Data must only be sent as a string no matter which format is used.
|
|
544
671
|
|
|
545
|
-
|
|
672
|
+
<working_memory_template>
|
|
546
673
|
${template.content}
|
|
674
|
+
</working_memory_template>
|
|
547
675
|
|
|
548
|
-
|
|
676
|
+
${hasEmptyWorkingMemoryTemplateObject ? "When working with json data, the object format below represents the template:" : ""}
|
|
677
|
+
${hasEmptyWorkingMemoryTemplateObject ? JSON.stringify(emptyWorkingMemoryTemplateObject) : ""}
|
|
678
|
+
|
|
679
|
+
<working_memory_data>
|
|
549
680
|
${data}
|
|
681
|
+
</working_memory_data>
|
|
550
682
|
|
|
551
683
|
Notes:
|
|
552
684
|
- Update memory whenever referenced information changes
|
|
@@ -557,16 +689,52 @@ Notes:
|
|
|
557
689
|
- IMPORTANT: You MUST call updateWorkingMemory in every response to a prompt where you received relevant information.
|
|
558
690
|
- IMPORTANT: Preserve the ${template.format === "json" ? "JSON" : "Markdown"} formatting structure above while updating the content.`;
|
|
559
691
|
}
|
|
692
|
+
__experimental_getWorkingMemoryToolInstructionVNext({
|
|
693
|
+
template,
|
|
694
|
+
data
|
|
695
|
+
}) {
|
|
696
|
+
return `WORKING_MEMORY_SYSTEM_INSTRUCTION:
|
|
697
|
+
Store and update any conversation-relevant information by calling the updateWorkingMemory tool.
|
|
698
|
+
|
|
699
|
+
Guidelines:
|
|
700
|
+
1. Store anything that could be useful later in the conversation
|
|
701
|
+
2. Update proactively when information changes, no matter how small
|
|
702
|
+
3. Use ${template.format === "json" ? "JSON" : "Markdown"} format for all data
|
|
703
|
+
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"
|
|
704
|
+
5. If your memory has not changed, you do not need to call the updateWorkingMemory tool. By default it will persist and be available for you in future interactions
|
|
705
|
+
6. Information not being relevant to the current conversation is not a valid reason to replace or remove working memory information. Your working memory spans across multiple conversations and may be needed again later, even if it's not currently relevant.
|
|
706
|
+
|
|
707
|
+
<working_memory_template>
|
|
708
|
+
${template.content}
|
|
709
|
+
</working_memory_template>
|
|
710
|
+
|
|
711
|
+
<working_memory_data>
|
|
712
|
+
${data}
|
|
713
|
+
</working_memory_data>
|
|
714
|
+
|
|
715
|
+
Notes:
|
|
716
|
+
- Update memory whenever referenced information changes
|
|
717
|
+
${template.content !== this.defaultWorkingMemoryTemplate ? `- Only store information if it's in the working memory template, do not store other information unless the user asks you to remember it, as that non-template information may be irrelevant` : `- If you're unsure whether to store something, store it (eg if the user tells you information about themselves, call updateWorkingMemory immediately to update it)
|
|
718
|
+
`}
|
|
719
|
+
- This system is here so that you can maintain the conversation when your context window is very short. Update your working memory because you may need it to maintain the conversation without the full conversation history
|
|
720
|
+
- REMEMBER: the way you update your working memory is by calling the updateWorkingMemory tool with the ${template.format === "json" ? "JSON" : "Markdown"} content. The system will store it for you. The user will not see it.
|
|
721
|
+
- IMPORTANT: You MUST call updateWorkingMemory in every response to a prompt where you received relevant information if that information is not already stored.
|
|
722
|
+
- IMPORTANT: Preserve the ${template.format === "json" ? "JSON" : "Markdown"} formatting structure above while updating the content.
|
|
723
|
+
`;
|
|
724
|
+
}
|
|
725
|
+
isVNextWorkingMemoryConfig(config) {
|
|
726
|
+
if (!config?.workingMemory) return false;
|
|
727
|
+
const isMDWorkingMemory = !(`schema` in config.workingMemory) && (typeof config.workingMemory.template === `string` || config.workingMemory.template) && config.workingMemory;
|
|
728
|
+
return Boolean(isMDWorkingMemory && isMDWorkingMemory.version === `vnext`);
|
|
729
|
+
}
|
|
560
730
|
getTools(config) {
|
|
561
731
|
const mergedConfig = this.getMergedThreadConfig(config);
|
|
562
732
|
if (mergedConfig.workingMemory?.enabled) {
|
|
563
|
-
if (mergedConfig.workingMemory.schema) {
|
|
564
|
-
return {
|
|
565
|
-
updateWorkingMemory: updateWorkingMemoryTool({ format: "json" })
|
|
566
|
-
};
|
|
567
|
-
}
|
|
568
733
|
return {
|
|
569
|
-
updateWorkingMemory:
|
|
734
|
+
updateWorkingMemory: this.isVNextWorkingMemoryConfig(mergedConfig) ? (
|
|
735
|
+
// use the new experimental tool
|
|
736
|
+
__experimental_updateWorkingMemoryToolVNext(mergedConfig)
|
|
737
|
+
) : updateWorkingMemoryTool(mergedConfig)
|
|
570
738
|
};
|
|
571
739
|
}
|
|
572
740
|
return {};
|