@mastra/server 1.61.1-alpha.1 → 1.62.0-alpha.11
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.
- package/CHANGELOG.md +97 -0
- package/dist/_types/@internal_core/dist/storage/index.d.ts +8 -0
- package/dist/{api-schema-manifest-BxnLWV5l.js → api-schema-manifest-BVgosvca.js} +2 -2
- package/dist/{api-schema-manifest-BxnLWV5l.js.map → api-schema-manifest-BVgosvca.js.map} +1 -1
- package/dist/{api-schema-manifest-Cbonk0PF.cjs → api-schema-manifest-DrTLp1Fv.cjs} +2 -2
- package/dist/{api-schema-manifest-Cbonk0PF.cjs.map → api-schema-manifest-DrTLp1Fv.cjs.map} +1 -1
- package/dist/{datasets-DmN9V4rU.js → datasets-CInAtVdf.js} +3 -1
- package/dist/datasets-CInAtVdf.js.map +1 -0
- package/dist/{datasets-CNtKg_3d.cjs → datasets-DYhcB-od.cjs} +3 -1
- package/dist/datasets-DYhcB-od.cjs.map +1 -0
- package/dist/{dist-Cw-T1gX6.js → dist-L0EogwX_.js} +476 -311
- package/dist/dist-L0EogwX_.js.map +1 -0
- package/dist/{dist-DERatX43.cjs → dist-Xj9TvH1A.cjs} +476 -311
- package/dist/dist-Xj9TvH1A.cjs.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +1 -1
- package/dist/docs/references/docs-server-middleware.md +30 -0
- package/dist/{observability-new-endpoints-Drx0C8uc.js → observability-new-endpoints-0RLfcyw6.js} +2 -1
- package/dist/observability-new-endpoints-0RLfcyw6.js.map +1 -0
- package/dist/{observability-new-endpoints-gRCFhnRr.cjs → observability-new-endpoints-4GcBP0uJ.cjs} +2 -1
- package/dist/observability-new-endpoints-4GcBP0uJ.cjs.map +1 -0
- package/dist/{routes-DGwUTyHr.cjs → routes-CDsvr7BB.cjs} +2 -2
- package/dist/{routes-DGwUTyHr.cjs.map → routes-CDsvr7BB.cjs.map} +1 -1
- package/dist/{routes-B6F4QBgN.js → routes-DCEudTA7.js} +2 -2
- package/dist/{routes-B6F4QBgN.js.map → routes-DCEudTA7.js.map} +1 -1
- package/dist/server/handlers/agent-builder.cjs +1 -1
- package/dist/server/handlers/agent-builder.js +1 -1
- package/dist/server/handlers/datasets.cjs +1 -1
- package/dist/server/handlers/datasets.d.ts +10 -0
- package/dist/server/handlers/datasets.d.ts.map +1 -1
- package/dist/server/handlers/datasets.js +1 -1
- package/dist/server/handlers/observability-new-endpoints.cjs +1 -1
- package/dist/server/handlers/observability-new-endpoints.d.ts +16 -0
- package/dist/server/handlers/observability-new-endpoints.d.ts.map +1 -1
- package/dist/server/handlers/observability-new-endpoints.js +1 -1
- package/dist/server/handlers/observability.cjs +1 -1
- package/dist/server/handlers/observability.js +1 -1
- package/dist/server/handlers/system.cjs +1 -1
- package/dist/server/handlers/system.js +1 -1
- package/dist/server/schemas/datasets.d.ts +4 -0
- package/dist/server/schemas/datasets.d.ts.map +1 -1
- package/dist/server/schemas/index.cjs +1 -1
- package/dist/server/schemas/index.js +1 -1
- package/dist/server/server-adapter/index.cjs +23 -3
- package/dist/server/server-adapter/index.cjs.map +1 -1
- package/dist/server/server-adapter/index.d.ts +14 -0
- package/dist/server/server-adapter/index.d.ts.map +1 -1
- package/dist/server/server-adapter/index.js +23 -4
- package/dist/server/server-adapter/index.js.map +1 -1
- package/dist/server/server-adapter/routes/datasets.d.ts +10 -0
- package/dist/server/server-adapter/routes/datasets.d.ts.map +1 -1
- package/dist/server/server-adapter/routes/observability.d.ts +8 -0
- package/dist/server/server-adapter/routes/observability.d.ts.map +1 -1
- package/package.json +6 -6
- package/dist/datasets-CNtKg_3d.cjs.map +0 -1
- package/dist/datasets-DmN9V4rU.js.map +0 -1
- package/dist/dist-Cw-T1gX6.js.map +0 -1
- package/dist/dist-DERatX43.cjs.map +0 -1
- package/dist/observability-new-endpoints-Drx0C8uc.js.map +0 -1
- package/dist/observability-new-endpoints-gRCFhnRr.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-
|
|
4696
|
+
//#region ../memory/dist/src-BATJenuZ.js
|
|
4697
4697
|
var __defProp$3 = Object.defineProperty;
|
|
4698
4698
|
var __exportAll = (all, no_symbols) => {
|
|
4699
4699
|
let target = {};
|
|
@@ -8927,6 +8927,7 @@ 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;
|
|
8930
8931
|
const source = Function.prototype.toString.call(fetch);
|
|
8931
8932
|
return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
|
|
8932
8933
|
}
|
|
@@ -13818,6 +13819,7 @@ var DownloadError$2 = class extends (_b$2$1 = AISDKError$3, _a$2$1 = symbol$2$1,
|
|
|
13818
13819
|
var initialGlobalFetch$2 = globalThis.fetch;
|
|
13819
13820
|
isNodeDefaultFetch$2(initialGlobalFetch$2);
|
|
13820
13821
|
function isNodeDefaultFetch$2(fetch) {
|
|
13822
|
+
if (typeof fetch !== "function") return false;
|
|
13821
13823
|
const source = Function.prototype.toString.call(fetch);
|
|
13822
13824
|
return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
|
|
13823
13825
|
}
|
|
@@ -23480,6 +23482,12 @@ function extractListItemsOnly(content) {
|
|
|
23480
23482
|
*/
|
|
23481
23483
|
const MAX_OBSERVATION_LINE_CHARS = 1e4;
|
|
23482
23484
|
/**
|
|
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
|
+
/**
|
|
23483
23491
|
* Truncate individual observation lines that exceed the maximum length.
|
|
23484
23492
|
*/
|
|
23485
23493
|
function sanitizeObservationLines(observations) {
|
|
@@ -23517,6 +23525,18 @@ function detectDegenerateRepetition(text) {
|
|
|
23517
23525
|
if (totalWindows > 5 && duplicateWindows / totalWindows > .4) return true;
|
|
23518
23526
|
const lines = text.split("\n");
|
|
23519
23527
|
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;
|
|
23520
23540
|
return false;
|
|
23521
23541
|
}
|
|
23522
23542
|
/**
|
|
@@ -23551,12 +23571,26 @@ function describeDegenerateOutput(text, snippetChars = 400) {
|
|
|
23551
23571
|
topWindow = window;
|
|
23552
23572
|
}
|
|
23553
23573
|
let longestLine = 0;
|
|
23554
|
-
|
|
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
|
+
}
|
|
23555
23586
|
const duplicateRatio = totalWindows > 0 ? (duplicateWindows / totalWindows).toFixed(2) : "n/a";
|
|
23587
|
+
const duplicateLineRatio = totalCountedLines > 0 ? (duplicateLines / totalCountedLines).toFixed(2) : "n/a";
|
|
23556
23588
|
const parts = [
|
|
23557
23589
|
`length=${text.length}`,
|
|
23558
23590
|
`sampledWindows=${totalWindows}`,
|
|
23559
23591
|
`duplicateRatio=${duplicateRatio}`,
|
|
23592
|
+
`duplicateLineRatio=${duplicateLineRatio}`,
|
|
23593
|
+
`countedLines=${totalCountedLines}`,
|
|
23560
23594
|
`longestLine=${longestLine}`,
|
|
23561
23595
|
`topWindowCount=${topCount}`
|
|
23562
23596
|
];
|
|
@@ -23824,7 +23858,19 @@ async function withOmTracingSpan({ phase, model, inputTokens, requestContext, ob
|
|
|
23824
23858
|
});
|
|
23825
23859
|
const childObservabilityContext = createObservabilityContext({ currentSpan: span });
|
|
23826
23860
|
if (!span) return callback(childObservabilityContext);
|
|
23827
|
-
return span.executeInContext(() =>
|
|
23861
|
+
return span.executeInContext(async () => {
|
|
23862
|
+
try {
|
|
23863
|
+
const result = await callback(childObservabilityContext);
|
|
23864
|
+
span.end();
|
|
23865
|
+
return result;
|
|
23866
|
+
} catch (error) {
|
|
23867
|
+
span.error({
|
|
23868
|
+
error,
|
|
23869
|
+
endSpan: true
|
|
23870
|
+
});
|
|
23871
|
+
throw error;
|
|
23872
|
+
}
|
|
23873
|
+
});
|
|
23828
23874
|
}
|
|
23829
23875
|
function filterObserverExtractors(extractors, skipContinuationHints) {
|
|
23830
23876
|
const configuredExtractors = extractors ?? [];
|
|
@@ -26923,6 +26969,149 @@ function createWorkingMemoryTool(config, options = {}) {
|
|
|
26923
26969
|
tool
|
|
26924
26970
|
};
|
|
26925
26971
|
}
|
|
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
|
+
}
|
|
26926
27115
|
const MINUTE = 6e4;
|
|
26927
27116
|
const HOUR = 60 * MINUTE;
|
|
26928
27117
|
const SHORT_TTL = 5 * MINUTE;
|
|
@@ -28917,10 +29106,11 @@ ObservationStrategy.create = ((om, opts) => {
|
|
|
28917
29106
|
if (deps.scope === "resource" && opts.resourceId) return new ResourceScopedObservationStrategy(deps, opts);
|
|
28918
29107
|
return new SyncObservationStrategy(deps, opts);
|
|
28919
29108
|
});
|
|
28920
|
-
async function loadMemoryContextMessages({ memory, messageList, threadId, resourceId }) {
|
|
29109
|
+
async function loadMemoryContextMessages({ memory, messageList, threadId, resourceId, runState }) {
|
|
28921
29110
|
const ctx = await memory.getContext({
|
|
28922
29111
|
threadId,
|
|
28923
|
-
resourceId
|
|
29112
|
+
resourceId,
|
|
29113
|
+
runState
|
|
28924
29114
|
});
|
|
28925
29115
|
for (const msg of ctx.messages) if (msg.role !== "system") messageList.add(msg, "memory");
|
|
28926
29116
|
return ctx;
|
|
@@ -29374,10 +29564,11 @@ var ObservationTurn = class {
|
|
|
29374
29564
|
* If a MemoryContextProvider is passed, loads historical messages and adds
|
|
29375
29565
|
* them to the MessageList. Without a provider, only fetches/caches the record.
|
|
29376
29566
|
*/
|
|
29377
|
-
async start(memory) {
|
|
29567
|
+
async start(memory, runState) {
|
|
29378
29568
|
if (this._started) throw new Error("Turn already started");
|
|
29379
29569
|
this._started = true;
|
|
29380
29570
|
this._record = await this.om.getOrCreateRecord(this.threadId, this.resourceId);
|
|
29571
|
+
runState?.set(`observational-memory:record:${this.threadId}:${this.resourceId ?? ""}`, this._record);
|
|
29381
29572
|
this._generationCountAtStart = this._record.generationCount;
|
|
29382
29573
|
this.memory = memory;
|
|
29383
29574
|
if (memory) {
|
|
@@ -29385,7 +29576,8 @@ var ObservationTurn = class {
|
|
|
29385
29576
|
memory,
|
|
29386
29577
|
messageList: this.messageList,
|
|
29387
29578
|
threadId: this.threadId,
|
|
29388
|
-
resourceId: this.resourceId
|
|
29579
|
+
resourceId: this.resourceId,
|
|
29580
|
+
runState
|
|
29389
29581
|
});
|
|
29390
29582
|
this._context = {
|
|
29391
29583
|
messages: ctx.messages,
|
|
@@ -29861,6 +30053,21 @@ var ReflectorRunner = class {
|
|
|
29861
30053
|
memory;
|
|
29862
30054
|
onReflectionCommitted;
|
|
29863
30055
|
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();
|
|
29864
30071
|
constructor(opts) {
|
|
29865
30072
|
this.reflectionConfig = opts.reflectionConfig;
|
|
29866
30073
|
this.observationConfig = opts.observationConfig;
|
|
@@ -29943,8 +30150,8 @@ var ReflectorRunner = class {
|
|
|
29943
30150
|
};
|
|
29944
30151
|
let reflectedTokens = 0;
|
|
29945
30152
|
let attemptNumber = 0;
|
|
29946
|
-
/**
|
|
29947
|
-
let
|
|
30153
|
+
/** True when the latest attempt returned an empty block for non-empty input. */
|
|
30154
|
+
let emptyOutput = false;
|
|
29948
30155
|
while (currentLevel <= maxLevel) {
|
|
29949
30156
|
attemptNumber++;
|
|
29950
30157
|
const isRetry = attemptNumber > 1;
|
|
@@ -30008,21 +30215,20 @@ var ReflectorRunner = class {
|
|
|
30008
30215
|
}
|
|
30009
30216
|
finalProviderMetadata = result.providerMetadata ?? finalProviderMetadata;
|
|
30010
30217
|
parsed = parseReflectorOutput(result.text, observations, activeExtractors);
|
|
30218
|
+
emptyOutput = !parsed.degenerate && observations.trim().length > 0 && parsed.observations.trim().length === 0;
|
|
30011
30219
|
if (parsed.degenerate) {
|
|
30012
30220
|
omDebug(`[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure. ${describeDegenerateOutput(result.text, 2e3)}`);
|
|
30013
30221
|
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;
|
|
30014
30225
|
} else reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
|
|
30015
30226
|
omDebug(`[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`);
|
|
30016
|
-
if (!parsed.degenerate && (validateCompression(reflectedTokens, targetThreshold) || currentLevel >= maxLevel)) break;
|
|
30017
|
-
if (parsed.degenerate && currentLevel >= maxLevel) {
|
|
30018
|
-
omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
|
|
30019
|
-
break;
|
|
30020
|
-
}
|
|
30021
|
-
if (!parsed.degenerate && previousObservations !== void 0 && parsed.observations === previousObservations) {
|
|
30022
|
-
omDebug(`[OM:callReflector] attempt #${attemptNumber} returned output identical to the previous attempt; escalating cannot help, stopping the ladder`);
|
|
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`);
|
|
30023
30230
|
break;
|
|
30024
30231
|
}
|
|
30025
|
-
previousObservations = parsed.observations;
|
|
30026
30232
|
if (streamContext?.writer) {
|
|
30027
30233
|
const failedMarker = createObservationFailedMarker({
|
|
30028
30234
|
cycleId: streamContext.cycleId,
|
|
@@ -30058,6 +30264,7 @@ var ReflectorRunner = class {
|
|
|
30058
30264
|
}
|
|
30059
30265
|
currentLevel = Math.min(currentLevel + 1, maxLevel);
|
|
30060
30266
|
}
|
|
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`);
|
|
30061
30268
|
const structuredExtraction = await extractStructuredValues({
|
|
30062
30269
|
agent,
|
|
30063
30270
|
source: "reflector",
|
|
@@ -30106,52 +30313,51 @@ var ReflectorRunner = class {
|
|
|
30106
30313
|
this.storage.setBufferingReflectionFlag(record.id, true).catch((err) => {
|
|
30107
30314
|
omError("[OM] Failed to set buffering reflection flag", err);
|
|
30108
30315
|
});
|
|
30109
|
-
|
|
30110
|
-
|
|
30111
|
-
|
|
30112
|
-
reflectionHooks?.onReflectionEnd?.({
|
|
30113
|
-
usage: outcome?.usage,
|
|
30114
|
-
...outcome?.providerMetadata ? { providerMetadata: outcome.providerMetadata } : {}
|
|
30115
|
-
});
|
|
30116
|
-
} catch (hookError) {
|
|
30117
|
-
omError("[OM] onReflectionEnd hook failed after async buffered reflection", hookError);
|
|
30118
|
-
}
|
|
30119
|
-
}, async (error) => {
|
|
30120
|
-
if (writer) try {
|
|
30121
|
-
const failedMarker = createBufferingFailedMarker({
|
|
30122
|
-
cycleId: `reflect-buf-${Date.now()}-${Math.random().toString(36).slice(2, 11)}`,
|
|
30123
|
-
operationType: "reflection",
|
|
30124
|
-
startedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
30125
|
-
tokensAttempted: observationTokens,
|
|
30126
|
-
error: error instanceof Error ? error.message : String(error),
|
|
30127
|
-
recordId: record.id,
|
|
30128
|
-
threadId: record.threadId ?? ""
|
|
30129
|
-
});
|
|
30130
|
-
writer.custom({
|
|
30131
|
-
...failedMarker,
|
|
30132
|
-
transient: true
|
|
30133
|
-
}).catch(() => {});
|
|
30134
|
-
await this.persistMarkerToStorage(failedMarker, record.threadId ?? "", record.resourceId ?? void 0);
|
|
30135
|
-
} catch (markerError) {
|
|
30136
|
-
omError("[OM] Failed to persist buffering-failed marker after async buffered reflection failure", markerError);
|
|
30137
|
-
}
|
|
30138
|
-
omError("[OM] Async buffered reflection failed", error);
|
|
30316
|
+
const asyncOp = (async () => {
|
|
30317
|
+
let outcome;
|
|
30318
|
+
let reflectionError;
|
|
30139
30319
|
try {
|
|
30140
|
-
reflectionHooks?.
|
|
30141
|
-
|
|
30142
|
-
|
|
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);
|
|
30143
30358
|
});
|
|
30144
|
-
} catch (hookError) {
|
|
30145
|
-
omError("[OM] onReflectionEnd hook failed after async buffered reflection failure", hookError);
|
|
30146
30359
|
}
|
|
30147
|
-
|
|
30148
|
-
}).finally(() => {
|
|
30149
|
-
BufferingCoordinator.asyncBufferingOps.delete(bufferKey);
|
|
30150
|
-
unregisterOp(record.id, "bufferingReflection");
|
|
30151
|
-
this.storage.setBufferingReflectionFlag(record.id, false).catch((err) => {
|
|
30152
|
-
omError("[OM] Failed to clear buffering reflection flag", err);
|
|
30153
|
-
});
|
|
30154
|
-
});
|
|
30360
|
+
})();
|
|
30155
30361
|
BufferingCoordinator.asyncBufferingOps.set(bufferKey, asyncOp);
|
|
30156
30362
|
}
|
|
30157
30363
|
/**
|
|
@@ -30412,6 +30618,13 @@ var ReflectorRunner = class {
|
|
|
30412
30618
|
return;
|
|
30413
30619
|
}
|
|
30414
30620
|
}
|
|
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
|
+
}
|
|
30415
30628
|
await this.storage.setReflectingFlag(record.id, true);
|
|
30416
30629
|
registerOp(record.id, "reflecting");
|
|
30417
30630
|
const cycleId = crypto.randomUUID();
|
|
@@ -30452,8 +30665,15 @@ var ReflectorRunner = class {
|
|
|
30452
30665
|
let reflectionUsage;
|
|
30453
30666
|
let reflectionProviderMetadata;
|
|
30454
30667
|
let reflectionError;
|
|
30455
|
-
|
|
30668
|
+
let lifecycleError;
|
|
30456
30669
|
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
|
+
}
|
|
30457
30677
|
const compressionStartLevel = await this.getCompressionStartLevel(requestContext);
|
|
30458
30678
|
const reflectResult = await this.call(record.activeObservations, void 0, streamContext, reflectThreshold, abortSignal, void 0, compressionStartLevel, requestContext, priorExtractedValues, observabilityContext, void 0, mainAgent, sendSignal);
|
|
30459
30679
|
reflectionUsage = reflectResult.usage;
|
|
@@ -30465,6 +30685,8 @@ var ReflectorRunner = class {
|
|
|
30465
30685
|
reflection: reflectResult.observations,
|
|
30466
30686
|
tokenCount: reflectionTokenCount
|
|
30467
30687
|
});
|
|
30688
|
+
if (reflectionTokenCount >= reflectThreshold) this.syncReflectionSuppression.set(lockKey, reflectionTokenCount);
|
|
30689
|
+
else this.syncReflectionSuppression.delete(lockKey);
|
|
30468
30690
|
await this.notifyReflectionCommitted({
|
|
30469
30691
|
parentThreadId: requestedThreadId ?? record.threadId ?? "",
|
|
30470
30692
|
resourceId: record.resourceId ?? "",
|
|
@@ -30523,18 +30745,28 @@ var ReflectorRunner = class {
|
|
|
30523
30745
|
await this.persistMarkerToStorage(failedMarker, threadId, record.resourceId ?? void 0);
|
|
30524
30746
|
}
|
|
30525
30747
|
reflectionError = error instanceof Error ? error : new Error(String(error));
|
|
30526
|
-
if (abortSignal?.aborted) throw error;
|
|
30748
|
+
if (lifecycleError !== void 0 || abortSignal?.aborted) throw error;
|
|
30749
|
+
this.syncReflectionSuppression.set(lockKey, observationTokens);
|
|
30527
30750
|
omError("[OM] Reflection failed", error);
|
|
30528
30751
|
} finally {
|
|
30529
|
-
await this.storage.setReflectingFlag(record.id, false);
|
|
30530
30752
|
try {
|
|
30531
|
-
|
|
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?.({
|
|
30532
30760
|
usage: reflectionUsage,
|
|
30533
30761
|
error: reflectionError,
|
|
30534
30762
|
...reflectionProviderMetadata ? { providerMetadata: reflectionProviderMetadata } : {}
|
|
30535
30763
|
});
|
|
30536
|
-
}
|
|
30537
|
-
|
|
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)}`);
|
|
30538
30770
|
}
|
|
30539
30771
|
}
|
|
30540
30772
|
}
|
|
@@ -30857,10 +31089,24 @@ function getLatestStepParts(parts) {
|
|
|
30857
31089
|
return parts;
|
|
30858
31090
|
}
|
|
30859
31091
|
/**
|
|
30860
|
-
* Returns true
|
|
30861
|
-
*
|
|
30862
|
-
*
|
|
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.
|
|
30863
31098
|
*/
|
|
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
|
+
}
|
|
30864
31110
|
function messageHasVisibleContent(msg) {
|
|
30865
31111
|
const content = msg.content;
|
|
30866
31112
|
if (content?.parts && Array.isArray(content.parts)) return content.parts.some((p) => {
|
|
@@ -30991,6 +31237,8 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
30991
31237
|
onIndexObservations;
|
|
30992
31238
|
/** Config-level lifecycle hooks fired for every observation/reflection cycle. */
|
|
30993
31239
|
hooks;
|
|
31240
|
+
/** Execution policy for config-level hooks on manual and turn-synchronous cycles. */
|
|
31241
|
+
hookExecution;
|
|
30994
31242
|
/** Observer agent runner — handles LLM calls for extracting observations. */
|
|
30995
31243
|
observer;
|
|
30996
31244
|
/** Reflector agent runner — handles LLM calls for compressing observations. */
|
|
@@ -31097,6 +31345,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
31097
31345
|
this.retrievalSearch = typeof config.retrieval === "object" && Boolean(config.retrieval.vector);
|
|
31098
31346
|
this.onIndexObservations = config.onIndexObservations;
|
|
31099
31347
|
this.hooks = config.hooks;
|
|
31348
|
+
this.hookExecution = config.hookExecution ?? "non-blocking";
|
|
31100
31349
|
this.mastra = config.mastra;
|
|
31101
31350
|
this.memory = config.memory;
|
|
31102
31351
|
this.curationCadence = config.curationCadence;
|
|
@@ -31628,7 +31877,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
31628
31877
|
}
|
|
31629
31878
|
const result = [];
|
|
31630
31879
|
for (const msg of allMessages) {
|
|
31631
|
-
if (msg.role === "system") continue;
|
|
31880
|
+
if (msg.role === "system" || isWorkingMemoryStateSignal(msg)) continue;
|
|
31632
31881
|
if (observedMessageIds?.has(msg.id)) continue;
|
|
31633
31882
|
const endMarkerIndex = findLastCompletedObservationBoundary(msg);
|
|
31634
31883
|
if (this.hasInProgressObservation(msg)) result.push(msg);
|
|
@@ -31850,7 +32099,7 @@ var ObservationalMemory = class ObservationalMemory {
|
|
|
31850
32099
|
},
|
|
31851
32100
|
filter: startDate ? { dateRange: { start: startDate } } : void 0
|
|
31852
32101
|
});
|
|
31853
|
-
return result.messages.filter((msg) => msg.role !== "system");
|
|
32102
|
+
return result.messages.filter((msg) => msg.role !== "system" && !isWorkingMemoryStateSignal(msg));
|
|
31854
32103
|
}
|
|
31855
32104
|
/**
|
|
31856
32105
|
* Format unobserved messages from other threads as <unobserved-context> blocks.
|
|
@@ -32309,7 +32558,7 @@ ${formattedMessages}
|
|
|
32309
32558
|
direction: "ASC"
|
|
32310
32559
|
},
|
|
32311
32560
|
filter: startDate ? { dateRange: { start: startDate } } : void 0
|
|
32312
|
-
})).messages.filter((
|
|
32561
|
+
})).messages.filter((message) => !this.observedMessageIds.has(message.id) && !isWorkingMemoryStateSignal(message));
|
|
32313
32562
|
if (filtered.length > 0) messagesByThread.set(thread.id, filtered);
|
|
32314
32563
|
}
|
|
32315
32564
|
if (messagesByThread.size === 0) return void 0;
|
|
@@ -32889,57 +33138,54 @@ ${formattedMessages}
|
|
|
32889
33138
|
};
|
|
32890
33139
|
}
|
|
32891
33140
|
/**
|
|
32892
|
-
* Compose
|
|
32893
|
-
*
|
|
32894
|
-
*
|
|
32895
|
-
* never fail an observation/reflection cycle; per-call hooks keep their
|
|
32896
|
-
* existing payloads and propagation semantics. Returns undefined when
|
|
32897
|
-
* neither is configured, so call sites stay zero-cost.
|
|
32898
|
-
*
|
|
32899
|
-
* Used internally by every pipeline path (manual observe/reflect,
|
|
32900
|
-
* turn-engine sync observation, async buffering); public only so the
|
|
32901
|
-
* observation turn engine can thread config-level reflection hooks into
|
|
32902
|
-
* reflector calls.
|
|
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.
|
|
32903
33144
|
*
|
|
32904
33145
|
* @internal
|
|
32905
33146
|
*/
|
|
32906
|
-
composeHooks(callHooks, context) {
|
|
33147
|
+
composeHooks(callHooks, context, execution = "configured") {
|
|
32907
33148
|
const configHooks = this.hooks;
|
|
32908
33149
|
if (!configHooks) return callHooks;
|
|
32909
33150
|
if (!callHooks && !Object.keys(configHooks).length) return void 0;
|
|
32910
|
-
const
|
|
33151
|
+
const shouldAwaitConfig = execution === "configured" && this.hookExecution === "await";
|
|
33152
|
+
const invokeConfigHook = async (name, arg) => {
|
|
32911
33153
|
const hook = configHooks[name];
|
|
32912
33154
|
if (!hook) return;
|
|
33155
|
+
if (shouldAwaitConfig) {
|
|
33156
|
+
await hook(arg);
|
|
33157
|
+
return;
|
|
33158
|
+
}
|
|
32913
33159
|
const logHookFailure = (error) => omDebug(`[OM:hooks] config-level ${name} hook failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
32914
33160
|
try {
|
|
32915
|
-
const
|
|
32916
|
-
if (
|
|
33161
|
+
const result = hook(arg);
|
|
33162
|
+
if (result && typeof result.then === "function") result.then(void 0, logHookFailure);
|
|
32917
33163
|
} catch (error) {
|
|
32918
33164
|
logHookFailure(error);
|
|
32919
33165
|
}
|
|
32920
33166
|
};
|
|
32921
33167
|
return {
|
|
32922
|
-
onObservationStart: () => {
|
|
32923
|
-
|
|
32924
|
-
callHooks?.onObservationStart?.();
|
|
33168
|
+
onObservationStart: async () => {
|
|
33169
|
+
await invokeConfigHook("onObservationStart", context);
|
|
33170
|
+
await callHooks?.onObservationStart?.();
|
|
32925
33171
|
},
|
|
32926
|
-
onObservationEnd: (result) => {
|
|
32927
|
-
|
|
33172
|
+
onObservationEnd: async (result) => {
|
|
33173
|
+
await invokeConfigHook("onObservationEnd", {
|
|
32928
33174
|
...context,
|
|
32929
33175
|
...result
|
|
32930
33176
|
});
|
|
32931
|
-
callHooks?.onObservationEnd?.(result);
|
|
33177
|
+
await callHooks?.onObservationEnd?.(result);
|
|
32932
33178
|
},
|
|
32933
|
-
onReflectionStart: () => {
|
|
32934
|
-
|
|
32935
|
-
callHooks?.onReflectionStart?.();
|
|
33179
|
+
onReflectionStart: async () => {
|
|
33180
|
+
await invokeConfigHook("onReflectionStart", context);
|
|
33181
|
+
await callHooks?.onReflectionStart?.();
|
|
32936
33182
|
},
|
|
32937
|
-
onReflectionEnd: (result) => {
|
|
32938
|
-
|
|
33183
|
+
onReflectionEnd: async (result) => {
|
|
33184
|
+
await invokeConfigHook("onReflectionEnd", {
|
|
32939
33185
|
...context,
|
|
32940
33186
|
...result
|
|
32941
33187
|
});
|
|
32942
|
-
callHooks?.onReflectionEnd?.(result);
|
|
33188
|
+
await callHooks?.onReflectionEnd?.(result);
|
|
32943
33189
|
}
|
|
32944
33190
|
};
|
|
32945
33191
|
}
|
|
@@ -32952,22 +33198,29 @@ ${formattedMessages}
|
|
|
32952
33198
|
* end hook reports `error` for failed cycles even though nothing throws.
|
|
32953
33199
|
*/
|
|
32954
33200
|
async runBufferedObservationCycle(context, run) {
|
|
32955
|
-
const hooks = this.composeHooks(void 0, context);
|
|
32956
|
-
hooks?.onObservationStart?.();
|
|
33201
|
+
const hooks = this.composeHooks(void 0, context, "non-blocking");
|
|
32957
33202
|
let runResult;
|
|
32958
33203
|
let runError;
|
|
33204
|
+
let lifecycleError;
|
|
32959
33205
|
try {
|
|
33206
|
+
await hooks?.onObservationStart?.();
|
|
32960
33207
|
runResult = await run();
|
|
32961
33208
|
return runResult;
|
|
32962
33209
|
} catch (error) {
|
|
33210
|
+
lifecycleError = error;
|
|
32963
33211
|
runError = error instanceof Error ? error : new Error(String(error));
|
|
32964
33212
|
throw error;
|
|
32965
33213
|
} finally {
|
|
32966
|
-
|
|
32967
|
-
|
|
32968
|
-
|
|
32969
|
-
|
|
32970
|
-
|
|
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
|
+
}
|
|
32971
33224
|
}
|
|
32972
33225
|
}
|
|
32973
33226
|
/**
|
|
@@ -32995,18 +33248,21 @@ ${formattedMessages}
|
|
|
32995
33248
|
let observed = false;
|
|
32996
33249
|
let observationUsage;
|
|
32997
33250
|
let observationProviderMetadata;
|
|
33251
|
+
let observationError;
|
|
33252
|
+
let lifecycleError;
|
|
33253
|
+
let observationStarted = false;
|
|
32998
33254
|
let generationBefore = -1;
|
|
32999
|
-
|
|
33000
|
-
|
|
33001
|
-
|
|
33002
|
-
|
|
33003
|
-
|
|
33004
|
-
|
|
33005
|
-
|
|
33006
|
-
|
|
33007
|
-
|
|
33008
|
-
|
|
33009
|
-
|
|
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?.();
|
|
33010
33266
|
const result = await ObservationStrategy.create(this, {
|
|
33011
33267
|
record: freshRecord,
|
|
33012
33268
|
threadId,
|
|
@@ -33024,17 +33280,22 @@ ${formattedMessages}
|
|
|
33024
33280
|
observed = result.observed;
|
|
33025
33281
|
observationUsage = result.usage;
|
|
33026
33282
|
observationProviderMetadata = result.providerMetadata;
|
|
33027
|
-
}
|
|
33028
|
-
|
|
33029
|
-
|
|
33030
|
-
|
|
33031
|
-
|
|
33032
|
-
|
|
33033
|
-
|
|
33034
|
-
|
|
33035
|
-
|
|
33036
|
-
|
|
33037
|
-
|
|
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;
|
|
33038
33299
|
const record = await this.getOrCreateRecord(threadId, resourceId);
|
|
33039
33300
|
const reflected = record.generationCount > generationBefore && generationBefore >= 0;
|
|
33040
33301
|
if (observed) this.maybeTriggerCadenceCuration(threadId, resourceId, record, requestContext).catch((error) => {
|
|
@@ -33108,11 +33369,18 @@ ${formattedMessages}
|
|
|
33108
33369
|
resourceId,
|
|
33109
33370
|
trigger: "manual"
|
|
33110
33371
|
});
|
|
33111
|
-
hooks?.onReflectionStart?.();
|
|
33112
33372
|
let reflectionUsage;
|
|
33113
33373
|
let reflectionProviderMetadata;
|
|
33114
33374
|
let reflectionError;
|
|
33375
|
+
let lifecycleError;
|
|
33115
33376
|
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
|
+
}
|
|
33116
33384
|
const thread = await this.storage.getThreadById({ threadId });
|
|
33117
33385
|
const previousOmMetadata = getThreadOMMetadata(thread?.metadata);
|
|
33118
33386
|
const priorExtractedValues = getPriorExtractedValues(previousOmMetadata, this.reflectionConfig.extractors);
|
|
@@ -33150,6 +33418,7 @@ ${formattedMessages}
|
|
|
33150
33418
|
};
|
|
33151
33419
|
} catch (error) {
|
|
33152
33420
|
reflectionError = error instanceof Error ? error : new Error(String(error));
|
|
33421
|
+
if (lifecycleError !== void 0) throw error;
|
|
33153
33422
|
omError("[OM] reflect() failed", error);
|
|
33154
33423
|
return {
|
|
33155
33424
|
reflected: false,
|
|
@@ -33157,13 +33426,25 @@ ${formattedMessages}
|
|
|
33157
33426
|
usage: void 0
|
|
33158
33427
|
};
|
|
33159
33428
|
} finally {
|
|
33160
|
-
|
|
33161
|
-
|
|
33162
|
-
|
|
33163
|
-
|
|
33164
|
-
}
|
|
33165
|
-
|
|
33166
|
-
|
|
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
|
+
}
|
|
33167
33448
|
}
|
|
33168
33449
|
}
|
|
33169
33450
|
/**
|
|
@@ -33455,7 +33736,9 @@ var ObservationalMemoryProcessor = class {
|
|
|
33455
33736
|
return messageList;
|
|
33456
33737
|
}
|
|
33457
33738
|
const { threadId, resourceId } = context;
|
|
33458
|
-
const
|
|
33739
|
+
const memoryContext = parseMemoryRequestContext(requestContext);
|
|
33740
|
+
const runState = memoryContext?.runState?.();
|
|
33741
|
+
const readOnly = memoryContext?.memoryConfig?.readOnly;
|
|
33459
33742
|
const actorModelContext = model?.modelId ? {
|
|
33460
33743
|
provider: model.provider,
|
|
33461
33744
|
modelId: model.modelId,
|
|
@@ -33472,7 +33755,8 @@ var ObservationalMemoryProcessor = class {
|
|
|
33472
33755
|
memory: this.memory,
|
|
33473
33756
|
messageList,
|
|
33474
33757
|
threadId,
|
|
33475
|
-
resourceId
|
|
33758
|
+
resourceId,
|
|
33759
|
+
runState
|
|
33476
33760
|
});
|
|
33477
33761
|
const systemMessages = ctx.omRecord ? await this.engine.buildContextSystemMessages({
|
|
33478
33762
|
threadId,
|
|
@@ -33513,7 +33797,7 @@ var ObservationalMemoryProcessor = class {
|
|
|
33513
33797
|
this.turn.sendStateSignal = args.sendStateSignal;
|
|
33514
33798
|
this.turn.agent = args.agent;
|
|
33515
33799
|
this.turn.requestContext = requestContext;
|
|
33516
|
-
await this.turn.start(this.memory);
|
|
33800
|
+
await this.turn.start(this.memory, runState);
|
|
33517
33801
|
if (stepNumber === 0 && this.temporalMarkers) await insertTemporalGapMarkers({
|
|
33518
33802
|
messageList,
|
|
33519
33803
|
sendSignal: args.sendSignal
|
|
@@ -33691,149 +33975,6 @@ var observational_memory_exports = /* @__PURE__ */ __exportAll({
|
|
|
33691
33975
|
summarizeConversation: () => summarizeConversation,
|
|
33692
33976
|
wrapInObservationGroup: () => wrapInObservationGroup
|
|
33693
33977
|
});
|
|
33694
|
-
/**
|
|
33695
|
-
* WorkingMemoryStateProcessor
|
|
33696
|
-
*
|
|
33697
|
-
* Experimental: delivers working memory to the model as a state signal instead
|
|
33698
|
-
* of folding it into the system message. Storage and the `setWorkingMemory`
|
|
33699
|
-
* tool are unchanged — this processor only changes the delivery path.
|
|
33700
|
-
*
|
|
33701
|
-
* Pattern matches `BrowserContextProcessor` in `@mastra/core/browser`:
|
|
33702
|
-
* - `stateId` namespaces the state lane on the thread.
|
|
33703
|
-
* - `cacheKey` is derived from the rendered payload so dedup is automatic.
|
|
33704
|
-
* - `contextWindow.hasSnapshot` re-injection ensures the model still sees the
|
|
33705
|
-
* current snapshot after older messages drop out of the window.
|
|
33706
|
-
*
|
|
33707
|
-
* Delta emission (markdown mode only): when a prior snapshot exists in the
|
|
33708
|
-
* context window, the processor emits a unified-diff delta against that
|
|
33709
|
-
* snapshot's contents. Schema mode and the snapshot fallback always emit a
|
|
33710
|
-
* full snapshot.
|
|
33711
|
-
*
|
|
33712
|
-
* @example
|
|
33713
|
-
* ```ts
|
|
33714
|
-
* new Memory({
|
|
33715
|
-
* options: {
|
|
33716
|
-
* workingMemory: {
|
|
33717
|
-
* enabled: true,
|
|
33718
|
-
* template: '...',
|
|
33719
|
-
* useStateSignals: true, // auto-attaches this processor
|
|
33720
|
-
* },
|
|
33721
|
-
* },
|
|
33722
|
-
* });
|
|
33723
|
-
* ```
|
|
33724
|
-
*/
|
|
33725
|
-
const WORKING_MEMORY_STATE_ID = "working-memory";
|
|
33726
|
-
const WORKING_MEMORY_STATE_PROCESSOR_ID = "working-memory-state";
|
|
33727
|
-
var WorkingMemoryStateProcessor = class {
|
|
33728
|
-
memory;
|
|
33729
|
-
memoryConfig;
|
|
33730
|
-
id = WORKING_MEMORY_STATE_PROCESSOR_ID;
|
|
33731
|
-
stateId = WORKING_MEMORY_STATE_ID;
|
|
33732
|
-
constructor(memory, memoryConfig) {
|
|
33733
|
-
this.memory = memory;
|
|
33734
|
-
this.memoryConfig = memoryConfig;
|
|
33735
|
-
}
|
|
33736
|
-
async computeStateSignal(args) {
|
|
33737
|
-
const template = await this.memory.getWorkingMemoryTemplate({ memoryConfig: this.memoryConfig });
|
|
33738
|
-
if (!template) return;
|
|
33739
|
-
const contents = (await this.memory.getWorkingMemory({
|
|
33740
|
-
threadId: args.threadId,
|
|
33741
|
-
resourceId: args.resourceId,
|
|
33742
|
-
memoryConfig: this.memoryConfig
|
|
33743
|
-
}))?.trim();
|
|
33744
|
-
if (!contents) return;
|
|
33745
|
-
const cacheKey = stableWorkingMemoryCacheKey({
|
|
33746
|
-
format: template.format,
|
|
33747
|
-
data: contents
|
|
33748
|
-
});
|
|
33749
|
-
const shouldMakeSnapshot = !args.contextWindow.hasSnapshot;
|
|
33750
|
-
if (args.tracking?.currentCacheKey === cacheKey && !shouldMakeSnapshot) return;
|
|
33751
|
-
const scope = this.memory.getMergedThreadConfig(this.memoryConfig).workingMemory?.scope ?? "resource";
|
|
33752
|
-
const deltaCandidate = template.format === "markdown" && !shouldMakeSnapshot ? buildMarkdownDelta({
|
|
33753
|
-
lastSnapshot: args.lastSnapshot,
|
|
33754
|
-
deltasSinceSnapshot: args.deltasSinceSnapshot,
|
|
33755
|
-
nextContents: contents
|
|
33756
|
-
}) : void 0;
|
|
33757
|
-
if (deltaCandidate) return {
|
|
33758
|
-
id: WORKING_MEMORY_STATE_ID,
|
|
33759
|
-
mode: "delta",
|
|
33760
|
-
cacheKey,
|
|
33761
|
-
tagName: "working-memory",
|
|
33762
|
-
contents: deltaCandidate.contents,
|
|
33763
|
-
delta: deltaCandidate.contents,
|
|
33764
|
-
value: contents,
|
|
33765
|
-
attributes: {
|
|
33766
|
-
format: template.format,
|
|
33767
|
-
scope,
|
|
33768
|
-
patch: "unified-diff"
|
|
33769
|
-
}
|
|
33770
|
-
};
|
|
33771
|
-
return {
|
|
33772
|
-
id: WORKING_MEMORY_STATE_ID,
|
|
33773
|
-
mode: "snapshot",
|
|
33774
|
-
cacheKey,
|
|
33775
|
-
tagName: "working-memory",
|
|
33776
|
-
contents,
|
|
33777
|
-
value: contents,
|
|
33778
|
-
attributes: {
|
|
33779
|
-
format: template.format,
|
|
33780
|
-
scope
|
|
33781
|
-
}
|
|
33782
|
-
};
|
|
33783
|
-
}
|
|
33784
|
-
};
|
|
33785
|
-
/**
|
|
33786
|
-
* Stable cache key for the rendered working memory payload. Returns a SHA-256
|
|
33787
|
-
* digest so dedup metadata stays compact regardless of payload size (working
|
|
33788
|
-
* memory blobs can grow arbitrarily long).
|
|
33789
|
-
*/
|
|
33790
|
-
function stableWorkingMemoryCacheKey(input) {
|
|
33791
|
-
const hash = createHash("sha256");
|
|
33792
|
-
hash.update(input.format);
|
|
33793
|
-
hash.update("\0");
|
|
33794
|
-
hash.update(input.data ?? "");
|
|
33795
|
-
return `sha256:${hash.digest("hex")}`;
|
|
33796
|
-
}
|
|
33797
|
-
/**
|
|
33798
|
-
* Build a unified-diff delta against the most recently emitted state. Prefers
|
|
33799
|
-
* the latest delta's `value` (the post-edit full text) when available, falling
|
|
33800
|
-
* back to the snapshot's `value` and finally the snapshot's `contents`. This
|
|
33801
|
-
* keeps deltas incremental (B→C) instead of cumulative against a stale
|
|
33802
|
-
* snapshot (A→C), which matters when many small edits land between snapshots.
|
|
33803
|
-
*
|
|
33804
|
-
* Returns undefined when:
|
|
33805
|
-
* - there's no prior state to diff against
|
|
33806
|
-
* - the prior state isn't a plain string (multimodal signal)
|
|
33807
|
-
*
|
|
33808
|
-
* In either case the caller falls back to emitting a full snapshot.
|
|
33809
|
-
*/
|
|
33810
|
-
function buildMarkdownDelta(args) {
|
|
33811
|
-
const { lastSnapshot, deltasSinceSnapshot, nextContents } = args;
|
|
33812
|
-
const prior = pickStringValue(readSignalValue(deltasSinceSnapshot.at(-1))) ?? pickStringValue(readSignalValue(lastSnapshot)) ?? (typeof lastSnapshot?.contents === "string" ? lastSnapshot.contents : void 0);
|
|
33813
|
-
if (!prior) return;
|
|
33814
|
-
return { contents: renderHunksOnly(prior, nextContents) };
|
|
33815
|
-
}
|
|
33816
|
-
function pickStringValue(value) {
|
|
33817
|
-
return typeof value === "string" ? value : void 0;
|
|
33818
|
-
}
|
|
33819
|
-
function readSignalValue(signal) {
|
|
33820
|
-
return (signal?.metadata)?.value;
|
|
33821
|
-
}
|
|
33822
|
-
/**
|
|
33823
|
-
* Render a unified-diff-style patch body containing only `@@` hunks and their
|
|
33824
|
-
* lines — dropping the filename preamble (`Index:` / `===` / `---` / `+++`)
|
|
33825
|
-
* that `createPatch` emits and the `` trailer.
|
|
33826
|
-
* The preamble exists for tooling like `patch -p1` to know which file to
|
|
33827
|
-
* apply to; we only ever diff a single working-memory blob. The newline
|
|
33828
|
-
* trailer is semantically meaningless to the model and adds noise to the
|
|
33829
|
-
* state signal.
|
|
33830
|
-
*/
|
|
33831
|
-
function renderHunksOnly(prior, next) {
|
|
33832
|
-
const { hunks } = structuredPatch("", "", prior, next, "", "", { context: 0 });
|
|
33833
|
-
return hunks.map((hunk) => {
|
|
33834
|
-
return [`@@ -${hunk.oldStart},${hunk.oldLines} +${hunk.newStart},${hunk.newLines} @@`, ...hunk.lines.filter((line) => !line.startsWith("\"))].join("\n");
|
|
33835
|
-
}).join("\n");
|
|
33836
|
-
}
|
|
33837
33978
|
var working_memory_state_exports = /* @__PURE__ */ __exportAll({
|
|
33838
33979
|
WORKING_MEMORY_STATE_ID: () => WORKING_MEMORY_STATE_ID,
|
|
33839
33980
|
WORKING_MEMORY_STATE_PROCESSOR_ID: () => WORKING_MEMORY_STATE_PROCESSOR_ID,
|
|
@@ -34660,14 +34801,18 @@ ${workingMemory}`;
|
|
|
34660
34801
|
if (!this.threadConfig.workingMemory?.enabled) return null;
|
|
34661
34802
|
return extractWorkingMemoryContent(text)?.trim() ?? null;
|
|
34662
34803
|
}
|
|
34663
|
-
async getWorkingMemory({ threadId, resourceId, memoryConfig }) {
|
|
34804
|
+
async getWorkingMemory({ threadId, resourceId, memoryConfig, runState }) {
|
|
34664
34805
|
const config = this.getMergedThreadConfig(memoryConfig || {});
|
|
34665
34806
|
if (!config.workingMemory?.enabled) return null;
|
|
34666
34807
|
const scope = config.workingMemory.scope || "resource";
|
|
34667
34808
|
let workingMemoryData = null;
|
|
34668
34809
|
if (scope === "resource" && !resourceId) throw new Error("Memory error: Resource-scoped working memory is enabled but no resourceId was provided. Either provide a resourceId or explicitly set workingMemory.scope to 'thread'.");
|
|
34669
|
-
if (scope === "resource" && resourceId)
|
|
34670
|
-
|
|
34810
|
+
if (scope === "resource" && resourceId) {
|
|
34811
|
+
const loadWorkingMemory = async () => {
|
|
34812
|
+
return (await (await this.getMemoryStore()).getResourceById({ resourceId }))?.workingMemory || null;
|
|
34813
|
+
};
|
|
34814
|
+
workingMemoryData = runState ? await runState.load(`working-memory:resource:${resourceId}`, loadWorkingMemory) : await loadWorkingMemory();
|
|
34815
|
+
} else workingMemoryData = (runState?.threadLoaded ? runState.thread : await this.getThreadById({ threadId }))?.metadata?.workingMemory;
|
|
34671
34816
|
if (!workingMemoryData) return null;
|
|
34672
34817
|
return workingMemoryData;
|
|
34673
34818
|
}
|
|
@@ -34699,16 +34844,18 @@ ${workingMemory}`;
|
|
|
34699
34844
|
content: (config.workingMemory.template || this.defaultWorkingMemoryTemplate).trim()
|
|
34700
34845
|
};
|
|
34701
34846
|
}
|
|
34702
|
-
async getSystemMessage({ threadId, resourceId, memoryConfig }) {
|
|
34847
|
+
async getSystemMessage({ threadId, resourceId, memoryConfig, runState }) {
|
|
34703
34848
|
const config = this.getMergedThreadConfig(memoryConfig);
|
|
34704
34849
|
this.assertWorkingMemoryStateSignalsCompatibility(config);
|
|
34705
34850
|
if (!config.workingMemory?.enabled) return null;
|
|
34706
34851
|
if (config.workingMemory?.useStateSignals) return null;
|
|
34707
|
-
const
|
|
34852
|
+
const loadTemplate = () => this.getWorkingMemoryTemplate({ memoryConfig });
|
|
34853
|
+
const workingMemoryTemplate = runState ? await runState.load("working-memory:template", loadTemplate) : await loadTemplate();
|
|
34708
34854
|
const workingMemoryData = await this.getWorkingMemory({
|
|
34709
34855
|
threadId,
|
|
34710
34856
|
resourceId,
|
|
34711
|
-
memoryConfig: config
|
|
34857
|
+
memoryConfig: config,
|
|
34858
|
+
runState
|
|
34712
34859
|
});
|
|
34713
34860
|
if (!workingMemoryTemplate) return null;
|
|
34714
34861
|
const workingMemoryConfig = config.workingMemory;
|
|
@@ -34741,7 +34888,7 @@ ${workingMemory}`;
|
|
|
34741
34888
|
* ```
|
|
34742
34889
|
*/
|
|
34743
34890
|
async getContext(opts) {
|
|
34744
|
-
const { threadId, resourceId, memoryConfig } = opts;
|
|
34891
|
+
const { threadId, resourceId, memoryConfig, runState } = opts;
|
|
34745
34892
|
const config = this.getMergedThreadConfig(memoryConfig);
|
|
34746
34893
|
const memoryStore = await this.getMemoryStore();
|
|
34747
34894
|
const systemParts = [];
|
|
@@ -34751,10 +34898,14 @@ ${workingMemory}`;
|
|
|
34751
34898
|
let otherThreadsContext;
|
|
34752
34899
|
const omEngine = await this.omEngine;
|
|
34753
34900
|
if (omEngine) {
|
|
34754
|
-
|
|
34901
|
+
const loadOmRecord = () => omEngine.getRecord(threadId, resourceId);
|
|
34902
|
+
omRecord = runState ? await runState.load(`observational-memory:record:${threadId}:${resourceId ?? ""}`, loadOmRecord) : await loadOmRecord();
|
|
34755
34903
|
if (omRecord?.activeObservations) {
|
|
34756
34904
|
hasObservations = true;
|
|
34757
|
-
if (omEngine.scope === "resource" && resourceId)
|
|
34905
|
+
if (omEngine.scope === "resource" && resourceId) {
|
|
34906
|
+
const loadOtherThreadsContext = () => omEngine.getOtherThreadsContext(resourceId, threadId);
|
|
34907
|
+
otherThreadsContext = runState ? await runState.load(`observational-memory:other-threads:${resourceId}:${threadId}:${omRecord.lastObservedAt ?? ""}`, loadOtherThreadsContext) : await loadOtherThreadsContext();
|
|
34908
|
+
}
|
|
34758
34909
|
const obsSystemMessage = await omEngine.buildContextSystemMessage({
|
|
34759
34910
|
threadId,
|
|
34760
34911
|
resourceId,
|
|
@@ -34782,30 +34933,41 @@ ${workingMemory}`;
|
|
|
34782
34933
|
const workingMemoryMessage = await this.getSystemMessage({
|
|
34783
34934
|
threadId,
|
|
34784
34935
|
resourceId,
|
|
34785
|
-
memoryConfig: config
|
|
34936
|
+
memoryConfig: config,
|
|
34937
|
+
runState
|
|
34786
34938
|
});
|
|
34787
34939
|
if (workingMemoryMessage) systemParts.push(workingMemoryMessage);
|
|
34788
34940
|
let messages;
|
|
34789
34941
|
if (omEngine && omRecord) {
|
|
34790
34942
|
const dateFilter = omRecord.lastObservedAt ? { dateRange: { start: new Date(new Date(omRecord.lastObservedAt).getTime() + 1) } } : void 0;
|
|
34791
|
-
|
|
34792
|
-
|
|
34793
|
-
|
|
34794
|
-
|
|
34795
|
-
|
|
34796
|
-
|
|
34797
|
-
|
|
34798
|
-
|
|
34799
|
-
|
|
34800
|
-
|
|
34801
|
-
|
|
34802
|
-
|
|
34803
|
-
|
|
34804
|
-
|
|
34805
|
-
|
|
34806
|
-
|
|
34807
|
-
|
|
34808
|
-
|
|
34943
|
+
const boundary = omRecord.lastObservedAt ? new Date(omRecord.lastObservedAt).toISOString() : "";
|
|
34944
|
+
if (omEngine.scope === "resource" && resourceId) {
|
|
34945
|
+
const loadMessages = async () => {
|
|
34946
|
+
return (await memoryStore.listMessagesByResourceId({
|
|
34947
|
+
resourceId,
|
|
34948
|
+
orderBy: {
|
|
34949
|
+
field: "createdAt",
|
|
34950
|
+
direction: "ASC"
|
|
34951
|
+
},
|
|
34952
|
+
perPage: false,
|
|
34953
|
+
filter: dateFilter
|
|
34954
|
+
})).messages;
|
|
34955
|
+
};
|
|
34956
|
+
messages = runState ? await runState.load(`observational-memory:messages:resource:${resourceId}:${boundary}`, loadMessages) : await loadMessages();
|
|
34957
|
+
} else {
|
|
34958
|
+
const loadMessages = async () => {
|
|
34959
|
+
return (await memoryStore.listMessages({
|
|
34960
|
+
threadId,
|
|
34961
|
+
orderBy: {
|
|
34962
|
+
field: "createdAt",
|
|
34963
|
+
direction: "ASC"
|
|
34964
|
+
},
|
|
34965
|
+
perPage: false,
|
|
34966
|
+
filter: dateFilter
|
|
34967
|
+
})).messages;
|
|
34968
|
+
};
|
|
34969
|
+
messages = runState ? await runState.load(`observational-memory:messages:thread:${threadId}:${boundary}`, loadMessages) : await loadMessages();
|
|
34970
|
+
}
|
|
34809
34971
|
} else {
|
|
34810
34972
|
const lastMessages = config.lastMessages;
|
|
34811
34973
|
if (lastMessages === false) messages = [];
|
|
@@ -34893,6 +35055,7 @@ ${workingMemory}`;
|
|
|
34893
35055
|
instruction: omConfig.observation.instruction,
|
|
34894
35056
|
threadTitle: omConfig.observation.threadTitle,
|
|
34895
35057
|
observeAttachments: omConfig.observation.observeAttachments,
|
|
35058
|
+
continuationHints: omConfig.observation.continuationHints,
|
|
34896
35059
|
extract: omConfig.observation.extract
|
|
34897
35060
|
} : void 0,
|
|
34898
35061
|
reflection: omConfig.reflection ? {
|
|
@@ -34903,6 +35066,7 @@ ${workingMemory}`;
|
|
|
34903
35066
|
bufferActivation: omConfig.reflection.bufferActivation,
|
|
34904
35067
|
blockAfter: omConfig.reflection.blockAfter,
|
|
34905
35068
|
instruction: omConfig.reflection.instruction,
|
|
35069
|
+
continuationHints: omConfig.reflection.continuationHints,
|
|
34906
35070
|
extract: omConfig.reflection.extract
|
|
34907
35071
|
} : void 0
|
|
34908
35072
|
});
|
|
@@ -41070,6 +41234,7 @@ async function cancelResponseBody(response) {
|
|
|
41070
41234
|
var initialGlobalFetch = globalThis.fetch;
|
|
41071
41235
|
isNodeDefaultFetch(initialGlobalFetch);
|
|
41072
41236
|
function isNodeDefaultFetch(fetch) {
|
|
41237
|
+
if (typeof fetch !== "function") return false;
|
|
41073
41238
|
const source = Function.prototype.toString.call(fetch);
|
|
41074
41239
|
return source.includes("internal/deps/undici") || source.includes("lazy loading of undici");
|
|
41075
41240
|
}
|
|
@@ -46196,4 +46361,4 @@ const agentBuilderWorkflows = {
|
|
|
46196
46361
|
//#endregion
|
|
46197
46362
|
export { agentBuilderWorkflows };
|
|
46198
46363
|
|
|
46199
|
-
//# sourceMappingURL=dist-
|
|
46364
|
+
//# sourceMappingURL=dist-L0EogwX_.js.map
|