@mastra/memory 1.26.2 → 1.27.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.
Files changed (33) hide show
  1. package/CHANGELOG.md +45 -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-agents-agent-approval.md +2 -0
  5. package/dist/docs/references/integrations-databases-postgresql.md +2 -1
  6. package/dist/docs/references/reference-memory-observational-memory.md +4 -0
  7. package/dist/index.cjs +1 -1
  8. package/dist/index.js +1 -1
  9. package/dist/processors/index.cjs +1 -1
  10. package/dist/processors/index.js +1 -1
  11. package/dist/processors/observational-memory/built-in-extractors.d.ts +13 -4
  12. package/dist/processors/observational-memory/built-in-extractors.d.ts.map +1 -1
  13. package/dist/processors/observational-memory/index.d.ts +1 -1
  14. package/dist/processors/observational-memory/index.d.ts.map +1 -1
  15. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  16. package/dist/processors/observational-memory/observation-turn/turn.d.ts +4 -0
  17. package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
  18. package/dist/processors/observational-memory/observational-memory.d.ts +5 -1
  19. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  20. package/dist/processors/observational-memory/observer-agent.d.ts +13 -0
  21. package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
  22. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/reflector-agent.d.ts +1 -0
  24. package/dist/processors/observational-memory/reflector-agent.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/token-counter.d.ts +1 -0
  26. package/dist/processors/observational-memory/token-counter.d.ts.map +1 -1
  27. package/dist/processors/observational-memory/types.d.ts +29 -0
  28. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  29. package/dist/{src-BYD6Wp5m.js → src-BUlG9vaB.js} +155 -59
  30. package/dist/{src-BYD6Wp5m.js.map → src-BUlG9vaB.js.map} +1 -1
  31. package/dist/{src-b5E69E65.cjs → src-MvtBOFYO.cjs} +155 -59
  32. package/dist/{src-b5E69E65.cjs.map → src-MvtBOFYO.cjs.map} +1 -1
  33. package/package.json +3 -3
@@ -15946,21 +15946,17 @@ Or as a standalone observation when closing out a broader task:
15946
15946
  Completion observations should be terse but specific about WHAT was completed.
15947
15947
  Prefer concrete resolved outcomes over abstract workflow status so the assistant remembers what is already done.`;
15948
15948
  buildObserverOutputFormat();
15949
- function buildObserverOutputFormat(extractors = []) {
15950
- const extractorSections = buildExtractorOutputSections(extractors);
15951
- const legacyContinuationSections = extractors.length === 0 ? `
15952
- <current-task>
15953
- State the current task(s) explicitly:
15954
- - Primary: What the agent is currently working on
15955
- - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
15956
- </current-task>
15957
-
15958
- <suggested-response>
15959
- Hint for the agent's immediate next message. Examples:
15960
- - "I've updated the navigation model. Let me walk you through the changes..."
15961
- - "The assistant should wait for the user to respond before continuing."
15962
- - Call the view tool on src/example.ts to continue debugging.
15963
- </suggested-response>` : "";
15949
+ /**
15950
+ * Build the Observer's output format.
15951
+ *
15952
+ * `extractors` distinguishes two cases that both look empty:
15953
+ * - `undefined` — the no-arg call behind the exported defaults (OBSERVER_OUTPUT_FORMAT_BASE,
15954
+ * OBSERVER_SYSTEM_PROMPT, REFLECTOR_SYSTEM_PROMPT), which keep describing both built-in
15955
+ * sections with their historical text. Runtime callers always pass the composed list.
15956
+ * - `[]` — the caller composed extractors and every section was disabled, so no continuation
15957
+ * sections are described at all.
15958
+ */
15959
+ function buildObserverOutputFormat(extractors) {
15964
15960
  return `Use priority levels:
15965
15961
  - 🔴 High: explicit user facts, preferences, unresolved goals, critical context
15966
15962
  - 🟡 Medium: project details, learned information, tool results
@@ -15986,7 +15982,19 @@ Date: Dec 5, 2025
15986
15982
  * 🔴 (09:15) Continued work on feature X
15987
15983
  </observations>
15988
15984
 
15989
- ${extractorSections || legacyContinuationSections}`;
15985
+ ${buildExtractorOutputSections(extractors ?? []) || (extractors === void 0 ? `
15986
+ <current-task>
15987
+ State the current task(s) explicitly:
15988
+ - Primary: What the agent is currently working on
15989
+ - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
15990
+ </current-task>
15991
+
15992
+ <suggested-response>
15993
+ Hint for the agent's immediate next message. Examples:
15994
+ - "I've updated the navigation model. Let me walk you through the changes..."
15995
+ - "The assistant should wait for the user to respond before continuing."
15996
+ - Call the view tool on src/example.ts to continue debugging.
15997
+ </suggested-response>` : "")}`;
15990
15998
  }
15991
15999
  /**
15992
16000
  * The guidelines for the Observer.
@@ -16013,10 +16021,22 @@ const OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
16013
16021
  * Build the complete observer system prompt.
16014
16022
  * @param multiThread - Whether this is for multi-thread batched observation (default: false)
16015
16023
  * @param instruction - Optional custom instructions to append to the prompt
16024
+ * @param includeThreadTitle - Whether the Observer should also produce a thread title
16025
+ * @param extractors - Active extractors, used to decide which sections the prompt describes.
16026
+ * Omitted only by the exported no-arg defaults; pass `[]` to describe no continuation sections at all.
16016
16027
  */
16017
- function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors = []) {
16028
+ function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors) {
16018
16029
  const outputFormat = buildObserverOutputFormat(extractors);
16019
- const multiThreadTitleInstruction = includeThreadTitle ? ` Each thread's observations, current-task, suggested-response, and thread-title should be nested inside a <thread id="..."> block within <observations>.` : ` Each thread's observations, current-task, and suggested-response should be nested inside a <thread id="..."> block within <observations>.`;
16030
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
16031
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
16032
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
16033
+ const multiThreadSections = [
16034
+ "observations",
16035
+ ...currentTaskEnabled ? ["current-task"] : [],
16036
+ ...suggestedResponseEnabled ? ["suggested-response"] : [],
16037
+ ...includeThreadTitle ? ["thread-title"] : []
16038
+ ];
16039
+ const multiThreadTitleInstruction = ` Each thread's ${multiThreadSections.length <= 2 ? multiThreadSections.join(" and ") : `${multiThreadSections.slice(0, -1).join(", ")}, and ${multiThreadSections[multiThreadSections.length - 1]}`} should be nested inside a <thread id="..."> block within <observations>.`;
16020
16040
  const multiThreadTitleExample = includeThreadTitle ? `
16021
16041
  <thread-title>Feature X implementation</thread-title>` : "";
16022
16042
  const multiThreadSecondTitleExample = includeThreadTitle ? `
@@ -16046,28 +16066,28 @@ For multi-thread output, wrap each thread's observations like this:
16046
16066
  <thread id="thread_id_1">
16047
16067
  Date: Dec 4, 2025
16048
16068
  * 🔴 (14:30) User prefers direct answers
16049
- * 🔴 (14:31) Working on feature X
16069
+ * 🔴 (14:31) Working on feature X${currentTaskEnabled ? `
16050
16070
 
16051
16071
  <current-task>
16052
16072
  What the agent is currently working on in this thread
16053
- </current-task>
16073
+ </current-task>` : ""}${suggestedResponseEnabled ? `
16054
16074
 
16055
16075
  <suggested-response>
16056
16076
  Hint for the agent's next message in this thread
16057
- </suggested-response>${multiThreadTitleExample}
16077
+ </suggested-response>` : ""}${multiThreadTitleExample}
16058
16078
  </thread>
16059
16079
 
16060
16080
  <thread id="thread_id_2">
16061
16081
  Date: Dec 5, 2025
16062
- * 🔴 (09:15) User asked about deployment
16082
+ * 🔴 (09:15) User asked about deployment${currentTaskEnabled ? `
16063
16083
 
16064
16084
  <current-task>
16065
16085
  Current task for this thread
16066
- </current-task>
16086
+ </current-task>` : ""}${suggestedResponseEnabled ? `
16067
16087
 
16068
16088
  <suggested-response>
16069
16089
  Suggested response for this thread
16070
- </suggested-response>${multiThreadSecondTitleExample}
16090
+ </suggested-response>` : ""}${multiThreadSecondTitleExample}
16071
16091
  </thread>
16072
16092
  </observations>
16073
16093
 
@@ -16077,7 +16097,7 @@ ${OBSERVER_GUIDELINES}
16077
16097
 
16078
16098
  Remember: These observations are the assistant's ONLY memory. Make them count.
16079
16099
 
16080
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
16100
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${customInstructions}`;
16081
16101
  return `You are the memory consciousness of an AI assistant. Your observations will be the ONLY information the assistant has about past interactions with this user.
16082
16102
 
16083
16103
  Extract observations that will help the assistant remember:
@@ -16102,7 +16122,7 @@ Simply output your observations without any thread-related markup.
16102
16122
 
16103
16123
  Remember: These observations are the assistant's ONLY memory. Make them count.
16104
16124
 
16105
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority. If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
16125
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${suggestedResponseEnabled ? " If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks." : ""}${customInstructions}`;
16106
16126
  }
16107
16127
  /**
16108
16128
  * Observer Agent System Prompt (default - for backwards compatibility)
@@ -16794,7 +16814,7 @@ function optimizeObservationsForContext(observations) {
16794
16814
  let optimized = stripEphemeralAnchorIds(observations);
16795
16815
  optimized = optimized.replace(/🟡\s*/g, "");
16796
16816
  optimized = optimized.replace(/🟢\s*/g, "");
16797
- optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\]/g, "");
16817
+ optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\](?!\()/g, "");
16798
16818
  optimized = optimized.replace(/\s*->\s*/g, " ");
16799
16819
  optimized = optimized.replace(/ +/g, " ");
16800
16820
  optimized = optimized.replace(/\n{3,}/g, "\n\n");
@@ -18216,6 +18236,7 @@ var TokenCounter = class TokenCounter {
18216
18236
  defaultModelContext;
18217
18237
  modelContextStorage = new async_hooks.AsyncLocalStorage();
18218
18238
  inFlightAttachmentCounts = /* @__PURE__ */ new Map();
18239
+ multimodalToolResultCounts = /* @__PURE__ */ new WeakMap();
18219
18240
  static TOKENS_PER_MESSAGE = 3.8;
18220
18241
  static TOKENS_PER_CONVERSATION = 24;
18221
18242
  constructor(options) {
@@ -18278,6 +18299,9 @@ var TokenCounter = class TokenCounter {
18278
18299
  }
18279
18300
  countMultimodalToolResultContent(part, toolResult) {
18280
18301
  if (!toolResult || typeof toolResult !== "object") return;
18302
+ const resultKey = buildEstimateKey("tool-result-multimodal-content-source", JSON.stringify(toolResult));
18303
+ const cached = this.multimodalToolResultCounts.get(part);
18304
+ if (cached?.resultKey === resultKey) return cached.tokens;
18281
18305
  const output = toolResult;
18282
18306
  const content = output.type === "content" && Array.isArray(output.value) ? output.value : output.content;
18283
18307
  if (!Array.isArray(content)) return;
@@ -18389,10 +18413,15 @@ var TokenCounter = class TokenCounter {
18389
18413
  countJsonContentPart(contentPart);
18390
18414
  }
18391
18415
  if (!hasAttachment) return;
18392
- return this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
18416
+ const estimate = this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
18393
18417
  type: "content",
18394
18418
  value: cacheParts
18395
18419
  }), tokens);
18420
+ this.multimodalToolResultCounts.set(part, {
18421
+ resultKey,
18422
+ tokens: estimate
18423
+ });
18424
+ return estimate;
18396
18425
  }
18397
18426
  estimateImageAssetTokens(part, asset, kind) {
18398
18427
  const modelContext = this.getModelContext();
@@ -20379,23 +20408,43 @@ function createThreadTitleExtractor() {
20379
20408
  metadataKeyPath: "threadTitle"
20380
20409
  }, true);
20381
20410
  }
20411
+ /**
20412
+ * Normalize the user-facing `continuationHints` config into explicit per-section flags.
20413
+ * Both sections stay enabled unless the caller opts out, so omitting the config is a no-op.
20414
+ */
20415
+ function resolveContinuationHints(config) {
20416
+ if (config === void 0 || config === true) return {
20417
+ currentTask: true,
20418
+ suggestedResponse: true
20419
+ };
20420
+ if (config === false) return {
20421
+ currentTask: false,
20422
+ suggestedResponse: false
20423
+ };
20424
+ return {
20425
+ currentTask: config.currentTask ?? true,
20426
+ suggestedResponse: config.suggestedResponse ?? true
20427
+ };
20428
+ }
20382
20429
  function composeExtractors(options) {
20430
+ const continuationHints = resolveContinuationHints(options.continuationHints);
20383
20431
  const extractors = [];
20384
- if (options.includeContinuationHints) extractors.push(createCurrentTaskExtractor(), createSuggestedResponseExtractor());
20432
+ if (continuationHints.currentTask) extractors.push(createCurrentTaskExtractor());
20433
+ if (continuationHints.suggestedResponse) extractors.push(createSuggestedResponseExtractor());
20385
20434
  if (options.includeThreadTitle) extractors.push(createThreadTitleExtractor());
20386
20435
  extractors.push(...options.userExtractors ?? []);
20387
20436
  return validateExtractorList(extractors);
20388
20437
  }
20389
20438
  function composeObservationExtractors(config) {
20390
20439
  return composeExtractors({
20391
- includeContinuationHints: true,
20440
+ continuationHints: config.continuationHints,
20392
20441
  includeThreadTitle: config.threadTitle,
20393
20442
  userExtractors: config.extract
20394
20443
  });
20395
20444
  }
20396
20445
  function composeReflectionExtractors(config) {
20397
20446
  return composeExtractors({
20398
- includeContinuationHints: true,
20447
+ continuationHints: config.continuationHints,
20399
20448
  userExtractors: config.extract
20400
20449
  });
20401
20450
  }
@@ -22180,10 +22229,12 @@ var ObservationStep = class {
22180
22229
  resourceId,
22181
22230
  checkThreshold: true,
22182
22231
  messages: step0Messages,
22232
+ record: this.turn.record,
22183
22233
  currentModel: this.turn.actorModelContext,
22184
22234
  writer: this.turn.writer,
22185
22235
  messageList
22186
22236
  });
22237
+ this.turn.setRecord(activation.record);
22187
22238
  if (activation.activated) {
22188
22239
  activated = true;
22189
22240
  if (activation.activatedMessageIds?.length) messageList.removeByIds(activation.activatedMessageIds);
@@ -22225,6 +22276,7 @@ var ObservationStep = class {
22225
22276
  let statusSnapshot = await om.getStatus({
22226
22277
  threadId,
22227
22278
  resourceId,
22279
+ record: this.turn.record,
22228
22280
  messages: getObservableMessages(messageList)
22229
22281
  });
22230
22282
  if (statusSnapshot.shouldBuffer && !hasIncompleteToolCalls) {
@@ -22320,6 +22372,7 @@ var ObservationStep = class {
22320
22372
  statusSnapshot = await om.getStatus({
22321
22373
  threadId,
22322
22374
  resourceId,
22375
+ record: this.turn.record,
22323
22376
  messages: getObservableMessages(messageList)
22324
22377
  });
22325
22378
  }
@@ -22370,10 +22423,12 @@ var ObservationStep = class {
22370
22423
  const { threadId, resourceId, messageList } = this.turn;
22371
22424
  const om = this.turn.om;
22372
22425
  await om.waitForBuffering(threadId, resourceId);
22426
+ await this.turn.refreshRecord();
22373
22427
  const observableMessages = this.seededResponseMessage ? getObservableMessages(messageList).filter((msg) => msg.id !== this.turn.responseMessageId) : getObservableMessages(messageList);
22374
22428
  const freshStatus = await om.getStatus({
22375
22429
  threadId,
22376
22430
  resourceId,
22431
+ record: this.turn.record,
22377
22432
  messages: observableMessages
22378
22433
  });
22379
22434
  if (!freshStatus.shouldObserve) return {
@@ -22384,11 +22439,13 @@ var ObservationStep = class {
22384
22439
  const activation = await om.activate({
22385
22440
  threadId,
22386
22441
  resourceId,
22442
+ record: this.turn.record,
22387
22443
  messages: observableMessages,
22388
22444
  currentModel: this.turn.actorModelContext,
22389
22445
  writer: this.turn.writer,
22390
22446
  messageList
22391
22447
  });
22448
+ this.turn.setRecord(activation.record);
22392
22449
  if (activation.activated) {
22393
22450
  const postActivationRecord = activation.record;
22394
22451
  await om.reflector.maybeReflect({
@@ -22573,6 +22630,18 @@ var ObservationTurn = class {
22573
22630
  };
22574
22631
  return this._context;
22575
22632
  }
22633
+ /** Replace the cached turn record with a specific instance. */
22634
+ setRecord(record) {
22635
+ this._record = record;
22636
+ if (this._context) this._context.record = record;
22637
+ }
22638
+ /** Patch the cached turn record with merged fields. */
22639
+ patchRecord(patch) {
22640
+ this.setRecord({
22641
+ ...this.record,
22642
+ ...patch
22643
+ });
22644
+ }
22576
22645
  /**
22577
22646
  * Create a step handle. If a previous step exists, it is finalized
22578
22647
  * (its output messages will be saved at the start of the new step's prepare()).
@@ -22627,7 +22696,7 @@ var ObservationTurn = class {
22627
22696
  * @internal
22628
22697
  */
22629
22698
  async refreshRecord() {
22630
- this._record = await this.om.getOrCreateRecord(this.threadId, this.resourceId);
22699
+ this.setRecord(await this.om.getOrCreateRecord(this.threadId, this.resourceId));
22631
22700
  }
22632
22701
  /**
22633
22702
  * Refresh cross-thread context for resource scope. Called per-step.
@@ -22682,9 +22751,13 @@ var ObservationTurn = class {
22682
22751
  * - Preserving ALL important information (reflections become the ENTIRE memory)
22683
22752
  *
22684
22753
  * @param instruction - Optional custom instructions to append to the prompt
22754
+ * @param extractors - Active extractors, used to decide which sections the prompt describes
22685
22755
  */
22686
- function buildReflectorSystemPrompt(instruction, extractors = []) {
22756
+ function buildReflectorSystemPrompt(instruction, extractors) {
22687
22757
  const outputFormat = buildObserverOutputFormat(extractors);
22758
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
22759
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
22760
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
22688
22761
  return `You are the memory consciousness of an AI assistant. Your memory observation reflections will be the ONLY information the assistant has about past interactions with this user.
22689
22762
 
22690
22763
  The following instructions were given to another part of your psyche (the observer) to create memories.
@@ -22761,7 +22834,7 @@ Date: Dec 4, 2025
22761
22834
 
22762
22835
  ${outputFormat}
22763
22836
 
22764
- User messages are extremely important. If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority. If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks.${instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : ""}`;
22837
+ User messages are extremely important.${currentTaskEnabled ? " If the user asks a question or gives a new task, make it clear in <current-task> that this is the priority." : ""}${suggestedResponseEnabled ? " If the assistant needs to respond to the user, indicate in <suggested-response> that it should pause for user reply before continuing other tasks." : ""}${customInstructions}`;
22765
22838
  }
22766
22839
  buildReflectorSystemPrompt();
22767
22840
  /**
@@ -24225,7 +24298,8 @@ var ObservationalMemory = class ObservationalMemory {
24225
24298
  observeAttachments: config.observation?.observeAttachments ?? true,
24226
24299
  extractors: composeObservationExtractors({
24227
24300
  threadTitle: config.observation?.threadTitle ?? false,
24228
- extract: config.observation?.extract
24301
+ extract: config.observation?.extract,
24302
+ continuationHints: config.observation?.continuationHints
24229
24303
  })
24230
24304
  };
24231
24305
  this.reflectionConfig = {
@@ -24242,7 +24316,10 @@ var ObservationalMemory = class ObservationalMemory {
24242
24316
  activateOnProviderChange: config.reflection?.activateOnProviderChange ?? false,
24243
24317
  blockAfter: asyncBufferingDisabled ? void 0 : resolveBlockAfter(config.reflection?.blockAfter ?? (config.reflection?.bufferActivation ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.bufferActivation ? 1.2 : void 0), config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens),
24244
24318
  instruction: config.reflection?.instruction,
24245
- extractors: composeReflectionExtractors({ extract: config.reflection?.extract })
24319
+ extractors: composeReflectionExtractors({
24320
+ extract: config.reflection?.extract,
24321
+ continuationHints: config.reflection?.continuationHints
24322
+ })
24246
24323
  };
24247
24324
  this.tokenCounter = new TokenCounter({ model: typeof observationModel === "string" ? observationModel : void 0 });
24248
24325
  this.onDebugEvent = config.onDebugEvent;
@@ -25357,8 +25434,9 @@ ${formattedMessages}
25357
25434
  return;
25358
25435
  }
25359
25436
  const omMetadata = (0, _mastra_core_memory.getThreadOMMetadata)((await this.storage.getThreadById({ threadId }))?.metadata);
25360
- const currentTask = omMetadata?.currentTask;
25361
- const suggestedResponse = omMetadata?.suggestedResponse;
25437
+ const activeExtractors = [...this.observationConfig.extractors, ...this.reflectionConfig.extractors];
25438
+ const currentTask = activeExtractors.some((extractor) => extractor.slug === "current-task") ? omMetadata?.currentTask : void 0;
25439
+ const suggestedResponse = activeExtractors.some((extractor) => extractor.slug === "suggested-response") ? omMetadata?.suggestedResponse : void 0;
25362
25440
  const currentDate = opts.currentDate ?? /* @__PURE__ */ new Date();
25363
25441
  return this.formatObservationsForContext(record.activeObservations, currentTask, suggestedResponse, omMetadata?.extracted, unobservedContextBlocks, currentDate, this.retrieval);
25364
25442
  }
@@ -25483,11 +25561,11 @@ ${formattedMessages}
25483
25561
  * ```
25484
25562
  */
25485
25563
  async getStatus(opts) {
25486
- const { threadId, resourceId } = opts;
25487
- const record = await this.getOrCreateRecord(threadId, resourceId);
25564
+ const { threadId, resourceId, record: providedRecord, messages } = opts;
25565
+ const record = providedRecord ?? await this.getOrCreateRecord(threadId, resourceId);
25488
25566
  const currentObservationTokens = record.observationTokenCount ?? 0;
25489
25567
  let unobservedMessages;
25490
- if (opts.messages) unobservedMessages = this.getUnobservedMessages(opts.messages, record);
25568
+ if (messages) unobservedMessages = this.getUnobservedMessages(messages, record);
25491
25569
  else {
25492
25570
  const rawMessages = await this.loadMessagesFromStorage(threadId, resourceId, record.lastObservedAt ? new Date(record.lastObservedAt) : void 0);
25493
25571
  unobservedMessages = this.getUnobservedMessages(rawMessages, record);
@@ -25644,6 +25722,7 @@ ${formattedMessages}
25644
25722
  async buffer(opts) {
25645
25723
  const { threadId, resourceId, requestContext, observabilityContext } = opts;
25646
25724
  let record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
25725
+ const inMemoryRecord = record;
25647
25726
  if (!this.buffering.isAsyncObservationEnabled()) return {
25648
25727
  buffered: false,
25649
25728
  record
@@ -25662,6 +25741,8 @@ ${formattedMessages}
25662
25741
  await existingOp;
25663
25742
  } catch {}
25664
25743
  registerOp(record.id, "bufferingObservation");
25744
+ inMemoryRecord.isBufferingObservation = true;
25745
+ inMemoryRecord.lastBufferedAtTokens = currentTokens;
25665
25746
  this.storage.setBufferingObservationFlag(record.id, true, currentTokens).catch((err) => {
25666
25747
  omError("[OM] Failed to set buffering observation flag", err);
25667
25748
  });
@@ -25671,6 +25752,14 @@ ${formattedMessages}
25671
25752
  });
25672
25753
  BufferingCoordinator.asyncBufferingOps.set(bufferKey, opPromise);
25673
25754
  record = await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record;
25755
+ const setBufferingState = (isBufferingObservation, lastBufferedAtTokens) => {
25756
+ inMemoryRecord.isBufferingObservation = isBufferingObservation;
25757
+ record.isBufferingObservation = isBufferingObservation;
25758
+ if (lastBufferedAtTokens !== void 0) {
25759
+ inMemoryRecord.lastBufferedAtTokens = lastBufferedAtTokens;
25760
+ record.lastBufferedAtTokens = lastBufferedAtTokens;
25761
+ }
25762
+ };
25674
25763
  let flagCleared = false;
25675
25764
  try {
25676
25765
  let candidateMessages;
@@ -25692,10 +25781,13 @@ ${formattedMessages}
25692
25781
  }
25693
25782
  const minNewTokens = (this.observationConfig.bufferTokens ?? 5e3) / 2;
25694
25783
  const newTokens = await this.tokenCounter.countMessagesAsync(candidateMessages);
25695
- if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) return {
25696
- buffered: false,
25697
- record
25698
- };
25784
+ if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) {
25785
+ setBufferingState(false);
25786
+ return {
25787
+ buffered: false,
25788
+ record
25789
+ };
25790
+ }
25699
25791
  if (opts.beforeBuffer) await opts.beforeBuffer(candidateMessages);
25700
25792
  else if (opts.messages) this.sealMessagesForBuffering(candidateMessages);
25701
25793
  const cycleId = `buffer-obs-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
@@ -25750,13 +25842,14 @@ ${formattedMessages}
25750
25842
  });
25751
25843
  await this.storage.setBufferingObservationFlag(record.id, false, newTokens).catch(() => {});
25752
25844
  flagCleared = true;
25845
+ setBufferingState(false, newTokens);
25753
25846
  BufferingCoordinator.lastBufferedBoundary.set(bufferKey, newTokens);
25754
25847
  const maxTimestamp = this.getMaxMessageTimestamp(candidateMessages);
25755
25848
  const cursor = new Date(maxTimestamp.getTime() + 1);
25756
25849
  BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
25757
25850
  return {
25758
25851
  buffered: true,
25759
- record: await this.getOrCreateRecord(threadId, resourceId)
25852
+ record: await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record
25760
25853
  };
25761
25854
  } catch (error) {
25762
25855
  omError("[OM] buffer() failed", error);
@@ -25768,7 +25861,10 @@ ${formattedMessages}
25768
25861
  unregisterOp(record.id, "bufferingObservation");
25769
25862
  BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
25770
25863
  resolveOp();
25771
- if (!flagCleared) await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
25864
+ if (!flagCleared) {
25865
+ setBufferingState(false);
25866
+ await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
25867
+ }
25772
25868
  }
25773
25869
  }
25774
25870
  /**
@@ -25794,7 +25890,7 @@ ${formattedMessages}
25794
25890
  /** @internal Used by ObservationStep. */
25795
25891
  async activate(opts) {
25796
25892
  const { threadId, resourceId } = opts;
25797
- const record = await this.getOrCreateRecord(threadId, resourceId);
25893
+ const record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
25798
25894
  if (this.buffering.isAsyncObservationEnabled()) {
25799
25895
  const lockKey = this.buffering.getLockKey(threadId, resourceId);
25800
25896
  const bufKey = this.buffering.getObservationBufferKey(lockKey);
@@ -25840,6 +25936,7 @@ ${formattedMessages}
25840
25936
  const status = await this.getStatus({
25841
25937
  threadId,
25842
25938
  resourceId,
25939
+ record,
25843
25940
  messages: thresholdMessages
25844
25941
  });
25845
25942
  if (status.pendingTokens < status.threshold) return {
@@ -26559,31 +26656,30 @@ var ObservationalMemoryProcessor = class {
26559
26656
  threadId,
26560
26657
  resourceId
26561
26658
  });
26562
- const freshRecord = await this.engine.getOrCreateRecord(threadId, resourceId);
26659
+ const turnRecord = this.turn.record;
26563
26660
  await this.engine.emitProgress({
26564
- record: freshRecord,
26661
+ record: turnRecord,
26565
26662
  stepNumber,
26566
26663
  pendingTokens: ctx.status.pendingTokens,
26567
26664
  threshold: ctx.status.threshold,
26568
26665
  effectiveObservationTokensThreshold: ctx.status.effectiveObservationTokensThreshold,
26569
- currentObservationTokens: freshRecord.observationTokenCount ?? 0,
26666
+ currentObservationTokens: turnRecord.observationTokenCount ?? 0,
26570
26667
  writer,
26571
26668
  threadId,
26572
26669
  resourceId
26573
26670
  });
26574
- const allDbMsgs = getObservableMessages(messageList);
26575
- const tokenCounter = this.engine.getTokenCounter();
26576
- const contextTokens = await tokenCounter.countMessagesAsync(allDbMsgs);
26577
- const otherThreadsContext = this.turn.context.otherThreadsContext;
26578
- const finalTotalPending = contextTokens + (otherThreadsContext ? tokenCounter.countString(otherThreadsContext) : 0);
26579
- await this.engine.getStorage().setPendingMessageTokens(freshRecord.id, finalTotalPending).catch(() => {});
26671
+ const finalTotalPending = ctx.status.pendingTokens;
26672
+ try {
26673
+ await this.engine.getStorage().setPendingMessageTokens(turnRecord.id, finalTotalPending);
26674
+ this.turn.patchRecord({ pendingMessageTokens: finalTotalPending });
26675
+ } catch {}
26580
26676
  if (reproCaptureEnabled) writeProcessInputStepReproCapture({
26581
26677
  threadId,
26582
26678
  resourceId,
26583
26679
  stepNumber,
26584
26680
  args,
26585
26681
  preRecord: preRecordSnapshot,
26586
- postRecord: safeCaptureJson(freshRecord),
26682
+ postRecord: safeCaptureJson(turnRecord),
26587
26683
  preMessages: preMessagesSnapshot,
26588
26684
  preBufferedChunks: [],
26589
26685
  preContextTokenCount: 0,
@@ -28950,4 +29046,4 @@ Object.defineProperty(exports, "wrapInObservationGroup", {
28950
29046
  }
28951
29047
  });
28952
29048
 
28953
- //# sourceMappingURL=src-b5E69E65.cjs.map
29049
+ //# sourceMappingURL=src-MvtBOFYO.cjs.map