@mastra/memory 1.0.0-beta.10 → 1.0.0-beta.11

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/dist/index.cjs CHANGED
@@ -38,7 +38,7 @@ function _interopNamespace(e) {
38
38
  var z4__namespace = /*#__PURE__*/_interopNamespace(z4);
39
39
  var xxhash__default = /*#__PURE__*/_interopDefault(xxhash);
40
40
 
41
- // ../_vendored/ai_v4/dist/chunk-IHGBB4AL.js
41
+ // ../_vendored/ai_v4/dist/chunk-OPIPXJLE.js
42
42
  var __create = Object.create;
43
43
  var __defProp = Object.defineProperty;
44
44
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
@@ -400,7 +400,7 @@ function getErrorMessage2(error) {
400
400
  function isAbortError(error) {
401
401
  return error instanceof Error && (error.name === "AbortError" || error.name === "TimeoutError");
402
402
  }
403
- var validatorSymbol = Symbol.for("vercel.ai.validator");
403
+ var validatorSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
404
404
  function validator(validate) {
405
405
  return { [validatorSymbol]: true, validate };
406
406
  }
@@ -458,7 +458,7 @@ function safeParseJSON({
458
458
  };
459
459
  }
460
460
  }
461
- var ignoreOverride = Symbol("Let zodToJsonSchema decide on which parser to use");
461
+ var ignoreOverride = /* @__PURE__ */ Symbol("Let zodToJsonSchema decide on which parser to use");
462
462
  var defaultOptions = {
463
463
  name: void 0,
464
464
  $refStrategy: "root",
@@ -2266,7 +2266,7 @@ function zodSchema(zodSchema22, options) {
2266
2266
  }
2267
2267
  );
2268
2268
  }
2269
- var schemaSymbol = Symbol.for("vercel.ai.schema");
2269
+ var schemaSymbol = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
2270
2270
  function jsonSchema(jsonSchema22, {
2271
2271
  validate
2272
2272
  } = {}) {
@@ -2353,7 +2353,7 @@ function _makeCompatibilityCheck(ownVersion) {
2353
2353
  }
2354
2354
  var isCompatible = _makeCompatibilityCheck(VERSION);
2355
2355
  var major = VERSION.split(".")[0];
2356
- var GLOBAL_OPENTELEMETRY_API_KEY = Symbol.for("opentelemetry.js.api." + major);
2356
+ var GLOBAL_OPENTELEMETRY_API_KEY = /* @__PURE__ */ Symbol.for("opentelemetry.js.api." + major);
2357
2357
  var _global = _globalThis;
2358
2358
  function registerGlobal(type, instance, diag, allowOverride) {
2359
2359
  var _a172;
@@ -4716,7 +4716,7 @@ function secureJsonParse(text4) {
4716
4716
  Error.stackTraceLimit = stackTraceLimit;
4717
4717
  }
4718
4718
  }
4719
- var validatorSymbol2 = Symbol.for("vercel.ai.validator");
4719
+ var validatorSymbol2 = /* @__PURE__ */ Symbol.for("vercel.ai.validator");
4720
4720
  function validator2(validate) {
4721
4721
  return { [validatorSymbol2]: true, validate };
4722
4722
  }
@@ -5030,7 +5030,7 @@ var getRelativePath2 = (pathA, pathB) => {
5030
5030
  }
5031
5031
  return [(pathA.length - i).toString(), ...pathB.slice(i)].join("/");
5032
5032
  };
5033
- var ignoreOverride2 = Symbol(
5033
+ var ignoreOverride2 = /* @__PURE__ */ Symbol(
5034
5034
  "Let zodToJsonSchema decide on which parser to use"
5035
5035
  );
5036
5036
  var defaultOptions2 = {
@@ -6150,7 +6150,7 @@ function zodSchema2(zodSchema22, options) {
6150
6150
  return zod3Schema(zodSchema22);
6151
6151
  }
6152
6152
  }
6153
- var schemaSymbol2 = Symbol.for("vercel.ai.schema");
6153
+ var schemaSymbol2 = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
6154
6154
  function jsonSchema2(jsonSchema22, {
6155
6155
  validate
6156
6156
  } = {}) {
@@ -6205,7 +6205,7 @@ var require_get_context = chunkSG3GRV3O_cjs.__commonJS({
6205
6205
  getContext: () => getContext3
6206
6206
  });
6207
6207
  module.exports = __toCommonJS(get_context_exports);
6208
- var SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
6208
+ var SYMBOL_FOR_REQ_CONTEXT = /* @__PURE__ */ Symbol.for("@vercel/request-context");
6209
6209
  function getContext3() {
6210
6210
  const fromSymbol = globalThis;
6211
6211
  return fromSymbol[SYMBOL_FOR_REQ_CONTEXT]?.get?.() ?? {};
@@ -7234,7 +7234,7 @@ function _makeCompatibilityCheck2(ownVersion) {
7234
7234
  }
7235
7235
  var isCompatible2 = _makeCompatibilityCheck2(VERSION22);
7236
7236
  var major2 = VERSION22.split(".")[0];
7237
- var GLOBAL_OPENTELEMETRY_API_KEY2 = Symbol.for("opentelemetry.js.api." + major2);
7237
+ var GLOBAL_OPENTELEMETRY_API_KEY2 = /* @__PURE__ */ Symbol.for("opentelemetry.js.api." + major2);
7238
7238
  var _global2 = _globalThis2;
7239
7239
  function registerGlobal2(type, instance, diag, allowOverride) {
7240
7240
  var _a162;
@@ -9680,7 +9680,7 @@ function addAdditionalPropertiesToJsonSchema(jsonSchema22) {
9680
9680
  }
9681
9681
  return jsonSchema22;
9682
9682
  }
9683
- var ignoreOverride3 = Symbol(
9683
+ var ignoreOverride3 = /* @__PURE__ */ Symbol(
9684
9684
  "Let zodToJsonSchema decide on which parser to use"
9685
9685
  );
9686
9686
  var defaultOptions3 = {
@@ -10762,7 +10762,7 @@ var zod3ToJsonSchema = (schema, options) => {
10762
10762
  combined.$schema = "http://json-schema.org/draft-07/schema#";
10763
10763
  return combined;
10764
10764
  };
10765
- var schemaSymbol3 = Symbol.for("vercel.ai.schema");
10765
+ var schemaSymbol3 = /* @__PURE__ */ Symbol.for("vercel.ai.schema");
10766
10766
  function lazySchema(createSchema) {
10767
10767
  let schema;
10768
10768
  return () => {
@@ -11163,7 +11163,7 @@ var require_get_context2 = chunkZUQPUTTO_cjs.__commonJS({
11163
11163
  getContext: () => getContext3
11164
11164
  });
11165
11165
  module.exports = __toCommonJS(get_context_exports);
11166
- var SYMBOL_FOR_REQ_CONTEXT = Symbol.for("@vercel/request-context");
11166
+ var SYMBOL_FOR_REQ_CONTEXT = /* @__PURE__ */ Symbol.for("@vercel/request-context");
11167
11167
  function getContext3() {
11168
11168
  const fromSymbol = globalThis;
11169
11169
  return fromSymbol[SYMBOL_FOR_REQ_CONTEXT]?.get?.() ?? {};
@@ -12196,7 +12196,7 @@ function _makeCompatibilityCheck3(ownVersion) {
12196
12196
  }
12197
12197
  var isCompatible3 = _makeCompatibilityCheck3(VERSION23);
12198
12198
  var major3 = VERSION23.split(".")[0];
12199
- var GLOBAL_OPENTELEMETRY_API_KEY3 = Symbol.for("opentelemetry.js.api." + major3);
12199
+ var GLOBAL_OPENTELEMETRY_API_KEY3 = /* @__PURE__ */ Symbol.for("opentelemetry.js.api." + major3);
12200
12200
  var _global3 = _globalThis3;
12201
12201
  function registerGlobal3(type, instance, diag, allowOverride) {
12202
12202
  var _a146;
@@ -14431,6 +14431,9 @@ var DefaultEmbedManyResult3 = class {
14431
14431
  createIdGenerator3({ prefix: "aiobj", size: 24 });
14432
14432
  createIdGenerator3({ prefix: "aiobj", size: 24 });
14433
14433
  function deepMergeWorkingMemory(existing, update) {
14434
+ if (!update || typeof update !== "object" || Object.keys(update).length === 0) {
14435
+ return existing && typeof existing === "object" ? { ...existing } : {};
14436
+ }
14434
14437
  if (!existing || typeof existing !== "object") {
14435
14438
  return update;
14436
14439
  }
@@ -14504,6 +14507,9 @@ var updateWorkingMemoryTool = (memoryConfig) => {
14504
14507
  existingData = null;
14505
14508
  }
14506
14509
  }
14510
+ if (inputData.memory === void 0 || inputData.memory === null) {
14511
+ return { success: true, message: "No memory data provided, existing memory unchanged." };
14512
+ }
14507
14513
  let newData;
14508
14514
  if (typeof inputData.memory === "string") {
14509
14515
  try {
@@ -15288,6 +15294,233 @@ ${template.content !== this.defaultWorkingMemoryTemplate ? `- Only store informa
15288
15294
  const memoryStore = await this.getMemoryStore();
15289
15295
  await memoryStore.deleteMessages(messageIds);
15290
15296
  }
15297
+ /**
15298
+ * Clone a thread and its messages to create a new independent thread.
15299
+ * The cloned thread will have metadata tracking its source.
15300
+ *
15301
+ * If semantic recall is enabled, the cloned messages will also be embedded
15302
+ * and added to the vector store for semantic search.
15303
+ *
15304
+ * @param args - Clone configuration options
15305
+ * @param args.sourceThreadId - ID of the thread to clone
15306
+ * @param args.newThreadId - ID for the new cloned thread (if not provided, a random UUID will be generated)
15307
+ * @param args.resourceId - Resource ID for the new thread (defaults to source thread's resourceId)
15308
+ * @param args.title - Title for the new cloned thread
15309
+ * @param args.metadata - Additional metadata to merge with clone metadata
15310
+ * @param args.options - Options for filtering which messages to include
15311
+ * @param args.options.messageLimit - Maximum number of messages to copy (from most recent)
15312
+ * @param args.options.messageFilter - Filter messages by date range or specific IDs
15313
+ * @param memoryConfig - Optional memory configuration override
15314
+ * @returns The newly created thread and the cloned messages
15315
+ *
15316
+ * @example
15317
+ * ```typescript
15318
+ * // Clone entire thread
15319
+ * const { thread, clonedMessages } = await memory.cloneThread({
15320
+ * sourceThreadId: 'thread-123',
15321
+ * });
15322
+ *
15323
+ * // Clone with custom ID
15324
+ * const { thread, clonedMessages } = await memory.cloneThread({
15325
+ * sourceThreadId: 'thread-123',
15326
+ * newThreadId: 'my-custom-thread-id',
15327
+ * });
15328
+ *
15329
+ * // Clone with message limit
15330
+ * const { thread, clonedMessages } = await memory.cloneThread({
15331
+ * sourceThreadId: 'thread-123',
15332
+ * title: 'My cloned conversation',
15333
+ * options: {
15334
+ * messageLimit: 10, // Only clone last 10 messages
15335
+ * },
15336
+ * });
15337
+ *
15338
+ * // Clone with date filter
15339
+ * const { thread, clonedMessages } = await memory.cloneThread({
15340
+ * sourceThreadId: 'thread-123',
15341
+ * options: {
15342
+ * messageFilter: {
15343
+ * startDate: new Date('2024-01-01'),
15344
+ * endDate: new Date('2024-06-01'),
15345
+ * },
15346
+ * },
15347
+ * });
15348
+ * ```
15349
+ */
15350
+ async cloneThread(args, memoryConfig) {
15351
+ const memoryStore = await this.getMemoryStore();
15352
+ const result = await memoryStore.cloneThread(args);
15353
+ const config = this.getMergedThreadConfig(memoryConfig);
15354
+ if (this.vector && config.semanticRecall && result.clonedMessages.length > 0) {
15355
+ await this.embedClonedMessages(result.clonedMessages, config);
15356
+ }
15357
+ return result;
15358
+ }
15359
+ /**
15360
+ * Embed cloned messages for semantic recall.
15361
+ * This is similar to the embedding logic in saveMessages but operates on already-saved messages.
15362
+ */
15363
+ async embedClonedMessages(messages, config) {
15364
+ if (!this.vector || !this.embedder) {
15365
+ return;
15366
+ }
15367
+ const embeddingData = [];
15368
+ let dimension;
15369
+ await Promise.all(
15370
+ messages.map(async (message) => {
15371
+ let textForEmbedding = null;
15372
+ if (message.content?.content && typeof message.content.content === "string" && message.content.content.trim() !== "") {
15373
+ textForEmbedding = message.content.content;
15374
+ } else if (message.content?.parts && message.content.parts.length > 0) {
15375
+ const joined = message.content.parts.filter((part) => part.type === "text").map((part) => part.text).join(" ").trim();
15376
+ if (joined) textForEmbedding = joined;
15377
+ }
15378
+ if (!textForEmbedding) return;
15379
+ const result = await this.embedMessageContent(textForEmbedding);
15380
+ dimension = result.dimension;
15381
+ embeddingData.push({
15382
+ embeddings: result.embeddings,
15383
+ metadata: result.chunks.map(() => ({
15384
+ message_id: message.id,
15385
+ thread_id: message.threadId,
15386
+ resource_id: message.resourceId
15387
+ }))
15388
+ });
15389
+ })
15390
+ );
15391
+ if (embeddingData.length > 0 && dimension !== void 0) {
15392
+ const { indexName } = await this.createEmbeddingIndex(dimension, config);
15393
+ const allVectors = [];
15394
+ const allMetadata = [];
15395
+ for (const data of embeddingData) {
15396
+ allVectors.push(...data.embeddings);
15397
+ allMetadata.push(...data.metadata);
15398
+ }
15399
+ await this.vector.upsert({
15400
+ indexName,
15401
+ vectors: allVectors,
15402
+ metadata: allMetadata
15403
+ });
15404
+ }
15405
+ }
15406
+ /**
15407
+ * Get the clone metadata from a thread if it was cloned from another thread.
15408
+ *
15409
+ * @param thread - The thread to check
15410
+ * @returns The clone metadata if the thread is a clone, null otherwise
15411
+ *
15412
+ * @example
15413
+ * ```typescript
15414
+ * const thread = await memory.getThreadById({ threadId: 'thread-123' });
15415
+ * const cloneInfo = memory.getCloneMetadata(thread);
15416
+ * if (cloneInfo) {
15417
+ * console.log(`This thread was cloned from ${cloneInfo.sourceThreadId}`);
15418
+ * }
15419
+ * ```
15420
+ */
15421
+ getCloneMetadata(thread) {
15422
+ if (!thread?.metadata?.clone) {
15423
+ return null;
15424
+ }
15425
+ return thread.metadata.clone;
15426
+ }
15427
+ /**
15428
+ * Check if a thread is a clone of another thread.
15429
+ *
15430
+ * @param thread - The thread to check
15431
+ * @returns True if the thread is a clone, false otherwise
15432
+ *
15433
+ * @example
15434
+ * ```typescript
15435
+ * const thread = await memory.getThreadById({ threadId: 'thread-123' });
15436
+ * if (memory.isClone(thread)) {
15437
+ * console.log('This is a cloned thread');
15438
+ * }
15439
+ * ```
15440
+ */
15441
+ isClone(thread) {
15442
+ return this.getCloneMetadata(thread) !== null;
15443
+ }
15444
+ /**
15445
+ * Get the source thread that a cloned thread was created from.
15446
+ *
15447
+ * @param threadId - ID of the cloned thread
15448
+ * @returns The source thread if found, null if the thread is not a clone or source doesn't exist
15449
+ *
15450
+ * @example
15451
+ * ```typescript
15452
+ * const sourceThread = await memory.getSourceThread('cloned-thread-123');
15453
+ * if (sourceThread) {
15454
+ * console.log(`Original thread: ${sourceThread.title}`);
15455
+ * }
15456
+ * ```
15457
+ */
15458
+ async getSourceThread(threadId) {
15459
+ const thread = await this.getThreadById({ threadId });
15460
+ const cloneMetadata = this.getCloneMetadata(thread);
15461
+ if (!cloneMetadata) {
15462
+ return null;
15463
+ }
15464
+ return this.getThreadById({ threadId: cloneMetadata.sourceThreadId });
15465
+ }
15466
+ /**
15467
+ * List all threads that were cloned from a specific source thread.
15468
+ *
15469
+ * @param sourceThreadId - ID of the source thread
15470
+ * @param resourceId - Optional resource ID to filter by
15471
+ * @returns Array of threads that are clones of the source thread
15472
+ *
15473
+ * @example
15474
+ * ```typescript
15475
+ * const clones = await memory.listClones('original-thread-123', 'user-456');
15476
+ * console.log(`Found ${clones.length} clones of this thread`);
15477
+ * ```
15478
+ */
15479
+ async listClones(sourceThreadId, resourceId) {
15480
+ let targetResourceId = resourceId;
15481
+ if (!targetResourceId) {
15482
+ const sourceThread = await this.getThreadById({ threadId: sourceThreadId });
15483
+ if (!sourceThread) {
15484
+ return [];
15485
+ }
15486
+ targetResourceId = sourceThread.resourceId;
15487
+ }
15488
+ const { threads } = await this.listThreadsByResourceId({
15489
+ resourceId: targetResourceId,
15490
+ perPage: false
15491
+ // Get all threads
15492
+ });
15493
+ return threads.filter((thread) => {
15494
+ const cloneMetadata = this.getCloneMetadata(thread);
15495
+ return cloneMetadata?.sourceThreadId === sourceThreadId;
15496
+ });
15497
+ }
15498
+ /**
15499
+ * Get the clone history chain for a thread (all ancestors back to the original).
15500
+ *
15501
+ * @param threadId - ID of the thread to get history for
15502
+ * @returns Array of threads from oldest ancestor to the given thread (inclusive)
15503
+ *
15504
+ * @example
15505
+ * ```typescript
15506
+ * const history = await memory.getCloneHistory('deeply-cloned-thread');
15507
+ * // Returns: [originalThread, firstClone, secondClone, deeplyClonedThread]
15508
+ * ```
15509
+ */
15510
+ async getCloneHistory(threadId) {
15511
+ const history = [];
15512
+ let currentThreadId = threadId;
15513
+ while (currentThreadId) {
15514
+ const thread = await this.getThreadById({ threadId: currentThreadId });
15515
+ if (!thread) {
15516
+ break;
15517
+ }
15518
+ history.unshift(thread);
15519
+ const cloneMetadata = this.getCloneMetadata(thread);
15520
+ currentThreadId = cloneMetadata?.sourceThreadId ?? null;
15521
+ }
15522
+ return history;
15523
+ }
15291
15524
  };
15292
15525
 
15293
15526
  Object.defineProperty(exports, "extractWorkingMemoryContent", {