@mastra/memory 1.37.1 → 1.38.0-alpha.0

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.
@@ -23844,6 +23844,7 @@ async function summarizeConversation(opts) {
23844
23844
  providerOptions: OBSERVATIONAL_MEMORY_DEFAULTS.observation.providerOptions,
23845
23845
  maxTokensPerBatch: OBSERVATIONAL_MEMORY_DEFAULTS.observation.maxTokensPerBatch,
23846
23846
  bufferOnIdle: false,
23847
+ observeOnContextOverflow: false,
23847
23848
  observeAttachments: "auto",
23848
23849
  instruction: opts.instructions,
23849
23850
  threadTitle: false,
@@ -31338,6 +31339,7 @@ var ObservationalMemory = class ObservationalMemory {
31338
31339
  maxTokensPerBatch: config.observation?.maxTokensPerBatch ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.maxTokensPerBatch,
31339
31340
  bufferTokens: asyncBufferingDisabled ? void 0 : resolveBufferTokens(config.observation?.bufferTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferTokens, config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens),
31340
31341
  bufferOnIdle: config.observation?.bufferOnIdle ?? false,
31342
+ observeOnContextOverflow: config.observation?.observeOnContextOverflow ?? true,
31341
31343
  bufferActivation: asyncBufferingDisabled ? void 0 : config.observation?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferActivation,
31342
31344
  activateAfterIdle: parseActivationTTLConfig(observationActivateAfterIdle, observationActivateAfterIdlePath),
31343
31345
  activateOnProviderChange: config.observation?.activateOnProviderChange ?? config.activateOnProviderChange ?? false,
@@ -33358,7 +33360,9 @@ ${formattedMessages}
33358
33360
  recordInsideLock = freshRecord;
33359
33361
  generationBefore = freshRecord.generationCount;
33360
33362
  const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(threadId, resourceId, freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0);
33361
- if (!this.meetsObservationThreshold({
33363
+ if (opts.force) {
33364
+ if (unobservedMessages.length === 0) return;
33365
+ } else if (!this.meetsObservationThreshold({
33362
33366
  record: freshRecord,
33363
33367
  unobservedTokens: await this.tokenCounter.countMessagesAsync(unobservedMessages)
33364
33368
  })) return;
@@ -33666,6 +33670,55 @@ ${formattedMessages}
33666
33670
  }
33667
33671
  };
33668
33672
  //#endregion
33673
+ //#region src/processors/observational-memory/context-overflow.ts
33674
+ /**
33675
+ * Detects provider errors that reject a request for exceeding the model's context window.
33676
+ *
33677
+ * Providers report this with different codes and wording, so this matches the known shapes
33678
+ * (OpenAI and OpenAI-compatible APIs, Anthropic, Google, Bedrock, xAI, Mistral, local servers)
33679
+ * against the error's message, code, response body and causes.
33680
+ */
33681
+ const CONTEXT_OVERFLOW_PATTERNS = [
33682
+ /context[_ ]length[_ ]exceeded/i,
33683
+ /maximum context length/i,
33684
+ /maximum prompt length/i,
33685
+ /prompt is too long/i,
33686
+ /input is too long/i,
33687
+ /exceed\w*\b[^.]{0,40}\bcontext (?:window|length|limit|size)/i,
33688
+ /input token count[^.]{0,40}exceeds the maximum/i,
33689
+ /reduce the length of the (?:messages|prompt|input)/i
33690
+ ];
33691
+ const MAX_CAUSE_DEPTH = 4;
33692
+ function collectErrorText(error, depth = 0) {
33693
+ if (depth > MAX_CAUSE_DEPTH || error == null) return [];
33694
+ if (typeof error === "string") return [error];
33695
+ if (typeof error !== "object") return [];
33696
+ const record = error;
33697
+ const texts = [];
33698
+ for (const key of [
33699
+ "message",
33700
+ "code",
33701
+ "type",
33702
+ "responseBody"
33703
+ ]) {
33704
+ const value = record[key];
33705
+ if (typeof value === "string") texts.push(value);
33706
+ }
33707
+ if (record.data && typeof record.data === "object") texts.push(...collectErrorText(record.data.error ?? record.data, depth + 1));
33708
+ if (record.error && typeof record.error === "object") texts.push(...collectErrorText(record.error, depth + 1));
33709
+ texts.push(...collectErrorText(record.cause, depth + 1));
33710
+ return texts;
33711
+ }
33712
+ function isRateLimited(error, depth = 0) {
33713
+ if (depth > MAX_CAUSE_DEPTH || error == null || typeof error !== "object") return false;
33714
+ const record = error;
33715
+ return record.statusCode === 429 || isRateLimited(record.cause, depth + 1);
33716
+ }
33717
+ function isContextOverflowError(error) {
33718
+ if (isRateLimited(error)) return false;
33719
+ return collectErrorText(error).some((text) => CONTEXT_OVERFLOW_PATTERNS.some((pattern) => pattern.test(text)));
33720
+ }
33721
+ //#endregion
33669
33722
  //#region src/processors/observational-memory/temporal-markers.ts
33670
33723
  const TEMPORAL_GAP_REMINDER_TYPE = "temporal-gap";
33671
33724
  function getTemporalGapReminderText(gapText, timestamp) {
@@ -33776,6 +33829,8 @@ function getOmObservabilityContext(args) {
33776
33829
  }
33777
33830
  /** Key used to store gateway detection result in per-processor state. */
33778
33831
  const GATEWAY_STATE_KEY = "__isGatewayModel";
33832
+ /** Step number OM last recovered from a context-overflow error, so each step retries at most once. */
33833
+ const CONTEXT_OVERFLOW_STEP_KEY = "__omContextOverflowStep";
33779
33834
  /** Check if the model is routed through a Mastra gateway (duck-type check to avoid cross-package instanceof issues). */
33780
33835
  function isMastraGatewayModel(model) {
33781
33836
  return typeof model === "object" && model !== null && "gatewayId" in model && model.gatewayId === "mastra";
@@ -34015,6 +34070,42 @@ var ObservationalMemoryProcessor = class {
34015
34070
  return messageList;
34016
34071
  });
34017
34072
  }
34073
+ async processAPIError(args) {
34074
+ const { error, messageList, requestContext, stepNumber, state } = args;
34075
+ if (!this.engine.getObservationConfig().observeOnContextOverflow) return;
34076
+ if (state[GATEWAY_STATE_KEY]) return;
34077
+ if (state[CONTEXT_OVERFLOW_STEP_KEY] === stepNumber) return;
34078
+ if (!isContextOverflowError(error)) return;
34079
+ const context = this.engine.getThreadContext(requestContext, messageList);
34080
+ if (!context) return;
34081
+ if ((0, _mastra_core_memory.parseMemoryRequestContext)(requestContext)?.memoryConfig?.readOnly) return;
34082
+ state[CONTEXT_OVERFLOW_STEP_KEY] = stepNumber;
34083
+ omDebug(`[OM:processAPIError] context overflow at step ${stepNumber} — observing pending messages`);
34084
+ const { threadId, resourceId } = context;
34085
+ await this.engine.waitForBuffering(threadId, resourceId);
34086
+ const messages = getObservableMessages(messageList);
34087
+ const { activated } = await this.engine.activate({
34088
+ threadId,
34089
+ resourceId,
34090
+ messages,
34091
+ messageList,
34092
+ writer: args.writer
34093
+ });
34094
+ const { observed } = await this.engine.getTokenCounter().runWithModelContext(state.__omActorModelContext, () => this.engine.observe({
34095
+ threadId,
34096
+ resourceId,
34097
+ messages: getObservableMessages(messageList),
34098
+ messageList,
34099
+ force: true,
34100
+ agent: args.agent,
34101
+ sendSignal: args.sendSignal,
34102
+ sendStateSignal: args.sendStateSignal,
34103
+ requestContext,
34104
+ writer: args.writer,
34105
+ observabilityContext: getOmObservabilityContext(args)
34106
+ }));
34107
+ return { retry: activated || observed };
34108
+ }
34018
34109
  get config() {
34019
34110
  return this.engine.config;
34020
34111
  }
@@ -35468,6 +35559,7 @@ ${workingMemory}`;
35468
35559
  providerOptions: omConfig.observation.providerOptions,
35469
35560
  bufferTokens: omConfig.observation.bufferTokens,
35470
35561
  bufferOnIdle: omConfig.observation.bufferOnIdle,
35562
+ observeOnContextOverflow: omConfig.observation.observeOnContextOverflow,
35471
35563
  bufferActivation: omConfig.observation.bufferActivation,
35472
35564
  blockAfter: omConfig.observation.blockAfter,
35473
35565
  previousObserverTokens: omConfig.observation.previousObserverTokens,
@@ -36546,6 +36638,17 @@ Notes:
36546
36638
  return processors;
36547
36639
  }
36548
36640
  /**
36641
+ * Extends the base implementation to add ObservationalMemory as an error processor.
36642
+ * OM uses processAPIError to observe pending messages and retry when the provider
36643
+ * rejects a request for exceeding the model's context window.
36644
+ */
36645
+ async getErrorProcessors(configuredProcessors = [], context) {
36646
+ const processors = await super.getErrorProcessors(configuredProcessors, context);
36647
+ const om = await this.createOMProcessor(configuredProcessors, context);
36648
+ if (om) processors.push(om);
36649
+ return processors;
36650
+ }
36651
+ /**
36549
36652
  * Creates an ObservationalMemory processor wrapping the shared engine.
36550
36653
  * Returns null if OM is not configured, not supported, or already present
36551
36654
  * in the user's configured processors.
@@ -36903,4 +37006,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
36903
37006
  }
36904
37007
  });
36905
37008
 
36906
- //# sourceMappingURL=src-BU8L6v1o.cjs.map
37009
+ //# sourceMappingURL=src-BfhwVNr7.cjs.map