@mastra/memory 1.9.1-alpha.1 → 1.10.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 +77 -0
  2. package/dist/{chunk-T5FHEWK6.js → chunk-7A3UGAXY.js} +338 -116
  3. package/dist/chunk-7A3UGAXY.js.map +1 -0
  4. package/dist/{chunk-CNOHXG5O.cjs → chunk-EVBFYGDL.cjs} +338 -115
  5. package/dist/chunk-EVBFYGDL.cjs.map +1 -0
  6. package/dist/docs/SKILL.md +1 -1
  7. package/dist/docs/assets/SOURCE_MAP.json +52 -47
  8. package/dist/docs/references/docs-memory-observational-memory.md +36 -0
  9. package/dist/docs/references/reference-memory-observational-memory.md +42 -3
  10. package/dist/index.cjs +17 -10
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +20 -2
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +7 -4
  15. package/dist/index.js.map +1 -1
  16. package/dist/{observational-memory-APEZUJUQ.cjs → observational-memory-COYJCVX3.cjs} +32 -28
  17. package/dist/{observational-memory-APEZUJUQ.cjs.map → observational-memory-COYJCVX3.cjs.map} +1 -1
  18. package/dist/observational-memory-K2U3QQIO.js +3 -0
  19. package/dist/{observational-memory-OZ7TG4DZ.js.map → observational-memory-K2U3QQIO.js.map} +1 -1
  20. package/dist/processors/index.cjs +30 -26
  21. package/dist/processors/index.js +1 -1
  22. package/dist/processors/observational-memory/index.d.ts +1 -0
  23. package/dist/processors/observational-memory/index.d.ts.map +1 -1
  24. package/dist/processors/observational-memory/model-by-input-tokens.d.ts +14 -0
  25. package/dist/processors/observational-memory/model-by-input-tokens.d.ts.map +1 -0
  26. package/dist/processors/observational-memory/observational-memory.d.ts +19 -5
  27. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  28. package/dist/processors/observational-memory/types.d.ts +4 -2
  29. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  30. package/package.json +8 -8
  31. package/dist/chunk-CNOHXG5O.cjs.map +0 -1
  32. package/dist/chunk-T5FHEWK6.js.map +0 -1
  33. package/dist/observational-memory-OZ7TG4DZ.js +0 -3
@@ -4,6 +4,7 @@ import { Agent } from '@mastra/core/agent';
4
4
  import { coreFeatures } from '@mastra/core/features';
5
5
  import { resolveModelConfig } from '@mastra/core/llm';
6
6
  import { setThreadOMMetadata, getThreadOMMetadata, parseMemoryRequestContext } from '@mastra/core/memory';
7
+ import { getOrCreateSpan, SpanType, createObservabilityContext } from '@mastra/core/observability';
7
8
  import { MessageHistory } from '@mastra/core/processors';
8
9
  import xxhash from 'xxhash-wasm';
9
10
  import { randomBytes, createHash, randomUUID } from 'crypto';
@@ -312,6 +313,53 @@ function createThreadUpdateMarker(params) {
312
313
  }
313
314
  };
314
315
  }
316
+
317
+ // src/processors/observational-memory/model-by-input-tokens.ts
318
+ function isTieredModelTarget(model) {
319
+ if (typeof model === "string") {
320
+ return true;
321
+ }
322
+ if (!model || typeof model !== "object") {
323
+ return false;
324
+ }
325
+ return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
326
+ }
327
+ function normalizeThresholds(config) {
328
+ const entries = Object.entries(config.upTo);
329
+ if (entries.length === 0) {
330
+ throw new Error('ModelByInputTokens requires at least one threshold in "upTo"');
331
+ }
332
+ for (const [limitStr, model] of entries) {
333
+ const limit = Number(limitStr);
334
+ if (!Number.isFinite(limit) || limit <= 0) {
335
+ throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
336
+ }
337
+ if (!isTieredModelTarget(model)) {
338
+ throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
339
+ }
340
+ }
341
+ return entries.map(([limitStr, model]) => ({ limit: Number(limitStr), model })).sort((a, b) => a.limit - b.limit);
342
+ }
343
+ var ModelByInputTokens = class {
344
+ thresholds;
345
+ constructor(config) {
346
+ this.thresholds = normalizeThresholds(config);
347
+ }
348
+ resolve(inputTokens) {
349
+ for (const { limit, model } of this.thresholds) {
350
+ if (inputTokens <= limit) {
351
+ return model;
352
+ }
353
+ }
354
+ const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
355
+ throw new Error(
356
+ `ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`
357
+ );
358
+ }
359
+ getThresholds() {
360
+ return this.thresholds.map((t) => t.limit);
361
+ }
362
+ };
315
363
  var OBSERVATION_GROUP_PATTERN = /<observation-group\s([^>]*)>([\s\S]*?)<\/observation-group>/g;
316
364
  var ATTRIBUTE_PATTERN = /([\w][\w-]*)="([^"]*)"/g;
317
365
  var REFLECTION_GROUP_SPLIT_PATTERN = /^##\s+Group\s+/m;
@@ -3466,8 +3514,10 @@ var ObservationalMemory = class _ObservationalMemory {
3466
3514
  onDebugEvent;
3467
3515
  /** Internal Observer agent - created lazily */
3468
3516
  observerAgent;
3517
+ observerAgentModel;
3469
3518
  /** Internal Reflector agent - created lazily */
3470
3519
  reflectorAgent;
3520
+ reflectorAgentModel;
3471
3521
  shouldObscureThreadIds = false;
3472
3522
  hasher = xxhash();
3473
3523
  threadIdCache = /* @__PURE__ */ new Map();
@@ -3774,7 +3824,15 @@ var ObservationalMemory = class _ObservationalMemory {
3774
3824
  this.storage = config.storage;
3775
3825
  this.scope = config.scope ?? "thread";
3776
3826
  this.retrieval = this.scope === "thread" && (config.retrieval ?? OBSERVATIONAL_MEMORY_DEFAULTS.retrieval);
3777
- const resolveModel = (m) => m === "default" ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.model : m;
3827
+ const resolveModel = (m) => {
3828
+ if (m === "default") {
3829
+ return OBSERVATIONAL_MEMORY_DEFAULTS.observation.model;
3830
+ }
3831
+ if (m instanceof ModelByInputTokens) {
3832
+ return m;
3833
+ }
3834
+ return m;
3835
+ };
3778
3836
  const observationModel = resolveModel(config.model) ?? resolveModel(config.observation?.model) ?? resolveModel(config.reflection?.model);
3779
3837
  const reflectionModel = resolveModel(config.model) ?? resolveModel(config.reflection?.model) ?? resolveModel(config.observation?.model);
3780
3838
  if (!observationModel || !reflectionModel) {
@@ -3791,7 +3849,9 @@ See https://mastra.ai/docs/memory/observational-memory#models for model recommen
3791
3849
  const messageTokens = config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens;
3792
3850
  const observationTokens = config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens;
3793
3851
  const isSharedBudget = config.shareTokenBudget ?? false;
3794
- const isDefaultModelSelection = (model) => model === void 0 || model === "default";
3852
+ const isDefaultModelSelection = (model) => {
3853
+ return model === void 0 || model === "default";
3854
+ };
3795
3855
  const observationSelectedModel = config.model ?? config.observation?.model ?? config.reflection?.model;
3796
3856
  const reflectionSelectedModel = config.model ?? config.reflection?.model ?? config.observation?.model;
3797
3857
  const observationDefaultMaxOutputTokens = config.observation?.modelSettings?.maxOutputTokens ?? (isDefaultModelSelection(observationSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.maxOutputTokens : void 0);
@@ -3894,6 +3954,15 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3894
3954
  async waitForBuffering(threadId, resourceId, timeoutMs = 3e4) {
3895
3955
  return _ObservationalMemory.awaitBuffering(threadId, resourceId, this.scope, timeoutMs);
3896
3956
  }
3957
+ getConcreteModel(model, inputTokens) {
3958
+ if (model instanceof ModelByInputTokens) {
3959
+ if (inputTokens === void 0) {
3960
+ throw new Error("ModelByInputTokens requires inputTokens for resolution");
3961
+ }
3962
+ return model.resolve(inputTokens);
3963
+ }
3964
+ return model;
3965
+ }
3897
3966
  getModelToResolve(model) {
3898
3967
  if (Array.isArray(model)) {
3899
3968
  return model[0]?.model ?? "unknown";
@@ -3932,7 +4001,11 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3932
4001
  */
3933
4002
  async getCompressionStartLevel(requestContext) {
3934
4003
  try {
3935
- const resolved = await this.resolveModelContext(this.reflectionConfig.model, requestContext);
4004
+ const modelConfig = this.getConcreteModel(
4005
+ this.reflectionConfig.model,
4006
+ this.reflectionConfig.model instanceof ModelByInputTokens ? 1 : void 0
4007
+ );
4008
+ const resolved = await this.resolveModelContext(modelConfig, requestContext);
3936
4009
  const modelId = resolved?.modelId ?? "";
3937
4010
  if (modelId.includes("gemini-2.5-flash")) {
3938
4011
  return 2;
@@ -3954,34 +4027,97 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3954
4027
  runWithTokenCounterModelContext(modelContext, fn) {
3955
4028
  return this.tokenCounter.runWithModelContext(modelContext, fn);
3956
4029
  }
4030
+ async formatRoutingModel(model, requestContext) {
4031
+ if (!model) {
4032
+ return void 0;
4033
+ }
4034
+ if (typeof model === "string") {
4035
+ return model;
4036
+ }
4037
+ const resolvedModel = await this.resolveModelContext(model, requestContext);
4038
+ if (resolvedModel) {
4039
+ return this.formatModelName(resolvedModel);
4040
+ }
4041
+ const runtimeModel = this.getRuntimeModelContext(model);
4042
+ return runtimeModel ? this.formatModelName(runtimeModel) : void 0;
4043
+ }
4044
+ async withOmTracingSpan(options) {
4045
+ const { phase, inputTokens, resolvedModel, selectedThreshold, routingModel, requestContext, tracingContext, fn } = options;
4046
+ const selectedModel = await this.formatRoutingModel(resolvedModel, requestContext) ?? "(unknown)";
4047
+ if (!tracingContext) {
4048
+ return fn();
4049
+ }
4050
+ const span = getOrCreateSpan({
4051
+ type: SpanType.GENERIC,
4052
+ name: `om.${phase}`,
4053
+ attributes: {
4054
+ omPhase: phase,
4055
+ omInputTokens: inputTokens,
4056
+ omSelectedModel: selectedModel,
4057
+ ...selectedThreshold !== void 0 ? { omSelectedThreshold: selectedThreshold } : {},
4058
+ ...routingModel ? {
4059
+ omRoutingStrategy: "model-by-input-tokens",
4060
+ omRoutingThresholds: routingModel.getThresholds().join(",")
4061
+ } : {}
4062
+ },
4063
+ tracingContext,
4064
+ requestContext
4065
+ });
4066
+ if (!span) {
4067
+ return fn();
4068
+ }
4069
+ const observabilityContext = createObservabilityContext({ currentSpan: span });
4070
+ return span.executeInContext(() => fn(observabilityContext));
4071
+ }
3957
4072
  /**
3958
4073
  * Get the full config including resolved model names.
3959
4074
  * This is async because it needs to resolve the model configs.
3960
4075
  */
3961
4076
  async getResolvedConfig(requestContext) {
3962
- const safeResolveModel = async (modelConfig) => {
4077
+ const resolveRouting = async (modelConfig) => {
3963
4078
  try {
4079
+ if (modelConfig instanceof ModelByInputTokens) {
4080
+ const routing = await Promise.all(
4081
+ modelConfig.getThresholds().map(async (upTo) => {
4082
+ const resolvedModel = modelConfig.resolve(upTo);
4083
+ const resolved2 = await this.resolveModelContext(resolvedModel, requestContext);
4084
+ return {
4085
+ upTo,
4086
+ model: resolved2?.modelId ? this.formatModelName(resolved2) : "(unknown)"
4087
+ };
4088
+ })
4089
+ );
4090
+ return {
4091
+ model: routing[0]?.model ?? "(unknown)",
4092
+ routing
4093
+ };
4094
+ }
3964
4095
  const resolved = await this.resolveModelContext(modelConfig, requestContext);
3965
- return resolved?.modelId ? this.formatModelName(resolved) : "(unknown)";
4096
+ return {
4097
+ model: resolved?.modelId ? this.formatModelName(resolved) : "(unknown)"
4098
+ };
3966
4099
  } catch (error) {
3967
4100
  omError("[OM] Failed to resolve model config", error);
3968
- return "(unknown)";
4101
+ return { model: "(unknown)" };
3969
4102
  }
3970
4103
  };
3971
- const [observationModelName, reflectionModelName] = await Promise.all([
3972
- safeResolveModel(this.observationConfig.model),
3973
- safeResolveModel(this.reflectionConfig.model)
4104
+ const [observationResolved, reflectionResolved] = await Promise.all([
4105
+ resolveRouting(this.observationConfig.model),
4106
+ resolveRouting(this.reflectionConfig.model)
3974
4107
  ]);
3975
4108
  return {
3976
4109
  scope: this.scope,
4110
+ shareTokenBudget: this.observationConfig.shareTokenBudget,
3977
4111
  observation: {
3978
4112
  messageTokens: this.observationConfig.messageTokens,
3979
- model: observationModelName,
3980
- previousObserverTokens: this.observationConfig.previousObserverTokens
4113
+ model: observationResolved.model,
4114
+ previousObserverTokens: this.observationConfig.previousObserverTokens,
4115
+ routing: observationResolved.routing
3981
4116
  },
3982
4117
  reflection: {
3983
4118
  observationTokens: this.reflectionConfig.observationTokens,
3984
- model: reflectionModelName
4119
+ model: reflectionResolved.model,
4120
+ routing: reflectionResolved.routing
3985
4121
  }
3986
4122
  };
3987
4123
  }
@@ -4083,8 +4219,11 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
4083
4219
  /**
4084
4220
  * Get or create the Observer agent
4085
4221
  */
4086
- getObserverAgent() {
4087
- if (!this.observerAgent) {
4222
+ getObserverAgent(model) {
4223
+ if (this.observerAgent && this.observerAgentModel === void 0) {
4224
+ return this.observerAgent;
4225
+ }
4226
+ if (!this.observerAgent || this.observerAgentModel !== model) {
4088
4227
  const systemPrompt = buildObserverSystemPrompt(
4089
4228
  false,
4090
4229
  this.observationConfig.instruction,
@@ -4094,23 +4233,28 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
4094
4233
  id: "observational-memory-observer",
4095
4234
  name: "Observer",
4096
4235
  instructions: systemPrompt,
4097
- model: this.observationConfig.model
4236
+ model
4098
4237
  });
4238
+ this.observerAgentModel = model;
4099
4239
  }
4100
4240
  return this.observerAgent;
4101
4241
  }
4102
4242
  /**
4103
4243
  * Get or create the Reflector agent
4104
4244
  */
4105
- getReflectorAgent() {
4106
- if (!this.reflectorAgent) {
4245
+ getReflectorAgent(model) {
4246
+ if (this.reflectorAgent && this.reflectorAgentModel === void 0) {
4247
+ return this.reflectorAgent;
4248
+ }
4249
+ if (!this.reflectorAgent || this.reflectorAgentModel !== model) {
4107
4250
  const systemPrompt = buildReflectorSystemPrompt(this.reflectionConfig.instruction);
4108
4251
  this.reflectorAgent = new Agent({
4109
4252
  id: "observational-memory-reflector",
4110
4253
  name: "Reflector",
4111
4254
  instructions: systemPrompt,
4112
- model: this.reflectionConfig.model
4255
+ model
4113
4256
  });
4257
+ this.reflectorAgentModel = model;
4114
4258
  }
4115
4259
  return this.reflectorAgent;
4116
4260
  }
@@ -4590,7 +4734,6 @@ ${unreflectedContent}` : bufferedReflection;
4590
4734
  * Call the Observer agent to extract observations.
4591
4735
  */
4592
4736
  async callObserver(existingObservations, messagesToObserve, abortSignal, options) {
4593
- const agent = this.getObserverAgent();
4594
4737
  const observerMessages = [
4595
4738
  {
4596
4739
  role: "user",
@@ -4605,18 +4748,35 @@ ${unreflectedContent}` : bufferedReflection;
4605
4748
  },
4606
4749
  buildObserverHistoryMessage(messagesToObserve)
4607
4750
  ];
4751
+ const inputTokens = this.tokenCounter.countMessages(messagesToObserve);
4752
+ const requestContext = options?.requestContext;
4753
+ const tracingContext = options?.tracingContext;
4754
+ const routingModel = this.observationConfig.model instanceof ModelByInputTokens ? this.observationConfig.model : void 0;
4755
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => inputTokens <= threshold);
4756
+ const resolvedModel = this.getConcreteModel(this.observationConfig.model, inputTokens);
4757
+ const agent = this.getObserverAgent(resolvedModel);
4608
4758
  const doGenerate = async () => {
4609
- const result2 = await this.withAbortCheck(async () => {
4610
- const streamResult = await agent.stream(observerMessages, {
4611
- modelSettings: {
4612
- ...this.observationConfig.modelSettings
4613
- },
4614
- providerOptions: this.observationConfig.providerOptions,
4615
- ...abortSignal ? { abortSignal } : {},
4616
- ...options?.requestContext ? { requestContext: options.requestContext } : {}
4617
- });
4618
- return streamResult.getFullOutput();
4619
- }, abortSignal);
4759
+ const result2 = await this.withOmTracingSpan({
4760
+ phase: "observer",
4761
+ inputTokens,
4762
+ resolvedModel,
4763
+ selectedThreshold,
4764
+ routingModel,
4765
+ requestContext,
4766
+ tracingContext,
4767
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4768
+ const streamResult = await agent.stream(observerMessages, {
4769
+ ...observabilityContext,
4770
+ modelSettings: {
4771
+ ...this.observationConfig.modelSettings
4772
+ },
4773
+ providerOptions: this.observationConfig.providerOptions,
4774
+ ...abortSignal ? { abortSignal } : {},
4775
+ ...requestContext ? { requestContext } : {}
4776
+ });
4777
+ return streamResult.getFullOutput();
4778
+ }, abortSignal)
4779
+ });
4620
4780
  return result2;
4621
4781
  };
4622
4782
  let result = await doGenerate();
@@ -4649,18 +4809,12 @@ ${unreflectedContent}` : bufferedReflection;
4649
4809
  * Returns per-thread results with observations, currentTask, and suggestedContinuation,
4650
4810
  * plus the total usage for the batch.
4651
4811
  */
4652
- async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, abortSignal, requestContext, wasTruncated) {
4812
+ async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, abortSignal, requestContext, wasTruncated, tracingContext) {
4653
4813
  const systemPrompt = buildObserverSystemPrompt(
4654
4814
  true,
4655
4815
  this.observationConfig.instruction,
4656
4816
  this.observationConfig.threadTitle
4657
4817
  );
4658
- const agent = new Agent({
4659
- id: "multi-thread-observer",
4660
- name: "multi-thread-observer",
4661
- model: this.observationConfig.model,
4662
- instructions: systemPrompt
4663
- });
4664
4818
  const observerMessages = [
4665
4819
  {
4666
4820
  role: "user",
@@ -4681,18 +4835,38 @@ ${unreflectedContent}` : bufferedReflection;
4681
4835
  for (const msg of allMessages) {
4682
4836
  this.observedMessageIds.add(msg.id);
4683
4837
  }
4838
+ const inputTokens = this.tokenCounter.countMessages(allMessages);
4839
+ const routingModel = this.observationConfig.model instanceof ModelByInputTokens ? this.observationConfig.model : void 0;
4840
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => inputTokens <= threshold);
4841
+ const resolvedModel = this.getConcreteModel(this.observationConfig.model, inputTokens);
4842
+ const agent = new Agent({
4843
+ id: "multi-thread-observer",
4844
+ name: "multi-thread-observer",
4845
+ model: resolvedModel,
4846
+ instructions: systemPrompt
4847
+ });
4684
4848
  const doGenerate = async () => {
4685
- const result2 = await this.withAbortCheck(async () => {
4686
- const streamResult = await agent.stream(observerMessages, {
4687
- modelSettings: {
4688
- ...this.observationConfig.modelSettings
4689
- },
4690
- providerOptions: this.observationConfig.providerOptions,
4691
- ...abortSignal ? { abortSignal } : {},
4692
- ...requestContext ? { requestContext } : {}
4693
- });
4694
- return streamResult.getFullOutput();
4695
- }, abortSignal);
4849
+ const result2 = await this.withOmTracingSpan({
4850
+ phase: "observer",
4851
+ inputTokens,
4852
+ resolvedModel,
4853
+ selectedThreshold,
4854
+ routingModel,
4855
+ requestContext,
4856
+ tracingContext,
4857
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4858
+ const streamResult = await agent.stream(observerMessages, {
4859
+ ...observabilityContext,
4860
+ modelSettings: {
4861
+ ...this.observationConfig.modelSettings
4862
+ },
4863
+ providerOptions: this.observationConfig.providerOptions,
4864
+ ...abortSignal ? { abortSignal } : {},
4865
+ ...requestContext ? { requestContext } : {}
4866
+ });
4867
+ return streamResult.getFullOutput();
4868
+ }, abortSignal)
4869
+ });
4696
4870
  return result2;
4697
4871
  };
4698
4872
  let result = await doGenerate();
@@ -4734,9 +4908,12 @@ ${unreflectedContent}` : bufferedReflection;
4734
4908
  * Call the Reflector agent to condense observations.
4735
4909
  * Includes compression validation and retry logic.
4736
4910
  */
4737
- async callReflector(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext) {
4738
- const agent = this.getReflectorAgent();
4911
+ async callReflector(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext, tracingContext) {
4739
4912
  const originalTokens = this.tokenCounter.countObservations(observations);
4913
+ const routingModel = this.reflectionConfig.model instanceof ModelByInputTokens ? this.reflectionConfig.model : void 0;
4914
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => originalTokens <= threshold);
4915
+ const resolvedModel = this.getConcreteModel(this.reflectionConfig.model, originalTokens);
4916
+ const agent = this.getReflectorAgent(resolvedModel);
4740
4917
  const targetThreshold = observationTokensThreshold ?? getMaxThreshold(this.reflectionConfig.observationTokens);
4741
4918
  let totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
4742
4919
  const startLevel = compressionStartLevel ?? 0;
@@ -4753,37 +4930,47 @@ ${unreflectedContent}` : bufferedReflection;
4753
4930
  `[OM:callReflector] ${isRetry ? `retry #${attemptNumber - 1}` : "first attempt"}: level=${currentLevel}, originalTokens=${originalTokens}, targetThreshold=${targetThreshold}, promptLen=${prompt.length}, skipContinuationHints=${skipContinuationHints}`
4754
4931
  );
4755
4932
  let chunkCount = 0;
4756
- const result = await this.withAbortCheck(async () => {
4757
- const streamResult = await agent.stream(prompt, {
4758
- modelSettings: {
4759
- ...this.reflectionConfig.modelSettings
4760
- },
4761
- providerOptions: this.reflectionConfig.providerOptions,
4762
- ...abortSignal ? { abortSignal } : {},
4763
- ...requestContext ? { requestContext } : {},
4764
- ...attemptNumber === 1 ? {
4765
- onChunk(chunk) {
4766
- chunkCount++;
4767
- if (chunkCount === 1 || chunkCount % 50 === 0) {
4768
- const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
4769
- omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
4770
- }
4771
- },
4772
- onFinish(event) {
4773
- omDebug(
4774
- `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
4775
- );
4776
- },
4777
- onAbort(event) {
4778
- omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
4933
+ const result = await this.withOmTracingSpan({
4934
+ phase: "reflector",
4935
+ inputTokens: originalTokens,
4936
+ resolvedModel,
4937
+ selectedThreshold,
4938
+ routingModel,
4939
+ requestContext,
4940
+ tracingContext,
4941
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4942
+ const streamResult = await agent.stream(prompt, {
4943
+ ...observabilityContext,
4944
+ modelSettings: {
4945
+ ...this.reflectionConfig.modelSettings
4779
4946
  },
4780
- onError({ error }) {
4781
- omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
4782
- }
4783
- } : {}
4784
- });
4785
- return streamResult.getFullOutput();
4786
- }, abortSignal);
4947
+ providerOptions: this.reflectionConfig.providerOptions,
4948
+ ...abortSignal ? { abortSignal } : {},
4949
+ ...requestContext ? { requestContext } : {},
4950
+ ...attemptNumber === 1 ? {
4951
+ onChunk(chunk) {
4952
+ chunkCount++;
4953
+ if (chunkCount === 1 || chunkCount % 50 === 0) {
4954
+ const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
4955
+ omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
4956
+ }
4957
+ },
4958
+ onFinish(event) {
4959
+ omDebug(
4960
+ `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
4961
+ );
4962
+ },
4963
+ onAbort(event) {
4964
+ omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
4965
+ },
4966
+ onError({ error }) {
4967
+ omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
4968
+ }
4969
+ } : {}
4970
+ });
4971
+ return streamResult.getFullOutput();
4972
+ }, abortSignal)
4973
+ });
4787
4974
  omDebug(
4788
4975
  `[OM:callReflector] attempt #${attemptNumber} returned: textLen=${result.text?.length}, textPreview="${result.text?.slice(0, 120)}...", inputTokens=${result.usage?.inputTokens ?? result.totalUsage?.inputTokens}, outputTokens=${result.usage?.outputTokens ?? result.totalUsage?.outputTokens}`
4789
4976
  );
@@ -5088,7 +5275,7 @@ ${suggestedResponse}
5088
5275
  * Tries async activation first if enabled, then falls back to sync observation.
5089
5276
  * Returns whether observation succeeded.
5090
5277
  */
5091
- async handleThresholdReached(messageList, record, threadId, resourceId, threshold, lockKey, writer, abortSignal, abort, requestContext) {
5278
+ async handleThresholdReached(messageList, record, threadId, resourceId, threshold, lockKey, writer, abortSignal, abort, requestContext, tracingContext) {
5092
5279
  let observationSucceeded = false;
5093
5280
  let updatedRecord = record;
5094
5281
  let activatedMessageIds;
@@ -5187,7 +5374,8 @@ ${suggestedResponse}
5187
5374
  currentThreadMessages: freshUnobservedMessages,
5188
5375
  writer,
5189
5376
  abortSignal,
5190
- requestContext
5377
+ requestContext,
5378
+ tracingContext
5191
5379
  });
5192
5380
  } else {
5193
5381
  await this.doSynchronousObservation({
@@ -5196,7 +5384,8 @@ ${suggestedResponse}
5196
5384
  unobservedMessages: freshUnobservedMessages,
5197
5385
  writer,
5198
5386
  abortSignal,
5199
- requestContext
5387
+ requestContext,
5388
+ tracingContext
5200
5389
  });
5201
5390
  }
5202
5391
  updatedRecord = await this.getOrCreateRecord(threadId, resourceId);
@@ -5466,7 +5655,17 @@ ${suggestedResponse}
5466
5655
  * 5. Filter out already-observed messages
5467
5656
  */
5468
5657
  async processInputStep(args) {
5469
- const { messageList, requestContext, stepNumber, state: _state, writer, abortSignal, abort, model } = args;
5658
+ const {
5659
+ messageList,
5660
+ requestContext,
5661
+ tracingContext,
5662
+ stepNumber,
5663
+ state: _state,
5664
+ writer,
5665
+ abortSignal,
5666
+ abort,
5667
+ model
5668
+ } = args;
5470
5669
  const state = _state ?? {};
5471
5670
  omDebug(
5472
5671
  `[OM:processInputStep:ENTER] step=${stepNumber}, hasMastraMemory=${!!requestContext?.get("MastraMemory")}, hasMemoryInfo=${!!messageList?.serialize()?.memoryInfo?.threadId}`
@@ -5588,7 +5787,8 @@ ${suggestedResponse}
5588
5787
  threadId,
5589
5788
  writer,
5590
5789
  messageList,
5591
- requestContext
5790
+ requestContext,
5791
+ tracingContext
5592
5792
  });
5593
5793
  record = await this.getOrCreateRecord(threadId, resourceId);
5594
5794
  }
@@ -5605,7 +5805,8 @@ ${suggestedResponse}
5605
5805
  threadId,
5606
5806
  writer,
5607
5807
  messageList,
5608
- requestContext
5808
+ requestContext,
5809
+ tracingContext
5609
5810
  });
5610
5811
  record = await this.getOrCreateRecord(threadId, resourceId);
5611
5812
  } else if (this.isAsyncReflectionEnabled()) {
@@ -5661,7 +5862,8 @@ ${suggestedResponse}
5661
5862
  lockKey,
5662
5863
  writer,
5663
5864
  unbufferedPendingTokens,
5664
- requestContext
5865
+ requestContext,
5866
+ tracingContext
5665
5867
  );
5666
5868
  }
5667
5869
  } else if (this.isAsyncObservationEnabled()) {
@@ -5677,7 +5879,8 @@ ${suggestedResponse}
5677
5879
  lockKey,
5678
5880
  writer,
5679
5881
  unbufferedPendingTokens,
5680
- requestContext
5882
+ requestContext,
5883
+ tracingContext
5681
5884
  );
5682
5885
  }
5683
5886
  }
@@ -5696,7 +5899,8 @@ ${suggestedResponse}
5696
5899
  writer,
5697
5900
  abortSignal,
5698
5901
  abort,
5699
- requestContext
5902
+ requestContext,
5903
+ tracingContext
5700
5904
  );
5701
5905
  if (observationSucceeded) {
5702
5906
  const observedIds = activatedMessageIds?.length ? activatedMessageIds : Array.isArray(updatedRecord.observedMessageIds) ? updatedRecord.observedMessageIds : void 0;
@@ -6105,7 +6309,16 @@ ${threadClose}`;
6105
6309
  * Do synchronous observation (fallback when no buffering)
6106
6310
  */
6107
6311
  async doSynchronousObservation(opts) {
6108
- const { record, threadId, unobservedMessages, writer, abortSignal, reflectionHooks, requestContext } = opts;
6312
+ const {
6313
+ record,
6314
+ threadId,
6315
+ unobservedMessages,
6316
+ writer,
6317
+ abortSignal,
6318
+ reflectionHooks,
6319
+ requestContext,
6320
+ tracingContext
6321
+ } = opts;
6109
6322
  this.emitDebugEvent({
6110
6323
  type: "observation_triggered",
6111
6324
  timestamp: /* @__PURE__ */ new Date(),
@@ -6164,6 +6377,7 @@ ${threadClose}`;
6164
6377
  const threadOMMetadata = getThreadOMMetadata(thread?.metadata);
6165
6378
  const result = await this.callObserver(observerContext, messagesToObserve, abortSignal, {
6166
6379
  requestContext,
6380
+ tracingContext,
6167
6381
  priorCurrentTask: threadOMMetadata?.currentTask,
6168
6382
  priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
6169
6383
  priorThreadTitle: thread?.title,
@@ -6271,7 +6485,8 @@ ${threadClose}`;
6271
6485
  writer,
6272
6486
  abortSignal,
6273
6487
  reflectionHooks,
6274
- requestContext
6488
+ requestContext,
6489
+ tracingContext
6275
6490
  });
6276
6491
  } catch (error) {
6277
6492
  if (lastMessage?.id) {
@@ -6289,10 +6504,7 @@ ${threadClose}`;
6289
6504
  });
6290
6505
  }
6291
6506
  }
6292
- if (abortSignal?.aborted) {
6293
- throw error;
6294
- }
6295
- omError("[OM] Observation failed", error);
6507
+ throw error;
6296
6508
  } finally {
6297
6509
  await this.storage.setObservingFlag(record.id, false);
6298
6510
  unregisterOp(record.id, "observing");
@@ -6312,7 +6524,7 @@ ${threadClose}`;
6312
6524
  * @param lockKey - Lock key for this scope
6313
6525
  * @param writer - Optional stream writer for emitting buffering markers
6314
6526
  */
6315
- async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext) {
6527
+ async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext, tracingContext) {
6316
6528
  const bufferKey = this.getObservationBufferKey(lockKey);
6317
6529
  const currentTokens = contextWindowTokens ?? await this.tokenCounter.countMessagesAsync(unobservedMessages) + (record.pendingMessageTokens ?? 0);
6318
6530
  _ObservationalMemory.lastBufferedBoundary.set(bufferKey, currentTokens);
@@ -6326,7 +6538,8 @@ ${threadClose}`;
6326
6538
  unobservedMessages,
6327
6539
  bufferKey,
6328
6540
  writer,
6329
- requestContext
6541
+ requestContext,
6542
+ tracingContext
6330
6543
  ).finally(() => {
6331
6544
  _ObservationalMemory.asyncBufferingOps.delete(bufferKey);
6332
6545
  unregisterOp(record.id, "bufferingObservation");
@@ -6340,7 +6553,7 @@ ${threadClose}`;
6340
6553
  * Internal method that waits for existing buffering operation and then runs new buffering.
6341
6554
  * This implements the mutex-wait behavior.
6342
6555
  */
6343
- async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext) {
6556
+ async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext, tracingContext) {
6344
6557
  const existingOp = _ObservationalMemory.asyncBufferingOps.get(bufferKey);
6345
6558
  if (existingOp) {
6346
6559
  try {
@@ -6420,7 +6633,8 @@ ${threadClose}`;
6420
6633
  cycleId,
6421
6634
  startedAt,
6422
6635
  writer,
6423
- requestContext
6636
+ requestContext,
6637
+ tracingContext
6424
6638
  );
6425
6639
  const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
6426
6640
  const cursor = new Date(maxTs.getTime() + 1);
@@ -6450,7 +6664,7 @@ ${threadClose}`;
6450
6664
  * The observer sees: active observations + existing buffered observations + message history
6451
6665
  * (excluding already-buffered messages).
6452
6666
  */
6453
- async doAsyncBufferedObservation(record, threadId, messagesToBuffer, cycleId, startedAt, writer, requestContext) {
6667
+ async doAsyncBufferedObservation(record, threadId, messagesToBuffer, cycleId, startedAt, writer, requestContext, tracingContext) {
6454
6668
  const bufferedChunks = this.getBufferedChunks(record);
6455
6669
  const bufferedChunksText = bufferedChunks.map((c) => c.observations).join("\n\n");
6456
6670
  const combinedObservations = this.combineObservationsForBuffering(record.activeObservations, bufferedChunksText);
@@ -6465,6 +6679,7 @@ ${threadClose}`;
6465
6679
  {
6466
6680
  skipContinuationHints: true,
6467
6681
  requestContext,
6682
+ tracingContext,
6468
6683
  priorCurrentTask: threadOMMetadata?.currentTask,
6469
6684
  priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
6470
6685
  priorThreadTitle: thread?.title,
@@ -6905,7 +7120,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
6905
7120
  writer,
6906
7121
  abortSignal,
6907
7122
  reflectionHooks,
6908
- requestContext
7123
+ requestContext,
7124
+ tracingContext
6909
7125
  } = opts;
6910
7126
  const { threads: allThreads } = await this.storage.listThreads({ filter: { resourceId } });
6911
7127
  const threadMetadataMap = /* @__PURE__ */ new Map();
@@ -7083,7 +7299,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7083
7299
  batchPriorMetadata,
7084
7300
  abortSignal,
7085
7301
  requestContext,
7086
- wasTruncated
7302
+ wasTruncated,
7303
+ tracingContext
7087
7304
  );
7088
7305
  return batchResult;
7089
7306
  });
@@ -7211,7 +7428,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7211
7428
  writer,
7212
7429
  abortSignal,
7213
7430
  reflectionHooks,
7214
- requestContext
7431
+ requestContext,
7432
+ tracingContext
7215
7433
  });
7216
7434
  } catch (error) {
7217
7435
  for (const [threadId, msgs] of threadsWithMessages) {
@@ -7233,10 +7451,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7233
7451
  }
7234
7452
  }
7235
7453
  }
7236
- if (abortSignal?.aborted) {
7237
- throw error;
7238
- }
7239
- omError("[OM] Resource-scoped observation failed", error);
7454
+ throw error;
7240
7455
  } finally {
7241
7456
  await this.storage.setObservingFlag(record.id, false);
7242
7457
  unregisterOp(record.id, "observing");
@@ -7284,7 +7499,16 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7284
7499
  * in the background at intervals, and activated when the threshold is reached.
7285
7500
  */
7286
7501
  async maybeReflect(opts) {
7287
- const { record, observationTokens, writer, abortSignal, messageList, reflectionHooks, requestContext } = opts;
7502
+ const {
7503
+ record,
7504
+ observationTokens,
7505
+ writer,
7506
+ abortSignal,
7507
+ messageList,
7508
+ reflectionHooks,
7509
+ requestContext,
7510
+ tracingContext
7511
+ } = opts;
7288
7512
  const lockKey = this.getLockKey(record.threadId, record.resourceId);
7289
7513
  const reflectThreshold = getMaxThreshold(this.reflectionConfig.observationTokens);
7290
7514
  if (this.isAsyncReflectionEnabled() && observationTokens < reflectThreshold) {
@@ -7363,7 +7587,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7363
7587
  abortSignal,
7364
7588
  void 0,
7365
7589
  void 0,
7366
- requestContext
7590
+ requestContext,
7591
+ tracingContext
7367
7592
  );
7368
7593
  const reflectionTokenCount = this.tokenCounter.countObservations(reflectResult.observations);
7369
7594
  await this.storage.createReflectionGeneration({
@@ -7409,10 +7634,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7409
7634
  await writer.custom(failedMarker).catch(() => {
7410
7635
  });
7411
7636
  }
7412
- if (abortSignal?.aborted) {
7413
- throw error;
7414
- }
7415
- omError("[OM] Reflection failed", error);
7637
+ throw error;
7416
7638
  } finally {
7417
7639
  await this.storage.setReflectingFlag(record.id, false);
7418
7640
  reflectionHooks?.onReflectionEnd?.();
@@ -7604,6 +7826,6 @@ function getObservationsAsOf(activeObservations, asOf) {
7604
7826
  return chunks.join("\n\n");
7605
7827
  }
7606
7828
 
7607
- export { OBSERVATIONAL_MEMORY_DEFAULTS, OBSERVATION_CONTEXT_INSTRUCTIONS, OBSERVATION_CONTEXT_PROMPT, OBSERVATION_CONTINUATION_HINT, OBSERVER_SYSTEM_PROMPT, ObservationalMemory, TokenCounter, buildObserverPrompt, buildObserverSystemPrompt, combineObservationGroupRanges, deriveObservationGroupProvenance, extractCurrentTask, formatMessagesForObserver, formatToolResultForObserver, getObservationsAsOf, hasCurrentTaskSection, injectAnchorIds, optimizeObservationsForContext, parseAnchorId, parseObservationGroups, parseObserverOutput, reconcileObservationGroupsFromReflection, renderObservationGroupsForReflection, resolveToolResultValue, stripEphemeralAnchorIds, stripObservationGroups, truncateStringByTokens, wrapInObservationGroup };
7608
- //# sourceMappingURL=chunk-T5FHEWK6.js.map
7609
- //# sourceMappingURL=chunk-T5FHEWK6.js.map
7829
+ export { ModelByInputTokens, OBSERVATIONAL_MEMORY_DEFAULTS, OBSERVATION_CONTEXT_INSTRUCTIONS, OBSERVATION_CONTEXT_PROMPT, OBSERVATION_CONTINUATION_HINT, OBSERVER_SYSTEM_PROMPT, ObservationalMemory, TokenCounter, buildObserverPrompt, buildObserverSystemPrompt, combineObservationGroupRanges, deriveObservationGroupProvenance, extractCurrentTask, formatMessagesForObserver, formatToolResultForObserver, getObservationsAsOf, hasCurrentTaskSection, injectAnchorIds, optimizeObservationsForContext, parseAnchorId, parseObservationGroups, parseObserverOutput, reconcileObservationGroupsFromReflection, renderObservationGroupsForReflection, resolveToolResultValue, stripEphemeralAnchorIds, stripObservationGroups, truncateStringByTokens, wrapInObservationGroup };
7830
+ //# sourceMappingURL=chunk-7A3UGAXY.js.map
7831
+ //# sourceMappingURL=chunk-7A3UGAXY.js.map