@mastra/memory 1.37.1 → 1.38.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.
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-harness-background-tasks.md +13 -10
- package/dist/docs/references/docs-memory-overview.md +31 -0
- package/dist/docs/references/reference-memory-observational-memory.md +13 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/processors/index.cjs +1 -1
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/context-overflow.d.ts +2 -0
- package/dist/processors/observational-memory/context-overflow.d.ts.map +1 -0
- package/dist/processors/observational-memory/observational-memory.d.ts +5 -0
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts +2 -1
- package/dist/processors/observational-memory/processor.d.ts.map +1 -1
- package/dist/processors/observational-memory/summarize.d.ts.map +1 -1
- package/dist/processors/observational-memory/types.d.ts +14 -0
- package/dist/processors/observational-memory/types.d.ts.map +1 -1
- package/dist/{src-DWoBX5f9.js → src-CTyZJ6A-.js} +171 -31
- package/dist/src-CTyZJ6A-.js.map +1 -0
- package/dist/{src-BU8L6v1o.cjs → src-DZmiwOWq.cjs} +171 -31
- package/dist/src-DZmiwOWq.cjs.map +1 -0
- package/package.json +9 -9
- package/dist/src-BU8L6v1o.cjs.map +0 -1
- package/dist/src-DWoBX5f9.js.map +0 -1
|
@@ -19825,21 +19825,22 @@ function safeSlice(str, end) {
|
|
|
19825
19825
|
return str.slice(0, safeEnd);
|
|
19826
19826
|
}
|
|
19827
19827
|
//#endregion
|
|
19828
|
-
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/tokenx/1.
|
|
19828
|
+
//#region ../../../../../setup-pnpm/node_modules/.bin/store/v11/links/@/tokenx/1.6.0/394289cb1bed8c542941f77748eea1a31bd3419018d0fb2ac7029ece2458cdd1/node_modules/tokenx/dist/index.mjs
|
|
19829
19829
|
const PATTERNS = {
|
|
19830
19830
|
whitespace: /^\s+$/,
|
|
19831
|
-
|
|
19832
|
-
|
|
19833
|
-
|
|
19834
|
-
|
|
19831
|
+
structuredWhitespace: /\n\s/,
|
|
19832
|
+
cjk: /[\u4E00-\u9FFF\u3400-\u4DBF\u3000-\u30FF\uFF00-\uFFEF\u2E80-\u2EFF\u31C0-\u31EF\u3200-\u32FF\u3300-\u33FF\uAC00-\uD7AF\u1100-\u11FF\u3130-\u318F\uA960-\uA97F\uD7B0-\uD7FF]/,
|
|
19833
|
+
numeric: /^\d+$/,
|
|
19834
|
+
punctuation: /[.,!?;(){}[\]<>:/\\|@#$%^&*+=`~_"-]/
|
|
19835
19835
|
};
|
|
19836
|
-
const TOKEN_SPLIT_PATTERN =
|
|
19836
|
+
const TOKEN_SPLIT_PATTERN = new RegExp(`(\\s+|${PATTERNS.punctuation.source}+)`);
|
|
19837
19837
|
const DEFAULT_CHARS_PER_TOKEN = 6;
|
|
19838
19838
|
const SHORT_TOKEN_THRESHOLD = 3;
|
|
19839
|
+
const KANA_CHARS_PER_TOKEN = 1.35;
|
|
19839
19840
|
const DEFAULT_LANGUAGE_CONFIGS = [
|
|
19840
19841
|
{
|
|
19841
19842
|
pattern: /[äöüßẞ]/i,
|
|
19842
|
-
averageCharsPerToken:
|
|
19843
|
+
averageCharsPerToken: 2.6
|
|
19843
19844
|
},
|
|
19844
19845
|
{
|
|
19845
19846
|
pattern: /[éèêëàâîïôûùüÿçœæáíóúñ]/i,
|
|
@@ -19847,39 +19848,75 @@ const DEFAULT_LANGUAGE_CONFIGS = [
|
|
|
19847
19848
|
},
|
|
19848
19849
|
{
|
|
19849
19850
|
pattern: /[ąćęłńóśźżěščřžýůúďťň]/i,
|
|
19850
|
-
averageCharsPerToken:
|
|
19851
|
+
averageCharsPerToken: 2.5
|
|
19852
|
+
},
|
|
19853
|
+
{
|
|
19854
|
+
pattern: /[\u0430-\u044F\u0451]/i,
|
|
19855
|
+
averageCharsPerToken: 4
|
|
19856
|
+
},
|
|
19857
|
+
{
|
|
19858
|
+
pattern: /[\u03AC-\u03CE]/i,
|
|
19859
|
+
averageCharsPerToken: 2.75
|
|
19860
|
+
},
|
|
19861
|
+
{
|
|
19862
|
+
pattern: /^\p{Extended_Pictographic}[\p{Extended_Pictographic}\p{Emoji_Component}]*$/u,
|
|
19863
|
+
averageCharsPerToken: .75
|
|
19851
19864
|
}
|
|
19852
19865
|
];
|
|
19853
19866
|
/**
|
|
19854
|
-
*
|
|
19867
|
+
* Walks a text as (segment, estimated token count) pairs. The segments
|
|
19868
|
+
* concatenate back to the original text; whitespace segments count zero
|
|
19869
|
+
* tokens unless they carry structure (indentation or blank lines).
|
|
19855
19870
|
*/
|
|
19856
|
-
function
|
|
19857
|
-
if (!text) return
|
|
19858
|
-
const
|
|
19859
|
-
const
|
|
19860
|
-
|
|
19861
|
-
|
|
19862
|
-
|
|
19871
|
+
function* walkSegments(text, options = {}) {
|
|
19872
|
+
if (!text) return;
|
|
19873
|
+
const resolvedOptions = resolveOptions(options);
|
|
19874
|
+
for (const segment of text.split(TOKEN_SPLIT_PATTERN)) if (segment) yield {
|
|
19875
|
+
segment,
|
|
19876
|
+
tokenCount: estimateSegmentTokens(segment, resolvedOptions)
|
|
19877
|
+
};
|
|
19863
19878
|
}
|
|
19864
|
-
function
|
|
19865
|
-
|
|
19866
|
-
|
|
19867
|
-
|
|
19879
|
+
function resolveOptions(options) {
|
|
19880
|
+
return {
|
|
19881
|
+
defaultCharsPerToken: options.defaultCharsPerToken ?? DEFAULT_CHARS_PER_TOKEN,
|
|
19882
|
+
languageConfigs: options.languageConfigs ?? DEFAULT_LANGUAGE_CONFIGS
|
|
19883
|
+
};
|
|
19884
|
+
}
|
|
19885
|
+
function estimateSegmentTokens(segment, { languageConfigs, defaultCharsPerToken }) {
|
|
19886
|
+
if (PATTERNS.whitespace.test(segment)) return PATTERNS.structuredWhitespace.test(segment) ? 1 : 0;
|
|
19887
|
+
const languageCharsPerToken = getLanguageSpecificCharsPerToken(segment, languageConfigs);
|
|
19888
|
+
if (languageCharsPerToken !== void 0) return Math.ceil(getCharacterCount(segment) / languageCharsPerToken);
|
|
19889
|
+
if (PATTERNS.cjk.test(segment)) return estimateCjkTokens(segment);
|
|
19890
|
+
if (PATTERNS.numeric.test(segment)) return Math.ceil(segment.length / 3);
|
|
19868
19891
|
if (segment.length <= SHORT_TOKEN_THRESHOLD) return 1;
|
|
19869
|
-
if (PATTERNS.punctuation.test(segment)) return
|
|
19870
|
-
|
|
19871
|
-
const charsPerToken$1 = getLanguageSpecificCharsPerToken(segment, languageConfigs) ?? defaultCharsPerToken;
|
|
19872
|
-
return Math.ceil(segment.length / charsPerToken$1);
|
|
19873
|
-
}
|
|
19874
|
-
const charsPerToken = getLanguageSpecificCharsPerToken(segment, languageConfigs) ?? defaultCharsPerToken;
|
|
19875
|
-
return Math.ceil(segment.length / charsPerToken);
|
|
19892
|
+
if (PATTERNS.punctuation.test(segment)) return Math.ceil(segment.length / 2);
|
|
19893
|
+
return Math.ceil(segment.length / defaultCharsPerToken);
|
|
19876
19894
|
}
|
|
19877
19895
|
function getLanguageSpecificCharsPerToken(segment, languageConfigs) {
|
|
19878
|
-
for (const config of languageConfigs) if (config.pattern
|
|
19896
|
+
for (const config of languageConfigs) if (segment.search(config.pattern) !== -1) return config.averageCharsPerToken;
|
|
19879
19897
|
}
|
|
19880
19898
|
function getCharacterCount(text) {
|
|
19881
19899
|
return Array.from(text).length;
|
|
19882
19900
|
}
|
|
19901
|
+
function estimateCjkTokens(segment) {
|
|
19902
|
+
let kanaCount = 0;
|
|
19903
|
+
let otherCount = 0;
|
|
19904
|
+
for (const character of segment) {
|
|
19905
|
+
const codePoint = character.codePointAt(0);
|
|
19906
|
+
if (codePoint >= 12352 && codePoint <= 12543) kanaCount++;
|
|
19907
|
+
else otherCount++;
|
|
19908
|
+
}
|
|
19909
|
+
return otherCount + Math.ceil(kanaCount / KANA_CHARS_PER_TOKEN);
|
|
19910
|
+
}
|
|
19911
|
+
/**
|
|
19912
|
+
* Estimates the number of tokens in a text string using heuristic rules
|
|
19913
|
+
*/
|
|
19914
|
+
function estimateTokenCount(text, options = {}) {
|
|
19915
|
+
if (!text) return 0;
|
|
19916
|
+
let tokenCount = 0;
|
|
19917
|
+
for (const segmentEstimate of walkSegments(text, options)) tokenCount += segmentEstimate.tokenCount;
|
|
19918
|
+
return tokenCount;
|
|
19919
|
+
}
|
|
19883
19920
|
//#endregion
|
|
19884
19921
|
//#region src/processors/observational-memory/tool-argument-helpers.ts
|
|
19885
19922
|
const DEFAULT_OBSERVER_TOOL_ARGUMENT_MAX_TOKENS = 2e3;
|
|
@@ -22400,7 +22437,7 @@ const IMAGE_FILE_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
|
22400
22437
|
"heif",
|
|
22401
22438
|
"avif"
|
|
22402
22439
|
]);
|
|
22403
|
-
const TOKEN_ESTIMATE_CACHE_VERSION =
|
|
22440
|
+
const TOKEN_ESTIMATE_CACHE_VERSION = 8;
|
|
22404
22441
|
/**
|
|
22405
22442
|
* Cache `source` marker for token estimates supplied by the caller via
|
|
22406
22443
|
* `part.providerMetadata.mastra.tokenEstimate`. Pipelines that strip the real
|
|
@@ -23844,6 +23881,7 @@ async function summarizeConversation(opts) {
|
|
|
23844
23881
|
providerOptions: OBSERVATIONAL_MEMORY_DEFAULTS.observation.providerOptions,
|
|
23845
23882
|
maxTokensPerBatch: OBSERVATIONAL_MEMORY_DEFAULTS.observation.maxTokensPerBatch,
|
|
23846
23883
|
bufferOnIdle: false,
|
|
23884
|
+
observeOnContextOverflow: false,
|
|
23847
23885
|
observeAttachments: "auto",
|
|
23848
23886
|
instruction: opts.instructions,
|
|
23849
23887
|
threadTitle: false,
|
|
@@ -31338,6 +31376,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
31338
31376
|
maxTokensPerBatch: config.observation?.maxTokensPerBatch ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.maxTokensPerBatch,
|
|
31339
31377
|
bufferTokens: asyncBufferingDisabled ? void 0 : resolveBufferTokens(config.observation?.bufferTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferTokens, config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens),
|
|
31340
31378
|
bufferOnIdle: config.observation?.bufferOnIdle ?? false,
|
|
31379
|
+
observeOnContextOverflow: config.observation?.observeOnContextOverflow ?? true,
|
|
31341
31380
|
bufferActivation: asyncBufferingDisabled ? void 0 : config.observation?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.bufferActivation,
|
|
31342
31381
|
activateAfterIdle: parseActivationTTLConfig(observationActivateAfterIdle, observationActivateAfterIdlePath),
|
|
31343
31382
|
activateOnProviderChange: config.observation?.activateOnProviderChange ?? config.activateOnProviderChange ?? false,
|
|
@@ -33358,7 +33397,9 @@ ${formattedMessages}
|
|
|
33358
33397
|
recordInsideLock = freshRecord;
|
|
33359
33398
|
generationBefore = freshRecord.generationCount;
|
|
33360
33399
|
const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(threadId, resourceId, freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0);
|
|
33361
|
-
if (
|
|
33400
|
+
if (opts.force) {
|
|
33401
|
+
if (unobservedMessages.length === 0) return;
|
|
33402
|
+
} else if (!this.meetsObservationThreshold({
|
|
33362
33403
|
record: freshRecord,
|
|
33363
33404
|
unobservedTokens: await this.tokenCounter.countMessagesAsync(unobservedMessages)
|
|
33364
33405
|
})) return;
|
|
@@ -33666,6 +33707,55 @@ ${formattedMessages}
|
|
|
33666
33707
|
}
|
|
33667
33708
|
};
|
|
33668
33709
|
//#endregion
|
|
33710
|
+
//#region src/processors/observational-memory/context-overflow.ts
|
|
33711
|
+
/**
|
|
33712
|
+
* Detects provider errors that reject a request for exceeding the model's context window.
|
|
33713
|
+
*
|
|
33714
|
+
* Providers report this with different codes and wording, so this matches the known shapes
|
|
33715
|
+
* (OpenAI and OpenAI-compatible APIs, Anthropic, Google, Bedrock, xAI, Mistral, local servers)
|
|
33716
|
+
* against the error's message, code, response body and causes.
|
|
33717
|
+
*/
|
|
33718
|
+
const CONTEXT_OVERFLOW_PATTERNS = [
|
|
33719
|
+
/context[_ ]length[_ ]exceeded/i,
|
|
33720
|
+
/maximum context length/i,
|
|
33721
|
+
/maximum prompt length/i,
|
|
33722
|
+
/prompt is too long/i,
|
|
33723
|
+
/input is too long/i,
|
|
33724
|
+
/exceed\w*\b[^.]{0,40}\bcontext (?:window|length|limit|size)/i,
|
|
33725
|
+
/input token count[^.]{0,40}exceeds the maximum/i,
|
|
33726
|
+
/reduce the length of the (?:messages|prompt|input)/i
|
|
33727
|
+
];
|
|
33728
|
+
const MAX_CAUSE_DEPTH = 4;
|
|
33729
|
+
function collectErrorText(error, depth = 0) {
|
|
33730
|
+
if (depth > MAX_CAUSE_DEPTH || error == null) return [];
|
|
33731
|
+
if (typeof error === "string") return [error];
|
|
33732
|
+
if (typeof error !== "object") return [];
|
|
33733
|
+
const record = error;
|
|
33734
|
+
const texts = [];
|
|
33735
|
+
for (const key of [
|
|
33736
|
+
"message",
|
|
33737
|
+
"code",
|
|
33738
|
+
"type",
|
|
33739
|
+
"responseBody"
|
|
33740
|
+
]) {
|
|
33741
|
+
const value = record[key];
|
|
33742
|
+
if (typeof value === "string") texts.push(value);
|
|
33743
|
+
}
|
|
33744
|
+
if (record.data && typeof record.data === "object") texts.push(...collectErrorText(record.data.error ?? record.data, depth + 1));
|
|
33745
|
+
if (record.error && typeof record.error === "object") texts.push(...collectErrorText(record.error, depth + 1));
|
|
33746
|
+
texts.push(...collectErrorText(record.cause, depth + 1));
|
|
33747
|
+
return texts;
|
|
33748
|
+
}
|
|
33749
|
+
function isRateLimited(error, depth = 0) {
|
|
33750
|
+
if (depth > MAX_CAUSE_DEPTH || error == null || typeof error !== "object") return false;
|
|
33751
|
+
const record = error;
|
|
33752
|
+
return record.statusCode === 429 || isRateLimited(record.cause, depth + 1);
|
|
33753
|
+
}
|
|
33754
|
+
function isContextOverflowError(error) {
|
|
33755
|
+
if (isRateLimited(error)) return false;
|
|
33756
|
+
return collectErrorText(error).some((text) => CONTEXT_OVERFLOW_PATTERNS.some((pattern) => pattern.test(text)));
|
|
33757
|
+
}
|
|
33758
|
+
//#endregion
|
|
33669
33759
|
//#region src/processors/observational-memory/temporal-markers.ts
|
|
33670
33760
|
const TEMPORAL_GAP_REMINDER_TYPE = "temporal-gap";
|
|
33671
33761
|
function getTemporalGapReminderText(gapText, timestamp) {
|
|
@@ -33776,6 +33866,8 @@ function getOmObservabilityContext(args) {
|
|
|
33776
33866
|
}
|
|
33777
33867
|
/** Key used to store gateway detection result in per-processor state. */
|
|
33778
33868
|
const GATEWAY_STATE_KEY = "__isGatewayModel";
|
|
33869
|
+
/** Step number OM last recovered from a context-overflow error, so each step retries at most once. */
|
|
33870
|
+
const CONTEXT_OVERFLOW_STEP_KEY = "__omContextOverflowStep";
|
|
33779
33871
|
/** Check if the model is routed through a Mastra gateway (duck-type check to avoid cross-package instanceof issues). */
|
|
33780
33872
|
function isMastraGatewayModel(model) {
|
|
33781
33873
|
return typeof model === "object" && model !== null && "gatewayId" in model && model.gatewayId === "mastra";
|
|
@@ -34015,6 +34107,42 @@ var ObservationalMemoryProcessor = class {
|
|
|
34015
34107
|
return messageList;
|
|
34016
34108
|
});
|
|
34017
34109
|
}
|
|
34110
|
+
async processAPIError(args) {
|
|
34111
|
+
const { error, messageList, requestContext, stepNumber, state } = args;
|
|
34112
|
+
if (!this.engine.getObservationConfig().observeOnContextOverflow) return;
|
|
34113
|
+
if (state[GATEWAY_STATE_KEY]) return;
|
|
34114
|
+
if (state[CONTEXT_OVERFLOW_STEP_KEY] === stepNumber) return;
|
|
34115
|
+
if (!isContextOverflowError(error)) return;
|
|
34116
|
+
const context = this.engine.getThreadContext(requestContext, messageList);
|
|
34117
|
+
if (!context) return;
|
|
34118
|
+
if ((0, _mastra_core_memory.parseMemoryRequestContext)(requestContext)?.memoryConfig?.readOnly) return;
|
|
34119
|
+
state[CONTEXT_OVERFLOW_STEP_KEY] = stepNumber;
|
|
34120
|
+
omDebug(`[OM:processAPIError] context overflow at step ${stepNumber} — observing pending messages`);
|
|
34121
|
+
const { threadId, resourceId } = context;
|
|
34122
|
+
await this.engine.waitForBuffering(threadId, resourceId);
|
|
34123
|
+
const messages = getObservableMessages(messageList);
|
|
34124
|
+
const { activated } = await this.engine.activate({
|
|
34125
|
+
threadId,
|
|
34126
|
+
resourceId,
|
|
34127
|
+
messages,
|
|
34128
|
+
messageList,
|
|
34129
|
+
writer: args.writer
|
|
34130
|
+
});
|
|
34131
|
+
const { observed } = await this.engine.getTokenCounter().runWithModelContext(state.__omActorModelContext, () => this.engine.observe({
|
|
34132
|
+
threadId,
|
|
34133
|
+
resourceId,
|
|
34134
|
+
messages: getObservableMessages(messageList),
|
|
34135
|
+
messageList,
|
|
34136
|
+
force: true,
|
|
34137
|
+
agent: args.agent,
|
|
34138
|
+
sendSignal: args.sendSignal,
|
|
34139
|
+
sendStateSignal: args.sendStateSignal,
|
|
34140
|
+
requestContext,
|
|
34141
|
+
writer: args.writer,
|
|
34142
|
+
observabilityContext: getOmObservabilityContext(args)
|
|
34143
|
+
}));
|
|
34144
|
+
return { retry: activated || observed };
|
|
34145
|
+
}
|
|
34018
34146
|
get config() {
|
|
34019
34147
|
return this.engine.config;
|
|
34020
34148
|
}
|
|
@@ -35468,6 +35596,7 @@ ${workingMemory}`;
|
|
|
35468
35596
|
providerOptions: omConfig.observation.providerOptions,
|
|
35469
35597
|
bufferTokens: omConfig.observation.bufferTokens,
|
|
35470
35598
|
bufferOnIdle: omConfig.observation.bufferOnIdle,
|
|
35599
|
+
observeOnContextOverflow: omConfig.observation.observeOnContextOverflow,
|
|
35471
35600
|
bufferActivation: omConfig.observation.bufferActivation,
|
|
35472
35601
|
blockAfter: omConfig.observation.blockAfter,
|
|
35473
35602
|
previousObserverTokens: omConfig.observation.previousObserverTokens,
|
|
@@ -36546,6 +36675,17 @@ Notes:
|
|
|
36546
36675
|
return processors;
|
|
36547
36676
|
}
|
|
36548
36677
|
/**
|
|
36678
|
+
* Extends the base implementation to add ObservationalMemory as an error processor.
|
|
36679
|
+
* OM uses processAPIError to observe pending messages and retry when the provider
|
|
36680
|
+
* rejects a request for exceeding the model's context window.
|
|
36681
|
+
*/
|
|
36682
|
+
async getErrorProcessors(configuredProcessors = [], context) {
|
|
36683
|
+
const processors = await super.getErrorProcessors(configuredProcessors, context);
|
|
36684
|
+
const om = await this.createOMProcessor(configuredProcessors, context);
|
|
36685
|
+
if (om) processors.push(om);
|
|
36686
|
+
return processors;
|
|
36687
|
+
}
|
|
36688
|
+
/**
|
|
36549
36689
|
* Creates an ObservationalMemory processor wrapping the shared engine.
|
|
36550
36690
|
* Returns null if OM is not configured, not supported, or already present
|
|
36551
36691
|
* in the user's configured processors.
|
|
@@ -36903,4 +37043,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
|
|
|
36903
37043
|
}
|
|
36904
37044
|
});
|
|
36905
37045
|
|
|
36906
|
-
//# sourceMappingURL=src-
|
|
37046
|
+
//# sourceMappingURL=src-DZmiwOWq.cjs.map
|