@mastra/memory 1.10.1-alpha.2 → 1.11.0-alpha.4

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 (53) hide show
  1. package/CHANGELOG.md +40 -0
  2. package/dist/{chunk-2QSOQQPM.js → chunk-D4D6ZFBQ.js} +567 -182
  3. package/dist/chunk-D4D6ZFBQ.js.map +1 -0
  4. package/dist/{chunk-NS47X3OB.cjs → chunk-VINRPDYQ.cjs} +567 -182
  5. package/dist/chunk-VINRPDYQ.cjs.map +1 -0
  6. package/dist/docs/SKILL.md +1 -1
  7. package/dist/docs/assets/SOURCE_MAP.json +47 -47
  8. package/dist/docs/references/docs-memory-observational-memory.md +49 -4
  9. package/dist/docs/references/reference-memory-observational-memory.md +32 -6
  10. package/dist/index.cjs +577 -36
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.ts +46 -0
  13. package/dist/index.d.ts.map +1 -1
  14. package/dist/index.js +570 -29
  15. package/dist/index.js.map +1 -1
  16. package/dist/{observational-memory-I5UTOG63.cjs → observational-memory-FATH657E.cjs} +26 -26
  17. package/dist/{observational-memory-I5UTOG63.cjs.map → observational-memory-FATH657E.cjs.map} +1 -1
  18. package/dist/{observational-memory-WMCWT577.js → observational-memory-SN7GKMHZ.js} +3 -3
  19. package/dist/{observational-memory-WMCWT577.js.map → observational-memory-SN7GKMHZ.js.map} +1 -1
  20. package/dist/processors/index.cjs +24 -24
  21. package/dist/processors/index.js +1 -1
  22. package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/observation-strategies/base.d.ts +9 -0
  24. package/dist/processors/observational-memory/observation-strategies/base.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/observation-strategies/resource-scoped.d.ts.map +1 -1
  26. package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
  27. package/dist/processors/observational-memory/observation-strategies/types.d.ts +2 -0
  28. package/dist/processors/observational-memory/observation-strategies/types.d.ts.map +1 -1
  29. package/dist/processors/observational-memory/observation-turn/index.d.ts +1 -1
  30. package/dist/processors/observational-memory/observation-turn/index.d.ts.map +1 -1
  31. package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
  32. package/dist/processors/observational-memory/observation-turn/turn.d.ts +19 -7
  33. package/dist/processors/observational-memory/observation-turn/turn.d.ts.map +1 -1
  34. package/dist/processors/observational-memory/observation-turn/types.d.ts +4 -0
  35. package/dist/processors/observational-memory/observation-turn/types.d.ts.map +1 -1
  36. package/dist/processors/observational-memory/observational-memory.d.ts +29 -2
  37. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  38. package/dist/processors/observational-memory/observer-runner.d.ts +14 -3
  39. package/dist/processors/observational-memory/observer-runner.d.ts.map +1 -1
  40. package/dist/processors/observational-memory/processor.d.ts +8 -12
  41. package/dist/processors/observational-memory/processor.d.ts.map +1 -1
  42. package/dist/processors/observational-memory/reflector-runner.d.ts +11 -1
  43. package/dist/processors/observational-memory/reflector-runner.d.ts.map +1 -1
  44. package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -1
  45. package/dist/processors/observational-memory/tracing.d.ts +17 -0
  46. package/dist/processors/observational-memory/tracing.d.ts.map +1 -0
  47. package/dist/processors/observational-memory/types.d.ts +19 -1
  48. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  49. package/dist/tools/om-tools.d.ts +96 -4
  50. package/dist/tools/om-tools.d.ts.map +1 -1
  51. package/package.json +5 -5
  52. package/dist/chunk-2QSOQQPM.js.map +0 -1
  53. package/dist/chunk-NS47X3OB.cjs.map +0 -1
@@ -11,8 +11,10 @@ var path = require('path');
11
11
  var crypto$1 = require('crypto');
12
12
  var tokenx = require('tokenx');
13
13
  var agent = require('@mastra/core/agent');
14
+ var observability = require('@mastra/core/observability');
14
15
  var async_hooks = require('async_hooks');
15
16
  var imageSize = require('image-size');
17
+ var util = require('util');
16
18
 
17
19
  function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
18
20
 
@@ -965,7 +967,8 @@ var ObservationStrategy = class _ObservationStrategy {
965
967
  writer,
966
968
  abortSignal,
967
969
  reflectionHooks,
968
- requestContext
970
+ requestContext,
971
+ observabilityContext: this.opts.observabilityContext
969
972
  });
970
973
  }
971
974
  } catch (error) {
@@ -1106,6 +1109,27 @@ ${threadClose}`;
1106
1109
  const boundary = lastObservedAt ? _ObservationStrategy.createMessageBoundary(lastObservedAt) : "\n\n";
1107
1110
  return `${existingObservations}${boundary}${newThreadSection}`;
1108
1111
  }
1112
+ async indexObservationGroups(observations, threadId, resourceId, observedAt) {
1113
+ if (!resourceId || !this.deps.onIndexObservations) {
1114
+ return;
1115
+ }
1116
+ const groups = parseObservationGroups(observations);
1117
+ if (groups.length === 0) {
1118
+ return;
1119
+ }
1120
+ await Promise.all(
1121
+ groups.map(
1122
+ (group) => this.deps.onIndexObservations({
1123
+ text: group.content,
1124
+ groupId: group.id,
1125
+ range: group.range,
1126
+ threadId,
1127
+ resourceId,
1128
+ observedAt
1129
+ })
1130
+ )
1131
+ );
1132
+ }
1109
1133
  // ── Marker persistence ──────────────────────────────────────
1110
1134
  /**
1111
1135
  * Persist a marker to the last assistant message in storage.
@@ -1239,6 +1263,7 @@ var SyncObservationStrategy = class extends ObservationStrategy {
1239
1263
  const omMeta = thread ? memory.getThreadOMMetadata(thread.metadata) : void 0;
1240
1264
  const result = await this.deps.observer.call(existingObservations, messages, this.opts.abortSignal, {
1241
1265
  requestContext: this.opts.requestContext,
1266
+ observabilityContext: this.opts.observabilityContext,
1242
1267
  priorCurrentTask: omMeta?.currentTask,
1243
1268
  priorSuggestedResponse: omMeta?.suggestedResponse,
1244
1269
  priorThreadTitle: omMeta?.threadTitle
@@ -1288,7 +1313,7 @@ var SyncObservationStrategy = class extends ObservationStrategy {
1288
1313
  };
1289
1314
  }
1290
1315
  async persist(processed) {
1291
- const { record, threadId, messages } = this.opts;
1316
+ const { record, threadId, resourceId, messages } = this.opts;
1292
1317
  const thread = await this.storage.getThreadById({ threadId });
1293
1318
  let threadUpdateMarker;
1294
1319
  if (thread) {
@@ -1325,6 +1350,7 @@ var SyncObservationStrategy = class extends ObservationStrategy {
1325
1350
  lastObservedAt: processed.lastObservedAt,
1326
1351
  observedMessageIds: processed.observedMessageIds
1327
1352
  });
1353
+ await this.indexObservationGroups(processed.observations, threadId, resourceId, processed.lastObservedAt);
1328
1354
  }
1329
1355
  async emitEndMarkers(cycleId, processed) {
1330
1356
  const actualTokensObserved = await this.tokenCounter.countMessagesAsync(this.opts.messages);
@@ -1390,7 +1416,8 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
1390
1416
  async observe(existingObservations, messages) {
1391
1417
  return this.deps.observer.call(existingObservations, messages, void 0, {
1392
1418
  skipContinuationHints: true,
1393
- requestContext: this.opts.requestContext
1419
+ requestContext: this.opts.requestContext,
1420
+ observabilityContext: this.opts.observabilityContext
1394
1421
  });
1395
1422
  }
1396
1423
  async process(output, _existingObservations) {
@@ -1429,7 +1456,7 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
1429
1456
  }
1430
1457
  async persist(processed) {
1431
1458
  if (!processed.observations) return;
1432
- const { record, messages } = this.opts;
1459
+ const { record, threadId, resourceId, messages } = this.opts;
1433
1460
  const messageTokens = await this.tokenCounter.countMessagesAsync(messages);
1434
1461
  await this.storage.updateBufferedObservations({
1435
1462
  id: record.id,
@@ -1446,6 +1473,7 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
1446
1473
  },
1447
1474
  lastBufferedAtTime: processed.lastObservedAt
1448
1475
  });
1476
+ await this.indexObservationGroups(processed.observations, threadId, resourceId, processed.lastObservedAt);
1449
1477
  }
1450
1478
  async emitEndMarkers(_cycleId, processed) {
1451
1479
  if (!processed.observations || !this.opts.writer) return;
@@ -1660,7 +1688,8 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
1660
1688
  batch.threadIds,
1661
1689
  this.opts.abortSignal,
1662
1690
  this.opts.requestContext,
1663
- this.priorMetadataByThread
1691
+ this.priorMetadataByThread,
1692
+ this.opts.observabilityContext
1664
1693
  );
1665
1694
  })
1666
1695
  );
@@ -1744,7 +1773,7 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
1744
1773
  };
1745
1774
  }
1746
1775
  async persist(processed) {
1747
- const { record } = this.opts;
1776
+ const { record, resourceId } = this.opts;
1748
1777
  const threadUpdateMarkers = [];
1749
1778
  if (processed.threadMetadataUpdates) {
1750
1779
  for (const update of processed.threadMetadataUpdates) {
@@ -1788,6 +1817,18 @@ var ResourceScopedObservationStrategy = class extends ObservationStrategy {
1788
1817
  lastObservedAt: processed.lastObservedAt,
1789
1818
  observedMessageIds: processed.observedMessageIds
1790
1819
  });
1820
+ if (resourceId) {
1821
+ await Promise.all(
1822
+ this.observationResults.map(
1823
+ ({ threadId, threadMessages, result }) => this.indexObservationGroups(
1824
+ result.observations,
1825
+ threadId,
1826
+ resourceId,
1827
+ this.getMaxMessageTimestamp(threadMessages)
1828
+ )
1829
+ )
1830
+ );
1831
+ }
1791
1832
  }
1792
1833
  async emitEndMarkers(cycleId, processed) {
1793
1834
  for (const obsResult of this.observationResults) {
@@ -1845,6 +1886,7 @@ ObservationStrategy.create = ((om, opts) => {
1845
1886
  reflector: om.reflector,
1846
1887
  observedMessageIds: om.observedMessageIds,
1847
1888
  obscureThreadIds: om.getObscureThreadIds(),
1889
+ onIndexObservations: om.onIndexObservations,
1848
1890
  emitDebugEvent: (e) => om.emitDebugEvent(e)
1849
1891
  };
1850
1892
  if (opts.cycleId) return new AsyncBufferObservationStrategy(deps, opts);
@@ -1913,7 +1955,8 @@ var ObservationStep = class {
1913
1955
  observationTokens: obsTokens,
1914
1956
  threadId,
1915
1957
  writer: this.turn.writer,
1916
- requestContext: this.turn.requestContext
1958
+ requestContext: this.turn.requestContext,
1959
+ observabilityContext: this.turn.observabilityContext
1917
1960
  });
1918
1961
  await this.turn.refreshRecord();
1919
1962
  if (this.turn.record.generationCount > preReflectGeneration) {
@@ -1945,8 +1988,19 @@ var ObservationStep = class {
1945
1988
  record: statusSnapshot.record,
1946
1989
  writer: this.turn.writer,
1947
1990
  requestContext: this.turn.requestContext,
1991
+ observabilityContext: this.turn.observabilityContext,
1948
1992
  beforeBuffer: async (candidates) => {
1993
+ if (candidates.length === 0) {
1994
+ return;
1995
+ }
1949
1996
  om.sealMessagesForBuffering(candidates);
1997
+ try {
1998
+ await this.turn.hooks?.onBufferChunkSealed?.();
1999
+ } catch (error) {
2000
+ omDebug(
2001
+ `[OM:buffer] onBufferChunkSealed hook failed: ${error instanceof Error ? error.message : String(error)}`
2002
+ );
2003
+ }
1950
2004
  if (this.turn.memory) {
1951
2005
  await this.turn.memory.persistMessages(candidates);
1952
2006
  }
@@ -2071,7 +2125,8 @@ var ObservationStep = class {
2071
2125
  threadId,
2072
2126
  writer: this.turn.writer,
2073
2127
  messageList,
2074
- requestContext: this.turn.requestContext
2128
+ requestContext: this.turn.requestContext,
2129
+ observabilityContext: this.turn.observabilityContext
2075
2130
  });
2076
2131
  return {
2077
2132
  succeeded: true,
@@ -2085,7 +2140,8 @@ var ObservationStep = class {
2085
2140
  resourceId,
2086
2141
  messages: messageList.get.all.db(),
2087
2142
  requestContext: this.turn.requestContext,
2088
- writer: this.turn.writer
2143
+ writer: this.turn.writer,
2144
+ observabilityContext: this.turn.observabilityContext
2089
2145
  });
2090
2146
  return { succeeded: obsResult.observed, record: obsResult.record };
2091
2147
  }
@@ -2093,12 +2149,6 @@ var ObservationStep = class {
2093
2149
 
2094
2150
  // src/processors/observational-memory/observation-turn/turn.ts
2095
2151
  var ObservationTurn = class {
2096
- constructor(om, threadId, resourceId, messageList) {
2097
- this.om = om;
2098
- this.threadId = threadId;
2099
- this.resourceId = resourceId;
2100
- this.messageList = messageList;
2101
- }
2102
2152
  _record;
2103
2153
  _context;
2104
2154
  _currentStep;
@@ -2112,6 +2162,22 @@ var ObservationTurn = class {
2112
2162
  writer;
2113
2163
  /** Optional request context for observation calls. */
2114
2164
  requestContext;
2165
+ /** Optional observability context for nested OM spans. */
2166
+ observabilityContext;
2167
+ /** Optional processor-provided hooks for turn/step lifecycle integration. */
2168
+ hooks;
2169
+ constructor(opts) {
2170
+ this.om = opts.om;
2171
+ this.threadId = opts.threadId;
2172
+ this.resourceId = opts.resourceId;
2173
+ this.messageList = opts.messageList;
2174
+ this.observabilityContext = opts.observabilityContext;
2175
+ this.hooks = opts.hooks;
2176
+ }
2177
+ om;
2178
+ threadId;
2179
+ resourceId;
2180
+ messageList;
2115
2181
  /** The current cached record. Refreshed after mutations (activate/observe/reflect). */
2116
2182
  get record() {
2117
2183
  if (!this._record) throw new Error("Turn not started \u2014 call start() first");
@@ -2174,7 +2240,7 @@ var ObservationTurn = class {
2174
2240
  return this._currentStep;
2175
2241
  }
2176
2242
  /**
2177
- * Finalize the turn: save any remaining messages, await in-flight buffering, return final state.
2243
+ * Finalize the turn: save any remaining messages and return the latest record state.
2178
2244
  */
2179
2245
  async end() {
2180
2246
  if (this._ended) throw new Error("Turn already ended");
@@ -2185,22 +2251,6 @@ var ObservationTurn = class {
2185
2251
  if (unsavedMessages.length > 0) {
2186
2252
  await this.om.persistMessages(unsavedMessages, this.threadId, this.resourceId);
2187
2253
  }
2188
- await this.om.waitForBuffering(this.threadId, this.resourceId);
2189
- const status = await this.om.getStatus({
2190
- threadId: this.threadId,
2191
- resourceId: this.resourceId,
2192
- messages: this.messageList.get.all.db()
2193
- });
2194
- if (status.shouldObserve) {
2195
- await this.om.observe({
2196
- threadId: this.threadId,
2197
- resourceId: this.resourceId,
2198
- messages: this.messageList.get.all.db(),
2199
- requestContext: this.requestContext,
2200
- writer: this.writer
2201
- });
2202
- }
2203
- await this.refreshRecord();
2204
2254
  return { record: this._record };
2205
2255
  }
2206
2256
  /**
@@ -3366,13 +3416,64 @@ function optimizeObservationsForContext(observations) {
3366
3416
  optimized = optimized.replace(/\n{3,}/g, "\n\n");
3367
3417
  return optimized.trim();
3368
3418
  }
3419
+ var PHASE_CONFIG = {
3420
+ observer: {
3421
+ name: "om.observer",
3422
+ entityName: "Observer"
3423
+ },
3424
+ "observer-multi-thread": {
3425
+ name: "om.observer.multi-thread",
3426
+ entityName: "MultiThreadObserver"
3427
+ },
3428
+ reflector: {
3429
+ name: "om.reflector",
3430
+ entityName: "Reflector"
3431
+ }
3432
+ };
3433
+ async function withOmTracingSpan({
3434
+ phase,
3435
+ model,
3436
+ inputTokens,
3437
+ requestContext,
3438
+ observabilityContext,
3439
+ metadata,
3440
+ callback
3441
+ }) {
3442
+ const config = PHASE_CONFIG[phase];
3443
+ const span = observability.getOrCreateSpan({
3444
+ type: observability.SpanType.GENERIC,
3445
+ name: config.name,
3446
+ entityType: observability.EntityType.OUTPUT_STEP_PROCESSOR,
3447
+ entityName: config.entityName,
3448
+ tracingContext: observabilityContext?.tracingContext ?? observabilityContext?.tracing,
3449
+ attributes: {
3450
+ metadata: {
3451
+ omPhase: phase,
3452
+ omInputTokens: inputTokens,
3453
+ omSelectedModel: typeof model === "string" ? model : "(dynamic-model)",
3454
+ ...metadata
3455
+ }
3456
+ },
3457
+ requestContext
3458
+ });
3459
+ const childObservabilityContext = observability.createObservabilityContext({ currentSpan: span });
3460
+ if (!span) {
3461
+ return callback(childObservabilityContext);
3462
+ }
3463
+ return span.executeInContext(() => callback(childObservabilityContext));
3464
+ }
3465
+
3466
+ // src/processors/observational-memory/observer-runner.ts
3369
3467
  var ObserverRunner = class {
3370
3468
  observationConfig;
3371
3469
  observedMessageIds;
3372
- observerAgent;
3470
+ resolveModel;
3471
+ tokenCounter;
3373
3472
  constructor(opts) {
3374
3473
  this.observationConfig = opts.observationConfig;
3375
3474
  this.observedMessageIds = opts.observedMessageIds;
3475
+ this.resolveModel = opts.resolveModel;
3476
+ this.tokenCounter = opts.tokenCounter;
3376
3477
  }
3377
3478
  createAgent(model, isMultiThread = false) {
3378
3479
  return new agent.Agent({
@@ -3386,10 +3487,6 @@ var ObserverRunner = class {
3386
3487
  model
3387
3488
  });
3388
3489
  }
3389
- getAgent(model) {
3390
- this.observerAgent ??= this.createAgent(model);
3391
- return this.observerAgent;
3392
- }
3393
3490
  async withAbortCheck(fn, abortSignal) {
3394
3491
  if (abortSignal?.aborted) {
3395
3492
  throw new Error("The operation was aborted.");
@@ -3404,7 +3501,9 @@ var ObserverRunner = class {
3404
3501
  * Call the Observer agent for a single thread.
3405
3502
  */
3406
3503
  async call(existingObservations, messagesToObserve, abortSignal, options) {
3407
- const agent = options?.model ? this.createAgent(options.model) : this.getAgent(this.observationConfig.model);
3504
+ const inputTokens = this.tokenCounter.countMessages(messagesToObserve);
3505
+ const resolvedModel = options?.model ? { model: options.model } : this.resolveModel(inputTokens);
3506
+ const agent = this.createAgent(resolvedModel.model);
3408
3507
  const observerMessages = [
3409
3508
  {
3410
3509
  role: "user",
@@ -3416,15 +3515,32 @@ var ObserverRunner = class {
3416
3515
  buildObserverHistoryMessage(messagesToObserve)
3417
3516
  ];
3418
3517
  const doGenerate = async () => {
3419
- return this.withAbortCheck(async () => {
3420
- const streamResult = await agent.stream(observerMessages, {
3421
- modelSettings: { ...this.observationConfig.modelSettings },
3422
- providerOptions: this.observationConfig.providerOptions,
3423
- ...abortSignal ? { abortSignal } : {},
3424
- ...options?.requestContext ? { requestContext: options.requestContext } : {}
3425
- });
3426
- return streamResult.getFullOutput();
3427
- }, abortSignal);
3518
+ return withOmTracingSpan({
3519
+ phase: "observer",
3520
+ model: resolvedModel.model,
3521
+ inputTokens,
3522
+ requestContext: options?.requestContext,
3523
+ observabilityContext: options?.observabilityContext,
3524
+ metadata: {
3525
+ omPreviousObserverTokens: this.observationConfig.previousObserverTokens,
3526
+ omThreadTitleEnabled: this.observationConfig.threadTitle,
3527
+ omSkipContinuationHints: options?.skipContinuationHints ?? false,
3528
+ omWasTruncated: options?.wasTruncated ?? false,
3529
+ ...resolvedModel.selectedThreshold !== void 0 ? { omSelectedThreshold: resolvedModel.selectedThreshold } : {},
3530
+ ...resolvedModel.routingStrategy ? { omRoutingStrategy: resolvedModel.routingStrategy } : {},
3531
+ ...resolvedModel.routingThresholds ? { omRoutingThresholds: resolvedModel.routingThresholds } : {}
3532
+ },
3533
+ callback: (childObservabilityContext) => this.withAbortCheck(async () => {
3534
+ const streamResult = await agent.stream(observerMessages, {
3535
+ modelSettings: { ...this.observationConfig.modelSettings },
3536
+ providerOptions: this.observationConfig.providerOptions,
3537
+ ...abortSignal ? { abortSignal } : {},
3538
+ ...options?.requestContext ? { requestContext: options.requestContext } : {},
3539
+ ...childObservabilityContext
3540
+ });
3541
+ return streamResult.getFullOutput();
3542
+ }, abortSignal)
3543
+ });
3428
3544
  };
3429
3545
  let result = await doGenerate();
3430
3546
  let parsed = parseObserverOutput(result.text);
@@ -3449,8 +3565,13 @@ var ObserverRunner = class {
3449
3565
  /**
3450
3566
  * Call the Observer agent for multiple threads in a single batched request.
3451
3567
  */
3452
- async callMultiThread(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, model) {
3453
- const agent = this.createAgent(model ?? this.observationConfig.model, true);
3568
+ async callMultiThread(existingObservations, messagesByThread, threadOrder, abortSignal, requestContext, priorMetadataByThread, observabilityContext, model) {
3569
+ const inputTokens = Array.from(messagesByThread.values()).reduce(
3570
+ (total, messages) => total + this.tokenCounter.countMessages(messages),
3571
+ 0
3572
+ );
3573
+ const resolvedModel = model ? { model } : this.resolveModel(inputTokens);
3574
+ const agent = this.createAgent(resolvedModel.model, true);
3454
3575
  const observerMessages = [
3455
3576
  {
3456
3577
  role: "user",
@@ -3470,15 +3591,31 @@ var ObserverRunner = class {
3470
3591
  }
3471
3592
  }
3472
3593
  const doGenerate = async () => {
3473
- return this.withAbortCheck(async () => {
3474
- const streamResult = await agent.stream(observerMessages, {
3475
- modelSettings: { ...this.observationConfig.modelSettings },
3476
- providerOptions: this.observationConfig.providerOptions,
3477
- ...abortSignal ? { abortSignal } : {},
3478
- ...requestContext ? { requestContext } : {}
3479
- });
3480
- return streamResult.getFullOutput();
3481
- }, abortSignal);
3594
+ return withOmTracingSpan({
3595
+ phase: "observer-multi-thread",
3596
+ model: resolvedModel.model,
3597
+ inputTokens,
3598
+ requestContext,
3599
+ observabilityContext,
3600
+ metadata: {
3601
+ omThreadCount: threadOrder.length,
3602
+ omPreviousObserverTokens: this.observationConfig.previousObserverTokens,
3603
+ omThreadTitleEnabled: this.observationConfig.threadTitle,
3604
+ ...resolvedModel.selectedThreshold !== void 0 ? { omSelectedThreshold: resolvedModel.selectedThreshold } : {},
3605
+ ...resolvedModel.routingStrategy ? { omRoutingStrategy: resolvedModel.routingStrategy } : {},
3606
+ ...resolvedModel.routingThresholds ? { omRoutingThresholds: resolvedModel.routingThresholds } : {}
3607
+ },
3608
+ callback: (childObservabilityContext) => this.withAbortCheck(async () => {
3609
+ const streamResult = await agent.stream(observerMessages, {
3610
+ modelSettings: { ...this.observationConfig.modelSettings },
3611
+ providerOptions: this.observationConfig.providerOptions,
3612
+ ...abortSignal ? { abortSignal } : {},
3613
+ ...requestContext ? { requestContext } : {},
3614
+ ...childObservabilityContext
3615
+ });
3616
+ return streamResult.getFullOutput();
3617
+ }, abortSignal)
3618
+ });
3482
3619
  };
3483
3620
  let result = await doGenerate();
3484
3621
  let parsed = parseMultiThreadObserverOutput(result.text);
@@ -3785,6 +3922,7 @@ var ReflectorRunner = class {
3785
3922
  reflectionConfig;
3786
3923
  observationConfig;
3787
3924
  tokenCounter;
3925
+ resolveModel;
3788
3926
  storage;
3789
3927
  scope;
3790
3928
  buffering;
@@ -3796,6 +3934,7 @@ var ReflectorRunner = class {
3796
3934
  this.reflectionConfig = opts.reflectionConfig;
3797
3935
  this.observationConfig = opts.observationConfig;
3798
3936
  this.tokenCounter = opts.tokenCounter;
3937
+ this.resolveModel = opts.resolveModel;
3799
3938
  this.storage = opts.storage;
3800
3939
  this.scope = opts.scope;
3801
3940
  this.buffering = opts.buffering;
@@ -3822,9 +3961,10 @@ var ReflectorRunner = class {
3822
3961
  /**
3823
3962
  * Call the Reflector agent with escalating compression levels.
3824
3963
  */
3825
- async call(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext, model) {
3826
- const agent = this.createAgent(model ?? this.reflectionConfig.model);
3964
+ async call(observations, manualPrompt, streamContext, observationTokensThreshold, abortSignal, skipContinuationHints, compressionStartLevel, requestContext, observabilityContext, model) {
3827
3965
  const originalTokens = this.tokenCounter.countObservations(observations);
3966
+ const resolvedModel = model ? { model } : this.resolveModel(originalTokens);
3967
+ const agent = this.createAgent(resolvedModel.model);
3828
3968
  const targetThreshold = observationTokensThreshold ?? getMaxThreshold(this.reflectionConfig.observationTokens);
3829
3969
  let totalUsage = { inputTokens: 0, outputTokens: 0, totalTokens: 0 };
3830
3970
  const startLevel = compressionStartLevel ?? 0;
@@ -3841,37 +3981,54 @@ var ReflectorRunner = class {
3841
3981
  `[OM:callReflector] ${isRetry ? `retry #${attemptNumber - 1}` : "first attempt"}: level=${currentLevel}, originalTokens=${originalTokens}, targetThreshold=${targetThreshold}, promptLen=${prompt.length}, skipContinuationHints=${skipContinuationHints}`
3842
3982
  );
3843
3983
  let chunkCount = 0;
3844
- const result = await withAbortCheck(async () => {
3845
- const streamResult = await agent.stream(prompt, {
3846
- modelSettings: {
3847
- ...this.reflectionConfig.modelSettings
3848
- },
3849
- providerOptions: this.reflectionConfig.providerOptions,
3850
- ...abortSignal ? { abortSignal } : {},
3851
- ...requestContext ? { requestContext } : {},
3852
- ...attemptNumber === 1 ? {
3853
- onChunk(chunk) {
3854
- chunkCount++;
3855
- if (chunkCount === 1 || chunkCount % 50 === 0) {
3856
- const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
3857
- omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
3858
- }
3859
- },
3860
- onFinish(event) {
3861
- omDebug(
3862
- `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
3863
- );
3864
- },
3865
- onAbort(event) {
3866
- omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
3984
+ const result = await withOmTracingSpan({
3985
+ phase: "reflector",
3986
+ model: resolvedModel.model,
3987
+ inputTokens: originalTokens,
3988
+ requestContext,
3989
+ observabilityContext,
3990
+ metadata: {
3991
+ omCompressionLevel: currentLevel,
3992
+ omCompressionAttempt: attemptNumber,
3993
+ omTargetThreshold: targetThreshold,
3994
+ omSkipContinuationHints: skipContinuationHints ?? false,
3995
+ ...resolvedModel.selectedThreshold !== void 0 ? { omSelectedThreshold: resolvedModel.selectedThreshold } : {},
3996
+ ...resolvedModel.routingStrategy ? { omRoutingStrategy: resolvedModel.routingStrategy } : {},
3997
+ ...resolvedModel.routingThresholds ? { omRoutingThresholds: resolvedModel.routingThresholds } : {}
3998
+ },
3999
+ callback: (childObservabilityContext) => withAbortCheck(async () => {
4000
+ const streamResult = await agent.stream(prompt, {
4001
+ modelSettings: {
4002
+ ...this.reflectionConfig.modelSettings
3867
4003
  },
3868
- onError({ error }) {
3869
- omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
3870
- }
3871
- } : {}
3872
- });
3873
- return streamResult.getFullOutput();
3874
- }, abortSignal);
4004
+ providerOptions: this.reflectionConfig.providerOptions,
4005
+ ...abortSignal ? { abortSignal } : {},
4006
+ ...requestContext ? { requestContext } : {},
4007
+ ...childObservabilityContext,
4008
+ ...attemptNumber === 1 ? {
4009
+ onChunk(chunk) {
4010
+ chunkCount++;
4011
+ if (chunkCount === 1 || chunkCount % 50 === 0) {
4012
+ const preview = chunk.type === "text-delta" ? ` text="${chunk.textDelta?.slice(0, 80)}..."` : chunk.type === "tool-call" ? ` tool=${chunk.toolName}` : "";
4013
+ omDebug(`[OM:callReflector] chunk#${chunkCount}: type=${chunk.type}${preview}`);
4014
+ }
4015
+ },
4016
+ onFinish(event) {
4017
+ omDebug(
4018
+ `[OM:callReflector] onFinish: chunks=${chunkCount}, finishReason=${event.finishReason}, inputTokens=${event.usage?.inputTokens}, outputTokens=${event.usage?.outputTokens}, textLen=${event.text?.length}`
4019
+ );
4020
+ },
4021
+ onAbort(event) {
4022
+ omDebug(`[OM:callReflector] onAbort: chunks=${chunkCount}, reason=${event?.reason ?? "unknown"}`);
4023
+ },
4024
+ onError({ error }) {
4025
+ omError(`[OM:callReflector] onError after ${chunkCount} chunks`, error);
4026
+ }
4027
+ } : {}
4028
+ });
4029
+ return streamResult.getFullOutput();
4030
+ }, abortSignal)
4031
+ });
3875
4032
  omDebug(
3876
4033
  `[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}`
3877
4034
  );
@@ -3938,7 +4095,7 @@ var ReflectorRunner = class {
3938
4095
  /**
3939
4096
  * Start an async buffered reflection in the background.
3940
4097
  */
3941
- startAsyncBufferedReflection(record, observationTokens, lockKey, writer, requestContext) {
4098
+ startAsyncBufferedReflection(record, observationTokens, lockKey, writer, requestContext, observabilityContext) {
3942
4099
  const bufferKey = this.buffering.getReflectionBufferKey(lockKey);
3943
4100
  if (this.buffering.isAsyncBufferingInProgress(bufferKey)) {
3944
4101
  return;
@@ -3948,7 +4105,7 @@ var ReflectorRunner = class {
3948
4105
  this.storage.setBufferingReflectionFlag(record.id, true).catch((err) => {
3949
4106
  omError("[OM] Failed to set buffering reflection flag", err);
3950
4107
  });
3951
- const asyncOp = this.doAsyncBufferedReflection(record, bufferKey, writer, requestContext).catch(async (error) => {
4108
+ const asyncOp = this.doAsyncBufferedReflection(record, bufferKey, writer, requestContext, observabilityContext).catch(async (error) => {
3952
4109
  if (writer) {
3953
4110
  const failedMarker = createBufferingFailedMarker({
3954
4111
  cycleId: `reflect-buf-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
@@ -3978,7 +4135,7 @@ var ReflectorRunner = class {
3978
4135
  * Perform async buffered reflection — reflects observations and stores to bufferedReflection.
3979
4136
  * Does NOT create a new generation or update activeObservations.
3980
4137
  */
3981
- async doAsyncBufferedReflection(record, _bufferKey, writer, requestContext) {
4138
+ async doAsyncBufferedReflection(record, _bufferKey, writer, requestContext, observabilityContext) {
3982
4139
  const freshRecord = await this.storage.getObservationalMemory(record.threadId, record.resourceId);
3983
4140
  const currentRecord = freshRecord ?? record;
3984
4141
  const observationTokens = currentRecord.observationTokenCount ?? 0;
@@ -4025,7 +4182,8 @@ var ReflectorRunner = class {
4025
4182
  void 0,
4026
4183
  true,
4027
4184
  compressionStartLevel,
4028
- requestContext
4185
+ requestContext,
4186
+ observabilityContext
4029
4187
  );
4030
4188
  const reflectionTokenCount = this.tokenCounter.countObservations(reflectResult.observations);
4031
4189
  omDebug(
@@ -4141,7 +4299,16 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4141
4299
  * @internal Used by observation strategies. Do not call directly.
4142
4300
  */
4143
4301
  async maybeReflect(opts) {
4144
- const { record, observationTokens, writer, abortSignal, messageList, reflectionHooks, requestContext } = opts;
4302
+ const {
4303
+ record,
4304
+ observationTokens,
4305
+ writer,
4306
+ abortSignal,
4307
+ messageList,
4308
+ reflectionHooks,
4309
+ requestContext,
4310
+ observabilityContext
4311
+ } = opts;
4145
4312
  const lockKey = this.buffering.getLockKey(record.threadId, record.resourceId);
4146
4313
  const reflectThreshold = getMaxThreshold(this.reflectionConfig.observationTokens);
4147
4314
  if (this.buffering.isAsyncReflectionEnabled() && observationTokens < reflectThreshold) {
@@ -4161,7 +4328,14 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4161
4328
  return observationTokens >= activationPoint;
4162
4329
  })();
4163
4330
  if (shouldTrigger) {
4164
- this.startAsyncBufferedReflection(record, observationTokens, lockKey, writer, requestContext);
4331
+ this.startAsyncBufferedReflection(
4332
+ record,
4333
+ observationTokens,
4334
+ lockKey,
4335
+ writer,
4336
+ requestContext,
4337
+ observabilityContext
4338
+ );
4165
4339
  }
4166
4340
  }
4167
4341
  if (observationTokens < reflectThreshold) {
@@ -4188,7 +4362,14 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4188
4362
  omDebug(
4189
4363
  `[OM:reflect] async activation failed, no blockAfter or below it (obsTokens=${observationTokens}, blockAfter=${this.reflectionConfig.blockAfter}) \u2014 starting background reflection`
4190
4364
  );
4191
- this.startAsyncBufferedReflection(record, observationTokens, lockKey, writer, requestContext);
4365
+ this.startAsyncBufferedReflection(
4366
+ record,
4367
+ observationTokens,
4368
+ lockKey,
4369
+ writer,
4370
+ requestContext,
4371
+ observabilityContext
4372
+ );
4192
4373
  return;
4193
4374
  }
4194
4375
  }
@@ -4236,7 +4417,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4236
4417
  abortSignal,
4237
4418
  void 0,
4238
4419
  compressionStartLevel,
4239
- requestContext
4420
+ requestContext,
4421
+ observabilityContext
4240
4422
  );
4241
4423
  const reflectionTokenCount = this.tokenCounter.countObservations(reflectResult.observations);
4242
4424
  await this.storage.createReflectionGeneration({
@@ -5524,11 +5706,12 @@ var ObservationalMemory = class _ObservationalMemory {
5524
5706
  storage;
5525
5707
  tokenCounter;
5526
5708
  scope;
5527
- /** Whether retrieval-mode observation groups are enabled (thread scope only). */
5709
+ /** Whether retrieval-mode observation groups are enabled. */
5528
5710
  retrieval;
5529
5711
  observationConfig;
5530
5712
  reflectionConfig;
5531
5713
  onDebugEvent;
5714
+ onIndexObservations;
5532
5715
  /** Observer agent runner — handles LLM calls for extracting observations. */
5533
5716
  observer;
5534
5717
  /** Reflector agent runner — handles LLM calls for compressing observations. */
@@ -5601,7 +5784,8 @@ var ObservationalMemory = class _ObservationalMemory {
5601
5784
  this.shouldObscureThreadIds = config.obscureThreadIds || false;
5602
5785
  this.storage = config.storage;
5603
5786
  this.scope = config.scope ?? "thread";
5604
- this.retrieval = this.scope === "thread" && (config.retrieval ?? false);
5787
+ this.retrieval = Boolean(config.retrieval);
5788
+ this.onIndexObservations = config.onIndexObservations;
5605
5789
  const resolveModel = (m) => m === "default" ? chunkD4J4XPGM_cjs.OBSERVATIONAL_MEMORY_DEFAULTS.observation.model : m;
5606
5790
  const observationModel = resolveModel(config.model) ?? resolveModel(config.observation?.model) ?? resolveModel(config.reflection?.model);
5607
5791
  const reflectionModel = resolveModel(config.model) ?? resolveModel(config.reflection?.model) ?? resolveModel(config.observation?.model);
@@ -5695,7 +5879,9 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
5695
5879
  this.messageHistory = new processors.MessageHistory({ storage: this.storage });
5696
5880
  this.observer = new ObserverRunner({
5697
5881
  observationConfig: this.observationConfig,
5698
- observedMessageIds: this.observedMessageIds
5882
+ observedMessageIds: this.observedMessageIds,
5883
+ resolveModel: (inputTokens) => this.resolveObservationModel(inputTokens),
5884
+ tokenCounter: this.tokenCounter
5699
5885
  });
5700
5886
  this.buffering = new BufferingCoordinator({
5701
5887
  observationConfig: this.observationConfig,
@@ -5712,7 +5898,8 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
5712
5898
  emitDebugEvent: (e) => this.emitDebugEvent(e),
5713
5899
  persistMarkerToStorage: (m, t, r) => this.persistMarkerToStorage(m, t, r),
5714
5900
  persistMarkerToMessage: (m, ml, t, r) => this.persistMarkerToMessage(m, ml, t, r),
5715
- getCompressionStartLevel: (rc) => this.getCompressionStartLevel(rc)
5901
+ getCompressionStartLevel: (rc) => this.getCompressionStartLevel(rc),
5902
+ resolveModel: (inputTokens) => this.resolveReflectionModel(inputTokens)
5716
5903
  });
5717
5904
  this.validateBufferConfig();
5718
5905
  omDebug(
@@ -5774,6 +5961,54 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
5774
5961
  }
5775
5962
  return model.provider ? `${model.provider}/${model.modelId}` : model.modelId;
5776
5963
  }
5964
+ resolveObservationModel(inputTokens) {
5965
+ return this.resolveTieredModel(this.observationConfig.model, inputTokens);
5966
+ }
5967
+ resolveReflectionModel(inputTokens) {
5968
+ return this.resolveTieredModel(this.reflectionConfig.model, inputTokens);
5969
+ }
5970
+ resolveTieredModel(model, inputTokens) {
5971
+ if (!(model instanceof ModelByInputTokens)) {
5972
+ return {
5973
+ model
5974
+ };
5975
+ }
5976
+ const thresholds = model.getThresholds();
5977
+ const selectedThreshold = thresholds.find((upTo) => inputTokens <= upTo) ?? thresholds.at(-1);
5978
+ return {
5979
+ model: model.resolve(inputTokens),
5980
+ selectedThreshold,
5981
+ routingStrategy: "model-by-input-tokens",
5982
+ routingThresholds: thresholds.join(",")
5983
+ };
5984
+ }
5985
+ async resolveModelRouting(modelConfig, requestContext) {
5986
+ try {
5987
+ if (modelConfig instanceof ModelByInputTokens) {
5988
+ const routing = await Promise.all(
5989
+ modelConfig.getThresholds().map(async (upTo) => {
5990
+ const resolvedModel = modelConfig.resolve(upTo);
5991
+ const resolved2 = await this.resolveModelContext(resolvedModel, requestContext);
5992
+ return {
5993
+ upTo,
5994
+ model: resolved2?.modelId ? this.formatModelName(resolved2) : "(unknown)"
5995
+ };
5996
+ })
5997
+ );
5998
+ return {
5999
+ model: routing[0]?.model ?? "(unknown)",
6000
+ routing
6001
+ };
6002
+ }
6003
+ const resolved = await this.resolveModelContext(modelConfig, requestContext);
6004
+ return {
6005
+ model: resolved?.modelId ? this.formatModelName(resolved) : "(unknown)"
6006
+ };
6007
+ } catch (error) {
6008
+ omError("[OM] Failed to resolve model config", error);
6009
+ return { model: "(unknown)" };
6010
+ }
6011
+ }
5777
6012
  async resolveModelContext(modelConfig, requestContext, inputTokens) {
5778
6013
  const modelToResolve = this.getModelToResolve(modelConfig, inputTokens);
5779
6014
  if (!modelToResolve) {
@@ -5806,29 +6041,22 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
5806
6041
  * This is async because it needs to resolve the model configs.
5807
6042
  */
5808
6043
  async getResolvedConfig(requestContext) {
5809
- const safeResolveModel = async (modelConfig) => {
5810
- try {
5811
- const resolved = await this.resolveModelContext(modelConfig, requestContext);
5812
- return resolved?.modelId ? this.formatModelName(resolved) : "(unknown)";
5813
- } catch (error) {
5814
- omError("[OM] Failed to resolve model config", error);
5815
- return "(unknown)";
5816
- }
5817
- };
5818
- const [observationModelName, reflectionModelName] = await Promise.all([
5819
- safeResolveModel(this.observationConfig.model),
5820
- safeResolveModel(this.reflectionConfig.model)
6044
+ const [observationResolved, reflectionResolved] = await Promise.all([
6045
+ this.resolveModelRouting(this.observationConfig.model, requestContext),
6046
+ this.resolveModelRouting(this.reflectionConfig.model, requestContext)
5821
6047
  ]);
5822
6048
  return {
5823
6049
  scope: this.scope,
5824
6050
  observation: {
5825
6051
  messageTokens: this.observationConfig.messageTokens,
5826
- model: observationModelName,
5827
- previousObserverTokens: this.observationConfig.previousObserverTokens
6052
+ model: observationResolved.model,
6053
+ previousObserverTokens: this.observationConfig.previousObserverTokens,
6054
+ routing: observationResolved.routing
5828
6055
  },
5829
6056
  reflection: {
5830
6057
  observationTokens: this.reflectionConfig.observationTokens,
5831
- model: reflectionModelName
6058
+ model: reflectionResolved.model,
6059
+ routing: reflectionResolved.routing
5832
6060
  }
5833
6061
  };
5834
6062
  }
@@ -6635,7 +6863,7 @@ ${grouped}` : grouped;
6635
6863
  * @param lockKey - Lock key for this scope
6636
6864
  * @param writer - Optional stream writer for emitting buffering markers
6637
6865
  */
6638
- async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext) {
6866
+ async startAsyncBufferedObservation(record, threadId, unobservedMessages, lockKey, writer, contextWindowTokens, requestContext, observabilityContext) {
6639
6867
  const bufferKey = this.buffering.getObservationBufferKey(lockKey);
6640
6868
  const currentTokens = contextWindowTokens ?? await this.tokenCounter.countMessagesAsync(unobservedMessages) + (record.pendingMessageTokens ?? 0);
6641
6869
  BufferingCoordinator.lastBufferedBoundary.set(bufferKey, currentTokens);
@@ -6649,7 +6877,8 @@ ${grouped}` : grouped;
6649
6877
  unobservedMessages,
6650
6878
  bufferKey,
6651
6879
  writer,
6652
- requestContext
6880
+ requestContext,
6881
+ observabilityContext
6653
6882
  ).finally(() => {
6654
6883
  BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
6655
6884
  unregisterOp(record.id, "bufferingObservation");
@@ -6663,7 +6892,7 @@ ${grouped}` : grouped;
6663
6892
  * Internal method that waits for existing buffering operation and then runs new buffering.
6664
6893
  * This implements the mutex-wait behavior.
6665
6894
  */
6666
- async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext) {
6895
+ async runAsyncBufferedObservation(record, threadId, unobservedMessages, bufferKey, writer, requestContext, observabilityContext) {
6667
6896
  const existingOp = BufferingCoordinator.asyncBufferingOps.get(bufferKey);
6668
6897
  if (existingOp) {
6669
6898
  try {
@@ -6735,7 +6964,8 @@ ${grouped}` : grouped;
6735
6964
  cycleId,
6736
6965
  startedAt,
6737
6966
  writer,
6738
- requestContext
6967
+ requestContext,
6968
+ observabilityContext
6739
6969
  }).run();
6740
6970
  const maxTs = this.getMaxMessageTimestamp(messagesToBuffer);
6741
6971
  const cursor = new Date(maxTs.getTime() + 1);
@@ -7282,7 +7512,7 @@ ${grouped}` : grouped;
7282
7512
  */
7283
7513
  /** @internal Used by ObservationStep. */
7284
7514
  async buffer(opts) {
7285
- const { threadId, resourceId, requestContext } = opts;
7515
+ const { threadId, resourceId, requestContext, observabilityContext } = opts;
7286
7516
  let record = opts.record ?? await this.getOrCreateRecord(threadId, resourceId);
7287
7517
  if (!this.buffering.isAsyncObservationEnabled()) {
7288
7518
  return { buffered: false, record };
@@ -7378,7 +7608,8 @@ ${grouped}` : grouped;
7378
7608
  cycleId,
7379
7609
  startedAt,
7380
7610
  writer,
7381
- requestContext
7611
+ requestContext,
7612
+ observabilityContext
7382
7613
  }).run();
7383
7614
  await this.storage.setBufferingObservationFlag(record.id, false, newTokens).catch(() => {
7384
7615
  });
@@ -7582,7 +7813,8 @@ ${grouped}` : grouped;
7582
7813
  messages: unobservedMessages,
7583
7814
  reflectionHooks,
7584
7815
  requestContext,
7585
- writer: opts.writer
7816
+ writer: opts.writer,
7817
+ observabilityContext: opts.observabilityContext
7586
7818
  }).run();
7587
7819
  observed = true;
7588
7820
  } finally {
@@ -7604,7 +7836,7 @@ ${grouped}` : grouped;
7604
7836
  * );
7605
7837
  * ```
7606
7838
  */
7607
- async reflect(threadId, resourceId, prompt, requestContext) {
7839
+ async reflect(threadId, resourceId, prompt, requestContext, observabilityContext) {
7608
7840
  const record = await this.getOrCreateRecord(threadId, resourceId);
7609
7841
  if (!record.activeObservations) {
7610
7842
  return { reflected: false, record };
@@ -7621,7 +7853,9 @@ ${grouped}` : grouped;
7621
7853
  void 0,
7622
7854
  void 0,
7623
7855
  void 0,
7624
- requestContext
7856
+ requestContext,
7857
+ observabilityContext,
7858
+ void 0
7625
7859
  );
7626
7860
  const reflectionTokenCount = this.tokenCounter.countObservations(reflectResult.observations);
7627
7861
  await this.storage.createReflectionGeneration({
@@ -7723,7 +7957,14 @@ ${grouped}` : grouped;
7723
7957
  * ```
7724
7958
  */
7725
7959
  beginTurn(opts) {
7726
- return new ObservationTurn(this, opts.threadId, opts.resourceId, opts.messageList);
7960
+ return new ObservationTurn({
7961
+ om: this,
7962
+ threadId: opts.threadId,
7963
+ resourceId: opts.resourceId,
7964
+ messageList: opts.messageList,
7965
+ observabilityContext: opts.observabilityContext,
7966
+ hooks: opts.hooks
7967
+ });
7727
7968
  }
7728
7969
  };
7729
7970
  var OM_REPRO_CAPTURE_DIR = process.env.OM_REPRO_CAPTURE_DIR ?? ".mastra-om-repro";
@@ -7739,6 +7980,7 @@ function safeCaptureJson(value) {
7739
7980
  JSON.stringify(value, (_key, current) => {
7740
7981
  if (typeof current === "bigint") return current.toString();
7741
7982
  if (typeof current === "function") return "[function]";
7983
+ if (typeof current === "symbol") return current.toString();
7742
7984
  if (current instanceof Error) return { name: current.name, message: current.message, stack: current.stack };
7743
7985
  if (current instanceof Set) return { __type: "Set", values: Array.from(current.values()) };
7744
7986
  if (current instanceof Map) return { __type: "Map", entries: Array.from(current.entries()) };
@@ -7746,6 +7988,87 @@ function safeCaptureJson(value) {
7746
7988
  })
7747
7989
  );
7748
7990
  }
7991
+ function safeCaptureJsonOrError(value) {
7992
+ try {
7993
+ return { ok: true, value: safeCaptureJson(value) };
7994
+ } catch (error) {
7995
+ return {
7996
+ ok: false,
7997
+ error: safeCaptureJson({
7998
+ message: error instanceof Error ? error.message : String(error),
7999
+ stack: error instanceof Error ? error.stack : void 0,
8000
+ inspected: util.inspect(value, { depth: 3, maxArrayLength: 20, breakLength: 120 })
8001
+ })
8002
+ };
8003
+ }
8004
+ }
8005
+ function formatCaptureDate(value) {
8006
+ if (!value) return void 0;
8007
+ if (value instanceof Date) return value.toISOString();
8008
+ try {
8009
+ return new Date(value).toISOString();
8010
+ } catch {
8011
+ return void 0;
8012
+ }
8013
+ }
8014
+ function summarizeOmTurn(value) {
8015
+ if (!value || typeof value !== "object") {
8016
+ return value;
8017
+ }
8018
+ const turn = value;
8019
+ return {
8020
+ __type: "ObservationTurn",
8021
+ threadId: turn.threadId,
8022
+ resourceId: turn.resourceId,
8023
+ started: turn._started,
8024
+ ended: turn._ended,
8025
+ generationCountAtStart: turn._generationCountAtStart,
8026
+ record: turn._record ? {
8027
+ id: turn._record.id,
8028
+ scope: turn._record.scope,
8029
+ threadId: turn._record.threadId,
8030
+ resourceId: turn._record.resourceId,
8031
+ createdAt: formatCaptureDate(turn._record.createdAt),
8032
+ updatedAt: formatCaptureDate(turn._record.updatedAt),
8033
+ lastObservedAt: formatCaptureDate(turn._record.lastObservedAt),
8034
+ generationCount: turn._record.generationCount,
8035
+ observationTokenCount: turn._record.observationTokenCount,
8036
+ pendingMessageTokens: turn._record.pendingMessageTokens,
8037
+ isBufferingObservation: turn._record.isBufferingObservation,
8038
+ isBufferingReflection: turn._record.isBufferingReflection
8039
+ } : void 0,
8040
+ context: turn._context ? {
8041
+ messageCount: Array.isArray(turn._context.messages) ? turn._context.messages.length : void 0,
8042
+ hasSystemMessage: Array.isArray(turn._context.systemMessage) ? turn._context.systemMessage.length > 0 : Boolean(turn._context.systemMessage),
8043
+ continuationId: turn._context.continuation?.id,
8044
+ hasOtherThreadsContext: Boolean(turn._context.otherThreadsContext),
8045
+ recordId: turn._context.record?.id
8046
+ } : void 0,
8047
+ currentStep: turn._currentStep ? {
8048
+ stepNumber: turn._currentStep.stepNumber,
8049
+ prepared: turn._currentStep._prepared,
8050
+ context: turn._currentStep._context ? {
8051
+ activated: turn._currentStep._context.activated,
8052
+ observed: turn._currentStep._context.observed,
8053
+ buffered: turn._currentStep._context.buffered,
8054
+ reflected: turn._currentStep._context.reflected,
8055
+ didThresholdCleanup: turn._currentStep._context.didThresholdCleanup,
8056
+ messageCount: Array.isArray(turn._currentStep._context.messages) ? turn._currentStep._context.messages.length : void 0,
8057
+ systemMessageCount: Array.isArray(turn._currentStep._context.systemMessage) ? turn._currentStep._context.systemMessage.length : void 0
8058
+ } : void 0
8059
+ } : void 0
8060
+ };
8061
+ }
8062
+ function sanitizeCaptureState(rawState) {
8063
+ return Object.fromEntries(
8064
+ Object.entries(rawState).map(([key, value]) => {
8065
+ if (key === "__omTurn") {
8066
+ return [key, summarizeOmTurn(value)];
8067
+ }
8068
+ return [key, value];
8069
+ })
8070
+ );
8071
+ }
7749
8072
  function buildReproMessageFingerprint(message) {
7750
8073
  const createdAt = message.createdAt instanceof Date ? message.createdAt.toISOString() : message.createdAt ? new Date(message.createdAt).toISOString() : "";
7751
8074
  return JSON.stringify({
@@ -7801,60 +8124,88 @@ function writeProcessInputStepReproCapture(params) {
7801
8124
  const addedMessageIds = contextMessages.map((message) => message.id).filter((id) => Boolean(id) && !preMessageIds.has(id));
7802
8125
  const idRemap = inferReproIdRemap(params.preMessages, contextMessages);
7803
8126
  const rawState = params.args.state ?? {};
7804
- const inputPayload = safeCaptureJson({
7805
- stepNumber: params.stepNumber,
7806
- threadId: params.threadId,
7807
- resourceId: params.resourceId,
7808
- readOnly: memoryContext?.memoryConfig?.readOnly,
7809
- messageCount: contextMessages.length,
7810
- messageIds: contextMessages.map((message) => message.id),
7811
- stateKeys: Object.keys(rawState),
7812
- state: rawState,
7813
- args: {
7814
- messages: params.args.messages,
7815
- steps: params.args.steps,
7816
- systemMessages: params.args.systemMessages,
7817
- retryCount: params.args.retryCount,
7818
- tools: params.args.tools,
7819
- toolChoice: params.args.toolChoice,
7820
- activeTools: params.args.activeTools,
7821
- providerOptions: params.args.providerOptions,
7822
- modelSettings: params.args.modelSettings,
7823
- structuredOutput: params.args.structuredOutput
7824
- }
7825
- });
7826
- const preStatePayload = safeCaptureJson({
7827
- record: params.preRecord,
7828
- bufferedChunks: params.preBufferedChunks,
7829
- contextTokenCount: params.preContextTokenCount,
7830
- messages: params.preMessages,
7831
- messageList: params.preSerializedMessageList
7832
- });
7833
- const outputPayload = safeCaptureJson({
7834
- details: params.details,
7835
- messageDiff: {
7836
- removedMessageIds,
7837
- addedMessageIds,
7838
- idRemap
8127
+ const sanitizedState = sanitizeCaptureState(rawState);
8128
+ const payloads = [
8129
+ {
8130
+ fileName: "input.json",
8131
+ data: {
8132
+ stepNumber: params.stepNumber,
8133
+ threadId: params.threadId,
8134
+ resourceId: params.resourceId,
8135
+ readOnly: memoryContext?.memoryConfig?.readOnly,
8136
+ messageCount: contextMessages.length,
8137
+ messageIds: contextMessages.map((message) => message.id),
8138
+ stateKeys: Object.keys(rawState),
8139
+ state: sanitizedState,
8140
+ args: {
8141
+ messages: params.args.messages,
8142
+ steps: params.args.steps,
8143
+ systemMessages: params.args.systemMessages,
8144
+ retryCount: params.args.retryCount,
8145
+ toolChoice: params.args.toolChoice,
8146
+ activeTools: params.args.activeTools,
8147
+ modelSettings: params.args.modelSettings,
8148
+ structuredOutput: params.args.structuredOutput
8149
+ }
8150
+ }
8151
+ },
8152
+ {
8153
+ fileName: "pre-state.json",
8154
+ data: {
8155
+ record: params.preRecord,
8156
+ bufferedChunks: params.preBufferedChunks,
8157
+ contextTokenCount: params.preContextTokenCount,
8158
+ messages: params.preMessages,
8159
+ messageList: params.preSerializedMessageList
8160
+ }
8161
+ },
8162
+ {
8163
+ fileName: "output.json",
8164
+ data: {
8165
+ details: params.details,
8166
+ messageDiff: {
8167
+ removedMessageIds,
8168
+ addedMessageIds,
8169
+ idRemap
8170
+ }
8171
+ }
8172
+ },
8173
+ {
8174
+ fileName: "post-state.json",
8175
+ data: {
8176
+ record: params.postRecord,
8177
+ bufferedChunks: params.postBufferedChunks,
8178
+ contextTokenCount: params.postContextTokenCount,
8179
+ messageCount: contextMessages.length,
8180
+ messageIds: contextMessages.map((message) => message.id),
8181
+ messages: contextMessages,
8182
+ messageList: params.messageList.serialize()
8183
+ }
7839
8184
  }
7840
- });
7841
- const postStatePayload = safeCaptureJson({
7842
- record: params.postRecord,
7843
- bufferedChunks: params.postBufferedChunks,
7844
- contextTokenCount: params.postContextTokenCount,
7845
- messageCount: contextMessages.length,
7846
- messageIds: contextMessages.map((message) => message.id),
7847
- messages: contextMessages,
7848
- messageList: params.messageList.serialize()
7849
- });
7850
- fs.writeFileSync(path.join(captureDir, "input.json"), `${JSON.stringify(inputPayload, null, 2)}
7851
- `);
7852
- fs.writeFileSync(path.join(captureDir, "pre-state.json"), `${JSON.stringify(preStatePayload, null, 2)}
7853
- `);
7854
- fs.writeFileSync(path.join(captureDir, "output.json"), `${JSON.stringify(outputPayload, null, 2)}
8185
+ ];
8186
+ const captureErrors = [];
8187
+ for (const payload of payloads) {
8188
+ const serialized = safeCaptureJsonOrError(payload.data);
8189
+ if (serialized.ok) {
8190
+ fs.writeFileSync(path.join(captureDir, payload.fileName), `${JSON.stringify(serialized.value, null, 2)}
7855
8191
  `);
7856
- fs.writeFileSync(path.join(captureDir, "post-state.json"), `${JSON.stringify(postStatePayload, null, 2)}
8192
+ continue;
8193
+ }
8194
+ captureErrors.push({ fileName: payload.fileName, error: serialized.error });
8195
+ fs.writeFileSync(
8196
+ path.join(captureDir, payload.fileName),
8197
+ `${JSON.stringify({ __captureError: serialized.error }, null, 2)}
8198
+ `
8199
+ );
8200
+ }
8201
+ if (captureErrors.length > 0) {
8202
+ fs.writeFileSync(path.join(captureDir, "capture-error.json"), `${JSON.stringify(captureErrors, null, 2)}
7857
8203
  `);
8204
+ params.debug?.(
8205
+ `[OM:repro-capture] wrote processInputStep capture with ${captureErrors.length} serialization error(s) to ${captureDir}`
8206
+ );
8207
+ return;
8208
+ }
7858
8209
  params.debug?.(`[OM:repro-capture] wrote processInputStep capture to ${captureDir}`);
7859
8210
  } catch (error) {
7860
8211
  params.debug?.(`[OM:repro-capture] failed to write processInputStep capture: ${String(error)}`);
@@ -7862,6 +8213,17 @@ function writeProcessInputStepReproCapture(params) {
7862
8213
  }
7863
8214
 
7864
8215
  // src/processors/observational-memory/processor.ts
8216
+ function getOmObservabilityContext(args) {
8217
+ if (!args.tracing || !args.tracingContext || !args.loggerVNext || !args.metrics) {
8218
+ return void 0;
8219
+ }
8220
+ return {
8221
+ tracing: args.tracing,
8222
+ tracingContext: args.tracingContext,
8223
+ loggerVNext: args.loggerVNext,
8224
+ metrics: args.metrics
8225
+ };
8226
+ }
7865
8227
  var ObservationalMemoryProcessor = class {
7866
8228
  id = "observational-memory";
7867
8229
  name = "Observational Memory";
@@ -7877,7 +8239,17 @@ var ObservationalMemoryProcessor = class {
7877
8239
  }
7878
8240
  // ─── Processor lifecycle hooks ──────────────────────────────────────────
7879
8241
  async processInputStep(args) {
7880
- const { messageList, requestContext, stepNumber, state: _state, writer, model, abortSignal, abort } = args;
8242
+ const {
8243
+ messageList,
8244
+ requestContext,
8245
+ stepNumber,
8246
+ state: _state,
8247
+ writer,
8248
+ model,
8249
+ abortSignal,
8250
+ abort,
8251
+ rotateResponseMessageId
8252
+ } = args;
7881
8253
  const state = _state ?? {};
7882
8254
  omDebug(
7883
8255
  `[OM:processInputStep:ENTER] step=${stepNumber}, hasMastraMemory=${!!requestContext?.get("MastraMemory")}, hasMemoryInfo=${!!messageList?.serialize()?.memoryInfo?.threadId}`
@@ -7905,12 +8277,23 @@ var ObservationalMemoryProcessor = class {
7905
8277
  await this.turn.end().catch(() => {
7906
8278
  });
7907
8279
  }
7908
- this.turn = this.engine.beginTurn({ threadId, resourceId, messageList });
8280
+ this.turn = this.engine.beginTurn({
8281
+ threadId,
8282
+ resourceId,
8283
+ messageList,
8284
+ observabilityContext: getOmObservabilityContext(args),
8285
+ hooks: {
8286
+ onBufferChunkSealed: rotateResponseMessageId
8287
+ }
8288
+ });
7909
8289
  this.turn.writer = writer;
7910
8290
  this.turn.requestContext = requestContext;
7911
8291
  await this.turn.start(this.memory);
7912
8292
  state.__omTurn = this.turn;
7913
8293
  }
8294
+ const observabilityContext = getOmObservabilityContext(args);
8295
+ state.__omObservabilityContext = observabilityContext;
8296
+ this.turn.observabilityContext = observabilityContext;
7914
8297
  {
7915
8298
  const step = this.turn.step(stepNumber);
7916
8299
  let ctx;
@@ -7991,6 +8374,8 @@ var ObservationalMemoryProcessor = class {
7991
8374
  const state = _state ?? {};
7992
8375
  const context = this.engine.getThreadContext(requestContext, messageList);
7993
8376
  if (!context) return messageList;
8377
+ const observabilityContext = getOmObservabilityContext(args);
8378
+ state.__omObservabilityContext = observabilityContext;
7994
8379
  return this.engine.getTokenCounter().runWithModelContext(state.__omActorModelContext, async () => {
7995
8380
  const memoryContext = memory.parseMemoryRequestContext(requestContext);
7996
8381
  if (memoryContext?.memoryConfig?.readOnly) return messageList;
@@ -8065,5 +8450,5 @@ exports.stripEphemeralAnchorIds = stripEphemeralAnchorIds;
8065
8450
  exports.stripObservationGroups = stripObservationGroups;
8066
8451
  exports.truncateStringByTokens = truncateStringByTokens;
8067
8452
  exports.wrapInObservationGroup = wrapInObservationGroup;
8068
- //# sourceMappingURL=chunk-NS47X3OB.cjs.map
8069
- //# sourceMappingURL=chunk-NS47X3OB.cjs.map
8453
+ //# sourceMappingURL=chunk-VINRPDYQ.cjs.map
8454
+ //# sourceMappingURL=chunk-VINRPDYQ.cjs.map