@mastra/server 1.62.0-alpha.12 → 1.62.0-alpha.3

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 (38) hide show
  1. package/CHANGELOG.md +0 -90
  2. package/dist/_types/@internal_core/dist/storage/index.d.ts +13 -13
  3. package/dist/{datasets-DYhcB-od.cjs → datasets-CNtKg_3d.cjs} +1 -3
  4. package/dist/datasets-CNtKg_3d.cjs.map +1 -0
  5. package/dist/{datasets-CInAtVdf.js → datasets-DmN9V4rU.js} +1 -3
  6. package/dist/datasets-DmN9V4rU.js.map +1 -0
  7. package/dist/{dist-L0EogwX_.js → dist-HzWDFjPH.js} +275 -401
  8. package/dist/dist-HzWDFjPH.js.map +1 -0
  9. package/dist/{dist-Xj9TvH1A.cjs → dist-LHYHUQ8P.cjs} +275 -401
  10. package/dist/dist-LHYHUQ8P.cjs.map +1 -0
  11. package/dist/docs/SKILL.md +1 -1
  12. package/dist/docs/assets/SOURCE_MAP.json +1 -1
  13. package/dist/docs/references/docs-server-middleware.md +0 -30
  14. package/dist/server/handlers/agent-builder.cjs +1 -1
  15. package/dist/server/handlers/agent-builder.js +1 -1
  16. package/dist/server/handlers/datasets.cjs +1 -1
  17. package/dist/server/handlers/datasets.d.ts +0 -10
  18. package/dist/server/handlers/datasets.d.ts.map +1 -1
  19. package/dist/server/handlers/datasets.js +1 -1
  20. package/dist/server/handlers/observability-new-endpoints.d.ts +28 -28
  21. package/dist/server/schemas/datasets.d.ts +0 -4
  22. package/dist/server/schemas/datasets.d.ts.map +1 -1
  23. package/dist/server/schemas/index.cjs +1 -1
  24. package/dist/server/schemas/index.js +1 -1
  25. package/dist/server/server-adapter/index.cjs +2 -22
  26. package/dist/server/server-adapter/index.cjs.map +1 -1
  27. package/dist/server/server-adapter/index.d.ts +0 -14
  28. package/dist/server/server-adapter/index.d.ts.map +1 -1
  29. package/dist/server/server-adapter/index.js +3 -22
  30. package/dist/server/server-adapter/index.js.map +1 -1
  31. package/dist/server/server-adapter/routes/datasets.d.ts +0 -10
  32. package/dist/server/server-adapter/routes/datasets.d.ts.map +1 -1
  33. package/dist/server/server-adapter/routes/observability.d.ts +14 -14
  34. package/package.json +6 -6
  35. package/dist/datasets-CInAtVdf.js.map +0 -1
  36. package/dist/datasets-DYhcB-od.cjs.map +0 -1
  37. package/dist/dist-L0EogwX_.js.map +0 -1
  38. package/dist/dist-Xj9TvH1A.cjs.map +0 -1
@@ -4693,7 +4693,7 @@ function splitLines(text) {
4693
4693
  return result;
4694
4694
  }
4695
4695
  //#endregion
4696
- //#region ../memory/dist/src-BATJenuZ.js
4696
+ //#region ../memory/dist/src-BlQjkJzk.js
4697
4697
  var __defProp$3 = Object.defineProperty;
4698
4698
  var __exportAll = (all, no_symbols) => {
4699
4699
  let target = {};
@@ -8927,7 +8927,6 @@ async function cancelResponseBody$1(response) {
8927
8927
  var initialGlobalFetch$1 = globalThis.fetch;
8928
8928
  isNodeDefaultFetch$1(initialGlobalFetch$1);
8929
8929
  function isNodeDefaultFetch$1(fetch) {
8930
- if (typeof fetch !== "function") return false;
8931
8930
  const source = Function.prototype.toString.call(fetch);
8932
8931
  return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
8933
8932
  }
@@ -13819,7 +13818,6 @@ var DownloadError$2 = class extends (_b$2$1 = AISDKError$3, _a$2$1 = symbol$2$1,
13819
13818
  var initialGlobalFetch$2 = globalThis.fetch;
13820
13819
  isNodeDefaultFetch$2(initialGlobalFetch$2);
13821
13820
  function isNodeDefaultFetch$2(fetch) {
13822
- if (typeof fetch !== "function") return false;
13823
13821
  const source = Function.prototype.toString.call(fetch);
13824
13822
  return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
13825
13823
  }
@@ -23482,12 +23480,6 @@ function extractListItemsOnly(content) {
23482
23480
  */
23483
23481
  const MAX_OBSERVATION_LINE_CHARS = 1e4;
23484
23482
  /**
23485
- * Minimum trimmed line length considered by the duplicate-line degenerate
23486
- * check. Short lines (blank lines, separators, terse bullets) legitimately
23487
- * repeat; long identical lines almost never do.
23488
- */
23489
- const MIN_DUPLICATE_LINE_CHARS = 24;
23490
- /**
23491
23483
  * Truncate individual observation lines that exceed the maximum length.
23492
23484
  */
23493
23485
  function sanitizeObservationLines(observations) {
@@ -23525,18 +23517,6 @@ function detectDegenerateRepetition(text) {
23525
23517
  if (totalWindows > 5 && duplicateWindows / totalWindows > .4) return true;
23526
23518
  const lines = text.split("\n");
23527
23519
  for (const line of lines) if (line.length > 5e4) return true;
23528
- const seenLines = /* @__PURE__ */ new Map();
23529
- let duplicateLines = 0;
23530
- let totalCountedLines = 0;
23531
- for (const line of lines) {
23532
- const trimmed = line.trim();
23533
- if (trimmed.length < MIN_DUPLICATE_LINE_CHARS) continue;
23534
- totalCountedLines++;
23535
- const count = (seenLines.get(trimmed) ?? 0) + 1;
23536
- seenLines.set(trimmed, count);
23537
- if (count > 1) duplicateLines++;
23538
- }
23539
- if (totalCountedLines >= 20 && duplicateLines / totalCountedLines > .5) return true;
23540
23520
  return false;
23541
23521
  }
23542
23522
  /**
@@ -23571,26 +23551,12 @@ function describeDegenerateOutput(text, snippetChars = 400) {
23571
23551
  topWindow = window;
23572
23552
  }
23573
23553
  let longestLine = 0;
23574
- const seenLines = /* @__PURE__ */ new Map();
23575
- let duplicateLines = 0;
23576
- let totalCountedLines = 0;
23577
- for (const line of text.split("\n")) {
23578
- if (line.length > longestLine) longestLine = line.length;
23579
- const trimmed = line.trim();
23580
- if (trimmed.length < MIN_DUPLICATE_LINE_CHARS) continue;
23581
- totalCountedLines++;
23582
- const count = (seenLines.get(trimmed) ?? 0) + 1;
23583
- seenLines.set(trimmed, count);
23584
- if (count > 1) duplicateLines++;
23585
- }
23554
+ for (const line of text.split("\n")) if (line.length > longestLine) longestLine = line.length;
23586
23555
  const duplicateRatio = totalWindows > 0 ? (duplicateWindows / totalWindows).toFixed(2) : "n/a";
23587
- const duplicateLineRatio = totalCountedLines > 0 ? (duplicateLines / totalCountedLines).toFixed(2) : "n/a";
23588
23556
  const parts = [
23589
23557
  `length=${text.length}`,
23590
23558
  `sampledWindows=${totalWindows}`,
23591
23559
  `duplicateRatio=${duplicateRatio}`,
23592
- `duplicateLineRatio=${duplicateLineRatio}`,
23593
- `countedLines=${totalCountedLines}`,
23594
23560
  `longestLine=${longestLine}`,
23595
23561
  `topWindowCount=${topCount}`
23596
23562
  ];
@@ -26969,149 +26935,6 @@ function createWorkingMemoryTool(config, options = {}) {
26969
26935
  tool
26970
26936
  };
26971
26937
  }
26972
- /**
26973
- * WorkingMemoryStateProcessor
26974
- *
26975
- * Experimental: delivers working memory to the model as a state signal instead
26976
- * of folding it into the system message. Storage and the `setWorkingMemory`
26977
- * tool are unchanged — this processor only changes the delivery path.
26978
- *
26979
- * Pattern matches `BrowserContextProcessor` in `@mastra/core/browser`:
26980
- * - `stateId` namespaces the state lane on the thread.
26981
- * - `cacheKey` is derived from the rendered payload so dedup is automatic.
26982
- * - `contextWindow.hasSnapshot` re-injection ensures the model still sees the
26983
- * current snapshot after older messages drop out of the window.
26984
- *
26985
- * Delta emission (markdown mode only): when a prior snapshot exists in the
26986
- * context window, the processor emits a unified-diff delta against that
26987
- * snapshot's contents. Schema mode and the snapshot fallback always emit a
26988
- * full snapshot.
26989
- *
26990
- * @example
26991
- * ```ts
26992
- * new Memory({
26993
- * options: {
26994
- * workingMemory: {
26995
- * enabled: true,
26996
- * template: '...',
26997
- * useStateSignals: true, // auto-attaches this processor
26998
- * },
26999
- * },
27000
- * });
27001
- * ```
27002
- */
27003
- const WORKING_MEMORY_STATE_ID = "working-memory";
27004
- const WORKING_MEMORY_STATE_PROCESSOR_ID = "working-memory-state";
27005
- var WorkingMemoryStateProcessor = class {
27006
- memory;
27007
- memoryConfig;
27008
- id = WORKING_MEMORY_STATE_PROCESSOR_ID;
27009
- stateId = WORKING_MEMORY_STATE_ID;
27010
- constructor(memory, memoryConfig) {
27011
- this.memory = memory;
27012
- this.memoryConfig = memoryConfig;
27013
- }
27014
- async computeStateSignal(args) {
27015
- const template = await this.memory.getWorkingMemoryTemplate({ memoryConfig: this.memoryConfig });
27016
- if (!template) return;
27017
- const contents = (await this.memory.getWorkingMemory({
27018
- threadId: args.threadId,
27019
- resourceId: args.resourceId,
27020
- memoryConfig: this.memoryConfig
27021
- }))?.trim();
27022
- if (!contents) return;
27023
- const cacheKey = stableWorkingMemoryCacheKey({
27024
- format: template.format,
27025
- data: contents
27026
- });
27027
- const shouldMakeSnapshot = !args.contextWindow.hasSnapshot;
27028
- if (args.tracking?.currentCacheKey === cacheKey && !shouldMakeSnapshot) return;
27029
- const scope = this.memory.getMergedThreadConfig(this.memoryConfig).workingMemory?.scope ?? "resource";
27030
- const deltaCandidate = template.format === "markdown" && !shouldMakeSnapshot ? buildMarkdownDelta({
27031
- lastSnapshot: args.lastSnapshot,
27032
- deltasSinceSnapshot: args.deltasSinceSnapshot,
27033
- nextContents: contents
27034
- }) : void 0;
27035
- if (deltaCandidate) return {
27036
- id: WORKING_MEMORY_STATE_ID,
27037
- mode: "delta",
27038
- cacheKey,
27039
- tagName: "working-memory",
27040
- contents: deltaCandidate.contents,
27041
- delta: deltaCandidate.contents,
27042
- value: contents,
27043
- attributes: {
27044
- format: template.format,
27045
- scope,
27046
- patch: "unified-diff"
27047
- }
27048
- };
27049
- return {
27050
- id: WORKING_MEMORY_STATE_ID,
27051
- mode: "snapshot",
27052
- cacheKey,
27053
- tagName: "working-memory",
27054
- contents,
27055
- value: contents,
27056
- attributes: {
27057
- format: template.format,
27058
- scope
27059
- }
27060
- };
27061
- }
27062
- };
27063
- /**
27064
- * Stable cache key for the rendered working memory payload. Returns a SHA-256
27065
- * digest so dedup metadata stays compact regardless of payload size (working
27066
- * memory blobs can grow arbitrarily long).
27067
- */
27068
- function stableWorkingMemoryCacheKey(input) {
27069
- const hash = createHash("sha256");
27070
- hash.update(input.format);
27071
- hash.update("\0");
27072
- hash.update(input.data ?? "");
27073
- return `sha256:${hash.digest("hex")}`;
27074
- }
27075
- /**
27076
- * Build a unified-diff delta against the most recently emitted state. Prefers
27077
- * the latest delta's `value` (the post-edit full text) when available, falling
27078
- * back to the snapshot's `value` and finally the snapshot's `contents`. This
27079
- * keeps deltas incremental (B→C) instead of cumulative against a stale
27080
- * snapshot (A→C), which matters when many small edits land between snapshots.
27081
- *
27082
- * Returns undefined when:
27083
- * - there's no prior state to diff against
27084
- * - the prior state isn't a plain string (multimodal signal)
27085
- *
27086
- * In either case the caller falls back to emitting a full snapshot.
27087
- */
27088
- function buildMarkdownDelta(args) {
27089
- const { lastSnapshot, deltasSinceSnapshot, nextContents } = args;
27090
- const prior = pickStringValue(readSignalValue(deltasSinceSnapshot.at(-1))) ?? pickStringValue(readSignalValue(lastSnapshot)) ?? (typeof lastSnapshot?.contents === "string" ? lastSnapshot.contents : void 0);
27091
- if (!prior) return;
27092
- return { contents: renderHunksOnly(prior, nextContents) };
27093
- }
27094
- function pickStringValue(value) {
27095
- return typeof value === "string" ? value : void 0;
27096
- }
27097
- function readSignalValue(signal) {
27098
- return (signal?.metadata)?.value;
27099
- }
27100
- /**
27101
- * Render a unified-diff-style patch body containing only `@@` hunks and their
27102
- * lines — dropping the filename preamble (`Index:` / `===` / `---` / `+++`)
27103
- * that `createPatch` emits and the `` trailer.
27104
- * The preamble exists for tooling like `patch -p1` to know which file to
27105
- * apply to; we only ever diff a single working-memory blob. The newline
27106
- * trailer is semantically meaningless to the model and adds noise to the
27107
- * state signal.
27108
- */
27109
- function renderHunksOnly(prior, next) {
27110
- const { hunks } = structuredPatch("", "", prior, next, "", "", { context: 0 });
27111
- return hunks.map((hunk) => {
27112
- return [`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`, ...hunk.lines.filter((line) => !line.startsWith("\"))].join("\n");
27113
- }).join("\n");
27114
- }
27115
26938
  const MINUTE = 6e4;
27116
26939
  const HOUR = 60 * MINUTE;
27117
26940
  const SHORT_TTL = 5 * MINUTE;
@@ -30053,21 +29876,6 @@ var ReflectorRunner = class {
30053
29876
  memory;
30054
29877
  onReflectionCommitted;
30055
29878
  mastra;
30056
- /**
30057
- * Per-lock-key observation-token count of the last unproductive synchronous
30058
- * reflection (failed, or committed while still over the reflection
30059
- * threshold). `call()` already runs the full bounded compression ladder for
30060
- * a given input, so re-running it against unchanged observations cannot
30061
- * succeed — threshold-triggered sync reflection is skipped while the count
30062
- * is unchanged and retried as soon as the input differs.
30063
- * Keyed by lock key (thread/resource), which is stable across generations —
30064
- * record ids change every time a generation is created.
30065
- *
30066
- * Lifecycle: an entry is deleted when a sync reflection finishes under
30067
- * threshold and replaced on each unproductive attempt. Entries are one
30068
- * number per active thread/resource key and live for the runner's lifetime.
30069
- */
30070
- syncReflectionSuppression = /* @__PURE__ */ new Map();
30071
29879
  constructor(opts) {
30072
29880
  this.reflectionConfig = opts.reflectionConfig;
30073
29881
  this.observationConfig = opts.observationConfig;
@@ -30150,8 +29958,8 @@ var ReflectorRunner = class {
30150
29958
  };
30151
29959
  let reflectedTokens = 0;
30152
29960
  let attemptNumber = 0;
30153
- /** True when the latest attempt returned an empty block for non-empty input. */
30154
- let emptyOutput = false;
29961
+ /** Observations from the previous attempt, used to detect a no-progress ladder. */
29962
+ let previousObservations;
30155
29963
  while (currentLevel <= maxLevel) {
30156
29964
  attemptNumber++;
30157
29965
  const isRetry = attemptNumber > 1;
@@ -30215,20 +30023,21 @@ var ReflectorRunner = class {
30215
30023
  }
30216
30024
  finalProviderMetadata = result.providerMetadata ?? finalProviderMetadata;
30217
30025
  parsed = parseReflectorOutput(result.text, observations, activeExtractors);
30218
- emptyOutput = !parsed.degenerate && observations.trim().length > 0 && parsed.observations.trim().length === 0;
30219
30026
  if (parsed.degenerate) {
30220
30027
  omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure. ${describeDegenerateOutput(result.text, 2e3)}`);
30221
30028
  reflectedTokens = originalTokens;
30222
- } else if (emptyOutput) {
30223
- omDebug(`[OM:callReflector] attempt #${attemptNumber}: empty observations block for non-empty input, treating as compression failure`);
30224
- reflectedTokens = originalTokens;
30225
30029
  } else reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
30226
30030
  omDebug(`[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`);
30227
- if (!parsed.degenerate && !emptyOutput && (validateCompression(reflectedTokens, targetThreshold) || currentLevel >= maxLevel)) break;
30228
- if ((parsed.degenerate || emptyOutput) && currentLevel >= maxLevel) {
30229
- omDebug(`[OM:callReflector] ${parsed.degenerate ? "degenerate" : "empty"} output persists at maxLevel=${maxLevel}, breaking`);
30031
+ if (!parsed.degenerate && (validateCompression(reflectedTokens, targetThreshold) || currentLevel >= maxLevel)) break;
30032
+ if (parsed.degenerate && currentLevel >= maxLevel) {
30033
+ omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
30034
+ break;
30035
+ }
30036
+ if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
30037
+ omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
30230
30038
  break;
30231
30039
  }
30040
+ previousObservations = parsed.observations;
30232
30041
  if (streamContext?.writer) {
30233
30042
  const failedMarker = createObservationFailedMarker({
30234
30043
  cycleId: streamContext.cycleId,
@@ -30264,7 +30073,6 @@ var ReflectorRunner = class {
30264
30073
  }
30265
30074
  currentLevel = Math.min(currentLevel + 1, maxLevel);
30266
30075
  }
30267
- if (observations.trim().length > 0 && parsed.observations.trim().length === 0) throw new Error(`Reflector produced empty output after ${attemptNumber} attempt(s)${parsed.degenerate ? " (degenerate repetition)" : ""} — refusing to commit an empty reflection over ${originalTokens} observation tokens`);
30268
30076
  const structuredExtraction = await extractStructuredValues({
30269
30077
  agent,
30270
30078
  source: "reflector",
@@ -30313,51 +30121,52 @@ var ReflectorRunner = class {
30313
30121
  this.storage.setBufferingReflectionFlag(record.id, true).catch((err) => {
30314
30122
  omError("[OM] Failed to set buffering reflection flag", err);
30315
30123
  });
30316
- const asyncOp = (async () => {
30317
- let outcome;
30318
- let reflectionError;
30124
+ reflectionHooks?.onReflectionStart?.();
30125
+ const asyncOp = this.doAsyncBufferedReflection(record, bufferKey, writer, requestContext, observabilityContext, priorExtractedValues, mainAgent, sendSignal).then((outcome) => {
30319
30126
  try {
30320
- await reflectionHooks?.onReflectionStart?.();
30321
- outcome = await this.doAsyncBufferedReflection(record, bufferKey, writer, requestContext, observabilityContext, priorExtractedValues, mainAgent, sendSignal);
30322
- } catch (error) {
30323
- reflectionError = error instanceof Error ? error : new Error(String(error));
30324
- if (writer) try {
30325
- const failedMarker = createBufferingFailedMarker({
30326
- cycleId: `reflect-buf-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
30327
- operationType: "reflection",
30328
- startedAt: (/* @__PURE__ */ new Date()).toISOString(),
30329
- tokensAttempted: observationTokens,
30330
- error: reflectionError.message,
30331
- recordId: record.id,
30332
- threadId: record.threadId ?? ""
30333
- });
30334
- writer.custom({
30335
- ...failedMarker,
30336
- transient: true
30337
- }).catch(() => {});
30338
- await this.persistMarkerToStorage(failedMarker, record.threadId ?? "", record.resourceId ?? void 0);
30339
- } catch (markerError) {
30340
- omError("[OM] Failed to persist buffering-failed marker after async buffered reflection failure", markerError);
30341
- }
30342
- omError("[OM] Async buffered reflection failed", error);
30343
- BufferingCoordinator.lastBufferedBoundary.delete(bufferKey);
30344
- } finally {
30345
- try {
30346
- await reflectionHooks?.onReflectionEnd?.({
30347
- usage: outcome?.usage,
30348
- error: reflectionError,
30349
- ...outcome?.providerMetadata ? { providerMetadata: outcome.providerMetadata } : {}
30350
- });
30351
- } catch (hookError) {
30352
- omError("[OM] onReflectionEnd hook failed after async buffered reflection", hookError);
30353
- }
30354
- BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
30355
- unregisterOp(record.id, "bufferingReflection");
30356
- this.storage.setBufferingReflectionFlag(record.id, false).catch((err) => {
30357
- omError("[OM] Failed to clear buffering reflection flag", err);
30127
+ reflectionHooks?.onReflectionEnd?.({
30128
+ usage: outcome?.usage,
30129
+ ...outcome?.providerMetadata ? { providerMetadata: outcome.providerMetadata } : {}
30358
30130
  });
30131
+ } catch (hookError) {
30132
+ omError("[OM] onReflectionEnd hook failed after async buffered reflection", hookError);
30359
30133
  }
30360
- })();
30134
+ }, async (error) => {
30135
+ if (writer) try {
30136
+ const failedMarker = createBufferingFailedMarker({
30137
+ cycleId: `reflect-buf-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
30138
+ operationType: "reflection",
30139
+ startedAt: (/* @__PURE__ */ new Date()).toISOString(),
30140
+ tokensAttempted: observationTokens,
30141
+ error: error instanceof Error ? error.message : String(error),
30142
+ recordId: record.id,
30143
+ threadId: record.threadId ?? ""
30144
+ });
30145
+ writer.custom({
30146
+ ...failedMarker,
30147
+ transient: true
30148
+ }).catch(() => {});
30149
+ await this.persistMarkerToStorage(failedMarker, record.threadId ?? "", record.resourceId ?? void 0);
30150
+ } catch (markerError) {
30151
+ omError("[OM] Failed to persist buffering-failed marker after async buffered reflection failure", markerError);
30152
+ }
30153
+ omError("[OM] Async buffered reflection failed", error);
30154
+ try {
30155
+ reflectionHooks?.onReflectionEnd?.({
30156
+ usage: void 0,
30157
+ error: error instanceof Error ? error : new Error(String(error))
30158
+ });
30159
+ } catch (hookError) {
30160
+ omError("[OM] onReflectionEnd hook failed after async buffered reflection failure", hookError);
30161
+ }
30162
+ BufferingCoordinator.lastBufferedBoundary.delete(bufferKey);
30163
+ }).finally(() => {
30164
+ BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
30165
+ unregisterOp(record.id, "bufferingReflection");
30166
+ this.storage.setBufferingReflectionFlag(record.id, false).catch((err) => {
30167
+ omError("[OM] Failed to clear buffering reflection flag", err);
30168
+ });
30169
+ });
30361
30170
  BufferingCoordinator.asyncBufferingOps.set(bufferKey, asyncOp);
30362
30171
  }
30363
30172
  /**
@@ -30618,13 +30427,6 @@ var ReflectorRunner = class {
30618
30427
  return;
30619
30428
  }
30620
30429
  }
30621
- if (activationTriggeredBy === "threshold") {
30622
- const suppressedAtTokens = this.syncReflectionSuppression.get(lockKey);
30623
- if (suppressedAtTokens !== void 0 && observationTokens === suppressedAtTokens) {
30624
- omDebug(`[OM:reflect] skipping sync reflection — observations unchanged at ${observationTokens} tokens since the last unproductive attempt; retrying once they change`);
30625
- return;
30626
- }
30627
- }
30628
30430
  await this.storage.setReflectingFlag(record.id, true);
30629
30431
  registerOp(record.id, "reflecting");
30630
30432
  const cycleId = crypto.randomUUID();
@@ -30665,15 +30467,8 @@ var ReflectorRunner = class {
30665
30467
  let reflectionUsage;
30666
30468
  let reflectionProviderMetadata;
30667
30469
  let reflectionError;
30668
- let lifecycleError;
30470
+ reflectionHooks?.onReflectionStart?.();
30669
30471
  try {
30670
- try {
30671
- await reflectionHooks?.onReflectionStart?.();
30672
- } catch (error) {
30673
- lifecycleError = error;
30674
- reflectionError = error instanceof Error ? error : new Error(String(error));
30675
- throw error;
30676
- }
30677
30472
  const compressionStartLevel = await this.getCompressionStartLevel(requestContext);
30678
30473
  const reflectResult = await this.call(record.activeObservations, void 0, streamContext, reflectThreshold, abortSignal, void 0, compressionStartLevel, requestContext, priorExtractedValues, observabilityContext, void 0, mainAgent, sendSignal);
30679
30474
  reflectionUsage = reflectResult.usage;
@@ -30685,8 +30480,6 @@ var ReflectorRunner = class {
30685
30480
  reflection: reflectResult.observations,
30686
30481
  tokenCount: reflectionTokenCount
30687
30482
  });
30688
- if (reflectionTokenCount >= reflectThreshold) this.syncReflectionSuppression.set(lockKey, reflectionTokenCount);
30689
- else this.syncReflectionSuppression.delete(lockKey);
30690
30483
  await this.notifyReflectionCommitted({
30691
30484
  parentThreadId: requestedThreadId ?? record.threadId ?? "",
30692
30485
  resourceId: record.resourceId ?? "",
@@ -30745,28 +30538,18 @@ var ReflectorRunner = class {
30745
30538
  await this.persistMarkerToStorage(failedMarker, threadId, record.resourceId ?? void 0);
30746
30539
  }
30747
30540
  reflectionError = error instanceof Error ? error : new Error(String(error));
30748
- if (lifecycleError !== void 0 || abortSignal?.aborted) throw error;
30749
- this.syncReflectionSuppression.set(lockKey, observationTokens);
30541
+ if (abortSignal?.aborted) throw error;
30750
30542
  omError("[OM] Reflection failed", error);
30751
30543
  } finally {
30544
+ await this.storage.setReflectingFlag(record.id, false);
30752
30545
  try {
30753
- await this.storage.setReflectingFlag(record.id, false);
30754
- } finally {
30755
- unregisterOp(record.id, "reflecting");
30756
- }
30757
- let endHookError;
30758
- try {
30759
- await reflectionHooks?.onReflectionEnd?.({
30546
+ reflectionHooks?.onReflectionEnd?.({
30760
30547
  usage: reflectionUsage,
30761
30548
  error: reflectionError,
30762
30549
  ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
30763
30550
  });
30764
- } catch (error) {
30765
- endHookError = error;
30766
- }
30767
- if (endHookError !== void 0) {
30768
- if (lifecycleError === void 0 && !abortSignal?.aborted) throw endHookError;
30769
- omDebug(`[OM:hooks] onReflectionEnd hook failed after cycle failure: ${endHookError instanceof Error ? endHookError.message : String(endHookError)}`);
30551
+ } finally {
30552
+ unregisterOp(record.id, "reflecting");
30770
30553
  }
30771
30554
  }
30772
30555
  }
@@ -31089,24 +30872,10 @@ function getLatestStepParts(parts) {
31089
30872
  return parts;
31090
30873
  }
31091
30874
  /**
31092
- * Returns true for persisted Working Memory state signals (`role: 'signal'`,
31093
- * `signal.type: 'state'`, `state.id: 'working-memory'`). OM must not observe these:
31094
- * they mirror memory OM itself manages, and re-observing them creates a self-feedback
31095
- * loop that can overwrite stored working memory (#21961). Only the working-memory lane
31096
- * is filtered — other state lanes are outside OM's write path, so re-observing them
31097
- * cannot corrupt OM-managed state; excluding them broadly is a separate decision.
30875
+ * Returns true when a message contains at least one part with visible user/assistant
30876
+ * content (text, tool-invocation, reasoning, image, file). Messages that only carry
30877
+ * internal `data-*` parts (buffering markers, observation markers, etc.) return false.
31098
30878
  */
31099
- function isWorkingMemoryStateSignal(message) {
31100
- if (message.role !== "signal") return false;
31101
- const signal = message.content.metadata?.signal;
31102
- if (!signal || typeof signal !== "object" || Array.isArray(signal)) return false;
31103
- const signalRecord = signal;
31104
- if ((signalRecord.type ?? message.type) !== "state") return false;
31105
- const metadata = signalRecord.metadata;
31106
- if (!metadata || typeof metadata !== "object" || Array.isArray(metadata)) return false;
31107
- const state = metadata.state;
31108
- return !!state && typeof state === "object" && !Array.isArray(state) && state.id === "working-memory";
31109
- }
31110
30879
  function messageHasVisibleContent(msg) {
31111
30880
  const content = msg.content;
31112
30881
  if (content?.parts && Array.isArray(content.parts)) return content.parts.some((p) => {
@@ -31237,8 +31006,6 @@ var ObservationalMemory = class ObservationalMemory {
31237
31006
  onIndexObservations;
31238
31007
  /** Config-level lifecycle hooks fired for every observation/reflection cycle. */
31239
31008
  hooks;
31240
- /** Execution policy for config-level hooks on manual and turn-synchronous cycles. */
31241
- hookExecution;
31242
31009
  /** Observer agent runner — handles LLM calls for extracting observations. */
31243
31010
  observer;
31244
31011
  /** Reflector agent runner — handles LLM calls for compressing observations. */
@@ -31345,7 +31112,6 @@ var ObservationalMemory = class ObservationalMemory {
31345
31112
  this.retrievalSearch = typeof config.retrieval === "object" && Boolean(config.retrieval.vector);
31346
31113
  this.onIndexObservations = config.onIndexObservations;
31347
31114
  this.hooks = config.hooks;
31348
- this.hookExecution = config.hookExecution ?? "non-blocking";
31349
31115
  this.mastra = config.mastra;
31350
31116
  this.memory = config.memory;
31351
31117
  this.curationCadence = config.curationCadence;
@@ -31877,7 +31643,7 @@ var ObservationalMemory = class ObservationalMemory {
31877
31643
  }
31878
31644
  const result = [];
31879
31645
  for (const msg of allMessages) {
31880
- if (msg.role === "system" || isWorkingMemoryStateSignal(msg)) continue;
31646
+ if (msg.role === "system") continue;
31881
31647
  if (observedMessageIds?.has(msg.id)) continue;
31882
31648
  const endMarkerIndex = findLastCompletedObservationBoundary(msg);
31883
31649
  if (this.hasInProgressObservation(msg)) result.push(msg);
@@ -32099,7 +31865,7 @@ var ObservationalMemory = class ObservationalMemory {
32099
31865
  },
32100
31866
  filter: startDate ? { dateRange: { start: startDate } } : void 0
32101
31867
  });
32102
- return result.messages.filter((msg) => msg.role !== "system" && !isWorkingMemoryStateSignal(msg));
31868
+ return result.messages.filter((msg) => msg.role !== "system");
32103
31869
  }
32104
31870
  /**
32105
31871
  * Format unobserved messages from other threads as <unobserved-context> blocks.
@@ -32558,7 +32324,7 @@ ${formattedMessages}
32558
32324
  direction: "ASC"
32559
32325
  },
32560
32326
  filter: startDate ? { dateRange: { start: startDate } } : void 0
32561
- })).messages.filter((message) => !this.observedMessageIds.has(message.id) && !isWorkingMemoryStateSignal(message));
32327
+ })).messages.filter((m) => !this.observedMessageIds.has(m.id));
32562
32328
  if (filtered.length > 0) messagesByThread.set(thread.id, filtered);
32563
32329
  }
32564
32330
  if (messagesByThread.size === 0) return void 0;
@@ -33138,54 +32904,57 @@ ${formattedMessages}
33138
32904
  };
33139
32905
  }
33140
32906
  /**
33141
- * Compose config-level hooks with optional per-call hooks and bind context to
33142
- * config-level callbacks. The configured policy applies unless a background
33143
- * path explicitly requests non-blocking invocation.
32907
+ * Compose the config-level hooks with optional per-call hooks into a single
32908
+ * `ObserveHooks` object, binding call context onto the config-level
32909
+ * callbacks. Config-level hooks are guarded so a throwing consumer hook can
32910
+ * never fail an observation/reflection cycle; per-call hooks keep their
32911
+ * existing payloads and propagation semantics. Returns undefined when
32912
+ * neither is configured, so call sites stay zero-cost.
32913
+ *
32914
+ * Used internally by every pipeline path (manual observe/reflect,
32915
+ * turn-engine sync observation, async buffering); public only so the
32916
+ * observation turn engine can thread config-level reflection hooks into
32917
+ * reflector calls.
33144
32918
  *
33145
32919
  * @internal
33146
32920
  */
33147
- composeHooks(callHooks, context, execution = "configured") {
32921
+ composeHooks(callHooks, context) {
33148
32922
  const configHooks = this.hooks;
33149
32923
  if (!configHooks) return callHooks;
33150
32924
  if (!callHooks && !Object.keys(configHooks).length) return void 0;
33151
- const shouldAwaitConfig = execution === "configured" && this.hookExecution === "await";
33152
- const invokeConfigHook = async (name, arg) => {
32925
+ const fireConfigHook = (name, arg) => {
33153
32926
  const hook = configHooks[name];
33154
32927
  if (!hook) return;
33155
- if (shouldAwaitConfig) {
33156
- await hook(arg);
33157
- return;
33158
- }
33159
32928
  const logHookFailure = (error) => omDebug(`[OM:hooks] config-level ${name} hook failed: ${error instanceof Error ? error.message : String(error)}`);
33160
32929
  try {
33161
- const result = hook(arg);
33162
- if (result && typeof result.then === "function") result.then(void 0, logHookFailure);
32930
+ const out = hook(arg);
32931
+ if (out && typeof out.then === "function") out.then(void 0, logHookFailure);
33163
32932
  } catch (error) {
33164
32933
  logHookFailure(error);
33165
32934
  }
33166
32935
  };
33167
32936
  return {
33168
- onObservationStart: async () => {
33169
- await invokeConfigHook("onObservationStart", context);
33170
- await callHooks?.onObservationStart?.();
32937
+ onObservationStart: () => {
32938
+ fireConfigHook("onObservationStart", context);
32939
+ callHooks?.onObservationStart?.();
33171
32940
  },
33172
- onObservationEnd: async (result) => {
33173
- await invokeConfigHook("onObservationEnd", {
32941
+ onObservationEnd: (result) => {
32942
+ fireConfigHook("onObservationEnd", {
33174
32943
  ...context,
33175
32944
  ...result
33176
32945
  });
33177
- await callHooks?.onObservationEnd?.(result);
32946
+ callHooks?.onObservationEnd?.(result);
33178
32947
  },
33179
- onReflectionStart: async () => {
33180
- await invokeConfigHook("onReflectionStart", context);
33181
- await callHooks?.onReflectionStart?.();
32948
+ onReflectionStart: () => {
32949
+ fireConfigHook("onReflectionStart", context);
32950
+ callHooks?.onReflectionStart?.();
33182
32951
  },
33183
- onReflectionEnd: async (result) => {
33184
- await invokeConfigHook("onReflectionEnd", {
32952
+ onReflectionEnd: (result) => {
32953
+ fireConfigHook("onReflectionEnd", {
33185
32954
  ...context,
33186
32955
  ...result
33187
32956
  });
33188
- await callHooks?.onReflectionEnd?.(result);
32957
+ callHooks?.onReflectionEnd?.(result);
33189
32958
  }
33190
32959
  };
33191
32960
  }
@@ -33198,29 +32967,22 @@ ${formattedMessages}
33198
32967
  * end hook reports `error` for failed cycles even though nothing throws.
33199
32968
  */
33200
32969
  async runBufferedObservationCycle(context, run) {
33201
- const hooks = this.composeHooks(void 0, context, "non-blocking");
32970
+ const hooks = this.composeHooks(void 0, context);
32971
+ hooks?.onObservationStart?.();
33202
32972
  let runResult;
33203
32973
  let runError;
33204
- let lifecycleError;
33205
32974
  try {
33206
- await hooks?.onObservationStart?.();
33207
32975
  runResult = await run();
33208
32976
  return runResult;
33209
32977
  } catch (error) {
33210
- lifecycleError = error;
33211
32978
  runError = error instanceof Error ? error : new Error(String(error));
33212
32979
  throw error;
33213
32980
  } finally {
33214
- try {
33215
- await hooks?.onObservationEnd?.({
33216
- usage: runResult?.usage,
33217
- error: runError ?? runResult?.error,
33218
- ...runResult?.providerMetadata ? { providerMetadata: runResult.providerMetadata } : {}
33219
- });
33220
- } catch (endHookError) {
33221
- if (lifecycleError === void 0) throw endHookError;
33222
- omDebug(`[OM:hooks] async-buffer onObservationEnd hook failed after cycle failure: ${endHookError instanceof Error ? endHookError.message : String(endHookError)}`);
33223
- }
32981
+ hooks?.onObservationEnd?.({
32982
+ usage: runResult?.usage,
32983
+ error: runError ?? runResult?.error,
32984
+ ...runResult?.providerMetadata ? { providerMetadata: runResult.providerMetadata } : {}
32985
+ });
33224
32986
  }
33225
32987
  }
33226
32988
  /**
@@ -33248,21 +33010,18 @@ ${formattedMessages}
33248
33010
  let observed = false;
33249
33011
  let observationUsage;
33250
33012
  let observationProviderMetadata;
33251
- let observationError;
33252
- let lifecycleError;
33253
- let observationStarted = false;
33254
33013
  let generationBefore = -1;
33255
- try {
33256
- await this.withLock(lockKey, async () => {
33257
- const freshRecord = await this.getOrCreateRecord(threadId, resourceId);
33258
- generationBefore = freshRecord.generationCount;
33259
- const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(threadId, resourceId, freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0);
33260
- if (!this.meetsObservationThreshold({
33261
- record: freshRecord,
33262
- unobservedTokens: await this.tokenCounter.countMessagesAsync(unobservedMessages)
33263
- })) return;
33264
- observationStarted = true;
33265
- await hooks?.onObservationStart?.();
33014
+ await this.withLock(lockKey, async () => {
33015
+ const freshRecord = await this.getOrCreateRecord(threadId, resourceId);
33016
+ generationBefore = freshRecord.generationCount;
33017
+ const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(threadId, resourceId, freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0);
33018
+ if (!this.meetsObservationThreshold({
33019
+ record: freshRecord,
33020
+ unobservedTokens: await this.tokenCounter.countMessagesAsync(unobservedMessages)
33021
+ })) return;
33022
+ hooks?.onObservationStart?.();
33023
+ let observationError;
33024
+ try {
33266
33025
  const result = await ObservationStrategy.create(this, {
33267
33026
  record: freshRecord,
33268
33027
  threadId,
@@ -33280,22 +33039,17 @@ ${formattedMessages}
33280
33039
  observed = result.observed;
33281
33040
  observationUsage = result.usage;
33282
33041
  observationProviderMetadata = result.providerMetadata;
33283
- });
33284
- } catch (error) {
33285
- lifecycleError = error;
33286
- observationError = error instanceof Error ? error : new Error(String(error));
33287
- }
33288
- if (observationStarted) try {
33289
- await hooks?.onObservationEnd?.({
33290
- usage: observationUsage,
33291
- error: observationError,
33292
- ...observationProviderMetadata ? { providerMetadata: observationProviderMetadata } : {}
33293
- });
33294
- } catch (endHookError) {
33295
- if (lifecycleError === void 0) throw endHookError;
33296
- omDebug(`[OM:hooks] onObservationEnd hook failed after cycle failure: ${endHookError instanceof Error ? endHookError.message : String(endHookError)}`);
33297
- }
33298
- if (lifecycleError !== void 0) throw lifecycleError;
33042
+ } catch (error) {
33043
+ observationError = error instanceof Error ? error : new Error(String(error));
33044
+ throw error;
33045
+ } finally {
33046
+ hooks?.onObservationEnd?.({
33047
+ usage: observationUsage,
33048
+ error: observationError,
33049
+ ...observationProviderMetadata ? { providerMetadata: observationProviderMetadata } : {}
33050
+ });
33051
+ }
33052
+ });
33299
33053
  const record = await this.getOrCreateRecord(threadId, resourceId);
33300
33054
  const reflected = record.generationCount > generationBefore && generationBefore >= 0;
33301
33055
  if (observed) this.maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext).catch((error) => {
@@ -33369,18 +33123,11 @@ ${formattedMessages}
33369
33123
  resourceId,
33370
33124
  trigger: "manual"
33371
33125
  });
33126
+ hooks?.onReflectionStart?.();
33372
33127
  let reflectionUsage;
33373
33128
  let reflectionProviderMetadata;
33374
33129
  let reflectionError;
33375
- let lifecycleError;
33376
33130
  try {
33377
- try {
33378
- await hooks?.onReflectionStart?.();
33379
- } catch (error) {
33380
- lifecycleError = error;
33381
- reflectionError = error instanceof Error ? error : new Error(String(error));
33382
- throw error;
33383
- }
33384
33131
  const thread = await this.storage.getThreadById({ threadId });
33385
33132
  const previousOmMetadata = getThreadOMMetadata(thread?.metadata);
33386
33133
  const priorExtractedValues = getPriorExtractedValues(previousOmMetadata, this.reflectionConfig.extractors);
@@ -33418,7 +33165,6 @@ ${formattedMessages}
33418
33165
  };
33419
33166
  } catch (error) {
33420
33167
  reflectionError = error instanceof Error ? error : new Error(String(error));
33421
- if (lifecycleError !== void 0) throw error;
33422
33168
  omError("[OM] reflect() failed", error);
33423
33169
  return {
33424
33170
  reflected: false,
@@ -33426,25 +33172,13 @@ ${formattedMessages}
33426
33172
  usage: void 0
33427
33173
  };
33428
33174
  } finally {
33429
- try {
33430
- await this.storage.setReflectingFlag(record.id, false);
33431
- } finally {
33432
- unregisterOp(record.id, "reflecting");
33433
- }
33434
- let endHookError;
33435
- try {
33436
- await hooks?.onReflectionEnd?.({
33437
- usage: reflectionUsage,
33438
- error: reflectionError,
33439
- ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
33440
- });
33441
- } catch (error) {
33442
- endHookError = error;
33443
- }
33444
- if (endHookError !== void 0) {
33445
- if (lifecycleError === void 0) throw endHookError;
33446
- omDebug(`[OM:hooks] onReflectionEnd hook failed after cycle failure: ${endHookError instanceof Error ? endHookError.message : String(endHookError)}`);
33447
- }
33175
+ hooks?.onReflectionEnd?.({
33176
+ usage: reflectionUsage,
33177
+ error: reflectionError,
33178
+ ...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
33179
+ });
33180
+ await this.storage.setReflectingFlag(record.id, false);
33181
+ unregisterOp(record.id, "reflecting");
33448
33182
  }
33449
33183
  }
33450
33184
  /**
@@ -33975,6 +33709,149 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
33975
33709
  summarizeConversation: () => summarizeConversation,
33976
33710
  wrapInObservationGroup: () => wrapInObservationGroup
33977
33711
  });
33712
+ /**
33713
+ * WorkingMemoryStateProcessor
33714
+ *
33715
+ * Experimental: delivers working memory to the model as a state signal instead
33716
+ * of folding it into the system message. Storage and the `setWorkingMemory`
33717
+ * tool are unchanged — this processor only changes the delivery path.
33718
+ *
33719
+ * Pattern matches `BrowserContextProcessor` in `@mastra/core/browser`:
33720
+ * - `stateId` namespaces the state lane on the thread.
33721
+ * - `cacheKey` is derived from the rendered payload so dedup is automatic.
33722
+ * - `contextWindow.hasSnapshot` re-injection ensures the model still sees the
33723
+ * current snapshot after older messages drop out of the window.
33724
+ *
33725
+ * Delta emission (markdown mode only): when a prior snapshot exists in the
33726
+ * context window, the processor emits a unified-diff delta against that
33727
+ * snapshot's contents. Schema mode and the snapshot fallback always emit a
33728
+ * full snapshot.
33729
+ *
33730
+ * @example
33731
+ * ```ts
33732
+ * new Memory({
33733
+ * options: {
33734
+ * workingMemory: {
33735
+ * enabled: true,
33736
+ * template: '...',
33737
+ * useStateSignals: true, // auto-attaches this processor
33738
+ * },
33739
+ * },
33740
+ * });
33741
+ * ```
33742
+ */
33743
+ const WORKING_MEMORY_STATE_ID = "working-memory";
33744
+ const WORKING_MEMORY_STATE_PROCESSOR_ID = "working-memory-state";
33745
+ var WorkingMemoryStateProcessor = class {
33746
+ memory;
33747
+ memoryConfig;
33748
+ id = WORKING_MEMORY_STATE_PROCESSOR_ID;
33749
+ stateId = WORKING_MEMORY_STATE_ID;
33750
+ constructor(memory, memoryConfig) {
33751
+ this.memory = memory;
33752
+ this.memoryConfig = memoryConfig;
33753
+ }
33754
+ async computeStateSignal(args) {
33755
+ const template = await this.memory.getWorkingMemoryTemplate({ memoryConfig: this.memoryConfig });
33756
+ if (!template) return;
33757
+ const contents = (await this.memory.getWorkingMemory({
33758
+ threadId: args.threadId,
33759
+ resourceId: args.resourceId,
33760
+ memoryConfig: this.memoryConfig
33761
+ }))?.trim();
33762
+ if (!contents) return;
33763
+ const cacheKey = stableWorkingMemoryCacheKey({
33764
+ format: template.format,
33765
+ data: contents
33766
+ });
33767
+ const shouldMakeSnapshot = !args.contextWindow.hasSnapshot;
33768
+ if (args.tracking?.currentCacheKey === cacheKey && !shouldMakeSnapshot) return;
33769
+ const scope = this.memory.getMergedThreadConfig(this.memoryConfig).workingMemory?.scope ?? "resource";
33770
+ const deltaCandidate = template.format === "markdown" && !shouldMakeSnapshot ? buildMarkdownDelta({
33771
+ lastSnapshot: args.lastSnapshot,
33772
+ deltasSinceSnapshot: args.deltasSinceSnapshot,
33773
+ nextContents: contents
33774
+ }) : void 0;
33775
+ if (deltaCandidate) return {
33776
+ id: WORKING_MEMORY_STATE_ID,
33777
+ mode: "delta",
33778
+ cacheKey,
33779
+ tagName: "working-memory",
33780
+ contents: deltaCandidate.contents,
33781
+ delta: deltaCandidate.contents,
33782
+ value: contents,
33783
+ attributes: {
33784
+ format: template.format,
33785
+ scope,
33786
+ patch: "unified-diff"
33787
+ }
33788
+ };
33789
+ return {
33790
+ id: WORKING_MEMORY_STATE_ID,
33791
+ mode: "snapshot",
33792
+ cacheKey,
33793
+ tagName: "working-memory",
33794
+ contents,
33795
+ value: contents,
33796
+ attributes: {
33797
+ format: template.format,
33798
+ scope
33799
+ }
33800
+ };
33801
+ }
33802
+ };
33803
+ /**
33804
+ * Stable cache key for the rendered working memory payload. Returns a SHA-256
33805
+ * digest so dedup metadata stays compact regardless of payload size (working
33806
+ * memory blobs can grow arbitrarily long).
33807
+ */
33808
+ function stableWorkingMemoryCacheKey(input) {
33809
+ const hash = createHash("sha256");
33810
+ hash.update(input.format);
33811
+ hash.update("\0");
33812
+ hash.update(input.data ?? "");
33813
+ return `sha256:${hash.digest("hex")}`;
33814
+ }
33815
+ /**
33816
+ * Build a unified-diff delta against the most recently emitted state. Prefers
33817
+ * the latest delta's `value` (the post-edit full text) when available, falling
33818
+ * back to the snapshot's `value` and finally the snapshot's `contents`. This
33819
+ * keeps deltas incremental (B→C) instead of cumulative against a stale
33820
+ * snapshot (A→C), which matters when many small edits land between snapshots.
33821
+ *
33822
+ * Returns undefined when:
33823
+ * - there's no prior state to diff against
33824
+ * - the prior state isn't a plain string (multimodal signal)
33825
+ *
33826
+ * In either case the caller falls back to emitting a full snapshot.
33827
+ */
33828
+ function buildMarkdownDelta(args) {
33829
+ const { lastSnapshot, deltasSinceSnapshot, nextContents } = args;
33830
+ const prior = pickStringValue(readSignalValue(deltasSinceSnapshot.at(-1))) ?? pickStringValue(readSignalValue(lastSnapshot)) ?? (typeof lastSnapshot?.contents === "string" ? lastSnapshot.contents : void 0);
33831
+ if (!prior) return;
33832
+ return { contents: renderHunksOnly(prior, nextContents) };
33833
+ }
33834
+ function pickStringValue(value) {
33835
+ return typeof value === "string" ? value : void 0;
33836
+ }
33837
+ function readSignalValue(signal) {
33838
+ return (signal?.metadata)?.value;
33839
+ }
33840
+ /**
33841
+ * Render a unified-diff-style patch body containing only `@@` hunks and their
33842
+ * lines — dropping the filename preamble (`Index:` / `===` / `---` / `+++`)
33843
+ * that `createPatch` emits and the `` trailer.
33844
+ * The preamble exists for tooling like `patch -p1` to know which file to
33845
+ * apply to; we only ever diff a single working-memory blob. The newline
33846
+ * trailer is semantically meaningless to the model and adds noise to the
33847
+ * state signal.
33848
+ */
33849
+ function renderHunksOnly(prior, next) {
33850
+ const { hunks } = structuredPatch("", "", prior, next, "", "", { context: 0 });
33851
+ return hunks.map((hunk) => {
33852
+ return [`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`, ...hunk.lines.filter((line) => !line.startsWith("\"))].join("\n");
33853
+ }).join("\n");
33854
+ }
33978
33855
  var working_memory_state_exports = /* @__PURE__ */ __exportAll({
33979
33856
  WORKING_MEMORY_STATE_ID: () => WORKING_MEMORY_STATE_ID,
33980
33857
  WORKING_MEMORY_STATE_PROCESSOR_ID: () => WORKING_MEMORY_STATE_PROCESSOR_ID,
@@ -35055,7 +34932,6 @@ ${workingMemory}`;
35055
34932
  instruction: omConfig.observation.instruction,
35056
34933
  threadTitle: omConfig.observation.threadTitle,
35057
34934
  observeAttachments: omConfig.observation.observeAttachments,
35058
- continuationHints: omConfig.observation.continuationHints,
35059
34935
  extract: omConfig.observation.extract
35060
34936
  } : void 0,
35061
34937
  reflection: omConfig.reflection ? {
@@ -35066,7 +34942,6 @@ ${workingMemory}`;
35066
34942
  bufferActivation: omConfig.reflection.bufferActivation,
35067
34943
  blockAfter: omConfig.reflection.blockAfter,
35068
34944
  instruction: omConfig.reflection.instruction,
35069
- continuationHints: omConfig.reflection.continuationHints,
35070
34945
  extract: omConfig.reflection.extract
35071
34946
  } : void 0
35072
34947
  });
@@ -41234,7 +41109,6 @@ async function cancelResponseBody(response) {
41234
41109
  var initialGlobalFetch = globalThis.fetch;
41235
41110
  isNodeDefaultFetch(initialGlobalFetch);
41236
41111
  function isNodeDefaultFetch(fetch) {
41237
- if (typeof fetch !== "function") return false;
41238
41112
  const source = Function.prototype.toString.call(fetch);
41239
41113
  return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
41240
41114
  }
@@ -46361,4 +46235,4 @@ const agentBuilderWorkflows = {
46361
46235
  //#endregion
46362
46236
  export { agentBuilderWorkflows };
46363
46237
 
46364
- //# sourceMappingURL=dist-L0EogwX_.js.map
46238
+ //# sourceMappingURL=dist-HzWDFjPH.js.map