@mastra/memory 1.6.0 → 1.6.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/CHANGELOG.md +54 -0
- package/dist/{chunk-5UYAHJVJ.cjs → chunk-D6II7EP4.cjs} +660 -531
- package/dist/chunk-D6II7EP4.cjs.map +1 -0
- package/dist/{chunk-A62BQK35.js → chunk-GBBQIJQF.js} +660 -531
- package/dist/chunk-GBBQIJQF.js.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +25 -25
- package/dist/docs/references/docs-agents-agent-approval.md +61 -31
- package/dist/docs/references/docs-agents-supervisor-agents.md +1 -1
- package/dist/docs/references/docs-memory-observational-memory.md +9 -0
- package/dist/docs/references/docs-memory-semantic-recall.md +17 -1
- package/dist/docs/references/reference-core-getMemory.md +2 -2
- package/dist/docs/references/reference-core-listMemory.md +1 -1
- package/dist/docs/references/reference-memory-clone-utilities.md +5 -5
- package/dist/docs/references/reference-memory-cloneThread.md +17 -21
- package/dist/docs/references/reference-memory-createThread.md +10 -10
- package/dist/docs/references/reference-memory-getThreadById.md +2 -2
- package/dist/docs/references/reference-memory-listThreads.md +5 -5
- package/dist/docs/references/reference-memory-memory-class.md +12 -14
- package/dist/docs/references/reference-memory-observational-memory.md +102 -94
- package/dist/docs/references/reference-processors-token-limiter-processor.md +11 -13
- package/dist/docs/references/reference-storage-dynamodb.md +9 -9
- package/dist/docs/references/reference-storage-libsql.md +2 -2
- package/dist/docs/references/reference-storage-mongodb.md +5 -5
- package/dist/docs/references/reference-storage-postgresql.md +25 -25
- package/dist/docs/references/reference-storage-upstash.md +3 -3
- package/dist/docs/references/reference-vectors-libsql.md +31 -31
- package/dist/docs/references/reference-vectors-mongodb.md +32 -32
- package/dist/docs/references/reference-vectors-pg.md +60 -44
- package/dist/docs/references/reference-vectors-upstash.md +25 -25
- package/dist/index.cjs +246 -57
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +246 -57
- package/dist/index.js.map +1 -1
- package/dist/{observational-memory-MXI54VC7.cjs → observational-memory-AHVELJX4.cjs} +17 -17
- package/dist/{observational-memory-MXI54VC7.cjs.map → observational-memory-AHVELJX4.cjs.map} +1 -1
- package/dist/{observational-memory-SR6G4HN5.js → observational-memory-QFQUF5EY.js} +3 -3
- package/dist/{observational-memory-SR6G4HN5.js.map → observational-memory-QFQUF5EY.js.map} +1 -1
- package/dist/processors/index.cjs +15 -15
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/date-utils.d.ts +35 -0
- package/dist/processors/observational-memory/date-utils.d.ts.map +1 -0
- package/dist/processors/observational-memory/markers.d.ts +94 -0
- package/dist/processors/observational-memory/markers.d.ts.map +1 -0
- package/dist/processors/observational-memory/observational-memory.d.ts +0 -76
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/operation-registry.d.ts +14 -0
- package/dist/processors/observational-memory/operation-registry.d.ts.map +1 -0
- package/dist/processors/observational-memory/thresholds.d.ts +52 -0
- package/dist/processors/observational-memory/thresholds.d.ts.map +1 -0
- package/dist/processors/observational-memory/token-counter.d.ts +4 -0
- package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
- package/dist/tools/working-memory.d.ts.map +1 -1
- package/package.json +7 -7
- package/dist/chunk-5UYAHJVJ.cjs.map +0 -1
- package/dist/chunk-A62BQK35.js.map +0 -1
|
@@ -4,9 +4,9 @@ The UpstashVector class provides vector search using [Upstash Vector](https://up
|
|
|
4
4
|
|
|
5
5
|
## Constructor Options
|
|
6
6
|
|
|
7
|
-
**url
|
|
7
|
+
**url** (`string`): Upstash Vector database URL
|
|
8
8
|
|
|
9
|
-
**token
|
|
9
|
+
**token** (`string`): Upstash Vector API token
|
|
10
10
|
|
|
11
11
|
## Methods
|
|
12
12
|
|
|
@@ -14,41 +14,41 @@ The UpstashVector class provides vector search using [Upstash Vector](https://up
|
|
|
14
14
|
|
|
15
15
|
Note: This method is a no-op for Upstash as indexes are created automatically.
|
|
16
16
|
|
|
17
|
-
**indexName
|
|
17
|
+
**indexName** (`string`): Name of the index to create
|
|
18
18
|
|
|
19
|
-
**dimension
|
|
19
|
+
**dimension** (`number`): Vector dimension (must match your embedding model)
|
|
20
20
|
|
|
21
|
-
**metric
|
|
21
|
+
**metric** (`'cosine' | 'euclidean' | 'dotproduct'`): Distance metric for similarity search (Default: `cosine`)
|
|
22
22
|
|
|
23
23
|
### upsert()
|
|
24
24
|
|
|
25
|
-
**indexName
|
|
25
|
+
**indexName** (`string`): Name of the index to upsert into
|
|
26
26
|
|
|
27
|
-
**vectors
|
|
27
|
+
**vectors** (`number[][]`): Array of embedding vectors
|
|
28
28
|
|
|
29
|
-
**sparseVectors
|
|
29
|
+
**sparseVectors** (`{ indices: number[], values: number[] }[]`): Array of sparse vectors for hybrid search. Each sparse vector must have matching indices and values arrays.
|
|
30
30
|
|
|
31
|
-
**metadata
|
|
31
|
+
**metadata** (`Record<string, any>[]`): Metadata for each vector
|
|
32
32
|
|
|
33
|
-
**ids
|
|
33
|
+
**ids** (`string[]`): Optional vector IDs (auto-generated if not provided)
|
|
34
34
|
|
|
35
35
|
### query()
|
|
36
36
|
|
|
37
|
-
**indexName
|
|
37
|
+
**indexName** (`string`): Name of the index to query
|
|
38
38
|
|
|
39
|
-
**queryVector
|
|
39
|
+
**queryVector** (`number[]`): Query vector to find similar vectors
|
|
40
40
|
|
|
41
|
-
**sparseVector
|
|
41
|
+
**sparseVector** (`{ indices: number[], values: number[] }`): Optional sparse vector for hybrid search. Must have matching indices and values arrays.
|
|
42
42
|
|
|
43
|
-
**topK
|
|
43
|
+
**topK** (`number`): Number of results to return (Default: `10`)
|
|
44
44
|
|
|
45
|
-
**filter
|
|
45
|
+
**filter** (`Record<string, any>`): Metadata filters for the query
|
|
46
46
|
|
|
47
|
-
**includeVector
|
|
47
|
+
**includeVector** (`boolean`): Whether to include vectors in the results (Default: `false`)
|
|
48
48
|
|
|
49
|
-
**fusionAlgorithm
|
|
49
|
+
**fusionAlgorithm** (`FusionAlgorithm`): Algorithm used to combine dense and sparse search results in hybrid search (e.g., RRF - Reciprocal Rank Fusion)
|
|
50
50
|
|
|
51
|
-
**queryMode
|
|
51
|
+
**queryMode** (`QueryMode`): Search mode: 'DENSE' for dense-only, 'SPARSE' for sparse-only, or 'HYBRID' for combined search
|
|
52
52
|
|
|
53
53
|
### listIndexes()
|
|
54
54
|
|
|
@@ -56,7 +56,7 @@ Returns an array of index names (namespaces) as strings.
|
|
|
56
56
|
|
|
57
57
|
### describeIndex()
|
|
58
58
|
|
|
59
|
-
**indexName
|
|
59
|
+
**indexName** (`string`): Name of the index to describe
|
|
60
60
|
|
|
61
61
|
Returns:
|
|
62
62
|
|
|
@@ -70,15 +70,15 @@ interface IndexStats {
|
|
|
70
70
|
|
|
71
71
|
### deleteIndex()
|
|
72
72
|
|
|
73
|
-
**indexName
|
|
73
|
+
**indexName** (`string`): Name of the index (namespace) to delete
|
|
74
74
|
|
|
75
75
|
### updateVector()
|
|
76
76
|
|
|
77
|
-
**indexName
|
|
77
|
+
**indexName** (`string`): Name of the index to update
|
|
78
78
|
|
|
79
|
-
**id
|
|
79
|
+
**id** (`string`): ID of the item to update
|
|
80
80
|
|
|
81
|
-
**update
|
|
81
|
+
**update** (`object`): Update object containing vector, sparse vector, and/or metadata
|
|
82
82
|
|
|
83
83
|
The `update` object can have the following properties:
|
|
84
84
|
|
|
@@ -88,9 +88,9 @@ The `update` object can have the following properties:
|
|
|
88
88
|
|
|
89
89
|
### deleteVector()
|
|
90
90
|
|
|
91
|
-
**indexName
|
|
91
|
+
**indexName** (`string`): Name of the index from which to delete the item
|
|
92
92
|
|
|
93
|
-
**id
|
|
93
|
+
**id** (`string`): ID of the item to delete
|
|
94
94
|
|
|
95
95
|
Attempts to delete an item by its ID from the specified index. Logs an error message if the deletion fails.
|
|
96
96
|
|
package/dist/index.cjs
CHANGED
|
@@ -9587,7 +9587,7 @@ function withUserAgentSuffix2(headers, ...userAgentSuffixParts) {
|
|
|
9587
9587
|
);
|
|
9588
9588
|
return Object.fromEntries(normalizedHeaders.entries());
|
|
9589
9589
|
}
|
|
9590
|
-
var VERSION4 = "4.0.
|
|
9590
|
+
var VERSION4 = "4.0.19";
|
|
9591
9591
|
var getOriginalFetch3 = () => globalThis.fetch;
|
|
9592
9592
|
var getFromApi2 = async ({
|
|
9593
9593
|
url,
|
|
@@ -9672,8 +9672,8 @@ function loadOptionalSetting2({
|
|
|
9672
9672
|
}
|
|
9673
9673
|
return settingValue;
|
|
9674
9674
|
}
|
|
9675
|
-
var suspectProtoRx2 = /"
|
|
9676
|
-
var suspectConstructorRx2 = /"
|
|
9675
|
+
var suspectProtoRx2 = /"(?:_|\\u005[Ff])(?:_|\\u005[Ff])(?:p|\\u0070)(?:r|\\u0072)(?:o|\\u006[Ff])(?:t|\\u0074)(?:o|\\u006[Ff])(?:_|\\u005[Ff])(?:_|\\u005[Ff])"\s*:/;
|
|
9676
|
+
var suspectConstructorRx2 = /"(?:c|\\u0063)(?:o|\\u006[Ff])(?:n|\\u006[Ee])(?:s|\\u0073)(?:t|\\u0074)(?:r|\\u0072)(?:u|\\u0075)(?:c|\\u0063)(?:t|\\u0074)(?:o|\\u006[Ff])(?:r|\\u0072)"\s*:/;
|
|
9677
9677
|
function _parse2(text4) {
|
|
9678
9678
|
const obj = JSON.parse(text4);
|
|
9679
9679
|
if (obj === null || typeof obj !== "object") {
|
|
@@ -9693,7 +9693,7 @@ function filter2(obj) {
|
|
|
9693
9693
|
if (Object.prototype.hasOwnProperty.call(node, "__proto__")) {
|
|
9694
9694
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
9695
9695
|
}
|
|
9696
|
-
if (Object.prototype.hasOwnProperty.call(node, "constructor") && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
9696
|
+
if (Object.prototype.hasOwnProperty.call(node, "constructor") && node.constructor !== null && typeof node.constructor === "object" && Object.prototype.hasOwnProperty.call(node.constructor, "prototype")) {
|
|
9697
9697
|
throw new SyntaxError("Object contains forbidden prototype property");
|
|
9698
9698
|
}
|
|
9699
9699
|
for (const key in node) {
|
|
@@ -12257,16 +12257,14 @@ var GatewayVideoModel = class {
|
|
|
12257
12257
|
var _a932;
|
|
12258
12258
|
const resolvedHeaders = await resolve2(this.config.headers());
|
|
12259
12259
|
try {
|
|
12260
|
-
const {
|
|
12261
|
-
responseHeaders,
|
|
12262
|
-
value: responseBody
|
|
12263
|
-
} = await postJsonToApi2({
|
|
12260
|
+
const { responseHeaders, value: responseBody } = await postJsonToApi2({
|
|
12264
12261
|
url: this.getUrl(),
|
|
12265
12262
|
headers: combineHeaders2(
|
|
12266
12263
|
resolvedHeaders,
|
|
12267
12264
|
headers != null ? headers : {},
|
|
12268
12265
|
this.getModelConfigHeaders(),
|
|
12269
|
-
await resolve2(this.config.o11yHeaders)
|
|
12266
|
+
await resolve2(this.config.o11yHeaders),
|
|
12267
|
+
{ accept: "text/event-stream" }
|
|
12270
12268
|
),
|
|
12271
12269
|
body: {
|
|
12272
12270
|
prompt,
|
|
@@ -12279,9 +12277,70 @@ var GatewayVideoModel = class {
|
|
|
12279
12277
|
...providerOptions && { providerOptions },
|
|
12280
12278
|
...image && { image: maybeEncodeVideoFile(image) }
|
|
12281
12279
|
},
|
|
12282
|
-
successfulResponseHandler:
|
|
12283
|
-
|
|
12284
|
-
|
|
12280
|
+
successfulResponseHandler: async ({
|
|
12281
|
+
response,
|
|
12282
|
+
url,
|
|
12283
|
+
requestBodyValues
|
|
12284
|
+
}) => {
|
|
12285
|
+
if (response.body == null) {
|
|
12286
|
+
throw new APICallError3({
|
|
12287
|
+
message: "SSE response body is empty",
|
|
12288
|
+
url,
|
|
12289
|
+
requestBodyValues,
|
|
12290
|
+
statusCode: response.status
|
|
12291
|
+
});
|
|
12292
|
+
}
|
|
12293
|
+
const eventStream = parseJsonEventStream2({
|
|
12294
|
+
stream: response.body,
|
|
12295
|
+
schema: gatewayVideoEventSchema
|
|
12296
|
+
});
|
|
12297
|
+
const reader = eventStream.getReader();
|
|
12298
|
+
const { done, value: parseResult } = await reader.read();
|
|
12299
|
+
reader.releaseLock();
|
|
12300
|
+
if (done || !parseResult) {
|
|
12301
|
+
throw new APICallError3({
|
|
12302
|
+
message: "SSE stream ended without a data event",
|
|
12303
|
+
url,
|
|
12304
|
+
requestBodyValues,
|
|
12305
|
+
statusCode: response.status
|
|
12306
|
+
});
|
|
12307
|
+
}
|
|
12308
|
+
if (!parseResult.success) {
|
|
12309
|
+
throw new APICallError3({
|
|
12310
|
+
message: "Failed to parse video SSE event",
|
|
12311
|
+
cause: parseResult.error,
|
|
12312
|
+
url,
|
|
12313
|
+
requestBodyValues,
|
|
12314
|
+
statusCode: response.status
|
|
12315
|
+
});
|
|
12316
|
+
}
|
|
12317
|
+
const event = parseResult.value;
|
|
12318
|
+
if (event.type === "error") {
|
|
12319
|
+
throw new APICallError3({
|
|
12320
|
+
message: event.message,
|
|
12321
|
+
statusCode: event.statusCode,
|
|
12322
|
+
url,
|
|
12323
|
+
requestBodyValues,
|
|
12324
|
+
responseHeaders: Object.fromEntries([...response.headers]),
|
|
12325
|
+
responseBody: JSON.stringify(event),
|
|
12326
|
+
data: {
|
|
12327
|
+
error: {
|
|
12328
|
+
message: event.message,
|
|
12329
|
+
type: event.errorType,
|
|
12330
|
+
param: event.param
|
|
12331
|
+
}
|
|
12332
|
+
}
|
|
12333
|
+
});
|
|
12334
|
+
}
|
|
12335
|
+
return {
|
|
12336
|
+
value: {
|
|
12337
|
+
videos: event.videos,
|
|
12338
|
+
warnings: event.warnings,
|
|
12339
|
+
providerMetadata: event.providerMetadata
|
|
12340
|
+
},
|
|
12341
|
+
responseHeaders: Object.fromEntries([...response.headers])
|
|
12342
|
+
};
|
|
12343
|
+
},
|
|
12285
12344
|
failedResponseHandler: createJsonErrorResponseHandler2({
|
|
12286
12345
|
errorSchema: z4.z.any(),
|
|
12287
12346
|
errorToMessage: (data) => data
|
|
@@ -12353,11 +12412,21 @@ var gatewayVideoWarningSchema = z4.z.discriminatedUnion("type", [
|
|
|
12353
12412
|
message: z4.z.string()
|
|
12354
12413
|
})
|
|
12355
12414
|
]);
|
|
12356
|
-
var
|
|
12357
|
-
|
|
12358
|
-
|
|
12359
|
-
|
|
12360
|
-
|
|
12415
|
+
var gatewayVideoEventSchema = z4.z.discriminatedUnion("type", [
|
|
12416
|
+
z4.z.object({
|
|
12417
|
+
type: z4.z.literal("result"),
|
|
12418
|
+
videos: z4.z.array(gatewayVideoDataSchema),
|
|
12419
|
+
warnings: z4.z.array(gatewayVideoWarningSchema).optional(),
|
|
12420
|
+
providerMetadata: z4.z.record(z4.z.string(), providerMetadataEntrySchema22).optional()
|
|
12421
|
+
}),
|
|
12422
|
+
z4.z.object({
|
|
12423
|
+
type: z4.z.literal("error"),
|
|
12424
|
+
message: z4.z.string(),
|
|
12425
|
+
errorType: z4.z.string(),
|
|
12426
|
+
statusCode: z4.z.number(),
|
|
12427
|
+
param: z4.z.unknown().nullable()
|
|
12428
|
+
})
|
|
12429
|
+
]);
|
|
12361
12430
|
var parallelSearchInputSchema = lazySchema(
|
|
12362
12431
|
() => zodSchema3(
|
|
12363
12432
|
zod.z.object({
|
|
@@ -12534,7 +12603,7 @@ async function getVercelRequestId2() {
|
|
|
12534
12603
|
var _a932;
|
|
12535
12604
|
return (_a932 = (0, import_oidc3.getContext)().headers) == null ? void 0 : _a932["x-vercel-id"];
|
|
12536
12605
|
}
|
|
12537
|
-
var VERSION5 = "3.0.
|
|
12606
|
+
var VERSION5 = "3.0.66";
|
|
12538
12607
|
var AI_GATEWAY_PROTOCOL_VERSION2 = "0.0.1";
|
|
12539
12608
|
function createGatewayProvider2(options = {}) {
|
|
12540
12609
|
var _a932, _b92;
|
|
@@ -12577,13 +12646,18 @@ function createGatewayProvider2(options = {}) {
|
|
|
12577
12646
|
settingValue: void 0,
|
|
12578
12647
|
environmentVariableName: "VERCEL_REGION"
|
|
12579
12648
|
});
|
|
12649
|
+
const projectId = loadOptionalSetting2({
|
|
12650
|
+
settingValue: void 0,
|
|
12651
|
+
environmentVariableName: "VERCEL_PROJECT_ID"
|
|
12652
|
+
});
|
|
12580
12653
|
return async () => {
|
|
12581
12654
|
const requestId = await getVercelRequestId2();
|
|
12582
12655
|
return {
|
|
12583
12656
|
...deploymentId && { "ai-o11y-deployment-id": deploymentId },
|
|
12584
12657
|
...environment && { "ai-o11y-environment": environment },
|
|
12585
12658
|
...region && { "ai-o11y-region": region },
|
|
12586
|
-
...requestId && { "ai-o11y-request-id": requestId }
|
|
12659
|
+
...requestId && { "ai-o11y-request-id": requestId },
|
|
12660
|
+
...projectId && { "ai-o11y-project-id": projectId }
|
|
12587
12661
|
};
|
|
12588
12662
|
};
|
|
12589
12663
|
};
|
|
@@ -13602,7 +13676,7 @@ function getTotalTimeoutMs(timeout) {
|
|
|
13602
13676
|
}
|
|
13603
13677
|
return timeout.totalMs;
|
|
13604
13678
|
}
|
|
13605
|
-
var VERSION33 = "6.0.
|
|
13679
|
+
var VERSION33 = "6.0.116";
|
|
13606
13680
|
var dataContentSchema3 = z4.z.union([
|
|
13607
13681
|
z4.z.string(),
|
|
13608
13682
|
z4.z.instanceof(Uint8Array),
|
|
@@ -15152,6 +15226,25 @@ var updateWorkingMemoryTool = (memoryConfig) => {
|
|
|
15152
15226
|
workingMemory = JSON.stringify(mergedData);
|
|
15153
15227
|
} else {
|
|
15154
15228
|
workingMemory = typeof inputData.memory === "string" ? inputData.memory : JSON.stringify(inputData.memory);
|
|
15229
|
+
const existingRaw = await memory.getWorkingMemory({
|
|
15230
|
+
threadId,
|
|
15231
|
+
resourceId,
|
|
15232
|
+
memoryConfig
|
|
15233
|
+
});
|
|
15234
|
+
if (existingRaw) {
|
|
15235
|
+
const template = await memory.getWorkingMemoryTemplate({ memoryConfig });
|
|
15236
|
+
if (template?.content) {
|
|
15237
|
+
const normalizedNew = workingMemory.replace(/\s+/g, " ").trim();
|
|
15238
|
+
const normalizedTemplate = template.content.replace(/\s+/g, " ").trim();
|
|
15239
|
+
const normalizedExisting = existingRaw.replace(/\s+/g, " ").trim();
|
|
15240
|
+
if (normalizedNew === normalizedTemplate && normalizedExisting !== normalizedTemplate) {
|
|
15241
|
+
return {
|
|
15242
|
+
success: false,
|
|
15243
|
+
message: "Attempted to replace existing working memory with empty template. Update skipped to prevent data loss."
|
|
15244
|
+
};
|
|
15245
|
+
}
|
|
15246
|
+
}
|
|
15247
|
+
}
|
|
15155
15248
|
}
|
|
15156
15249
|
await memory.updateWorkingMemory({
|
|
15157
15250
|
threadId,
|
|
@@ -15242,6 +15335,7 @@ function normalizeObservationalMemoryConfig(config) {
|
|
|
15242
15335
|
var CHARS_PER_TOKEN = 4;
|
|
15243
15336
|
var DEFAULT_MESSAGE_RANGE = { before: 1, after: 1 };
|
|
15244
15337
|
var DEFAULT_TOP_K = 4;
|
|
15338
|
+
var VECTOR_DELETE_BATCH_SIZE = 100;
|
|
15245
15339
|
var isZodObject = (v) => v instanceof zod.ZodObject;
|
|
15246
15340
|
var Memory = class extends memory.MastraMemory {
|
|
15247
15341
|
constructor(config = {}) {
|
|
@@ -15431,6 +15525,45 @@ var Memory = class extends memory.MastraMemory {
|
|
|
15431
15525
|
async deleteThread(threadId) {
|
|
15432
15526
|
const memoryStore = await this.getMemoryStore();
|
|
15433
15527
|
await memoryStore.deleteThread({ threadId });
|
|
15528
|
+
if (this.vector) {
|
|
15529
|
+
void this.deleteThreadVectors(threadId);
|
|
15530
|
+
}
|
|
15531
|
+
}
|
|
15532
|
+
/**
|
|
15533
|
+
* Lists all vector indexes that match the memory messages prefix.
|
|
15534
|
+
* Handles separator differences across vector store backends (e.g. '_' vs '-').
|
|
15535
|
+
*/
|
|
15536
|
+
async getMemoryVectorIndexes() {
|
|
15537
|
+
if (!this.vector) return [];
|
|
15538
|
+
const separator = this.vector.indexSeparator ?? "_";
|
|
15539
|
+
const prefix = `memory${separator}messages`;
|
|
15540
|
+
const indexes = await this.vector.listIndexes();
|
|
15541
|
+
return indexes.filter((name21) => name21.startsWith(prefix));
|
|
15542
|
+
}
|
|
15543
|
+
/**
|
|
15544
|
+
* Deletes all vector embeddings associated with a thread.
|
|
15545
|
+
* This is called internally by deleteThread to clean up orphaned vectors.
|
|
15546
|
+
*
|
|
15547
|
+
* @param threadId - The ID of the thread whose vectors should be deleted
|
|
15548
|
+
*/
|
|
15549
|
+
async deleteThreadVectors(threadId) {
|
|
15550
|
+
try {
|
|
15551
|
+
const memoryIndexes = await this.getMemoryVectorIndexes();
|
|
15552
|
+
await Promise.all(
|
|
15553
|
+
memoryIndexes.map(async (indexName) => {
|
|
15554
|
+
try {
|
|
15555
|
+
await this.vector.deleteVectors({
|
|
15556
|
+
indexName,
|
|
15557
|
+
filter: { thread_id: threadId }
|
|
15558
|
+
});
|
|
15559
|
+
} catch {
|
|
15560
|
+
this.logger.debug(`Failed to delete vectors for thread ${threadId} in ${indexName}, skipping`);
|
|
15561
|
+
}
|
|
15562
|
+
})
|
|
15563
|
+
);
|
|
15564
|
+
} catch {
|
|
15565
|
+
this.logger.debug(`Failed to clean up vectors for thread ${threadId}`);
|
|
15566
|
+
}
|
|
15434
15567
|
}
|
|
15435
15568
|
async updateWorkingMemory({
|
|
15436
15569
|
threadId,
|
|
@@ -15448,25 +15581,33 @@ var Memory = class extends memory.MastraMemory {
|
|
|
15448
15581
|
`Memory error: Resource-scoped working memory is enabled but no resourceId was provided. Either provide a resourceId or explicitly set workingMemory.scope to 'thread'.`
|
|
15449
15582
|
);
|
|
15450
15583
|
}
|
|
15451
|
-
const
|
|
15452
|
-
|
|
15453
|
-
|
|
15454
|
-
|
|
15455
|
-
|
|
15456
|
-
|
|
15457
|
-
|
|
15458
|
-
|
|
15459
|
-
|
|
15460
|
-
throw new Error(`Thread ${threadId} not found`);
|
|
15461
|
-
}
|
|
15462
|
-
await memoryStore.updateThread({
|
|
15463
|
-
id: threadId,
|
|
15464
|
-
title: thread.title || "",
|
|
15465
|
-
metadata: {
|
|
15466
|
-
...thread.metadata,
|
|
15584
|
+
const mutexKey = scope === "resource" ? `resource-${resourceId}` : `thread-${threadId}`;
|
|
15585
|
+
const mutex = this.updateWorkingMemoryMutexes.has(mutexKey) ? this.updateWorkingMemoryMutexes.get(mutexKey) : new asyncMutex.Mutex();
|
|
15586
|
+
this.updateWorkingMemoryMutexes.set(mutexKey, mutex);
|
|
15587
|
+
const release = await mutex.acquire();
|
|
15588
|
+
try {
|
|
15589
|
+
const memoryStore = await this.getMemoryStore();
|
|
15590
|
+
if (scope === "resource" && resourceId) {
|
|
15591
|
+
await memoryStore.updateResource({
|
|
15592
|
+
resourceId,
|
|
15467
15593
|
workingMemory
|
|
15594
|
+
});
|
|
15595
|
+
} else {
|
|
15596
|
+
const thread = await this.getThreadById({ threadId });
|
|
15597
|
+
if (!thread) {
|
|
15598
|
+
throw new Error(`Thread ${threadId} not found`);
|
|
15468
15599
|
}
|
|
15469
|
-
|
|
15600
|
+
await memoryStore.updateThread({
|
|
15601
|
+
id: threadId,
|
|
15602
|
+
title: thread.title || "",
|
|
15603
|
+
metadata: {
|
|
15604
|
+
...thread.metadata,
|
|
15605
|
+
workingMemory
|
|
15606
|
+
}
|
|
15607
|
+
});
|
|
15608
|
+
}
|
|
15609
|
+
} finally {
|
|
15610
|
+
release();
|
|
15470
15611
|
}
|
|
15471
15612
|
}
|
|
15472
15613
|
updateWorkingMemoryMutexes = /* @__PURE__ */ new Map();
|
|
@@ -15492,16 +15633,26 @@ var Memory = class extends memory.MastraMemory {
|
|
|
15492
15633
|
const existingWorkingMemory = await this.getWorkingMemory({ threadId, resourceId, memoryConfig }) || "";
|
|
15493
15634
|
const template = await this.getWorkingMemoryTemplate({ memoryConfig });
|
|
15494
15635
|
let reason = "";
|
|
15636
|
+
const normalizeForComparison = (str) => str.replace(/\s+/g, " ").trim();
|
|
15637
|
+
const normalizedNewMemory = normalizeForComparison(workingMemory);
|
|
15638
|
+
const normalizedTemplate = template?.content ? normalizeForComparison(template.content) : "";
|
|
15495
15639
|
if (existingWorkingMemory) {
|
|
15496
15640
|
if (searchString && existingWorkingMemory?.includes(searchString)) {
|
|
15497
15641
|
workingMemory = existingWorkingMemory.replace(searchString, workingMemory);
|
|
15498
15642
|
reason = `found and replaced searchString with newMemory`;
|
|
15499
|
-
} else if (existingWorkingMemory.includes(workingMemory) || template?.content?.trim() === workingMemory.trim()
|
|
15643
|
+
} else if (existingWorkingMemory.includes(workingMemory) || template?.content?.trim() === workingMemory.trim() || // Also check normalized versions to catch template variations with different whitespace
|
|
15644
|
+
normalizedNewMemory === normalizedTemplate) {
|
|
15500
15645
|
return {
|
|
15501
15646
|
success: false,
|
|
15502
15647
|
reason: `attempted to insert duplicate data into working memory. this entry was skipped`
|
|
15503
15648
|
};
|
|
15504
15649
|
} else {
|
|
15650
|
+
if (normalizedNewMemory === normalizedTemplate) {
|
|
15651
|
+
return {
|
|
15652
|
+
success: false,
|
|
15653
|
+
reason: `attempted to append empty template to working memory. this entry was skipped`
|
|
15654
|
+
};
|
|
15655
|
+
}
|
|
15505
15656
|
if (searchString) {
|
|
15506
15657
|
reason = `attempted to replace working memory string that doesn't exist. Appending to working memory instead.`;
|
|
15507
15658
|
} else {
|
|
@@ -15510,7 +15661,7 @@ var Memory = class extends memory.MastraMemory {
|
|
|
15510
15661
|
workingMemory = existingWorkingMemory + `
|
|
15511
15662
|
${workingMemory}`;
|
|
15512
15663
|
}
|
|
15513
|
-
} else if (workingMemory === template?.content) {
|
|
15664
|
+
} else if (workingMemory === template?.content || normalizedNewMemory === normalizedTemplate) {
|
|
15514
15665
|
return {
|
|
15515
15666
|
success: false,
|
|
15516
15667
|
reason: `try again when you have data to add. newMemory was equal to the working memory template`
|
|
@@ -15518,7 +15669,13 @@ ${workingMemory}`;
|
|
|
15518
15669
|
} else {
|
|
15519
15670
|
reason = `started new working memory`;
|
|
15520
15671
|
}
|
|
15521
|
-
|
|
15672
|
+
if (template?.content) {
|
|
15673
|
+
workingMemory = workingMemory.replaceAll(template.content, "");
|
|
15674
|
+
const templateWithUnixLineEndings = template.content.replace(/\r\n/g, "\n");
|
|
15675
|
+
const templateWithWindowsLineEndings = template.content.replace(/\n/g, "\r\n");
|
|
15676
|
+
workingMemory = workingMemory.replaceAll(templateWithUnixLineEndings, "");
|
|
15677
|
+
workingMemory = workingMemory.replaceAll(templateWithWindowsLineEndings, "");
|
|
15678
|
+
}
|
|
15522
15679
|
const scope = config.workingMemory.scope || "resource";
|
|
15523
15680
|
if (scope === "resource" && !resourceId) {
|
|
15524
15681
|
throw new Error(
|
|
@@ -15994,24 +16151,25 @@ Notes:
|
|
|
15994
16151
|
const messageIdsNeedingDeletion = /* @__PURE__ */ new Set([...messageIdsWithClearedContent, ...messageIdsWithNewEmbeddings]);
|
|
15995
16152
|
if (messageIdsNeedingDeletion.size > 0) {
|
|
15996
16153
|
try {
|
|
15997
|
-
const
|
|
15998
|
-
const
|
|
15999
|
-
|
|
16000
|
-
|
|
16001
|
-
|
|
16002
|
-
|
|
16003
|
-
|
|
16004
|
-
|
|
16005
|
-
|
|
16006
|
-
|
|
16007
|
-
|
|
16008
|
-
|
|
16009
|
-
|
|
16154
|
+
const memoryIndexes = await this.getMemoryVectorIndexes();
|
|
16155
|
+
const idsToDelete = [...messageIdsNeedingDeletion];
|
|
16156
|
+
await Promise.all(
|
|
16157
|
+
memoryIndexes.map(async (indexName) => {
|
|
16158
|
+
for (let i = 0; i < idsToDelete.length; i += VECTOR_DELETE_BATCH_SIZE) {
|
|
16159
|
+
const batch = idsToDelete.slice(i, i + VECTOR_DELETE_BATCH_SIZE);
|
|
16160
|
+
try {
|
|
16161
|
+
await this.vector.deleteVectors({
|
|
16162
|
+
indexName,
|
|
16163
|
+
filter: { message_id: { $in: batch } }
|
|
16164
|
+
});
|
|
16165
|
+
} catch {
|
|
16166
|
+
this.logger.debug(`Failed to delete vector batch in ${indexName} (batch offset ${i}), skipping`);
|
|
16167
|
+
}
|
|
16010
16168
|
}
|
|
16011
|
-
}
|
|
16012
|
-
|
|
16169
|
+
})
|
|
16170
|
+
);
|
|
16013
16171
|
} catch {
|
|
16014
|
-
this.logger.debug(`
|
|
16172
|
+
this.logger.debug(`Failed to clean up old vectors during message update`);
|
|
16015
16173
|
}
|
|
16016
16174
|
}
|
|
16017
16175
|
if (embeddingData.length > 0 && dimension !== void 0) {
|
|
@@ -16062,6 +16220,37 @@ Notes:
|
|
|
16062
16220
|
}
|
|
16063
16221
|
const memoryStore = await this.getMemoryStore();
|
|
16064
16222
|
await memoryStore.deleteMessages(messageIds);
|
|
16223
|
+
if (this.vector) {
|
|
16224
|
+
void this.deleteMessageVectors(messageIds);
|
|
16225
|
+
}
|
|
16226
|
+
}
|
|
16227
|
+
/**
|
|
16228
|
+
* Deletes vector embeddings for specific messages.
|
|
16229
|
+
* This is called internally by deleteMessages to clean up orphaned vectors.
|
|
16230
|
+
*
|
|
16231
|
+
* @param messageIds - The IDs of the messages whose vectors should be deleted
|
|
16232
|
+
*/
|
|
16233
|
+
async deleteMessageVectors(messageIds) {
|
|
16234
|
+
try {
|
|
16235
|
+
const memoryIndexes = await this.getMemoryVectorIndexes();
|
|
16236
|
+
await Promise.all(
|
|
16237
|
+
memoryIndexes.map(async (indexName) => {
|
|
16238
|
+
for (let i = 0; i < messageIds.length; i += VECTOR_DELETE_BATCH_SIZE) {
|
|
16239
|
+
const batch = messageIds.slice(i, i + VECTOR_DELETE_BATCH_SIZE);
|
|
16240
|
+
try {
|
|
16241
|
+
await this.vector.deleteVectors({
|
|
16242
|
+
indexName,
|
|
16243
|
+
filter: { message_id: { $in: batch } }
|
|
16244
|
+
});
|
|
16245
|
+
} catch {
|
|
16246
|
+
this.logger.debug(`Failed to delete vector batch in ${indexName} (batch offset ${i}), skipping`);
|
|
16247
|
+
}
|
|
16248
|
+
}
|
|
16249
|
+
})
|
|
16250
|
+
);
|
|
16251
|
+
} catch {
|
|
16252
|
+
this.logger.debug(`Failed to clean up vectors for deleted messages`);
|
|
16253
|
+
}
|
|
16065
16254
|
}
|
|
16066
16255
|
/**
|
|
16067
16256
|
* Clone a thread and its messages to create a new independent thread.
|
|
@@ -16476,7 +16665,7 @@ Notes:
|
|
|
16476
16665
|
"Observational memory async buffering is enabled by default but the installed version of @mastra/core does not support it. Either upgrade @mastra/core, @mastra/memory, and your storage adapter (@mastra/libsql, @mastra/pg, or @mastra/mongodb) to the latest version, or explicitly disable async buffering by setting `observation: { bufferTokens: false }` in your observationalMemory config."
|
|
16477
16666
|
);
|
|
16478
16667
|
}
|
|
16479
|
-
const { ObservationalMemory } = await import('./observational-memory-
|
|
16668
|
+
const { ObservationalMemory } = await import('./observational-memory-AHVELJX4.cjs');
|
|
16480
16669
|
return new ObservationalMemory({
|
|
16481
16670
|
storage: memoryStore,
|
|
16482
16671
|
scope: omConfig.scope,
|