@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
@@ -6,6 +6,7 @@ var agent = require('@mastra/core/agent');
6
6
  var features = require('@mastra/core/features');
7
7
  var llm = require('@mastra/core/llm');
8
8
  var memory = require('@mastra/core/memory');
9
+ var observability = require('@mastra/core/observability');
9
10
  var processors = require('@mastra/core/processors');
10
11
  var xxhash = require('xxhash-wasm');
11
12
  var crypto$1 = require('crypto');
@@ -319,6 +320,53 @@ function createThreadUpdateMarker(params) {
319
320
  }
320
321
  };
321
322
  }
323
+
324
+ // src/processors/observational-memory/model-by-input-tokens.ts
325
+ function isTieredModelTarget(model) {
326
+ if (typeof model === "string") {
327
+ return true;
328
+ }
329
+ if (!model || typeof model !== "object") {
330
+ return false;
331
+ }
332
+ return "modelId" in model || "id" in model || "providerId" in model || "provider" in model || "doGenerate" in model && "doStream" in model;
333
+ }
334
+ function normalizeThresholds(config) {
335
+ const entries = Object.entries(config.upTo);
336
+ if (entries.length === 0) {
337
+ throw new Error('ModelByInputTokens requires at least one threshold in "upTo"');
338
+ }
339
+ for (const [limitStr, model] of entries) {
340
+ const limit = Number(limitStr);
341
+ if (!Number.isFinite(limit) || limit <= 0) {
342
+ throw new Error(`ModelByInputTokens threshold keys must be positive numbers. Got: ${limitStr}`);
343
+ }
344
+ if (!isTieredModelTarget(model)) {
345
+ throw new Error(`ModelByInputTokens requires a valid model target for threshold ${limitStr}`);
346
+ }
347
+ }
348
+ return entries.map(([limitStr, model]) => ({ limit: Number(limitStr), model })).sort((a, b) => a.limit - b.limit);
349
+ }
350
+ var ModelByInputTokens = class {
351
+ thresholds;
352
+ constructor(config) {
353
+ this.thresholds = normalizeThresholds(config);
354
+ }
355
+ resolve(inputTokens) {
356
+ for (const { limit, model } of this.thresholds) {
357
+ if (inputTokens <= limit) {
358
+ return model;
359
+ }
360
+ }
361
+ const maxLimit = this.thresholds[this.thresholds.length - 1].limit;
362
+ throw new Error(
363
+ `ModelByInputTokens: input token count (${inputTokens}) exceeds the largest configured threshold (${maxLimit}). Please configure a higher threshold or use a larger model.`
364
+ );
365
+ }
366
+ getThresholds() {
367
+ return this.thresholds.map((t) => t.limit);
368
+ }
369
+ };
322
370
  var OBSERVATION_GROUP_PATTERN = /<observation-group\s([^>]*)>([\s\S]*?)<\/observation-group>/g;
323
371
  var ATTRIBUTE_PATTERN = /([\w][\w-]*)="([^"]*)"/g;
324
372
  var REFLECTION_GROUP_SPLIT_PATTERN = /^##\s+Group\s+/m;
@@ -3473,8 +3521,10 @@ var ObservationalMemory = class _ObservationalMemory {
3473
3521
  onDebugEvent;
3474
3522
  /** Internal Observer agent - created lazily */
3475
3523
  observerAgent;
3524
+ observerAgentModel;
3476
3525
  /** Internal Reflector agent - created lazily */
3477
3526
  reflectorAgent;
3527
+ reflectorAgentModel;
3478
3528
  shouldObscureThreadIds = false;
3479
3529
  hasher = xxhash__default.default();
3480
3530
  threadIdCache = /* @__PURE__ */ new Map();
@@ -3781,7 +3831,15 @@ var ObservationalMemory = class _ObservationalMemory {
3781
3831
  this.storage = config.storage;
3782
3832
  this.scope = config.scope ?? "thread";
3783
3833
  this.retrieval = this.scope === "thread" && (config.retrieval ?? OBSERVATIONAL_MEMORY_DEFAULTS.retrieval);
3784
- const resolveModel = (m) => m === "default" ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.model : m;
3834
+ const resolveModel = (m) => {
3835
+ if (m === "default") {
3836
+ return OBSERVATIONAL_MEMORY_DEFAULTS.observation.model;
3837
+ }
3838
+ if (m instanceof ModelByInputTokens) {
3839
+ return m;
3840
+ }
3841
+ return m;
3842
+ };
3785
3843
  const observationModel = resolveModel(config.model) ?? resolveModel(config.observation?.model) ?? resolveModel(config.reflection?.model);
3786
3844
  const reflectionModel = resolveModel(config.model) ?? resolveModel(config.reflection?.model) ?? resolveModel(config.observation?.model);
3787
3845
  if (!observationModel || !reflectionModel) {
@@ -3798,7 +3856,9 @@ See https://mastra.ai/docs/memory/observational-memory#models for model recommen
3798
3856
  const messageTokens = config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens;
3799
3857
  const observationTokens = config.reflection?.observationTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.reflection.observationTokens;
3800
3858
  const isSharedBudget = config.shareTokenBudget ?? false;
3801
- const isDefaultModelSelection = (model) => model === void 0 || model === "default";
3859
+ const isDefaultModelSelection = (model) => {
3860
+ return model === void 0 || model === "default";
3861
+ };
3802
3862
  const observationSelectedModel = config.model ?? config.observation?.model ?? config.reflection?.model;
3803
3863
  const reflectionSelectedModel = config.model ?? config.reflection?.model ?? config.observation?.model;
3804
3864
  const observationDefaultMaxOutputTokens = config.observation?.modelSettings?.maxOutputTokens ?? (isDefaultModelSelection(observationSelectedModel) ? OBSERVATIONAL_MEMORY_DEFAULTS.observation.modelSettings.maxOutputTokens : void 0);
@@ -3901,6 +3961,15 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3901
3961
  async waitForBuffering(threadId, resourceId, timeoutMs = 3e4) {
3902
3962
  return _ObservationalMemory.awaitBuffering(threadId, resourceId, this.scope, timeoutMs);
3903
3963
  }
3964
+ getConcreteModel(model, inputTokens) {
3965
+ if (model instanceof ModelByInputTokens) {
3966
+ if (inputTokens === void 0) {
3967
+ throw new Error("ModelByInputTokens requires inputTokens for resolution");
3968
+ }
3969
+ return model.resolve(inputTokens);
3970
+ }
3971
+ return model;
3972
+ }
3904
3973
  getModelToResolve(model) {
3905
3974
  if (Array.isArray(model)) {
3906
3975
  return model[0]?.model ?? "unknown";
@@ -3939,7 +4008,11 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3939
4008
  */
3940
4009
  async getCompressionStartLevel(requestContext) {
3941
4010
  try {
3942
- const resolved = await this.resolveModelContext(this.reflectionConfig.model, requestContext);
4011
+ const modelConfig = this.getConcreteModel(
4012
+ this.reflectionConfig.model,
4013
+ this.reflectionConfig.model instanceof ModelByInputTokens ? 1 : void 0
4014
+ );
4015
+ const resolved = await this.resolveModelContext(modelConfig, requestContext);
3943
4016
  const modelId = resolved?.modelId ?? "";
3944
4017
  if (modelId.includes("gemini-2.5-flash")) {
3945
4018
  return 2;
@@ -3961,34 +4034,97 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
3961
4034
  runWithTokenCounterModelContext(modelContext, fn) {
3962
4035
  return this.tokenCounter.runWithModelContext(modelContext, fn);
3963
4036
  }
4037
+ async formatRoutingModel(model, requestContext) {
4038
+ if (!model) {
4039
+ return void 0;
4040
+ }
4041
+ if (typeof model === "string") {
4042
+ return model;
4043
+ }
4044
+ const resolvedModel = await this.resolveModelContext(model, requestContext);
4045
+ if (resolvedModel) {
4046
+ return this.formatModelName(resolvedModel);
4047
+ }
4048
+ const runtimeModel = this.getRuntimeModelContext(model);
4049
+ return runtimeModel ? this.formatModelName(runtimeModel) : void 0;
4050
+ }
4051
+ async withOmTracingSpan(options) {
4052
+ const { phase, inputTokens, resolvedModel, selectedThreshold, routingModel, requestContext, tracingContext, fn } = options;
4053
+ const selectedModel = await this.formatRoutingModel(resolvedModel, requestContext) ?? "(unknown)";
4054
+ if (!tracingContext) {
4055
+ return fn();
4056
+ }
4057
+ const span = observability.getOrCreateSpan({
4058
+ type: observability.SpanType.GENERIC,
4059
+ name: `om.${phase}`,
4060
+ attributes: {
4061
+ omPhase: phase,
4062
+ omInputTokens: inputTokens,
4063
+ omSelectedModel: selectedModel,
4064
+ ...selectedThreshold !== void 0 ? { omSelectedThreshold: selectedThreshold } : {},
4065
+ ...routingModel ? {
4066
+ omRoutingStrategy: "model-by-input-tokens",
4067
+ omRoutingThresholds: routingModel.getThresholds().join(",")
4068
+ } : {}
4069
+ },
4070
+ tracingContext,
4071
+ requestContext
4072
+ });
4073
+ if (!span) {
4074
+ return fn();
4075
+ }
4076
+ const observabilityContext = observability.createObservabilityContext({ currentSpan: span });
4077
+ return span.executeInContext(() => fn(observabilityContext));
4078
+ }
3964
4079
  /**
3965
4080
  * Get the full config including resolved model names.
3966
4081
  * This is async because it needs to resolve the model configs.
3967
4082
  */
3968
4083
  async getResolvedConfig(requestContext) {
3969
- const safeResolveModel = async (modelConfig) => {
4084
+ const resolveRouting = async (modelConfig) => {
3970
4085
  try {
4086
+ if (modelConfig instanceof ModelByInputTokens) {
4087
+ const routing = await Promise.all(
4088
+ modelConfig.getThresholds().map(async (upTo) => {
4089
+ const resolvedModel = modelConfig.resolve(upTo);
4090
+ const resolved2 = await this.resolveModelContext(resolvedModel, requestContext);
4091
+ return {
4092
+ upTo,
4093
+ model: resolved2?.modelId ? this.formatModelName(resolved2) : "(unknown)"
4094
+ };
4095
+ })
4096
+ );
4097
+ return {
4098
+ model: routing[0]?.model ?? "(unknown)",
4099
+ routing
4100
+ };
4101
+ }
3971
4102
  const resolved = await this.resolveModelContext(modelConfig, requestContext);
3972
- return resolved?.modelId ? this.formatModelName(resolved) : "(unknown)";
4103
+ return {
4104
+ model: resolved?.modelId ? this.formatModelName(resolved) : "(unknown)"
4105
+ };
3973
4106
  } catch (error) {
3974
4107
  omError("[OM] Failed to resolve model config", error);
3975
- return "(unknown)";
4108
+ return { model: "(unknown)" };
3976
4109
  }
3977
4110
  };
3978
- const [observationModelName, reflectionModelName] = await Promise.all([
3979
- safeResolveModel(this.observationConfig.model),
3980
- safeResolveModel(this.reflectionConfig.model)
4111
+ const [observationResolved, reflectionResolved] = await Promise.all([
4112
+ resolveRouting(this.observationConfig.model),
4113
+ resolveRouting(this.reflectionConfig.model)
3981
4114
  ]);
3982
4115
  return {
3983
4116
  scope: this.scope,
4117
+ shareTokenBudget: this.observationConfig.shareTokenBudget,
3984
4118
  observation: {
3985
4119
  messageTokens: this.observationConfig.messageTokens,
3986
- model: observationModelName,
3987
- previousObserverTokens: this.observationConfig.previousObserverTokens
4120
+ model: observationResolved.model,
4121
+ previousObserverTokens: this.observationConfig.previousObserverTokens,
4122
+ routing: observationResolved.routing
3988
4123
  },
3989
4124
  reflection: {
3990
4125
  observationTokens: this.reflectionConfig.observationTokens,
3991
- model: reflectionModelName
4126
+ model: reflectionResolved.model,
4127
+ routing: reflectionResolved.routing
3992
4128
  }
3993
4129
  };
3994
4130
  }
@@ -4090,8 +4226,11 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
4090
4226
  /**
4091
4227
  * Get or create the Observer agent
4092
4228
  */
4093
- getObserverAgent() {
4094
- if (!this.observerAgent) {
4229
+ getObserverAgent(model) {
4230
+ if (this.observerAgent && this.observerAgentModel === void 0) {
4231
+ return this.observerAgent;
4232
+ }
4233
+ if (!this.observerAgent || this.observerAgentModel !== model) {
4095
4234
  const systemPrompt = buildObserverSystemPrompt(
4096
4235
  false,
4097
4236
  this.observationConfig.instruction,
@@ -4101,23 +4240,28 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
4101
4240
  id: "observational-memory-observer",
4102
4241
  name: "Observer",
4103
4242
  instructions: systemPrompt,
4104
- model: this.observationConfig.model
4243
+ model
4105
4244
  });
4245
+ this.observerAgentModel = model;
4106
4246
  }
4107
4247
  return this.observerAgent;
4108
4248
  }
4109
4249
  /**
4110
4250
  * Get or create the Reflector agent
4111
4251
  */
4112
- getReflectorAgent() {
4113
- if (!this.reflectorAgent) {
4252
+ getReflectorAgent(model) {
4253
+ if (this.reflectorAgent && this.reflectorAgentModel === void 0) {
4254
+ return this.reflectorAgent;
4255
+ }
4256
+ if (!this.reflectorAgent || this.reflectorAgentModel !== model) {
4114
4257
  const systemPrompt = buildReflectorSystemPrompt(this.reflectionConfig.instruction);
4115
4258
  this.reflectorAgent = new agent.Agent({
4116
4259
  id: "observational-memory-reflector",
4117
4260
  name: "Reflector",
4118
4261
  instructions: systemPrompt,
4119
- model: this.reflectionConfig.model
4262
+ model
4120
4263
  });
4264
+ this.reflectorAgentModel = model;
4121
4265
  }
4122
4266
  return this.reflectorAgent;
4123
4267
  }
@@ -4597,7 +4741,6 @@ ${unreflectedContent}` : bufferedReflection;
4597
4741
  * Call the Observer agent to extract observations.
4598
4742
  */
4599
4743
  async callObserver(existingObservations, messagesToObserve, abortSignal, options) {
4600
- const agent = this.getObserverAgent();
4601
4744
  const observerMessages = [
4602
4745
  {
4603
4746
  role: "user",
@@ -4612,18 +4755,35 @@ ${unreflectedContent}` : bufferedReflection;
4612
4755
  },
4613
4756
  buildObserverHistoryMessage(messagesToObserve)
4614
4757
  ];
4758
+ const inputTokens = this.tokenCounter.countMessages(messagesToObserve);
4759
+ const requestContext = options?.requestContext;
4760
+ const tracingContext = options?.tracingContext;
4761
+ const routingModel = this.observationConfig.model instanceof ModelByInputTokens ? this.observationConfig.model : void 0;
4762
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => inputTokens <= threshold);
4763
+ const resolvedModel = this.getConcreteModel(this.observationConfig.model, inputTokens);
4764
+ const agent = this.getObserverAgent(resolvedModel);
4615
4765
  const doGenerate = async () => {
4616
- const result2 = await this.withAbortCheck(async () => {
4617
- const streamResult = await agent.stream(observerMessages, {
4618
- modelSettings: {
4619
- ...this.observationConfig.modelSettings
4620
- },
4621
- providerOptions: this.observationConfig.providerOptions,
4622
- ...abortSignal ? { abortSignal } : {},
4623
- ...options?.requestContext ? { requestContext: options.requestContext } : {}
4624
- });
4625
- return streamResult.getFullOutput();
4626
- }, abortSignal);
4766
+ const result2 = await this.withOmTracingSpan({
4767
+ phase: "observer",
4768
+ inputTokens,
4769
+ resolvedModel,
4770
+ selectedThreshold,
4771
+ routingModel,
4772
+ requestContext,
4773
+ tracingContext,
4774
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4775
+ const streamResult = await agent.stream(observerMessages, {
4776
+ ...observabilityContext,
4777
+ modelSettings: {
4778
+ ...this.observationConfig.modelSettings
4779
+ },
4780
+ providerOptions: this.observationConfig.providerOptions,
4781
+ ...abortSignal ? { abortSignal } : {},
4782
+ ...requestContext ? { requestContext } : {}
4783
+ });
4784
+ return streamResult.getFullOutput();
4785
+ }, abortSignal)
4786
+ });
4627
4787
  return result2;
4628
4788
  };
4629
4789
  let result = await doGenerate();
@@ -4656,18 +4816,12 @@ ${unreflectedContent}` : bufferedReflection;
4656
4816
  * Returns per-thread results with observations, currentTask, and suggestedContinuation,
4657
4817
  * plus the total usage for the batch.
4658
4818
  */
4659
- async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, abortSignal, requestContext, wasTruncated) {
4819
+ async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, abortSignal, requestContext, wasTruncated, tracingContext) {
4660
4820
  const systemPrompt = buildObserverSystemPrompt(
4661
4821
  true,
4662
4822
  this.observationConfig.instruction,
4663
4823
  this.observationConfig.threadTitle
4664
4824
  );
4665
- const agent$1 = new agent.Agent({
4666
- id: "multi-thread-observer",
4667
- name: "multi-thread-observer",
4668
- model: this.observationConfig.model,
4669
- instructions: systemPrompt
4670
- });
4671
4825
  const observerMessages = [
4672
4826
  {
4673
4827
  role: "user",
@@ -4688,18 +4842,38 @@ ${unreflectedContent}` : bufferedReflection;
4688
4842
  for (const msg of allMessages) {
4689
4843
  this.observedMessageIds.add(msg.id);
4690
4844
  }
4845
+ const inputTokens = this.tokenCounter.countMessages(allMessages);
4846
+ const routingModel = this.observationConfig.model instanceof ModelByInputTokens ? this.observationConfig.model : void 0;
4847
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => inputTokens <= threshold);
4848
+ const resolvedModel = this.getConcreteModel(this.observationConfig.model, inputTokens);
4849
+ const agent$1 = new agent.Agent({
4850
+ id: "multi-thread-observer",
4851
+ name: "multi-thread-observer",
4852
+ model: resolvedModel,
4853
+ instructions: systemPrompt
4854
+ });
4691
4855
  const doGenerate = async () => {
4692
- const result2 = await this.withAbortCheck(async () => {
4693
- const streamResult = await agent$1.stream(observerMessages, {
4694
- modelSettings: {
4695
- ...this.observationConfig.modelSettings
4696
- },
4697
- providerOptions: this.observationConfig.providerOptions,
4698
- ...abortSignal ? { abortSignal } : {},
4699
- ...requestContext ? { requestContext } : {}
4700
- });
4701
- return streamResult.getFullOutput();
4702
- }, abortSignal);
4856
+ const result2 = await this.withOmTracingSpan({
4857
+ phase: "observer",
4858
+ inputTokens,
4859
+ resolvedModel,
4860
+ selectedThreshold,
4861
+ routingModel,
4862
+ requestContext,
4863
+ tracingContext,
4864
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4865
+ const streamResult = await agent$1.stream(observerMessages, {
4866
+ ...observabilityContext,
4867
+ modelSettings: {
4868
+ ...this.observationConfig.modelSettings
4869
+ },
4870
+ providerOptions: this.observationConfig.providerOptions,
4871
+ ...abortSignal ? { abortSignal } : {},
4872
+ ...requestContext ? { requestContext } : {}
4873
+ });
4874
+ return streamResult.getFullOutput();
4875
+ }, abortSignal)
4876
+ });
4703
4877
  return result2;
4704
4878
  };
4705
4879
  let result = await doGenerate();
@@ -4741,9 +4915,12 @@ ${unreflectedContent}` : bufferedReflection;
4741
4915
  * Call the Reflector agent to condense observations.
4742
4916
  * Includes compression validation and retry logic.
4743
4917
  */
4744
- async callReflector(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext) {
4745
- const agent = this.getReflectorAgent();
4918
+ async callReflector(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext, tracingContext) {
4746
4919
  const originalTokens = this.tokenCounter.countObservations(observations);
4920
+ const routingModel = this.reflectionConfig.model instanceof ModelByInputTokens ? this.reflectionConfig.model : void 0;
4921
+ const selectedThreshold = routingModel?.getThresholds().find((threshold) => originalTokens <= threshold);
4922
+ const resolvedModel = this.getConcreteModel(this.reflectionConfig.model, originalTokens);
4923
+ const agent = this.getReflectorAgent(resolvedModel);
4747
4924
  const targetThreshold = observationTokensThreshold ?? getMaxThreshold(this.reflectionConfig.observationTokens);
4748
4925
  let totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
4749
4926
  const startLevel = compressionStartLevel ?? 0;
@@ -4760,37 +4937,47 @@ ${unreflectedContent}` : bufferedReflection;
4760
4937
  `[OM:callReflector] ${isRetry ? `retry #${attemptNumber - 1}` : "first attempt"}: level=${currentLevel}, originalTokens=${originalTokens}, targetThreshold=${targetThreshold}, promptLen=${prompt.length}, skipContinuationHints=${skipContinuationHints}`
4761
4938
  );
4762
4939
  let chunkCount = 0;
4763
- const result = await this.withAbortCheck(async () => {
4764
- const streamResult = await agent.stream(prompt, {
4765
- modelSettings: {
4766
- ...this.reflectionConfig.modelSettings
4767
- },
4768
- providerOptions: this.reflectionConfig.providerOptions,
4769
- ...abortSignal ? { abortSignal } : {},
4770
- ...requestContext ? { requestContext } : {},
4771
- ...attemptNumber === 1 ? {
4772
- onChunk(chunk) {
4773
- chunkCount++;
4774
- if (chunkCount === 1 || chunkCount % 50 === 0) {
4775
- const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
4776
- omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
4777
- }
4778
- },
4779
- onFinish(event) {
4780
- omDebug(
4781
- `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
4782
- );
4783
- },
4784
- onAbort(event) {
4785
- omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
4940
+ const result = await this.withOmTracingSpan({
4941
+ phase: "reflector",
4942
+ inputTokens: originalTokens,
4943
+ resolvedModel,
4944
+ selectedThreshold,
4945
+ routingModel,
4946
+ requestContext,
4947
+ tracingContext,
4948
+ fn: async (observabilityContext) => this.withAbortCheck(async () => {
4949
+ const streamResult = await agent.stream(prompt, {
4950
+ ...observabilityContext,
4951
+ modelSettings: {
4952
+ ...this.reflectionConfig.modelSettings
4786
4953
  },
4787
- onError({ error }) {
4788
- omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
4789
- }
4790
- } : {}
4791
- });
4792
- return streamResult.getFullOutput();
4793
- }, abortSignal);
4954
+ providerOptions: this.reflectionConfig.providerOptions,
4955
+ ...abortSignal ? { abortSignal } : {},
4956
+ ...requestContext ? { requestContext } : {},
4957
+ ...attemptNumber === 1 ? {
4958
+ onChunk(chunk) {
4959
+ chunkCount++;
4960
+ if (chunkCount === 1 || chunkCount % 50 === 0) {
4961
+ const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
4962
+ omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
4963
+ }
4964
+ },
4965
+ onFinish(event) {
4966
+ omDebug(
4967
+ `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
4968
+ );
4969
+ },
4970
+ onAbort(event) {
4971
+ omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
4972
+ },
4973
+ onError({ error }) {
4974
+ omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
4975
+ }
4976
+ } : {}
4977
+ });
4978
+ return streamResult.getFullOutput();
4979
+ }, abortSignal)
4980
+ });
4794
4981
  omDebug(
4795
4982
  `[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}`
4796
4983
  );
@@ -5095,7 +5282,7 @@ ${suggestedResponse}
5095
5282
  * Tries async activation first if enabled, then falls back to sync observation.
5096
5283
  * Returns whether observation succeeded.
5097
5284
  */
5098
- async handleThresholdReached(messageList, record, threadId, resourceId, threshold, lockKey, writer, abortSignal, abort, requestContext) {
5285
+ async handleThresholdReached(messageList, record, threadId, resourceId, threshold, lockKey, writer, abortSignal, abort, requestContext, tracingContext) {
5099
5286
  let observationSucceeded = false;
5100
5287
  let updatedRecord = record;
5101
5288
  let activatedMessageIds;
@@ -5194,7 +5381,8 @@ ${suggestedResponse}
5194
5381
  currentThreadMessages: freshUnobservedMessages,
5195
5382
  writer,
5196
5383
  abortSignal,
5197
- requestContext
5384
+ requestContext,
5385
+ tracingContext
5198
5386
  });
5199
5387
  } else {
5200
5388
  await this.doSynchronousObservation({
@@ -5203,7 +5391,8 @@ ${suggestedResponse}
5203
5391
  unobservedMessages: freshUnobservedMessages,
5204
5392
  writer,
5205
5393
  abortSignal,
5206
- requestContext
5394
+ requestContext,
5395
+ tracingContext
5207
5396
  });
5208
5397
  }
5209
5398
  updatedRecord = await this.getOrCreateRecord(threadId, resourceId);
@@ -5473,7 +5662,17 @@ ${suggestedResponse}
5473
5662
  * 5. Filter out already-observed messages
5474
5663
  */
5475
5664
  async processInputStep(args) {
5476
- const { messageList, requestContext, stepNumber, state: _state, writer, abortSignal, abort, model } = args;
5665
+ const {
5666
+ messageList,
5667
+ requestContext,
5668
+ tracingContext,
5669
+ stepNumber,
5670
+ state: _state,
5671
+ writer,
5672
+ abortSignal,
5673
+ abort,
5674
+ model
5675
+ } = args;
5477
5676
  const state = _state ?? {};
5478
5677
  omDebug(
5479
5678
  `[OM:processInputStep:ENTER] step=${stepNumber}, hasMastraMemory=${!!requestContext?.get("MastraMemory")}, hasMemoryInfo=${!!messageList?.serialize()?.memoryInfo?.threadId}`
@@ -5595,7 +5794,8 @@ ${suggestedResponse}
5595
5794
  threadId,
5596
5795
  writer,
5597
5796
  messageList,
5598
- requestContext
5797
+ requestContext,
5798
+ tracingContext
5599
5799
  });
5600
5800
  record = await this.getOrCreateRecord(threadId, resourceId);
5601
5801
  }
@@ -5612,7 +5812,8 @@ ${suggestedResponse}
5612
5812
  threadId,
5613
5813
  writer,
5614
5814
  messageList,
5615
- requestContext
5815
+ requestContext,
5816
+ tracingContext
5616
5817
  });
5617
5818
  record = await this.getOrCreateRecord(threadId, resourceId);
5618
5819
  } else if (this.isAsyncReflectionEnabled()) {
@@ -5668,7 +5869,8 @@ ${suggestedResponse}
5668
5869
  lockKey,
5669
5870
  writer,
5670
5871
  unbufferedPendingTokens,
5671
- requestContext
5872
+ requestContext,
5873
+ tracingContext
5672
5874
  );
5673
5875
  }
5674
5876
  } else if (this.isAsyncObservationEnabled()) {
@@ -5684,7 +5886,8 @@ ${suggestedResponse}
5684
5886
  lockKey,
5685
5887
  writer,
5686
5888
  unbufferedPendingTokens,
5687
- requestContext
5889
+ requestContext,
5890
+ tracingContext
5688
5891
  );
5689
5892
  }
5690
5893
  }
@@ -5703,7 +5906,8 @@ ${suggestedResponse}
5703
5906
  writer,
5704
5907
  abortSignal,
5705
5908
  abort,
5706
- requestContext
5909
+ requestContext,
5910
+ tracingContext
5707
5911
  );
5708
5912
  if (observationSucceeded) {
5709
5913
  const observedIds = activatedMessageIds?.length ? activatedMessageIds : Array.isArray(updatedRecord.observedMessageIds) ? updatedRecord.observedMessageIds : void 0;
@@ -6112,7 +6316,16 @@ ${threadClose}`;
6112
6316
  * Do synchronous observation (fallback when no buffering)
6113
6317
  */
6114
6318
  async doSynchronousObservation(opts) {
6115
- const { record, threadId, unobservedMessages, writer, abortSignal, reflectionHooks, requestContext } = opts;
6319
+ const {
6320
+ record,
6321
+ threadId,
6322
+ unobservedMessages,
6323
+ writer,
6324
+ abortSignal,
6325
+ reflectionHooks,
6326
+ requestContext,
6327
+ tracingContext
6328
+ } = opts;
6116
6329
  this.emitDebugEvent({
6117
6330
  type: "observation_triggered",
6118
6331
  timestamp: /* @__PURE__ */ new Date(),
@@ -6171,6 +6384,7 @@ ${threadClose}`;
6171
6384
  const threadOMMetadata = memory.getThreadOMMetadata(thread?.metadata);
6172
6385
  const result = await this.callObserver(observerContext, messagesToObserve, abortSignal, {
6173
6386
  requestContext,
6387
+ tracingContext,
6174
6388
  priorCurrentTask: threadOMMetadata?.currentTask,
6175
6389
  priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
6176
6390
  priorThreadTitle: thread?.title,
@@ -6278,7 +6492,8 @@ ${threadClose}`;
6278
6492
  writer,
6279
6493
  abortSignal,
6280
6494
  reflectionHooks,
6281
- requestContext
6495
+ requestContext,
6496
+ tracingContext
6282
6497
  });
6283
6498
  } catch (error) {
6284
6499
  if (lastMessage?.id) {
@@ -6296,10 +6511,7 @@ ${threadClose}`;
6296
6511
  });
6297
6512
  }
6298
6513
  }
6299
- if (abortSignal?.aborted) {
6300
- throw error;
6301
- }
6302
- omError("[OM] Observation failed", error);
6514
+ throw error;
6303
6515
  } finally {
6304
6516
  await this.storage.setObservingFlag(record.id, false);
6305
6517
  unregisterOp(record.id, "observing");
@@ -6319,7 +6531,7 @@ ${threadClose}`;
6319
6531
  * @param lockKey - Lock key for this scope
6320
6532
  * @param writer - Optional stream writer for emitting buffering markers
6321
6533
  */
6322
- async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext) {
6534
+ async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext, tracingContext) {
6323
6535
  const bufferKey = this.getObservationBufferKey(lockKey);
6324
6536
  const currentTokens = contextWindowTokens ?? await this.tokenCounter.countMessagesAsync(unobservedMessages) + (record.pendingMessageTokens ?? 0);
6325
6537
  _ObservationalMemory.lastBufferedBoundary.set(bufferKey, currentTokens);
@@ -6333,7 +6545,8 @@ ${threadClose}`;
6333
6545
  unobservedMessages,
6334
6546
  bufferKey,
6335
6547
  writer,
6336
- requestContext
6548
+ requestContext,
6549
+ tracingContext
6337
6550
  ).finally(() => {
6338
6551
  _ObservationalMemory.asyncBufferingOps.delete(bufferKey);
6339
6552
  unregisterOp(record.id, "bufferingObservation");
@@ -6347,7 +6560,7 @@ ${threadClose}`;
6347
6560
  * Internal method that waits for existing buffering operation and then runs new buffering.
6348
6561
  * This implements the mutex-wait behavior.
6349
6562
  */
6350
- async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext) {
6563
+ async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext, tracingContext) {
6351
6564
  const existingOp = _ObservationalMemory.asyncBufferingOps.get(bufferKey);
6352
6565
  if (existingOp) {
6353
6566
  try {
@@ -6427,7 +6640,8 @@ ${threadClose}`;
6427
6640
  cycleId,
6428
6641
  startedAt,
6429
6642
  writer,
6430
- requestContext
6643
+ requestContext,
6644
+ tracingContext
6431
6645
  );
6432
6646
  const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
6433
6647
  const cursor = new Date(maxTs.getTime() + 1);
@@ -6457,7 +6671,7 @@ ${threadClose}`;
6457
6671
  * The observer sees: active observations + existing buffered observations + message history
6458
6672
  * (excluding already-buffered messages).
6459
6673
  */
6460
- async doAsyncBufferedObservation(record, threadId, messagesToBuffer, cycleId, startedAt, writer, requestContext) {
6674
+ async doAsyncBufferedObservation(record, threadId, messagesToBuffer, cycleId, startedAt, writer, requestContext, tracingContext) {
6461
6675
  const bufferedChunks = this.getBufferedChunks(record);
6462
6676
  const bufferedChunksText = bufferedChunks.map((c) => c.observations).join("\n\n");
6463
6677
  const combinedObservations = this.combineObservationsForBuffering(record.activeObservations, bufferedChunksText);
@@ -6472,6 +6686,7 @@ ${threadClose}`;
6472
6686
  {
6473
6687
  skipContinuationHints: true,
6474
6688
  requestContext,
6689
+ tracingContext,
6475
6690
  priorCurrentTask: threadOMMetadata?.currentTask,
6476
6691
  priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
6477
6692
  priorThreadTitle: thread?.title,
@@ -6912,7 +7127,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
6912
7127
  writer,
6913
7128
  abortSignal,
6914
7129
  reflectionHooks,
6915
- requestContext
7130
+ requestContext,
7131
+ tracingContext
6916
7132
  } = opts;
6917
7133
  const { threads: allThreads } = await this.storage.listThreads({ filter: { resourceId } });
6918
7134
  const threadMetadataMap = /* @__PURE__ */ new Map();
@@ -7090,7 +7306,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7090
7306
  batchPriorMetadata,
7091
7307
  abortSignal,
7092
7308
  requestContext,
7093
- wasTruncated
7309
+ wasTruncated,
7310
+ tracingContext
7094
7311
  );
7095
7312
  return batchResult;
7096
7313
  });
@@ -7218,7 +7435,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7218
7435
  writer,
7219
7436
  abortSignal,
7220
7437
  reflectionHooks,
7221
- requestContext
7438
+ requestContext,
7439
+ tracingContext
7222
7440
  });
7223
7441
  } catch (error) {
7224
7442
  for (const [threadId, msgs] of threadsWithMessages) {
@@ -7240,10 +7458,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7240
7458
  }
7241
7459
  }
7242
7460
  }
7243
- if (abortSignal?.aborted) {
7244
- throw error;
7245
- }
7246
- omError("[OM] Resource-scoped observation failed", error);
7461
+ throw error;
7247
7462
  } finally {
7248
7463
  await this.storage.setObservingFlag(record.id, false);
7249
7464
  unregisterOp(record.id, "observing");
@@ -7291,7 +7506,16 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7291
7506
  * in the background at intervals, and activated when the threshold is reached.
7292
7507
  */
7293
7508
  async maybeReflect(opts) {
7294
- const { record, observationTokens, writer, abortSignal, messageList, reflectionHooks, requestContext } = opts;
7509
+ const {
7510
+ record,
7511
+ observationTokens,
7512
+ writer,
7513
+ abortSignal,
7514
+ messageList,
7515
+ reflectionHooks,
7516
+ requestContext,
7517
+ tracingContext
7518
+ } = opts;
7295
7519
  const lockKey = this.getLockKey(record.threadId, record.resourceId);
7296
7520
  const reflectThreshold = getMaxThreshold(this.reflectionConfig.observationTokens);
7297
7521
  if (this.isAsyncReflectionEnabled() && observationTokens < reflectThreshold) {
@@ -7370,7 +7594,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7370
7594
  abortSignal,
7371
7595
  void 0,
7372
7596
  void 0,
7373
- requestContext
7597
+ requestContext,
7598
+ tracingContext
7374
7599
  );
7375
7600
  const reflectionTokenCount = this.tokenCounter.countObservations(reflectResult.observations);
7376
7601
  await this.storage.createReflectionGeneration({
@@ -7416,10 +7641,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
7416
7641
  await writer.custom(failedMarker).catch(() => {
7417
7642
  });
7418
7643
  }
7419
- if (abortSignal?.aborted) {
7420
- throw error;
7421
- }
7422
- omError("[OM] Reflection failed", error);
7644
+ throw error;
7423
7645
  } finally {
7424
7646
  await this.storage.setReflectingFlag(record.id, false);
7425
7647
  reflectionHooks?.onReflectionEnd?.();
@@ -7611,6 +7833,7 @@ function getObservationsAsOf(activeObservations, asOf) {
7611
7833
  return chunks.join("\n\n");
7612
7834
  }
7613
7835
 
7836
+ exports.ModelByInputTokens = ModelByInputTokens;
7614
7837
  exports.OBSERVATIONAL_MEMORY_DEFAULTS = OBSERVATIONAL_MEMORY_DEFAULTS;
7615
7838
  exports.OBSERVATION_CONTEXT_INSTRUCTIONS = OBSERVATION_CONTEXT_INSTRUCTIONS;
7616
7839
  exports.OBSERVATION_CONTEXT_PROMPT = OBSERVATION_CONTEXT_PROMPT;
@@ -7639,5 +7862,5 @@ exports.stripEphemeralAnchorIds = stripEphemeralAnchorIds;
7639
7862
  exports.stripObservationGroups = stripObservationGroups;
7640
7863
  exports.truncateStringByTokens = truncateStringByTokens;
7641
7864
  exports.wrapInObservationGroup = wrapInObservationGroup;
7642
- //# sourceMappingURL=chunk-CNOHXG5O.cjs.map
7643
- //# sourceMappingURL=chunk-CNOHXG5O.cjs.map
7865
+ //# sourceMappingURL=chunk-EVBFYGDL.cjs.map
7866
+ //# sourceMappingURL=chunk-EVBFYGDL.cjs.map