@mastra/memory 1.30.0 → 1.31.0-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.
Files changed (35) hide show
  1. package/dist/_types/@internal_ai-sdk-v4/package.json +1 -0
  2. package/dist/docs/SKILL.md +1 -1
  3. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  4. package/dist/docs/references/docs-memory-message-history.md +21 -0
  5. package/dist/docs/references/docs-subagents.md +38 -7
  6. package/dist/docs/references/reference-memory-memory-class.md +2 -0
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.d.ts +11 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +1 -1
  11. package/dist/processors/index.cjs +1 -1
  12. package/dist/processors/index.js +1 -1
  13. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
  14. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts.map +1 -1
  15. package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
  16. package/dist/processors/observational-memory/observation-strategies/thread-title.d.ts +15 -0
  17. package/dist/processors/observational-memory/observation-strategies/thread-title.d.ts.map +1 -0
  18. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  19. package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
  20. package/dist/processors/observational-memory/observer-runner.d.ts.map +1 -1
  21. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  22. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/token-counter.d.ts +6 -1
  24. package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/tool-argument-helpers.d.ts +10 -0
  26. package/dist/processors/observational-memory/tool-argument-helpers.d.ts.map +1 -0
  27. package/dist/processors/observational-memory/tool-result-helpers.d.ts +1 -1
  28. package/dist/processors/observational-memory/tool-result-helpers.d.ts.map +1 -1
  29. package/dist/{src-oL_dDHN9.cjs → src-BCvV2aGL.cjs} +613 -74
  30. package/dist/src-BCvV2aGL.cjs.map +1 -0
  31. package/dist/{src-Dt8oPiQN.js → src-Ju0u9OWc.js} +614 -75
  32. package/dist/src-Ju0u9OWc.js.map +1 -0
  33. package/package.json +7 -7
  34. package/dist/src-Dt8oPiQN.js.map +0 -1
  35. package/dist/src-oL_dDHN9.cjs.map +0 -1
@@ -39,6 +39,7 @@ let _mastra_core_agent = require("@mastra/core/agent");
39
39
  let _mastra_core_features = require("@mastra/core/features");
40
40
  let _mastra_core_memory = require("@mastra/core/memory");
41
41
  let _mastra_core_observability = require("@mastra/core/observability");
42
+ let _mastra_core_processors = require("@mastra/core/processors");
42
43
  let _mastra_core_utils = require("@mastra/core/utils");
43
44
  let _mastra_schema_compat_schema = require("@mastra/schema-compat/schema");
44
45
  let async_mutex = require("async-mutex");
@@ -57,7 +58,6 @@ let probe_image_size_sync_js = require("probe-image-size/sync.js");
57
58
  probe_image_size_sync_js = __toESM$1(probe_image_size_sync_js, 1);
58
59
  let _mastra_core_schema = require("@mastra/core/schema");
59
60
  let _mastra_core_error = require("@mastra/core/error");
60
- let _mastra_core_processors = require("@mastra/core/processors");
61
61
  let diff = require("diff");
62
62
  let util = require("util");
63
63
  //#region ../_vendored/ai_v4/dist/dist-Cm5DZgxA.js
@@ -3735,7 +3735,7 @@ function trimStartOfStream() {
3735
3735
  };
3736
3736
  }
3737
3737
  //#endregion
3738
- //#region ../_vendored/ai_v5/dist/dist-Dqv4QeJJ.js
3738
+ //#region ../_vendored/ai_v5/dist/dist-DCHMJHX3.js
3739
3739
  var marker$1$4 = "vercel.ai.error";
3740
3740
  var symbol$1$3 = Symbol.for(marker$1$4);
3741
3741
  var _a$1$3;
@@ -18326,6 +18326,358 @@ function safeSlice(str, end) {
18326
18326
  return str.slice(0, safeEnd);
18327
18327
  }
18328
18328
  //#endregion
18329
+ //#region src/processors/observational-memory/tool-argument-helpers.ts
18330
+ const DEFAULT_OBSERVER_TOOL_ARGUMENT_MAX_TOKENS = 2e3;
18331
+ const OBSERVER_TOOL_ARGUMENT_INLINE_STRING_MAX_CHARS = 160;
18332
+ const OBSERVER_TOOL_ARGUMENT_MAX_DEPTH = 5;
18333
+ const OBSERVER_TOOL_ARGUMENT_MAX_ENTRIES_PER_CONTAINER = 20;
18334
+ const OBSERVER_TOOL_ARGUMENT_MAX_OUTLINE_ENTRIES = 100;
18335
+ const OBSERVER_TOOL_ARGUMENT_MAX_PATH_CHARS = 160;
18336
+ function isObjectLike$1(value) {
18337
+ return typeof value === "object" && value !== null;
18338
+ }
18339
+ function sanitizeSurrogates(value) {
18340
+ let sanitized = "";
18341
+ for (let index = 0; index < value.length; index++) {
18342
+ const code = value.charCodeAt(index);
18343
+ if (code >= 55296 && code <= 56319) {
18344
+ const next = value.charCodeAt(index + 1);
18345
+ if (next >= 56320 && next <= 57343) {
18346
+ sanitized += value.charAt(index) + value.charAt(index + 1);
18347
+ index++;
18348
+ } else sanitized += "�";
18349
+ continue;
18350
+ }
18351
+ sanitized += code >= 56320 && code <= 57343 ? "�" : value[index];
18352
+ }
18353
+ return sanitized;
18354
+ }
18355
+ function stablePathDigest(value) {
18356
+ let hash = 2166136261;
18357
+ for (let index = 0; index < value.length; index++) hash = Math.imul(hash ^ value.charCodeAt(index), 16777619);
18358
+ return (hash >>> 0).toString(16).padStart(8, "0");
18359
+ }
18360
+ function safeTail(value, length) {
18361
+ let start = Math.max(0, value.length - length);
18362
+ if (start > 0) {
18363
+ const code = value.charCodeAt(start);
18364
+ if (code >= 56320 && code <= 57343) start++;
18365
+ }
18366
+ return value.slice(start);
18367
+ }
18368
+ function truncatePath(path) {
18369
+ if (path.length <= OBSERVER_TOOL_ARGUMENT_MAX_PATH_CHARS) return path;
18370
+ const headLength = 50;
18371
+ const tailLength = 60;
18372
+ const omitted = path.length - headLength - tailLength;
18373
+ return `${safeSlice(path, headLength)}…[${omitted} chars; ${stablePathDigest(path)}]…${safeTail(path, tailLength)}`;
18374
+ }
18375
+ function formatPath(parent, key, isArray) {
18376
+ if (isArray) return truncatePath(`${parent}[${key}]`);
18377
+ const stringKey = String(key);
18378
+ const segment = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(stringKey) ? stringKey : `[${JSON.stringify(stringKey)}]`;
18379
+ return truncatePath(parent ? `${parent}.${segment}` : segment);
18380
+ }
18381
+ function formatPrimitive(value) {
18382
+ if (typeof value === "string") return JSON.stringify(value);
18383
+ if (typeof value === "bigint") return `<bigint> ${value}`;
18384
+ if (typeof value === "symbol" || typeof value === "function") return JSON.stringify(String(value));
18385
+ if (value === void 0) return "<undefined>";
18386
+ if (typeof value === "number" && Object.is(value, -0)) return "-0";
18387
+ return String(value);
18388
+ }
18389
+ function containerSummary(value) {
18390
+ if (!Array.isArray(value)) return "<object>";
18391
+ try {
18392
+ return `<array, ${value.length} ${value.length === 1 ? "item" : "items"}>`;
18393
+ } catch {
18394
+ return "<array, unknown length>";
18395
+ }
18396
+ }
18397
+ function readEntries(value) {
18398
+ const entries = [];
18399
+ try {
18400
+ if (Array.isArray(value)) {
18401
+ const length = value.length;
18402
+ const visibleLength = Math.min(length, OBSERVER_TOOL_ARGUMENT_MAX_ENTRIES_PER_CONTAINER);
18403
+ for (let index = 0; index < visibleLength; index++) {
18404
+ if (!(index in value)) {
18405
+ entries.push({
18406
+ key: index,
18407
+ unavailable: "hole"
18408
+ });
18409
+ continue;
18410
+ }
18411
+ try {
18412
+ entries.push({
18413
+ key: index,
18414
+ value: value[index]
18415
+ });
18416
+ } catch {
18417
+ entries.push({
18418
+ key: index,
18419
+ unavailable: "unreadable"
18420
+ });
18421
+ }
18422
+ }
18423
+ return {
18424
+ entries,
18425
+ hasMore: length > visibleLength,
18426
+ unavailable: false
18427
+ };
18428
+ }
18429
+ let hasMore = false;
18430
+ for (const key in value) {
18431
+ if (!Object.prototype.hasOwnProperty.call(value, key)) continue;
18432
+ if (entries.length >= OBSERVER_TOOL_ARGUMENT_MAX_ENTRIES_PER_CONTAINER) {
18433
+ hasMore = true;
18434
+ break;
18435
+ }
18436
+ try {
18437
+ entries.push({
18438
+ key,
18439
+ value: value[key]
18440
+ });
18441
+ } catch {
18442
+ entries.push({
18443
+ key,
18444
+ unavailable: "unreadable"
18445
+ });
18446
+ }
18447
+ }
18448
+ return {
18449
+ entries,
18450
+ hasMore,
18451
+ unavailable: false
18452
+ };
18453
+ } catch {
18454
+ return {
18455
+ entries,
18456
+ hasMore: false,
18457
+ unavailable: true
18458
+ };
18459
+ }
18460
+ }
18461
+ function fits(text, limits) {
18462
+ return text.length <= limits.maxCharacters && (0, tokenx.estimateTokenCount)(text) <= limits.maxTokens;
18463
+ }
18464
+ function joinEntries(entries, marker) {
18465
+ const lines = [...entries].sort((a, b) => a.order - b.order).map((entry) => entry.text);
18466
+ if (marker) lines.push(marker);
18467
+ return lines.join("\n");
18468
+ }
18469
+ function selectOutlineEntries(entries, limits) {
18470
+ const all = joinEntries(entries);
18471
+ if (fits(all, limits)) return all;
18472
+ const marker = "... [additional argument fields omitted by size limit]";
18473
+ const selected = [];
18474
+ const candidates = [...entries].sort((a, b) => {
18475
+ if (a.depth !== b.depth) return a.depth - b.depth;
18476
+ return (0, tokenx.estimateTokenCount)(a.text) - (0, tokenx.estimateTokenCount)(b.text) || a.text.length - b.text.length || a.order - b.order;
18477
+ });
18478
+ for (const candidate of candidates) if (fits(joinEntries([...selected, candidate], marker), limits)) selected.push(candidate);
18479
+ const rendered = joinEntries(selected, marker);
18480
+ if (fits(rendered, limits)) return rendered;
18481
+ if (fits(marker, limits)) return marker;
18482
+ return fits("…", limits) ? "…" : "";
18483
+ }
18484
+ function indentPreview(value) {
18485
+ return value.split("\n").map((line) => ` | ${line}`).join("\n");
18486
+ }
18487
+ function formatPreview(path, value, limits, prefix = "") {
18488
+ const sanitizedValue = sanitizeSurrogates(value);
18489
+ const marker = (visible) => {
18490
+ const omitted = sanitizedValue.length - visible.length;
18491
+ return `${path}:\n${indentPreview(visible)}${omitted > 0 ? `\n | ... [${omitted} characters omitted]` : ""}`;
18492
+ };
18493
+ let low = 0;
18494
+ let high = sanitizedValue.length;
18495
+ let best = "";
18496
+ while (low <= high) {
18497
+ const mid = Math.floor((low + high) / 2);
18498
+ const candidate = marker(safeSlice(sanitizedValue, mid));
18499
+ if (fits(prefix ? `${prefix}\n${candidate}` : candidate, limits)) {
18500
+ best = candidate;
18501
+ low = mid + 1;
18502
+ } else high = mid - 1;
18503
+ }
18504
+ return best;
18505
+ }
18506
+ function appendWithinBudget(base, addition, limits) {
18507
+ if (!addition) return;
18508
+ const candidate = base ? `${base}\n${addition}` : addition;
18509
+ return fits(candidate, limits) ? candidate : void 0;
18510
+ }
18511
+ /**
18512
+ * Formats tool arguments for the Observer without allowing a large early value
18513
+ * to hide concise sibling fields. A breadth-first structural outline is selected
18514
+ * before bounded previews of large strings are added.
18515
+ */
18516
+ function formatToolArgumentsForObserver(value, options) {
18517
+ const limits = {
18518
+ maxTokens: options?.maxTokens ?? DEFAULT_OBSERVER_TOOL_ARGUMENT_MAX_TOKENS,
18519
+ maxCharacters: options?.maxCharacters ?? Number.POSITIVE_INFINITY
18520
+ };
18521
+ if (limits.maxTokens <= 0 || limits.maxCharacters <= 0) return "";
18522
+ if (!isObjectLike$1(value)) {
18523
+ if (typeof value !== "string" || value.length <= OBSERVER_TOOL_ARGUMENT_INLINE_STRING_MAX_CHARS) {
18524
+ const primitive = formatPrimitive(value);
18525
+ return fits(primitive, limits) ? primitive : fits("…", limits) ? "…" : "";
18526
+ }
18527
+ const summary = `<string, ${value.length} characters; preview size-limited>`;
18528
+ const rendered = appendWithinBudget(summary, formatPreview("preview", value, limits, summary), limits);
18529
+ if (rendered) return rendered;
18530
+ if (fits(summary, limits)) return summary;
18531
+ return fits("…", limits) ? "…" : "";
18532
+ }
18533
+ const outline = [];
18534
+ const previews = [];
18535
+ const pending = [{
18536
+ path: "",
18537
+ value,
18538
+ depth: 0,
18539
+ ancestors: /* @__PURE__ */ new Set([value])
18540
+ }];
18541
+ let outlineEntries = 0;
18542
+ let order = 0;
18543
+ let structuralLimitReached = false;
18544
+ while (pending.length > 0 && outlineEntries < OBSERVER_TOOL_ARGUMENT_MAX_OUTLINE_ENTRIES) {
18545
+ const current = pending.shift();
18546
+ const read = readEntries(current.value);
18547
+ if (read.unavailable) {
18548
+ outline.push({
18549
+ text: `${current.path || "arguments"}: [unavailable container]`,
18550
+ depth: current.depth,
18551
+ order: order++
18552
+ });
18553
+ outlineEntries++;
18554
+ continue;
18555
+ }
18556
+ if (read.entries.length === 0 && !read.hasMore) {
18557
+ outline.push({
18558
+ text: `${current.path || "arguments"}: [empty ${Array.isArray(current.value) ? "array" : "object"}]`,
18559
+ depth: current.depth,
18560
+ order: order++
18561
+ });
18562
+ outlineEntries++;
18563
+ continue;
18564
+ }
18565
+ if (read.hasMore) {
18566
+ outline.push({
18567
+ text: `${current.path || (Array.isArray(current.value) ? "items" : "fields")}: ... [additional entries omitted]`,
18568
+ depth: current.depth,
18569
+ order: order++
18570
+ });
18571
+ outlineEntries++;
18572
+ }
18573
+ for (const entry of read.entries) {
18574
+ if (outlineEntries >= OBSERVER_TOOL_ARGUMENT_MAX_OUTLINE_ENTRIES) {
18575
+ structuralLimitReached = true;
18576
+ break;
18577
+ }
18578
+ const path = formatPath(current.path, entry.key, Array.isArray(current.value));
18579
+ outlineEntries++;
18580
+ if (entry.unavailable) {
18581
+ outline.push({
18582
+ text: `${path}: [${entry.unavailable}]`,
18583
+ depth: current.depth,
18584
+ order: order++
18585
+ });
18586
+ continue;
18587
+ }
18588
+ const entryValue = entry.value;
18589
+ if (typeof entryValue === "string" && entryValue.length > OBSERVER_TOOL_ARGUMENT_INLINE_STRING_MAX_CHARS) {
18590
+ outline.push({
18591
+ text: `${path}: <string, ${entryValue.length} characters; preview size-limited>`,
18592
+ depth: current.depth,
18593
+ order: order++
18594
+ });
18595
+ previews.push({
18596
+ path,
18597
+ value: entryValue
18598
+ });
18599
+ continue;
18600
+ }
18601
+ if (!isObjectLike$1(entryValue)) {
18602
+ outline.push({
18603
+ text: `${path}: ${formatPrimitive(entryValue)}`,
18604
+ depth: current.depth,
18605
+ order: order++
18606
+ });
18607
+ continue;
18608
+ }
18609
+ if (current.ancestors.has(entryValue)) {
18610
+ outline.push({
18611
+ text: `${path}: [circular]`,
18612
+ depth: current.depth,
18613
+ order: order++
18614
+ });
18615
+ continue;
18616
+ }
18617
+ const summary = containerSummary(entryValue);
18618
+ if (current.depth >= OBSERVER_TOOL_ARGUMENT_MAX_DEPTH) {
18619
+ outline.push({
18620
+ text: `${path}: ${summary} [max depth reached]`,
18621
+ depth: current.depth,
18622
+ order: order++
18623
+ });
18624
+ continue;
18625
+ }
18626
+ outline.push({
18627
+ text: `${path}: ${summary}`,
18628
+ depth: current.depth,
18629
+ order: order++
18630
+ });
18631
+ pending.push({
18632
+ path,
18633
+ value: entryValue,
18634
+ depth: current.depth + 1,
18635
+ ancestors: /* @__PURE__ */ new Set([...current.ancestors, entryValue])
18636
+ });
18637
+ }
18638
+ }
18639
+ if (pending.length > 0 || structuralLimitReached) outline.push({
18640
+ text: "... [additional nested entries omitted by structure limit]",
18641
+ depth: Number.POSITIVE_INFINITY,
18642
+ order: order++
18643
+ });
18644
+ if (previews.length === 0) return selectOutlineEntries(outline, limits);
18645
+ const previewHeader = "Large string previews (size-limited):";
18646
+ const renderedOutline = selectOutlineEntries(outline, limits);
18647
+ const withPreviewHeader = appendWithinBudget(renderedOutline, previewHeader, limits);
18648
+ if (!withPreviewHeader) return renderedOutline;
18649
+ let rendered = withPreviewHeader;
18650
+ let renderedPreviews = 0;
18651
+ let omittedPreviews = 0;
18652
+ for (let index = 0; index < previews.length; index++) {
18653
+ const remainingCount = previews.length - index;
18654
+ const remainingTokens = Math.max(0, limits.maxTokens - (0, tokenx.estimateTokenCount)(rendered));
18655
+ const remainingCharacters = Math.max(0, limits.maxCharacters - rendered.length - 1);
18656
+ const previewLimits = {
18657
+ maxTokens: (0, tokenx.estimateTokenCount)(rendered) + Math.floor(remainingTokens / remainingCount),
18658
+ maxCharacters: rendered.length + 1 + Math.floor(remainingCharacters / remainingCount)
18659
+ };
18660
+ const preview = formatPreview(previews[index].path, previews[index].value, previewLimits, rendered);
18661
+ if (!preview) {
18662
+ omittedPreviews++;
18663
+ continue;
18664
+ }
18665
+ const withPreview = appendWithinBudget(rendered, preview, limits);
18666
+ if (!withPreview) {
18667
+ omittedPreviews++;
18668
+ continue;
18669
+ }
18670
+ rendered = withPreview;
18671
+ renderedPreviews++;
18672
+ }
18673
+ if (renderedPreviews === 0) return renderedOutline;
18674
+ if (omittedPreviews > 0) {
18675
+ const marker = `... [${omittedPreviews} large string ${omittedPreviews === 1 ? "preview" : "previews"} omitted]`;
18676
+ rendered = appendWithinBudget(rendered, marker, limits) ?? rendered;
18677
+ }
18678
+ return rendered;
18679
+ }
18680
+ //#endregion
18329
18681
  //#region src/processors/observational-memory/tool-result-helpers.ts
18330
18682
  const ENCRYPTED_CONTENT_KEY = "encryptedContent";
18331
18683
  const ENCRYPTED_CONTENT_REDACTION_THRESHOLD = 256;
@@ -18404,7 +18756,7 @@ function truncateStringByTokens(text, maxTokens) {
18404
18756
  return best;
18405
18757
  }
18406
18758
  function formatToolResultForObserver(value, options) {
18407
- return truncateStringByTokens(stringifyToolResult(value), options?.maxTokens ?? 1e4);
18759
+ return truncateStringByTokens(stringifyToolResult(value), options?.maxTokens ?? 5e3);
18408
18760
  }
18409
18761
  //#endregion
18410
18762
  //#region src/processors/observational-memory/observer-agent.ts
@@ -19091,9 +19443,52 @@ function getTemporalGapMarkerText(msg) {
19091
19443
  if (metadata?.reminderType === "temporal-gap" && typeof metadata.gapText === "string") return metadata.gapText;
19092
19444
  if (typeof metadata?.systemReminder === "object" && metadata.systemReminder && "type" in metadata.systemReminder && metadata.systemReminder.type === "temporal-gap" && "gapText" in metadata.systemReminder && typeof metadata.systemReminder.gapText === "string") return metadata.systemReminder.gapText;
19093
19445
  }
19094
- function formatObserverMessage(msg, counter, options) {
19446
+ function isCallLikeToolInvocation(invocation) {
19447
+ return invocation.state === "call" || invocation.state === "partial-call" || invocation.state === "approval-requested" || invocation.state === "approval-responded";
19448
+ }
19449
+ function isTerminalToolInvocation(invocation) {
19450
+ return invocation.state === "result" || invocation.state === "output-error" || invocation.state === "output-denied";
19451
+ }
19452
+ function createObserverToolFormattingState(messages) {
19453
+ const exchanges = /* @__PURE__ */ new Map();
19454
+ const occurrences = /* @__PURE__ */ new Map();
19455
+ let occurrence = 0;
19456
+ for (const message of messages) {
19457
+ if (typeof message.content === "string" || !Array.isArray(message.content?.parts)) continue;
19458
+ for (const part of message.content.parts) {
19459
+ if (part.type !== "tool-invocation") continue;
19460
+ const invocation = part.toolInvocation;
19461
+ occurrences.set(part, occurrence);
19462
+ if (!isCallLikeToolInvocation(invocation) && !isTerminalToolInvocation(invocation)) {
19463
+ occurrence++;
19464
+ continue;
19465
+ }
19466
+ const exchange = exchanges.get(invocation.toolCallId) ?? { firstOccurrence: occurrence };
19467
+ if (isCallLikeToolInvocation(invocation) && (invocation.args !== void 0 || exchange.signature === void 0)) exchange.signature = invocation;
19468
+ if (isTerminalToolInvocation(invocation)) exchange.terminal = {
19469
+ ...invocation,
19470
+ occurrence
19471
+ };
19472
+ exchanges.set(invocation.toolCallId, exchange);
19473
+ occurrence++;
19474
+ }
19475
+ }
19476
+ for (const exchange of exchanges.values()) if (exchange.terminal?.args !== void 0) exchange.signature = exchange.terminal;
19477
+ else if (!exchange.signature && exchange.terminal) exchange.signature = exchange.terminal;
19478
+ return {
19479
+ exchanges,
19480
+ occurrences,
19481
+ emittedCalls: /* @__PURE__ */ new Set(),
19482
+ emittedOutcomes: /* @__PURE__ */ new Set()
19483
+ };
19484
+ }
19485
+ function formatObserverToolArguments(args, maxCharacters) {
19486
+ if (args === void 0) return maybeTruncate("[arguments unavailable]", maxCharacters);
19487
+ return formatToolArgumentsForObserver(args, { maxCharacters: maxCharacters || void 0 });
19488
+ }
19489
+ function formatObserverMessage(msg, counter, toolFormatting, options) {
19095
19490
  const maxLen = options?.maxPartLength;
19096
- const maxToolResultTokens = options?.maxToolResultTokens ?? 1e4;
19491
+ const maxToolResultTokens = options?.maxToolResultTokens ?? 5e3;
19097
19492
  const attachmentFilter = options?.attachmentFilter;
19098
19493
  const role = msg.role.charAt(0).toUpperCase() + msg.role.slice(1);
19099
19494
  const attachments = [];
@@ -19120,14 +19515,31 @@ function formatObserverMessage(msg, counter, options) {
19120
19515
  }
19121
19516
  if (part.type === "tool-invocation") {
19122
19517
  const inv = part.toolInvocation;
19518
+ const occurrence = toolFormatting.occurrences.get(part);
19519
+ const exchange = toolFormatting.exchanges.get(inv.toolCallId);
19520
+ if (exchange && occurrence === exchange.firstOccurrence && exchange.signature && !toolFormatting.emittedCalls.has(inv.toolCallId)) {
19521
+ toolFormatting.emittedCalls.add(inv.toolCallId);
19522
+ pushLine(`Tool Call ${exchange.signature.toolName}`, formatObserverToolArguments(exchange.signature.args, maxLen), partCreatedAt);
19523
+ }
19123
19524
  if (inv.state === "result") {
19124
19525
  const { value: resultForObserver } = resolveToolResultValue(part, inv.result);
19125
19526
  const { resultWithoutAttachments, attachments: extractedAttachments } = extractToolResultAttachments(resultForObserver, counter, attachmentFilter);
19126
19527
  if (extractedAttachments.length > 0) attachments.push(...extractedAttachments);
19127
- pushLine(`Tool Result ${inv.toolName}`, maybeTruncate(formatToolResultForObserver(resultWithoutAttachments, { maxTokens: maxToolResultTokens }), maxLen), partCreatedAt);
19528
+ if (exchange?.terminal?.occurrence === occurrence && !toolFormatting.emittedOutcomes.has(inv.toolCallId)) {
19529
+ toolFormatting.emittedOutcomes.add(inv.toolCallId);
19530
+ const hasResult = resultWithoutAttachments !== void 0 && (typeof resultWithoutAttachments !== "string" || resultWithoutAttachments.trim().length > 0);
19531
+ const body = inv.isError ? hasResult ? formatToolResultForObserver(resultWithoutAttachments, { maxTokens: maxToolResultTokens }) : inv.errorText?.trim() ? inv.errorText : "Tool execution failed" : hasResult ? formatToolResultForObserver(resultWithoutAttachments, { maxTokens: maxToolResultTokens }) : "[empty result]";
19532
+ pushLine(`${inv.isError ? "Tool Error" : "Tool Result"} ${inv.toolName}`, maybeTruncate(body, maxLen), partCreatedAt);
19533
+ }
19128
19534
  return;
19129
19535
  }
19130
- pushLine(`Tool Call ${inv.toolName}`, maybeTruncate(JSON.stringify(inv.args, null, 2), maxLen), partCreatedAt);
19536
+ if (exchange?.terminal?.occurrence === occurrence && !toolFormatting.emittedOutcomes.has(inv.toolCallId)) {
19537
+ toolFormatting.emittedOutcomes.add(inv.toolCallId);
19538
+ if (inv.state === "output-error") pushLine(`Tool Error ${inv.toolName}`, maybeTruncate(inv.errorText?.trim() ? inv.errorText : "Tool execution failed", maxLen), partCreatedAt);
19539
+ else if (inv.state === "output-denied") pushLine(`Tool Denied ${inv.toolName}`, maybeTruncate(inv.approval?.reason?.trim() ? inv.approval.reason : "Tool call was not approved by the user", maxLen), partCreatedAt);
19540
+ return;
19541
+ }
19542
+ if (!exchange) pushLine(`Tool Call ${inv.toolName}`, formatObserverToolArguments(inv.args, maxLen), partCreatedAt);
19131
19543
  return;
19132
19544
  }
19133
19545
  const partType = part.type;
@@ -19161,10 +19573,11 @@ function formatMessagesForObserver(messages, options) {
19161
19573
  nextImageId: 1,
19162
19574
  nextFileId: 1
19163
19575
  };
19576
+ const toolFormatting = createObserverToolFormattingState(messages);
19164
19577
  const sections = [];
19165
19578
  let context = {};
19166
19579
  for (const message of messages) {
19167
- const formatted = formatObserverMessage(message, counter, options);
19580
+ const formatted = formatObserverMessage(message, counter, toolFormatting, options);
19168
19581
  if (formatted.lines.length === 0) continue;
19169
19582
  const rendered = formatObserverLines(formatted.lines, context);
19170
19583
  if (!rendered.text) continue;
@@ -19187,13 +19600,14 @@ function buildObserverHistoryMessage(messages, options) {
19187
19600
  nextImageId: 1,
19188
19601
  nextFileId: 1
19189
19602
  };
19603
+ const toolFormatting = createObserverToolFormattingState(messages);
19190
19604
  const content = [{
19191
19605
  type: "text",
19192
19606
  text: "## New Message History to Observe\n\n"
19193
19607
  }];
19194
19608
  let context = {};
19195
19609
  messages.forEach((message) => {
19196
- const formatted = formatObserverMessage(message, counter, options);
19610
+ const formatted = formatObserverMessage(message, counter, toolFormatting, options);
19197
19611
  if (formatted.lines.length === 0 && formatted.attachments.length === 0) return;
19198
19612
  context = appendFormattedObserverMessage(content, formatted, context);
19199
19613
  });
@@ -19221,10 +19635,11 @@ function buildMultiThreadObserverHistoryMessage(messagesByThread, threadOrder, o
19221
19635
  const messages = messagesByThread.get(threadId);
19222
19636
  if (!messages || messages.length === 0) return;
19223
19637
  const threadContent = [];
19638
+ const toolFormatting = createObserverToolFormattingState(messages);
19224
19639
  let context = {};
19225
19640
  let hasVisibleContent = false;
19226
19641
  messages.forEach((message) => {
19227
- const formatted = formatObserverMessage(message, counter, options);
19642
+ const formatted = formatObserverMessage(message, counter, toolFormatting, options);
19228
19643
  if (formatted.lines.length === 0 && formatted.attachments.length === 0) return;
19229
19644
  context = appendFormattedObserverMessage(threadContent, formatted, context);
19230
19645
  hasVisibleContent = true;
@@ -19920,15 +20335,14 @@ var ObserverRunner = class {
19920
20335
  this.mastra = mastra;
19921
20336
  }
19922
20337
  createAgent(model, isMultiThread = false, memory, extractors = this.observationConfig.extractors ?? []) {
19923
- const agent = new _mastra_core_agent.Agent({
20338
+ return new _mastra_core_agent.Agent({
19924
20339
  id: isMultiThread ? "multi-thread-observer" : "observational-memory-observer",
19925
20340
  name: isMultiThread ? "multi-thread-observer" : "Observer",
19926
20341
  instructions: buildObserverSystemPrompt(isMultiThread, this.observationConfig.instruction, this.observationConfig.threadTitle, extractors),
19927
20342
  model,
19928
- ...memory ? { memory } : {}
20343
+ ...memory ? { memory } : {},
20344
+ ...this.mastra ? { mastra: this.mastra } : {}
19929
20345
  });
19930
- if (this.mastra) agent.__registerMastra(this.mastra);
19931
- return agent;
19932
20346
  }
19933
20347
  /**
19934
20348
  * Extract a router-style model ID (`provider/model`) from a model config.
@@ -21574,7 +21988,7 @@ var TokenCounter = class TokenCounter {
21574
21988
  let tokens = 0;
21575
21989
  let overheadDelta = 0;
21576
21990
  if (invocation.toolName) tokens += this.readOrPersistPartEstimate(part, "tool-call-name", invocation.toolName);
21577
- if (invocation.args) if (typeof invocation.args === "string") tokens += this.readOrPersistPartEstimate(part, "tool-call-args", invocation.args);
21991
+ if (invocation.args !== void 0) if (typeof invocation.args === "string") tokens += this.readOrPersistPartEstimate(part, "tool-call-args", invocation.args);
21578
21992
  else {
21579
21993
  const argsJson = JSON.stringify(invocation.args);
21580
21994
  tokens += this.readOrPersistPartEstimate(part, "tool-call-args-json", argsJson);
@@ -21620,8 +22034,11 @@ var TokenCounter = class TokenCounter {
21620
22034
  }
21621
22035
  if (state === "result") {
21622
22036
  extraMessageDelta++;
22037
+ const signature = this.countToolCallSignature(part, invocation);
22038
+ tokens += signature.tokens;
22039
+ overheadDelta += signature.overheadDelta;
21623
22040
  const { value: resultForCounting, usingStoredModelOutput } = this.resolveToolResultForTokenCounting(part, invocation.result);
21624
- if (resultForCounting !== void 0) {
22041
+ if (resultForCounting !== void 0 && (typeof resultForCounting !== "string" || resultForCounting.trim().length > 0)) {
21625
22042
  const contentTokens = this.countMultimodalToolResultContent(part, resultForCounting);
21626
22043
  if (contentTokens !== void 0) tokens += contentTokens;
21627
22044
  else {
@@ -21629,6 +22046,9 @@ var TokenCounter = class TokenCounter {
21629
22046
  tokens += this.readOrPersistPartEstimate(part, usingStoredModelOutput ? "tool-result-model-output-json" : "tool-result-json", formattedResult);
21630
22047
  }
21631
22048
  if (typeof resultForCounting !== "string") overheadDelta -= 12;
22049
+ } else {
22050
+ const fallback = invocation.isError ? invocation.errorText?.trim() ? invocation.errorText : "Tool execution failed" : "[empty result]";
22051
+ tokens += this.readOrPersistPartEstimate(part, invocation.isError ? "tool-result-error" : "tool-result-json", fallback);
21632
22052
  }
21633
22053
  return {
21634
22054
  tokens,
@@ -21638,7 +22058,10 @@ var TokenCounter = class TokenCounter {
21638
22058
  }
21639
22059
  if (state === "output-denied") {
21640
22060
  extraMessageDelta++;
21641
- const reason = invocation.approval?.reason ?? "Tool call was not approved by the user";
22061
+ const signature = this.countToolCallSignature(part, invocation);
22062
+ tokens += signature.tokens;
22063
+ overheadDelta += signature.overheadDelta;
22064
+ const reason = invocation.approval?.reason?.trim() ? invocation.approval.reason : "Tool call was not approved by the user";
21642
22065
  tokens += this.readOrPersistPartEstimate(part, "tool-result-denied", reason);
21643
22066
  return {
21644
22067
  tokens,
@@ -21648,7 +22071,10 @@ var TokenCounter = class TokenCounter {
21648
22071
  }
21649
22072
  if (state === "output-error") {
21650
22073
  extraMessageDelta++;
21651
- const errorMessage = typeof invocation.errorText === "string" ? invocation.errorText : "Tool execution failed";
22074
+ const signature = this.countToolCallSignature(part, invocation);
22075
+ tokens += signature.tokens;
22076
+ overheadDelta += signature.overheadDelta;
22077
+ const errorMessage = invocation.errorText?.trim() ? invocation.errorText : "Tool execution failed";
21652
22078
  tokens += this.readOrPersistPartEstimate(part, "tool-result-error", errorMessage);
21653
22079
  return {
21654
22080
  tokens,
@@ -21675,7 +22101,12 @@ var TokenCounter = class TokenCounter {
21675
22101
  };
21676
22102
  }
21677
22103
  /**
21678
- * Count tokens in a single message
22104
+ * Count tokens in a single message.
22105
+ *
22106
+ * Canonical terminal invocations carry their call signature and outcome in one part. Legacy or
22107
+ * foreign histories may instead repeat the same signature across separate call and result
22108
+ * messages; those signatures are intentionally counted once per message because this API has no
22109
+ * sequence context. The conservative overcount can activate observation earlier, never later.
21679
22110
  */
21680
22111
  countMessage(message) {
21681
22112
  let payloadTokens = this.countString(message.role);
@@ -24465,6 +24896,23 @@ var ObservationStrategy = class ObservationStrategy {
24465
24896
  }
24466
24897
  };
24467
24898
  //#endregion
24899
+ //#region src/processors/observational-memory/observation-strategies/thread-title.ts
24900
+ /**
24901
+ * Resolve the thread title an Observational Memory cycle should persist.
24902
+ *
24903
+ * Returns the trimmed candidate when it is a new, long-enough title, or
24904
+ * `undefined` when the current title must stay — including when the user
24905
+ * pinned it via `session.thread.rename()`, which sets the
24906
+ * `titlePinned` thread metadata flag.
24907
+ */
24908
+ function resolveThreadTitleUpdate(thread, generatedTitle) {
24909
+ const candidate = generatedTitle?.trim();
24910
+ if (!candidate || candidate.length < 3) return void 0;
24911
+ if ((0, _mastra_core_memory.isThreadTitlePinned)(thread?.metadata)) return void 0;
24912
+ if (candidate === thread?.title?.trim()) return void 0;
24913
+ return candidate;
24914
+ }
24915
+ //#endregion
24468
24916
  //#region src/processors/observational-memory/observation-strategies/sync.ts
24469
24917
  var SyncObservationStrategy = class extends ObservationStrategy {
24470
24918
  startedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -24617,8 +25065,8 @@ var SyncObservationStrategy = class extends ObservationStrategy {
24617
25065
  let threadUpdateMarker;
24618
25066
  if (thread) {
24619
25067
  const oldTitle = thread.title?.trim();
24620
- const newTitle = processed.threadTitle?.trim();
24621
- const shouldUpdateThreadTitle = !!newTitle && newTitle.length >= 3 && newTitle !== oldTitle;
25068
+ const newTitle = resolveThreadTitleUpdate(thread, processed.threadTitle);
25069
+ const shouldUpdateThreadTitle = newTitle !== void 0;
24622
25070
  const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
24623
25071
  const metadataUpdate = buildThreadMetadataFromExtractedValues(processed.extractors ?? this.observationConfig.extractors, processed.extractedValues);
24624
25072
  const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
@@ -24817,13 +25265,14 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
24817
25265
  abortSignal: this.opts.abortSignal
24818
25266
  });
24819
25267
  await this.indexObservationGroups(processed.observations, threadId, resourceId, processed.lastObservedAt);
24820
- const newTitle = processed.threadTitle?.trim();
24821
- const hasValidThreadTitle = !!newTitle && newTitle.length >= 3;
25268
+ const candidateTitle = processed.threadTitle?.trim();
25269
+ const hasValidThreadTitle = !!candidateTitle && candidateTitle.length >= 3;
24822
25270
  if (hasValidThreadTitle || processed.extractedValues) {
24823
25271
  const thread = await this.storage.getThreadById({ threadId });
24824
25272
  if (thread) {
24825
25273
  const oldTitle = thread.title?.trim();
24826
- const shouldUpdateThreadTitle = hasValidThreadTitle && newTitle !== oldTitle;
25274
+ const newTitle = resolveThreadTitleUpdate(thread, candidateTitle);
25275
+ const shouldUpdateThreadTitle = newTitle !== void 0;
24827
25276
  const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
24828
25277
  const metadataUpdate = buildThreadMetadataFromExtractedValues(processed.extractors ?? this.observationConfig.extractors, processed.extractedValues);
24829
25278
  const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
@@ -25180,8 +25629,8 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
25180
25629
  const thread = await this.storage.getThreadById({ threadId: update.threadId });
25181
25630
  if (thread) {
25182
25631
  const oldTitle = thread.title?.trim();
25183
- const newTitle = update.threadTitle?.trim();
25184
- const shouldUpdateThreadTitle = !!newTitle && newTitle.length >= 3 && newTitle !== oldTitle;
25632
+ const newTitle = resolveThreadTitleUpdate(thread, update.threadTitle);
25633
+ const shouldUpdateThreadTitle = newTitle !== void 0;
25185
25634
  const previousOmMetadata = (0, _mastra_core_memory.getThreadOMMetadata)(thread.metadata);
25186
25635
  const metadataUpdate = buildThreadMetadataFromExtractedValues(update.extractors ?? this.observationConfig.extractors, update.extracted);
25187
25636
  const newMetadata = (0, _mastra_core_memory.setThreadOMMetadata)(thread.metadata, {
@@ -26331,15 +26780,14 @@ var ReflectorRunner = class {
26331
26780
  this.mastra = mastra;
26332
26781
  }
26333
26782
  createAgent(model, memory, extractors = this.reflectionConfig.extractors) {
26334
- const agent = new _mastra_core_agent.Agent({
26783
+ return new _mastra_core_agent.Agent({
26335
26784
  id: "observational-memory-reflector",
26336
26785
  name: "Reflector",
26337
26786
  instructions: buildReflectorSystemPrompt(this.reflectionConfig.instruction, extractors),
26338
26787
  model,
26339
- ...memory ? { memory } : {}
26788
+ ...memory ? { memory } : {},
26789
+ ...this.mastra ? { mastra: this.mastra } : {}
26340
26790
  });
26341
- if (this.mastra) agent.__registerMastra(this.mastra);
26342
- return agent;
26343
26791
  }
26344
26792
  getObservationMarkerConfig(record) {
26345
26793
  return {
@@ -29385,9 +29833,8 @@ ${formattedMessages}
29385
29833
  currentTask: lastActivated.currentTask,
29386
29834
  threadTitle: chunkThreadTitle
29387
29835
  });
29388
- const oldTitle = thread.title?.trim();
29389
- const newTitle = chunkThreadTitle?.trim();
29390
- const shouldUpdateThreadTitle = !!newTitle && newTitle.length >= 3 && newTitle !== oldTitle;
29836
+ const newTitle = resolveThreadTitleUpdate(thread, chunkThreadTitle);
29837
+ const shouldUpdateThreadTitle = newTitle !== void 0;
29391
29838
  await this.storage.patchThread({
29392
29839
  id: threadId,
29393
29840
  ...shouldUpdateThreadTitle ? { title: newTitle } : {},
@@ -30390,6 +30837,9 @@ const DEFAULT_EMBEDDING_CACHE_MAX_SIZE = 1e3;
30390
30837
  * if packaged docs are unavailable.
30391
30838
  */
30392
30839
  var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30840
+ createMemoryTokenCounter() {
30841
+ return new TokenCounter();
30842
+ }
30393
30843
  _omEngine;
30394
30844
  _omEngineInstance;
30395
30845
  _mastraInstance;
@@ -30560,6 +31010,7 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30560
31010
  const thread = await this.getThreadById({ threadId });
30561
31011
  if (!thread && !resourceScope) throw new Error(`No thread found with id ${threadId}`);
30562
31012
  if (thread && thread.resourceId !== resourceId) throw new Error(`Thread with id ${threadId} is for resource with id ${thread.resourceId} but resource ${resourceId} was queried.`);
31013
+ return thread;
30563
31014
  }
30564
31015
  createMemorySpan(operationType, observabilityContext, input, attributes) {
30565
31016
  const currentSpan = observabilityContext?.tracingContext?.currentSpan;
@@ -30580,6 +31031,9 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30580
31031
  const { threadId, resourceId, perPage: perPageArg, page, orderBy, threadConfig, vectorSearchString, includeSystemReminders, hideSignals, filter, includeTotal } = args;
30581
31032
  const config = this.getMergedThreadConfig(threadConfig || {});
30582
31033
  const semanticRecallEnabled = Boolean(config.semanticRecall);
31034
+ const history = (0, _mastra_core_memory.normalizeMessageHistoryConfig)(config.lastMessages, config.messageHistory);
31035
+ const historyDisabledByConfig = !history.enabled && perPageArg === void 0;
31036
+ const shouldUseTokenLoader = perPageArg === void 0 && history.enabled && history.maxTokens !== void 0;
30583
31037
  const span = this.createMemorySpan("recall", args.observabilityContext, {
30584
31038
  threadId,
30585
31039
  resourceId,
@@ -30589,9 +31043,23 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30589
31043
  lastMessages: config.lastMessages
30590
31044
  });
30591
31045
  try {
30592
- if (resourceId) await this.validateThreadIsOwnedByResource(threadId, resourceId, config);
30593
- const perPage = perPageArg !== void 0 ? perPageArg : config.lastMessages;
30594
- const historyDisabledByConfig = config.lastMessages === false && perPageArg === void 0;
31046
+ if (historyDisabledByConfig && (!config.semanticRecall || !vectorSearchString || !this.vector)) {
31047
+ const result = {
31048
+ messages: [],
31049
+ usage: void 0,
31050
+ total: 0,
31051
+ page: page ?? 0,
31052
+ perPage: 0,
31053
+ hasMore: false
31054
+ };
31055
+ span?.end({
31056
+ output: { success: true },
31057
+ attributes: { messageCount: 0 }
31058
+ });
31059
+ return result;
31060
+ }
31061
+ const validatedThread = resourceId ? await this.validateThreadIsOwnedByResource(threadId, resourceId, config) : void 0;
31062
+ const perPage = perPageArg !== void 0 ? perPageArg : history.maxMessages ?? 0;
30595
31063
  const shouldGetNewestAndReverse = !orderBy && perPage !== false;
30596
31064
  const effectiveOrderBy = shouldGetNewestAndReverse ? {
30597
31065
  field: "createdAt",
@@ -30620,21 +31088,6 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30620
31088
  const resourceScope = typeof config?.semanticRecall === "object" && config?.semanticRecall?.scope !== `thread` || config.semanticRecall === true;
30621
31089
  if (resourceScope && !resourceId && config?.semanticRecall && vectorSearchString) throw new Error("Memory error: Resource-scoped semantic recall is enabled but no resourceId was provided. Either provide a resourceId or explicitly set semanticRecall.scope to 'thread'.");
30622
31090
  let usage;
30623
- if (historyDisabledByConfig && (!config.semanticRecall || !vectorSearchString || !this.vector)) {
30624
- const result = {
30625
- messages: [],
30626
- usage: void 0,
30627
- total: 0,
30628
- page: page ?? 0,
30629
- perPage: 0,
30630
- hasMore: false
30631
- };
30632
- span?.end({
30633
- output: { success: true },
30634
- attributes: { messageCount: 0 }
30635
- });
30636
- return result;
30637
- }
30638
31091
  if (config?.semanticRecall && vectorSearchString && this.vector) {
30639
31092
  const result = await this.embedMessageContent(vectorSearchString);
30640
31093
  usage = result.usage;
@@ -30656,28 +31109,71 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30656
31109
  const threshold = (typeof config.semanticRecall === "object" ? config.semanticRecall : void 0)?.threshold;
30657
31110
  const filteredVectorResults = threshold !== void 0 ? vectorResults.filter((r) => r.score >= threshold) : vectorResults;
30658
31111
  const memoryStore = await this.getMemoryStore();
30659
- const effectivePerPage = historyDisabledByConfig ? 0 : perPage;
30660
- const paginatedResult = await memoryStore.listMessages({
30661
- threadId,
30662
- resourceId,
30663
- perPage: effectivePerPage,
30664
- page,
30665
- orderBy: effectiveOrderBy,
30666
- filter,
30667
- ...includeTotal !== void 0 ? { includeTotal } : {},
30668
- ...filteredVectorResults?.length ? { include: filteredVectorResults.map((r) => ({
30669
- id: r.metadata?.message_id,
30670
- threadId: r.metadata?.thread_id,
30671
- withNextMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.after,
30672
- withPreviousMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.before
30673
- })) } : {}
30674
- });
30675
- const rawMessages = shouldGetNewestAndReverse ? paginatedResult.messages.reverse() : paginatedResult.messages;
31112
+ const include = filteredVectorResults.map((r) => ({
31113
+ id: r.metadata?.message_id,
31114
+ threadId: r.metadata?.thread_id,
31115
+ withNextMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.after,
31116
+ withPreviousMessages: typeof vectorConfig.messageRange === "number" ? vectorConfig.messageRange : vectorConfig.messageRange.before
31117
+ }));
31118
+ let rawMessages;
31119
+ let resultPage;
31120
+ let resultPerPage;
31121
+ let total;
31122
+ let hasMore;
31123
+ if (shouldUseTokenLoader) {
31124
+ const storedBoundary = (0, _mastra_core_memory.getMemoryTokenBoundary)(validatedThread ?? await memoryStore.getThreadById({
31125
+ threadId,
31126
+ resourceId
31127
+ }));
31128
+ const boundary = storedBoundary !== void 0 && storedBoundary.maxTokens === history.maxTokens && storedBoundary.atMaxRemoveTokens === history.atMaxRemoveTokens ? storedBoundary : void 0;
31129
+ rawMessages = (await (0, _mastra_core_memory.loadMessageHistory)({
31130
+ storage: memoryStore,
31131
+ threadId,
31132
+ resourceId,
31133
+ boundary,
31134
+ filter,
31135
+ maxMessages: history.maxMessages,
31136
+ maxTokens: history.maxTokens,
31137
+ atMaxRemoveTokens: history.atMaxRemoveTokens,
31138
+ tokenCounter: new TokenCounter(),
31139
+ initialTokens: 24
31140
+ })).messages;
31141
+ if (include.length) {
31142
+ const semanticMessages = await memoryStore.listMessages({
31143
+ threadId,
31144
+ resourceId,
31145
+ perPage: 0,
31146
+ include,
31147
+ includeTotal: false
31148
+ });
31149
+ rawMessages = new _mastra_core_agent.MessageList({
31150
+ threadId,
31151
+ resourceId
31152
+ }).add(rawMessages, "memory").add(semanticMessages.messages.filter((message) => !boundary || (0, _mastra_core_memory.isAfterMemoryTokenBoundary)(message, boundary)), "memory").get.all.db();
31153
+ }
31154
+ resultPage = 0;
31155
+ resultPerPage = history.maxMessages ?? false;
31156
+ total = rawMessages.length;
31157
+ hasMore = false;
31158
+ } else {
31159
+ const effectivePerPage = historyDisabledByConfig ? 0 : perPage;
31160
+ const paginatedResult = await memoryStore.listMessages({
31161
+ threadId,
31162
+ resourceId,
31163
+ perPage: effectivePerPage,
31164
+ page,
31165
+ orderBy: effectiveOrderBy,
31166
+ filter,
31167
+ ...includeTotal !== void 0 ? { includeTotal } : {},
31168
+ ...include.length ? { include } : {}
31169
+ });
31170
+ rawMessages = shouldGetNewestAndReverse ? paginatedResult.messages.reverse() : paginatedResult.messages;
31171
+ ({total, page: resultPage, perPage: resultPerPage, hasMore} = paginatedResult);
31172
+ }
30676
31173
  const messages = filterSystemReminderMessages(new _mastra_core_agent.MessageList({
30677
31174
  threadId,
30678
31175
  resourceId
30679
31176
  }).add(rawMessages, "memory").get.all.db(), includeSystemReminders, hideSignals);
30680
- const { total, page: resultPage, perPage: resultPerPage, hasMore } = paginatedResult;
30681
31177
  const recallResult = {
30682
31178
  messages,
30683
31179
  usage,
@@ -30730,6 +31226,13 @@ var Memory = class Memory extends _mastra_core_memory.MastraMemory {
30730
31226
  });
30731
31227
  return savedThread;
30732
31228
  }
31229
+ /**
31230
+ * Update a thread's title or metadata.
31231
+ *
31232
+ * Unlike `session.thread.rename()`, this does not pin the title, so
31233
+ * Observational Memory may still replace it with an extracted title. To
31234
+ * protect a manual rename, set `metadata.titlePinned` to `true`.
31235
+ */
30733
31236
  async updateThread({ id, title, metadata, memoryConfig }) {
30734
31237
  const updatedThread = await (await this.getMemoryStore()).patchThread({
30735
31238
  id,
@@ -31298,16 +31801,52 @@ ${workingMemory}`;
31298
31801
  messages = runState ? await runState.load(`observational-memory:messages:thread:${threadId}:${boundary}`, loadMessages) : await loadMessages();
31299
31802
  }
31300
31803
  } else {
31301
- const lastMessages = config.lastMessages;
31302
- if (lastMessages === false) messages = [];
31303
- else messages = (await memoryStore.listMessages({
31804
+ const lastMessages = (0, _mastra_core_memory.normalizeMessageHistoryConfig)(config.lastMessages, config.messageHistory);
31805
+ if (!lastMessages.enabled) messages = [];
31806
+ else if (lastMessages.maxTokens !== void 0) {
31807
+ const storedBoundary = (0, _mastra_core_memory.getMemoryTokenBoundary)(await memoryStore.getThreadById({
31808
+ threadId,
31809
+ resourceId
31810
+ }));
31811
+ const boundary = storedBoundary?.maxTokens === lastMessages.maxTokens && storedBoundary.atMaxRemoveTokens === lastMessages.atMaxRemoveTokens ? storedBoundary : void 0;
31812
+ const tokenCounter = this.createMemoryTokenCounter();
31813
+ const loaded = await (0, _mastra_core_memory.loadMessageHistory)({
31814
+ storage: memoryStore,
31815
+ threadId,
31816
+ resourceId,
31817
+ boundary,
31818
+ maxMessages: lastMessages.maxMessages,
31819
+ maxTokens: lastMessages.maxTokens,
31820
+ tokenCounter,
31821
+ initialTokens: 24
31822
+ });
31823
+ const messageList = new _mastra_core_agent.MessageList();
31824
+ messageList.add(loaded.messages, "memory");
31825
+ if (systemParts.length) messageList.addSystem(systemParts.join("\n\n"));
31826
+ await new _mastra_core_processors.TokenLimiterProcessor({
31827
+ limit: lastMessages.maxTokens,
31828
+ atMaxRemoveTokens: lastMessages.atMaxRemoveTokens,
31829
+ trimMode: "memory-only",
31830
+ tokenCounter
31831
+ }).processInput({
31832
+ messageList,
31833
+ messages: messageList.get.all.db(),
31834
+ systemMessages: messageList.getAllSystemMessages(),
31835
+ state: {},
31836
+ retryCount: 0,
31837
+ abort: (reason) => {
31838
+ throw new Error(reason);
31839
+ }
31840
+ });
31841
+ messages = messageList.get.all.db();
31842
+ } else messages = (await memoryStore.listMessages({
31304
31843
  threadId,
31305
31844
  resourceId,
31306
31845
  orderBy: {
31307
31846
  field: "createdAt",
31308
31847
  direction: "DESC"
31309
31848
  },
31310
- perPage: typeof lastMessages === "number" ? lastMessages : void 0,
31849
+ perPage: lastMessages.maxMessages,
31311
31850
  includeTotal: false
31312
31851
  })).messages.reverse();
31313
31852
  }
@@ -32730,4 +33269,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
32730
33269
  }
32731
33270
  });
32732
33271
 
32733
- //# sourceMappingURL=src-oL_dDHN9.cjs.map
33272
+ //# sourceMappingURL=src-BCvV2aGL.cjs.map