@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
@@ -15925,21 +15925,17 @@ Or as a standalone observation when closing out a broader task:
15925
15925
  Completion observations should be terse but specific about WHAT was completed.
15926
15926
  Prefer concrete resolved outcomes over abstract workflow status so the assistant remembers what is already done.`;
15927
15927
  buildObserverOutputFormat();
15928
- function buildObserverOutputFormat(extractors = []) {
15929
- const extractorSections = buildExtractorOutputSections(extractors);
15930
- const legacyContinuationSections = extractors.length === 0 ? `
15931
- <current-task>
15932
- State the current task(s) explicitly:
15933
- - Primary: What the agent is currently working on
15934
- - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
15935
- </current-task>
15936
-
15937
- <suggested-response>
15938
- Hint for the agent's immediate next message. Examples:
15939
- - "I've updated the navigation model. Let me walk you through the changes..."
15940
- - "The assistant should wait for the user to respond before continuing."
15941
- - Call the view tool on src/example.ts to continue debugging.
15942
- </suggested-response>` : "";
15928
+ /**
15929
+ * Build the Observer's output format.
15930
+ *
15931
+ * `extractors` distinguishes two cases that both look empty:
15932
+ * - `undefined` — the no-arg call behind the exported defaults (OBSERVER_OUTPUT_FORMAT_BASE,
15933
+ * OBSERVER_SYSTEM_PROMPT, REFLECTOR_SYSTEM_PROMPT), which keep describing both built-in
15934
+ * sections with their historical text. Runtime callers always pass the composed list.
15935
+ * - `[]` — the caller composed extractors and every section was disabled, so no continuation
15936
+ * sections are described at all.
15937
+ */
15938
+ function buildObserverOutputFormat(extractors) {
15943
15939
  return `Use priority levels:
15944
15940
  - 🔴 High: explicit user facts, preferences, unresolved goals, critical context
15945
15941
  - 🟡 Medium: project details, learned information, tool results
@@ -15965,7 +15961,19 @@ Date: Dec 5, 2025
15965
15961
  * 🔴 (09:15) Continued work on feature X
15966
15962
  </observations>
15967
15963
 
15968
- ${extractorSections || legacyContinuationSections}`;
15964
+ ${buildExtractorOutputSections(extractors ?? []) || (extractors === void 0 ? `
15965
+ <current-task>
15966
+ State the current task(s) explicitly:
15967
+ - Primary: What the agent is currently working on
15968
+ - Secondary: Other pending tasks (mark as "waiting for user" if appropriate)
15969
+ </current-task>
15970
+
15971
+ <suggested-response>
15972
+ Hint for the agent's immediate next message. Examples:
15973
+ - "I've updated the navigation model. Let me walk you through the changes..."
15974
+ - "The assistant should wait for the user to respond before continuing."
15975
+ - Call the view tool on src/example.ts to continue debugging.
15976
+ </suggested-response>` : "")}`;
15969
15977
  }
15970
15978
  /**
15971
15979
  * The guidelines for the Observer.
@@ -15992,10 +16000,22 @@ const OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
15992
16000
  * Build the complete observer system prompt.
15993
16001
  * @param multiThread - Whether this is for multi-thread batched observation (default: false)
15994
16002
  * @param instruction - Optional custom instructions to append to the prompt
16003
+ * @param includeThreadTitle - Whether the Observer should also produce a thread title
16004
+ * @param extractors - Active extractors, used to decide which sections the prompt describes.
16005
+ * Omitted only by the exported no-arg defaults; pass `[]` to describe no continuation sections at all.
15995
16006
  */
15996
- function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors = []) {
16007
+ function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false, extractors) {
15997
16008
  const outputFormat = buildObserverOutputFormat(extractors);
15998
- 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>.`;
16009
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
16010
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
16011
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
16012
+ const multiThreadSections = [
16013
+ "observations",
16014
+ ...currentTaskEnabled ? ["current-task"] : [],
16015
+ ...suggestedResponseEnabled ? ["suggested-response"] : [],
16016
+ ...includeThreadTitle ? ["thread-title"] : []
16017
+ ];
16018
+ 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>.`;
15999
16019
  const multiThreadTitleExample = includeThreadTitle ? `
16000
16020
  <thread-title>Feature X implementation</thread-title>` : "";
16001
16021
  const multiThreadSecondTitleExample = includeThreadTitle ? `
@@ -16025,28 +16045,28 @@ For multi-thread output, wrap each thread's observations like this:
16025
16045
  <thread id="thread_id_1">
16026
16046
  Date: Dec 4, 2025
16027
16047
  * 🔴 (14:30) User prefers direct answers
16028
- * 🔴 (14:31) Working on feature X
16048
+ * 🔴 (14:31) Working on feature X${currentTaskEnabled ? `
16029
16049
 
16030
16050
  <current-task>
16031
16051
  What the agent is currently working on in this thread
16032
- </current-task>
16052
+ </current-task>` : ""}${suggestedResponseEnabled ? `
16033
16053
 
16034
16054
  <suggested-response>
16035
16055
  Hint for the agent's next message in this thread
16036
- </suggested-response>${multiThreadTitleExample}
16056
+ </suggested-response>` : ""}${multiThreadTitleExample}
16037
16057
  </thread>
16038
16058
 
16039
16059
  <thread id="thread_id_2">
16040
16060
  Date: Dec 5, 2025
16041
- * 🔴 (09:15) User asked about deployment
16061
+ * 🔴 (09:15) User asked about deployment${currentTaskEnabled ? `
16042
16062
 
16043
16063
  <current-task>
16044
16064
  Current task for this thread
16045
- </current-task>
16065
+ </current-task>` : ""}${suggestedResponseEnabled ? `
16046
16066
 
16047
16067
  <suggested-response>
16048
16068
  Suggested response for this thread
16049
- </suggested-response>${multiThreadSecondTitleExample}
16069
+ </suggested-response>` : ""}${multiThreadSecondTitleExample}
16050
16070
  </thread>
16051
16071
  </observations>
16052
16072
 
@@ -16056,7 +16076,7 @@ ${OBSERVER_GUIDELINES}
16056
16076
 
16057
16077
  Remember: These observations are the assistant's ONLY memory. Make them count.
16058
16078
 
16059
- 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}` : ""}`;
16079
+ 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}`;
16060
16080
  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.
16061
16081
 
16062
16082
  Extract observations that will help the assistant remember:
@@ -16081,7 +16101,7 @@ Simply output your observations without any thread-related markup.
16081
16101
 
16082
16102
  Remember: These observations are the assistant's ONLY memory. Make them count.
16083
16103
 
16084
- 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}` : ""}`;
16104
+ 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}`;
16085
16105
  }
16086
16106
  /**
16087
16107
  * Observer Agent System Prompt (default - for backwards compatibility)
@@ -16773,7 +16793,7 @@ function optimizeObservationsForContext(observations) {
16773
16793
  let optimized = stripEphemeralAnchorIds(observations);
16774
16794
  optimized = optimized.replace(/🟡\s*/g, "");
16775
16795
  optimized = optimized.replace(/🟢\s*/g, "");
16776
- optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\]/g, "");
16796
+ optimized = optimized.replace(/\[(?![\d\s]*items collapsed)[^\]]+\](?!\()/g, "");
16777
16797
  optimized = optimized.replace(/\s*->\s*/g, " ");
16778
16798
  optimized = optimized.replace(/ +/g, " ");
16779
16799
  optimized = optimized.replace(/\n{3,}/g, "\n\n");
@@ -18195,6 +18215,7 @@ var TokenCounter = class TokenCounter {
18195
18215
  defaultModelContext;
18196
18216
  modelContextStorage = new AsyncLocalStorage();
18197
18217
  inFlightAttachmentCounts = /* @__PURE__ */ new Map();
18218
+ multimodalToolResultCounts = /* @__PURE__ */ new WeakMap();
18198
18219
  static TOKENS_PER_MESSAGE = 3.8;
18199
18220
  static TOKENS_PER_CONVERSATION = 24;
18200
18221
  constructor(options) {
@@ -18257,6 +18278,9 @@ var TokenCounter = class TokenCounter {
18257
18278
  }
18258
18279
  countMultimodalToolResultContent(part, toolResult) {
18259
18280
  if (!toolResult || typeof toolResult !== "object") return;
18281
+ const resultKey = buildEstimateKey("tool-result-multimodal-content-source", JSON.stringify(toolResult));
18282
+ const cached = this.multimodalToolResultCounts.get(part);
18283
+ if (cached?.resultKey === resultKey) return cached.tokens;
18260
18284
  const output = toolResult;
18261
18285
  const content = output.type === "content" && Array.isArray(output.value) ? output.value : output.content;
18262
18286
  if (!Array.isArray(content)) return;
@@ -18368,10 +18392,15 @@ var TokenCounter = class TokenCounter {
18368
18392
  countJsonContentPart(contentPart);
18369
18393
  }
18370
18394
  if (!hasAttachment) return;
18371
- return this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
18395
+ const estimate = this.readOrPersistFixedPartEstimate(part, "tool-result-multimodal-content", JSON.stringify({
18372
18396
  type: "content",
18373
18397
  value: cacheParts
18374
18398
  }), tokens);
18399
+ this.multimodalToolResultCounts.set(part, {
18400
+ resultKey,
18401
+ tokens: estimate
18402
+ });
18403
+ return estimate;
18375
18404
  }
18376
18405
  estimateImageAssetTokens(part, asset, kind) {
18377
18406
  const modelContext = this.getModelContext();
@@ -20358,23 +20387,43 @@ function createThreadTitleExtractor() {
20358
20387
  metadataKeyPath: "threadTitle"
20359
20388
  }, true);
20360
20389
  }
20390
+ /**
20391
+ * Normalize the user-facing `continuationHints` config into explicit per-section flags.
20392
+ * Both sections stay enabled unless the caller opts out, so omitting the config is a no-op.
20393
+ */
20394
+ function resolveContinuationHints(config) {
20395
+ if (config === void 0 || config === true) return {
20396
+ currentTask: true,
20397
+ suggestedResponse: true
20398
+ };
20399
+ if (config === false) return {
20400
+ currentTask: false,
20401
+ suggestedResponse: false
20402
+ };
20403
+ return {
20404
+ currentTask: config.currentTask ?? true,
20405
+ suggestedResponse: config.suggestedResponse ?? true
20406
+ };
20407
+ }
20361
20408
  function composeExtractors(options) {
20409
+ const continuationHints = resolveContinuationHints(options.continuationHints);
20362
20410
  const extractors = [];
20363
- if (options.includeContinuationHints) extractors.push(createCurrentTaskExtractor(), createSuggestedResponseExtractor());
20411
+ if (continuationHints.currentTask) extractors.push(createCurrentTaskExtractor());
20412
+ if (continuationHints.suggestedResponse) extractors.push(createSuggestedResponseExtractor());
20364
20413
  if (options.includeThreadTitle) extractors.push(createThreadTitleExtractor());
20365
20414
  extractors.push(...options.userExtractors ?? []);
20366
20415
  return validateExtractorList(extractors);
20367
20416
  }
20368
20417
  function composeObservationExtractors(config) {
20369
20418
  return composeExtractors({
20370
- includeContinuationHints: true,
20419
+ continuationHints: config.continuationHints,
20371
20420
  includeThreadTitle: config.threadTitle,
20372
20421
  userExtractors: config.extract
20373
20422
  });
20374
20423
  }
20375
20424
  function composeReflectionExtractors(config) {
20376
20425
  return composeExtractors({
20377
- includeContinuationHints: true,
20426
+ continuationHints: config.continuationHints,
20378
20427
  userExtractors: config.extract
20379
20428
  });
20380
20429
  }
@@ -22159,10 +22208,12 @@ var ObservationStep = class {
22159
22208
  resourceId,
22160
22209
  checkThreshold: true,
22161
22210
  messages: step0Messages,
22211
+ record: this.turn.record,
22162
22212
  currentModel: this.turn.actorModelContext,
22163
22213
  writer: this.turn.writer,
22164
22214
  messageList
22165
22215
  });
22216
+ this.turn.setRecord(activation.record);
22166
22217
  if (activation.activated) {
22167
22218
  activated = true;
22168
22219
  if (activation.activatedMessageIds?.length) messageList.removeByIds(activation.activatedMessageIds);
@@ -22204,6 +22255,7 @@ var ObservationStep = class {
22204
22255
  let statusSnapshot = await om.getStatus({
22205
22256
  threadId,
22206
22257
  resourceId,
22258
+ record: this.turn.record,
22207
22259
  messages: getObservableMessages(messageList)
22208
22260
  });
22209
22261
  if (statusSnapshot.shouldBuffer && !hasIncompleteToolCalls) {
@@ -22299,6 +22351,7 @@ var ObservationStep = class {
22299
22351
  statusSnapshot = await om.getStatus({
22300
22352
  threadId,
22301
22353
  resourceId,
22354
+ record: this.turn.record,
22302
22355
  messages: getObservableMessages(messageList)
22303
22356
  });
22304
22357
  }
@@ -22349,10 +22402,12 @@ var ObservationStep = class {
22349
22402
  const { threadId, resourceId, messageList } = this.turn;
22350
22403
  const om = this.turn.om;
22351
22404
  await om.waitForBuffering(threadId, resourceId);
22405
+ await this.turn.refreshRecord();
22352
22406
  const observableMessages = this.seededResponseMessage ? getObservableMessages(messageList).filter((msg) => msg.id !== this.turn.responseMessageId) : getObservableMessages(messageList);
22353
22407
  const freshStatus = await om.getStatus({
22354
22408
  threadId,
22355
22409
  resourceId,
22410
+ record: this.turn.record,
22356
22411
  messages: observableMessages
22357
22412
  });
22358
22413
  if (!freshStatus.shouldObserve) return {
@@ -22363,11 +22418,13 @@ var ObservationStep = class {
22363
22418
  const activation = await om.activate({
22364
22419
  threadId,
22365
22420
  resourceId,
22421
+ record: this.turn.record,
22366
22422
  messages: observableMessages,
22367
22423
  currentModel: this.turn.actorModelContext,
22368
22424
  writer: this.turn.writer,
22369
22425
  messageList
22370
22426
  });
22427
+ this.turn.setRecord(activation.record);
22371
22428
  if (activation.activated) {
22372
22429
  const postActivationRecord = activation.record;
22373
22430
  await om.reflector.maybeReflect({
@@ -22552,6 +22609,18 @@ var ObservationTurn = class {
22552
22609
  };
22553
22610
  return this._context;
22554
22611
  }
22612
+ /** Replace the cached turn record with a specific instance. */
22613
+ setRecord(record) {
22614
+ this._record = record;
22615
+ if (this._context) this._context.record = record;
22616
+ }
22617
+ /** Patch the cached turn record with merged fields. */
22618
+ patchRecord(patch) {
22619
+ this.setRecord({
22620
+ ...this.record,
22621
+ ...patch
22622
+ });
22623
+ }
22555
22624
  /**
22556
22625
  * Create a step handle. If a previous step exists, it is finalized
22557
22626
  * (its output messages will be saved at the start of the new step's prepare()).
@@ -22606,7 +22675,7 @@ var ObservationTurn = class {
22606
22675
  * @internal
22607
22676
  */
22608
22677
  async refreshRecord() {
22609
- this._record = await this.om.getOrCreateRecord(this.threadId, this.resourceId);
22678
+ this.setRecord(await this.om.getOrCreateRecord(this.threadId, this.resourceId));
22610
22679
  }
22611
22680
  /**
22612
22681
  * Refresh cross-thread context for resource scope. Called per-step.
@@ -22661,9 +22730,13 @@ var ObservationTurn = class {
22661
22730
  * - Preserving ALL important information (reflections become the ENTIRE memory)
22662
22731
  *
22663
22732
  * @param instruction - Optional custom instructions to append to the prompt
22733
+ * @param extractors - Active extractors, used to decide which sections the prompt describes
22664
22734
  */
22665
- function buildReflectorSystemPrompt(instruction, extractors = []) {
22735
+ function buildReflectorSystemPrompt(instruction, extractors) {
22666
22736
  const outputFormat = buildObserverOutputFormat(extractors);
22737
+ const customInstructions = instruction ? `\n\n=== CUSTOM INSTRUCTIONS ===\n\n${instruction}` : "";
22738
+ const currentTaskEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "current-task");
22739
+ const suggestedResponseEnabled = extractors === void 0 || extractors.some((extractor) => extractor.slug === "suggested-response");
22667
22740
  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.
22668
22741
 
22669
22742
  The following instructions were given to another part of your psyche (the observer) to create memories.
@@ -22740,7 +22813,7 @@ Date: Dec 4, 2025
22740
22813
 
22741
22814
  ${outputFormat}
22742
22815
 
22743
- 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}` : ""}`;
22816
+ 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}`;
22744
22817
  }
22745
22818
  buildReflectorSystemPrompt();
22746
22819
  /**
@@ -24204,7 +24277,8 @@ var ObservationalMemory = class ObservationalMemory {
24204
24277
  observeAttachments: config.observation?.observeAttachments ?? true,
24205
24278
  extractors: composeObservationExtractors({
24206
24279
  threadTitle: config.observation?.threadTitle ?? false,
24207
- extract: config.observation?.extract
24280
+ extract: config.observation?.extract,
24281
+ continuationHints: config.observation?.continuationHints
24208
24282
  })
24209
24283
  };
24210
24284
  this.reflectionConfig = {
@@ -24221,7 +24295,10 @@ var ObservationalMemory = class ObservationalMemory {
24221
24295
  activateOnProviderChange: config.reflection?.activateOnProviderChange ?? false,
24222
24296
  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),
24223
24297
  instruction: config.reflection?.instruction,
24224
- extractors: composeReflectionExtractors({ extract: config.reflection?.extract })
24298
+ extractors: composeReflectionExtractors({
24299
+ extract: config.reflection?.extract,
24300
+ continuationHints: config.reflection?.continuationHints
24301
+ })
24225
24302
  };
24226
24303
  this.tokenCounter = new TokenCounter({ model: typeof observationModel === "string" ? observationModel : void 0 });
24227
24304
  this.onDebugEvent = config.onDebugEvent;
@@ -25336,8 +25413,9 @@ ${formattedMessages}
25336
25413
  return;
25337
25414
  }
25338
25415
  const omMetadata = getThreadOMMetadata((await this.storage.getThreadById({ threadId }))?.metadata);
25339
- const currentTask = omMetadata?.currentTask;
25340
- const suggestedResponse = omMetadata?.suggestedResponse;
25416
+ const activeExtractors = [...this.observationConfig.extractors, ...this.reflectionConfig.extractors];
25417
+ const currentTask = activeExtractors.some((extractor) => extractor.slug === "current-task") ? omMetadata?.currentTask : void 0;
25418
+ const suggestedResponse = activeExtractors.some((extractor) => extractor.slug === "suggested-response") ? omMetadata?.suggestedResponse : void 0;
25341
25419
  const currentDate = opts.currentDate ?? /* @__PURE__ */ new Date();
25342
25420
  return this.formatObservationsForContext(record.activeObservations, currentTask, suggestedResponse, omMetadata?.extracted, unobservedContextBlocks, currentDate, this.retrieval);
25343
25421
  }
@@ -25462,11 +25540,11 @@ ${formattedMessages}
25462
25540
  * ```
25463
25541
  */
25464
25542
  async getStatus(opts) {
25465
- const { threadId, resourceId } = opts;
25466
- const record = await this.getOrCreateRecord(threadId, resourceId);
25543
+ const { threadId, resourceId, record: providedRecord, messages } = opts;
25544
+ const record = providedRecord ?? await this.getOrCreateRecord(threadId, resourceId);
25467
25545
  const currentObservationTokens = record.observationTokenCount ?? 0;
25468
25546
  let unobservedMessages;
25469
- if (opts.messages) unobservedMessages = this.getUnobservedMessages(opts.messages, record);
25547
+ if (messages) unobservedMessages = this.getUnobservedMessages(messages, record);
25470
25548
  else {
25471
25549
  const rawMessages = await this.loadMessagesFromStorage(threadId, resourceId, record.lastObservedAt ? new Date(record.lastObservedAt) : void 0);
25472
25550
  unobservedMessages = this.getUnobservedMessages(rawMessages, record);
@@ -25623,6 +25701,7 @@ ${formattedMessages}
25623
25701
  async buffer(opts) {
25624
25702
  const { threadId, resourceId, requestContext, observabilityContext } = opts;
25625
25703
  let record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
25704
+ const inMemoryRecord = record;
25626
25705
  if (!this.buffering.isAsyncObservationEnabled()) return {
25627
25706
  buffered: false,
25628
25707
  record
@@ -25641,6 +25720,8 @@ ${formattedMessages}
25641
25720
  await existingOp;
25642
25721
  } catch {}
25643
25722
  registerOp(record.id, "bufferingObservation");
25723
+ inMemoryRecord.isBufferingObservation = true;
25724
+ inMemoryRecord.lastBufferedAtTokens = currentTokens;
25644
25725
  this.storage.setBufferingObservationFlag(record.id, true, currentTokens).catch((err) => {
25645
25726
  omError("[OM] Failed to set buffering observation flag", err);
25646
25727
  });
@@ -25650,6 +25731,14 @@ ${formattedMessages}
25650
25731
  });
25651
25732
  BufferingCoordinator.asyncBufferingOps.set(bufferKey, opPromise);
25652
25733
  record = await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record;
25734
+ const setBufferingState = (isBufferingObservation, lastBufferedAtTokens) => {
25735
+ inMemoryRecord.isBufferingObservation = isBufferingObservation;
25736
+ record.isBufferingObservation = isBufferingObservation;
25737
+ if (lastBufferedAtTokens !== void 0) {
25738
+ inMemoryRecord.lastBufferedAtTokens = lastBufferedAtTokens;
25739
+ record.lastBufferedAtTokens = lastBufferedAtTokens;
25740
+ }
25741
+ };
25653
25742
  let flagCleared = false;
25654
25743
  try {
25655
25744
  let candidateMessages;
@@ -25671,10 +25760,13 @@ ${formattedMessages}
25671
25760
  }
25672
25761
  const minNewTokens = (this.observationConfig.bufferTokens ?? 5e3) / 2;
25673
25762
  const newTokens = await this.tokenCounter.countMessagesAsync(candidateMessages);
25674
- if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) return {
25675
- buffered: false,
25676
- record
25677
- };
25763
+ if (candidateMessages.length === 0 || !opts.skipMinimumTokenCheck && newTokens < minNewTokens) {
25764
+ setBufferingState(false);
25765
+ return {
25766
+ buffered: false,
25767
+ record
25768
+ };
25769
+ }
25678
25770
  if (opts.beforeBuffer) await opts.beforeBuffer(candidateMessages);
25679
25771
  else if (opts.messages) this.sealMessagesForBuffering(candidateMessages);
25680
25772
  const cycleId = `buffer-obs-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`;
@@ -25729,13 +25821,14 @@ ${formattedMessages}
25729
25821
  });
25730
25822
  await this.storage.setBufferingObservationFlag(record.id, false, newTokens).catch(() => {});
25731
25823
  flagCleared = true;
25824
+ setBufferingState(false, newTokens);
25732
25825
  BufferingCoordinator.lastBufferedBoundary.set(bufferKey, newTokens);
25733
25826
  const maxTimestamp = this.getMaxMessageTimestamp(candidateMessages);
25734
25827
  const cursor = new Date(maxTimestamp.getTime() + 1);
25735
25828
  BufferingCoordinator.lastBufferedAtTime.set(bufferKey, cursor);
25736
25829
  return {
25737
25830
  buffered: true,
25738
- record: await this.getOrCreateRecord(threadId, resourceId)
25831
+ record: await this.storage.getObservationalMemory(record.threadId, record.resourceId) ?? record
25739
25832
  };
25740
25833
  } catch (error) {
25741
25834
  omError("[OM] buffer() failed", error);
@@ -25747,7 +25840,10 @@ ${formattedMessages}
25747
25840
  unregisterOp(record.id, "bufferingObservation");
25748
25841
  BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
25749
25842
  resolveOp();
25750
- if (!flagCleared) await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
25843
+ if (!flagCleared) {
25844
+ setBufferingState(false);
25845
+ await this.storage.setBufferingObservationFlag(record.id, false).catch(() => {});
25846
+ }
25751
25847
  }
25752
25848
  }
25753
25849
  /**
@@ -25773,7 +25869,7 @@ ${formattedMessages}
25773
25869
  /** @internal Used by ObservationStep. */
25774
25870
  async activate(opts) {
25775
25871
  const { threadId, resourceId } = opts;
25776
- const record = await this.getOrCreateRecord(threadId, resourceId);
25872
+ const record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
25777
25873
  if (this.buffering.isAsyncObservationEnabled()) {
25778
25874
  const lockKey = this.buffering.getLockKey(threadId, resourceId);
25779
25875
  const bufKey = this.buffering.getObservationBufferKey(lockKey);
@@ -25819,6 +25915,7 @@ ${formattedMessages}
25819
25915
  const status = await this.getStatus({
25820
25916
  threadId,
25821
25917
  resourceId,
25918
+ record,
25822
25919
  messages: thresholdMessages
25823
25920
  });
25824
25921
  if (status.pendingTokens < status.threshold) return {
@@ -26538,31 +26635,30 @@ var ObservationalMemoryProcessor = class {
26538
26635
  threadId,
26539
26636
  resourceId
26540
26637
  });
26541
- const freshRecord = await this.engine.getOrCreateRecord(threadId, resourceId);
26638
+ const turnRecord = this.turn.record;
26542
26639
  await this.engine.emitProgress({
26543
- record: freshRecord,
26640
+ record: turnRecord,
26544
26641
  stepNumber,
26545
26642
  pendingTokens: ctx.status.pendingTokens,
26546
26643
  threshold: ctx.status.threshold,
26547
26644
  effectiveObservationTokensThreshold: ctx.status.effectiveObservationTokensThreshold,
26548
- currentObservationTokens: freshRecord.observationTokenCount ?? 0,
26645
+ currentObservationTokens: turnRecord.observationTokenCount ?? 0,
26549
26646
  writer,
26550
26647
  threadId,
26551
26648
  resourceId
26552
26649
  });
26553
- const allDbMsgs = getObservableMessages(messageList);
26554
- const tokenCounter = this.engine.getTokenCounter();
26555
- const contextTokens = await tokenCounter.countMessagesAsync(allDbMsgs);
26556
- const otherThreadsContext = this.turn.context.otherThreadsContext;
26557
- const finalTotalPending = contextTokens + (otherThreadsContext ? tokenCounter.countString(otherThreadsContext) : 0);
26558
- await this.engine.getStorage().setPendingMessageTokens(freshRecord.id, finalTotalPending).catch(() => {});
26650
+ const finalTotalPending = ctx.status.pendingTokens;
26651
+ try {
26652
+ await this.engine.getStorage().setPendingMessageTokens(turnRecord.id, finalTotalPending);
26653
+ this.turn.patchRecord({ pendingMessageTokens: finalTotalPending });
26654
+ } catch {}
26559
26655
  if (reproCaptureEnabled) writeProcessInputStepReproCapture({
26560
26656
  threadId,
26561
26657
  resourceId,
26562
26658
  stepNumber,
26563
26659
  args,
26564
26660
  preRecord: preRecordSnapshot,
26565
- postRecord: safeCaptureJson(freshRecord),
26661
+ postRecord: safeCaptureJson(turnRecord),
26566
26662
  preMessages: preMessagesSnapshot,
26567
26663
  preBufferedChunks: [],
26568
26664
  preContextTokenCount: 0,
@@ -28696,4 +28792,4 @@ Notes:
28696
28792
  //#endregion
28697
28793
  export { extractCurrentTask as A, OBSERVATION_CONTEXT_INSTRUCTIONS as B, WorkingMemoryExtractor as C, OBSERVER_SYSTEM_PROMPT as D, TokenCounter as E, injectAnchorIds as F, OBSERVATION_CONTINUATION_HINT as H, parseAnchorId as I, stripEphemeralAnchorIds as L, hasCurrentTaskSection as M, optimizeObservationsForContext as N, buildObserverPrompt as O, parseObserverOutput as P, Extractor as R, deepMergeWorkingMemory as S, summarizeConversation as T, OBSERVATION_CONTEXT_PROMPT as V, reconcileObservationGroupsFromReflection as _, extractWorkingMemoryContent as a, wrapInObservationGroup as b, WORKING_MEMORY_STATE_ID as c, getObservationsAsOf as d, ObservationalMemoryProcessor as f, parseObservationGroups as g, deriveObservationGroupProvenance as h, WorkingMemory as i, formatMessagesForObserver as j, buildObserverSystemPrompt as k, WORKING_MEMORY_STATE_PROCESSOR_ID as l, combineObservationGroupRanges as m, MessageHistory$1 as n, extractWorkingMemoryTags as o, ObservationalMemory as p, SemanticRecall as r, removeWorkingMemoryTags as s, Memory as t, WorkingMemoryStateProcessor as u, renderObservationGroupsForReflection as v, SUMMARIZE_THREAD_DEFAULTS as w, ModelByInputTokens as x, stripObservationGroups as y, OBSERVATIONAL_MEMORY_DEFAULTS as z };
28698
28794
 
28699
- //# sourceMappingURL=src-BYD6Wp5m.js.map
28795
+ //# sourceMappingURL=src-BUlG9vaB.js.map