@mastra/memory 0.0.0-studio-deploy-20260403185613 → 0.0.0-studio-deploy-20260403231316
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 +63 -3
- package/dist/{chunk-HLGFIN4J.cjs → chunk-4FMHSWZD.cjs} +149 -29
- package/dist/chunk-4FMHSWZD.cjs.map +1 -0
- package/dist/{chunk-DDQHE4NV.js → chunk-C7PARRAD.js} +149 -29
- package/dist/chunk-C7PARRAD.js.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +39 -39
- package/dist/docs/references/reference-processors-token-limiter-processor.md +2 -0
- package/dist/index.cjs +12 -12
- package/dist/index.js +4 -4
- package/dist/{observational-memory-34W4S4I5.cjs → observational-memory-5YDQLKHE.cjs} +26 -26
- package/dist/{observational-memory-34W4S4I5.cjs.map → observational-memory-5YDQLKHE.cjs.map} +1 -1
- package/dist/{observational-memory-B25SASRW.js → observational-memory-B7AUSTEY.js} +3 -3
- package/dist/{observational-memory-B25SASRW.js.map → observational-memory-B7AUSTEY.js.map} +1 -1
- package/dist/processors/index.cjs +24 -24
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/observation-strategies/async-buffer.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-strategies/sync.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/step.d.ts.map +1 -1
- package/dist/processors/observational-memory/observation-turn/types.d.ts +3 -0
- package/dist/processors/observational-memory/observation-turn/types.d.ts.map +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts +16 -1
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/observer-runner.d.ts +21 -0
- package/dist/processors/observational-memory/observer-runner.d.ts.map +1 -1
- package/dist/processors/observational-memory/processor.d.ts.map +1 -1
- package/dist/processors/observational-memory/repro-capture.d.ts +2 -0
- package/dist/processors/observational-memory/repro-capture.d.ts.map +1 -1
- package/package.json +8 -8
- package/dist/chunk-DDQHE4NV.js.map +0 -1
- package/dist/chunk-HLGFIN4J.cjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,11 +1,71 @@
|
|
|
1
1
|
# @mastra/memory
|
|
2
2
|
|
|
3
|
-
## 0.0.0-studio-deploy-
|
|
3
|
+
## 0.0.0-studio-deploy-20260403231316
|
|
4
4
|
|
|
5
5
|
### Patch Changes
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
|
|
7
|
+
- Fixed observational memory buffering so sealed assistant chunks stay split instead of being merged back into one persisted message during long tool runs. ([#14995](https://github.com/mastra-ai/mastra/pull/14995))
|
|
8
|
+
|
|
9
|
+
- Updated dependencies [[`c55b527`](https://github.com/mastra-ai/mastra/commit/c55b52758a31368b2077b0dbbc3badfe4063f560), [`7eb2596`](https://github.com/mastra-ai/mastra/commit/7eb25960d607e07468c9a10c5437abd2deaf1e9a)]:
|
|
10
|
+
- @mastra/core@0.0.0-studio-deploy-20260403231316
|
|
11
|
+
|
|
12
|
+
## 1.13.1
|
|
13
|
+
|
|
14
|
+
### Patch Changes
|
|
15
|
+
|
|
16
|
+
- Fixed thread titles not persisting when generated during async buffered observation. Titles now update immediately when the observer produces them, rather than being lost until activation. ([#14992](https://github.com/mastra-ai/mastra/pull/14992))
|
|
17
|
+
|
|
18
|
+
- Updated dependencies [[`cb15509`](https://github.com/mastra-ai/mastra/commit/cb15509b58f6a83e11b765c945082afc027db972), [`81e4259`](https://github.com/mastra-ai/mastra/commit/81e425939b4ceeb4f586e9b6d89c3b1c1f2d2fe7), [`951b8a1`](https://github.com/mastra-ai/mastra/commit/951b8a1b5ef7e1474c59dc4f2b9fc1a8b1e508b6), [`80c5668`](https://github.com/mastra-ai/mastra/commit/80c5668e365470d3a96d3e953868fd7a643ff67c), [`3d478c1`](https://github.com/mastra-ai/mastra/commit/3d478c1e13f17b80f330ac49d7aa42ef929b93ff), [`2b4ea10`](https://github.com/mastra-ai/mastra/commit/2b4ea10b053e4ea1ab232d536933a4a3c4cba999), [`a0544f0`](https://github.com/mastra-ai/mastra/commit/a0544f0a1e6bd52ac12676228967c1938e43648d), [`6039f17`](https://github.com/mastra-ai/mastra/commit/6039f176f9c457304825ff1df8c83b8e457376c0), [`06b928d`](https://github.com/mastra-ai/mastra/commit/06b928dfc2f5630d023467476cc5919dfa858d0a), [`6a8d984`](https://github.com/mastra-ai/mastra/commit/6a8d9841f2933456ee1598099f488d742b600054), [`c8c86aa`](https://github.com/mastra-ai/mastra/commit/c8c86aa1458017fbd1c0776fdc0c520d129df8a6)]:
|
|
19
|
+
- @mastra/core@1.22.0
|
|
20
|
+
|
|
21
|
+
## 1.13.1-alpha.0
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- Fixed thread titles not persisting when generated during async buffered observation. Titles now update immediately when the observer produces them, rather than being lost until activation. ([#14992](https://github.com/mastra-ai/mastra/pull/14992))
|
|
26
|
+
|
|
27
|
+
- Updated dependencies [[`cb15509`](https://github.com/mastra-ai/mastra/commit/cb15509b58f6a83e11b765c945082afc027db972), [`80c5668`](https://github.com/mastra-ai/mastra/commit/80c5668e365470d3a96d3e953868fd7a643ff67c), [`3d478c1`](https://github.com/mastra-ai/mastra/commit/3d478c1e13f17b80f330ac49d7aa42ef929b93ff), [`6039f17`](https://github.com/mastra-ai/mastra/commit/6039f176f9c457304825ff1df8c83b8e457376c0), [`06b928d`](https://github.com/mastra-ai/mastra/commit/06b928dfc2f5630d023467476cc5919dfa858d0a), [`6a8d984`](https://github.com/mastra-ai/mastra/commit/6a8d9841f2933456ee1598099f488d742b600054)]:
|
|
28
|
+
- @mastra/core@1.22.0-alpha.2
|
|
29
|
+
|
|
30
|
+
## 1.13.0
|
|
31
|
+
|
|
32
|
+
### Minor Changes
|
|
33
|
+
|
|
34
|
+
- Added `loadUnobservedMessages({ threadId, resourceId? })` as a public method on `ObservationalMemory`. ([#14921](https://github.com/mastra-ai/mastra/pull/14921))
|
|
35
|
+
|
|
36
|
+
This lets external consumers (e.g. the Mastra gateway proxy) load previously-stored messages that haven't been observed yet, without having to reimplement the internal storage query and part-level filtering logic. The method fetches the OM record, queries storage for messages after the `lastObservedAt` cursor, and applies part-level filtering so partially-observed messages only return their unobserved parts.
|
|
37
|
+
|
|
38
|
+
```ts
|
|
39
|
+
const unobserved = await om.loadUnobservedMessages({
|
|
40
|
+
threadId: 'thread-123',
|
|
41
|
+
resourceId: 'user-456',
|
|
42
|
+
});
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- Updated dependencies [[`9a43b47`](https://github.com/mastra-ai/mastra/commit/9a43b476465e86c9aca381c2831066b5c33c999a), [`ec5c319`](https://github.com/mastra-ai/mastra/commit/ec5c3197a50d034cb8e9cc494eebfddc684b5d81), [`6517789`](https://github.com/mastra-ai/mastra/commit/65177895b74b5471fe2245c7292f0176d9b3385d), [`13f4327`](https://github.com/mastra-ai/mastra/commit/13f4327f052faebe199cefbe906d33bf90238767), [`9ad6aa6`](https://github.com/mastra-ai/mastra/commit/9ad6aa6dfe858afc6955d1df5f3f78c40bb96b9c), [`2862127`](https://github.com/mastra-ai/mastra/commit/2862127d0a7cbd28523120ad64fea067a95838e6), [`3d16814`](https://github.com/mastra-ai/mastra/commit/3d16814c395931373543728994ff45ac98093074), [`7f498d0`](https://github.com/mastra-ai/mastra/commit/7f498d099eacef64fd43ee412e3bd6f87965a8a6), [`8cf8a67`](https://github.com/mastra-ai/mastra/commit/8cf8a67b061b737cb06d501fb8c1967a98bbf3cb), [`d7827e3`](https://github.com/mastra-ai/mastra/commit/d7827e393937c6cb0c7a744dde4d31538cb542b7)]:
|
|
48
|
+
- @mastra/core@1.21.0
|
|
49
|
+
|
|
50
|
+
## 1.13.0-alpha.0
|
|
51
|
+
|
|
52
|
+
### Minor Changes
|
|
53
|
+
|
|
54
|
+
- Added `loadUnobservedMessages({ threadId, resourceId? })` as a public method on `ObservationalMemory`. ([#14921](https://github.com/mastra-ai/mastra/pull/14921))
|
|
55
|
+
|
|
56
|
+
This lets external consumers (e.g. the Mastra gateway proxy) load previously-stored messages that haven't been observed yet, without having to reimplement the internal storage query and part-level filtering logic. The method fetches the OM record, queries storage for messages after the `lastObservedAt` cursor, and applies part-level filtering so partially-observed messages only return their unobserved parts.
|
|
57
|
+
|
|
58
|
+
```ts
|
|
59
|
+
const unobserved = await om.loadUnobservedMessages({
|
|
60
|
+
threadId: 'thread-123',
|
|
61
|
+
resourceId: 'user-456',
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### Patch Changes
|
|
66
|
+
|
|
67
|
+
- Updated dependencies [[`13f4327`](https://github.com/mastra-ai/mastra/commit/13f4327f052faebe199cefbe906d33bf90238767)]:
|
|
68
|
+
- @mastra/core@1.21.0-alpha.1
|
|
9
69
|
|
|
10
70
|
## 1.12.1
|
|
11
71
|
|
|
@@ -1406,8 +1406,6 @@ var SyncObservationStrategy = class extends ObservationStrategy {
|
|
|
1406
1406
|
}
|
|
1407
1407
|
}
|
|
1408
1408
|
};
|
|
1409
|
-
|
|
1410
|
-
// src/processors/observational-memory/observation-strategies/async-buffer.ts
|
|
1411
1409
|
var AsyncBufferObservationStrategy = class extends ObservationStrategy {
|
|
1412
1410
|
startedAt;
|
|
1413
1411
|
cycleId;
|
|
@@ -1498,6 +1496,30 @@ var AsyncBufferObservationStrategy = class extends ObservationStrategy {
|
|
|
1498
1496
|
lastBufferedAtTime: processed.lastObservedAt
|
|
1499
1497
|
});
|
|
1500
1498
|
await this.indexObservationGroups(processed.observations, threadId, resourceId, processed.lastObservedAt);
|
|
1499
|
+
const newTitle = processed.threadTitle?.trim();
|
|
1500
|
+
if (newTitle && newTitle.length >= 3) {
|
|
1501
|
+
const thread = await this.storage.getThreadById({ threadId });
|
|
1502
|
+
if (thread) {
|
|
1503
|
+
const oldTitle = thread.title?.trim();
|
|
1504
|
+
if (newTitle !== oldTitle) {
|
|
1505
|
+
const newMetadata = memory.setThreadOMMetadata(thread.metadata, {
|
|
1506
|
+
threadTitle: processed.threadTitle
|
|
1507
|
+
});
|
|
1508
|
+
await this.storage.updateThread({
|
|
1509
|
+
id: threadId,
|
|
1510
|
+
title: newTitle,
|
|
1511
|
+
metadata: newMetadata
|
|
1512
|
+
});
|
|
1513
|
+
const marker = createThreadUpdateMarker({
|
|
1514
|
+
cycleId: this.cycleId,
|
|
1515
|
+
threadId,
|
|
1516
|
+
oldTitle,
|
|
1517
|
+
newTitle
|
|
1518
|
+
});
|
|
1519
|
+
await this.streamMarker(marker);
|
|
1520
|
+
}
|
|
1521
|
+
}
|
|
1522
|
+
}
|
|
1501
1523
|
}
|
|
1502
1524
|
async emitEndMarkers(_cycleId, processed) {
|
|
1503
1525
|
if (!processed.observations || !this.opts.writer) return;
|
|
@@ -1952,6 +1974,7 @@ var ObservationStep = class {
|
|
|
1952
1974
|
let buffered = false;
|
|
1953
1975
|
let reflected = false;
|
|
1954
1976
|
let didThresholdCleanup = false;
|
|
1977
|
+
let observerExchange;
|
|
1955
1978
|
if (this.stepNumber === 0) {
|
|
1956
1979
|
const step0Messages = messageList.get.all.db();
|
|
1957
1980
|
const activation = await om.activate({
|
|
@@ -2007,6 +2030,26 @@ var ObservationStep = class {
|
|
|
2007
2030
|
if (statusSnapshot.shouldBuffer && !hasIncompleteToolCalls) {
|
|
2008
2031
|
const allMessages = messageList.get.all.db();
|
|
2009
2032
|
const unobservedMessages = om.getUnobservedMessages(allMessages, statusSnapshot.record);
|
|
2033
|
+
const candidates = om.getUnobservedMessages(unobservedMessages, statusSnapshot.record, {
|
|
2034
|
+
excludeBuffered: true
|
|
2035
|
+
});
|
|
2036
|
+
if (candidates.length > 0) {
|
|
2037
|
+
om.sealMessagesForBuffering(candidates);
|
|
2038
|
+
try {
|
|
2039
|
+
await this.turn.hooks?.onBufferChunkSealed?.();
|
|
2040
|
+
} catch (error) {
|
|
2041
|
+
omDebug(
|
|
2042
|
+
`[OM:buffer] onBufferChunkSealed hook failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2043
|
+
);
|
|
2044
|
+
}
|
|
2045
|
+
if (this.turn.memory) {
|
|
2046
|
+
await this.turn.memory.persistMessages(candidates);
|
|
2047
|
+
}
|
|
2048
|
+
messageList.removeByIds(candidates.map((msg) => msg.id));
|
|
2049
|
+
for (const msg of candidates) {
|
|
2050
|
+
messageList.add(msg, "memory");
|
|
2051
|
+
}
|
|
2052
|
+
}
|
|
2010
2053
|
void om.buffer({
|
|
2011
2054
|
threadId,
|
|
2012
2055
|
resourceId,
|
|
@@ -2015,23 +2058,7 @@ var ObservationStep = class {
|
|
|
2015
2058
|
record: statusSnapshot.record,
|
|
2016
2059
|
writer: this.turn.writer,
|
|
2017
2060
|
requestContext: this.turn.requestContext,
|
|
2018
|
-
observabilityContext: this.turn.observabilityContext
|
|
2019
|
-
beforeBuffer: async (candidates) => {
|
|
2020
|
-
if (candidates.length === 0) {
|
|
2021
|
-
return;
|
|
2022
|
-
}
|
|
2023
|
-
om.sealMessagesForBuffering(candidates);
|
|
2024
|
-
try {
|
|
2025
|
-
await this.turn.hooks?.onBufferChunkSealed?.();
|
|
2026
|
-
} catch (error) {
|
|
2027
|
-
omDebug(
|
|
2028
|
-
`[OM:buffer] onBufferChunkSealed hook failed: ${error instanceof Error ? error.message : String(error)}`
|
|
2029
|
-
);
|
|
2030
|
-
}
|
|
2031
|
-
if (this.turn.memory) {
|
|
2032
|
-
await this.turn.memory.persistMessages(candidates);
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2061
|
+
observabilityContext: this.turn.observabilityContext
|
|
2035
2062
|
}).catch((err) => {
|
|
2036
2063
|
omDebug(`[OM:buffer] fire-and-forget buffer failed: ${err?.message}`);
|
|
2037
2064
|
});
|
|
@@ -2050,6 +2077,7 @@ var ObservationStep = class {
|
|
|
2050
2077
|
if (statusSnapshot.shouldObserve && !hasIncompleteToolCalls) {
|
|
2051
2078
|
const preObsGeneration = this.turn.record.generationCount;
|
|
2052
2079
|
const obsResult = await this.runThresholdObservation();
|
|
2080
|
+
observerExchange = obsResult.observerExchange;
|
|
2053
2081
|
if (obsResult.succeeded) {
|
|
2054
2082
|
observed = true;
|
|
2055
2083
|
didThresholdCleanup = true;
|
|
@@ -2103,6 +2131,7 @@ var ObservationStep = class {
|
|
|
2103
2131
|
}
|
|
2104
2132
|
this._context = {
|
|
2105
2133
|
systemMessage,
|
|
2134
|
+
observerExchange,
|
|
2106
2135
|
activated,
|
|
2107
2136
|
observed,
|
|
2108
2137
|
buffered,
|
|
@@ -2170,7 +2199,11 @@ var ObservationStep = class {
|
|
|
2170
2199
|
writer: this.turn.writer,
|
|
2171
2200
|
observabilityContext: this.turn.observabilityContext
|
|
2172
2201
|
});
|
|
2173
|
-
return {
|
|
2202
|
+
return {
|
|
2203
|
+
succeeded: obsResult.observed,
|
|
2204
|
+
record: obsResult.record,
|
|
2205
|
+
observerExchange: om.observer.lastExchange
|
|
2206
|
+
};
|
|
2174
2207
|
}
|
|
2175
2208
|
};
|
|
2176
2209
|
|
|
@@ -3496,6 +3529,8 @@ var ObserverRunner = class {
|
|
|
3496
3529
|
observedMessageIds;
|
|
3497
3530
|
resolveModel;
|
|
3498
3531
|
tokenCounter;
|
|
3532
|
+
/** Captured prompt/response from the last observer call (for repro capture). */
|
|
3533
|
+
lastExchange;
|
|
3499
3534
|
constructor(opts) {
|
|
3500
3535
|
this.observationConfig = opts.observationConfig;
|
|
3501
3536
|
this.observedMessageIds = opts.observedMessageIds;
|
|
@@ -3571,15 +3606,38 @@ var ObserverRunner = class {
|
|
|
3571
3606
|
};
|
|
3572
3607
|
let result = await doGenerate();
|
|
3573
3608
|
let parsed = parseObserverOutput(result.text);
|
|
3609
|
+
let retriedDueToDegenerate = false;
|
|
3574
3610
|
if (parsed.degenerate) {
|
|
3575
3611
|
omDebug(`[OM:callObserver] degenerate repetition detected, retrying once`);
|
|
3576
3612
|
result = await doGenerate();
|
|
3577
3613
|
parsed = parseObserverOutput(result.text);
|
|
3614
|
+
retriedDueToDegenerate = true;
|
|
3578
3615
|
if (parsed.degenerate) {
|
|
3579
3616
|
omDebug(`[OM:callObserver] degenerate repetition on retry, failing`);
|
|
3580
3617
|
throw new Error("Observer produced degenerate output after retry");
|
|
3581
3618
|
}
|
|
3582
3619
|
}
|
|
3620
|
+
const systemPrompt = buildObserverSystemPrompt(
|
|
3621
|
+
false,
|
|
3622
|
+
this.observationConfig.instruction,
|
|
3623
|
+
this.observationConfig.threadTitle
|
|
3624
|
+
);
|
|
3625
|
+
this.lastExchange = {
|
|
3626
|
+
systemPrompt,
|
|
3627
|
+
observerMessages,
|
|
3628
|
+
rawOutput: result.text,
|
|
3629
|
+
parsedResult: {
|
|
3630
|
+
observations: parsed.observations,
|
|
3631
|
+
currentTask: parsed.currentTask,
|
|
3632
|
+
suggestedContinuation: parsed.suggestedContinuation,
|
|
3633
|
+
threadTitle: parsed.threadTitle,
|
|
3634
|
+
degenerate: parsed.degenerate
|
|
3635
|
+
},
|
|
3636
|
+
model: String(resolvedModel.model),
|
|
3637
|
+
inputTokens,
|
|
3638
|
+
isMultiThread: false,
|
|
3639
|
+
retriedDueToDegenerate
|
|
3640
|
+
};
|
|
3583
3641
|
const usage = result.totalUsage ?? result.usage;
|
|
3584
3642
|
return {
|
|
3585
3643
|
observations: parsed.observations,
|
|
@@ -3646,15 +3704,36 @@ var ObserverRunner = class {
|
|
|
3646
3704
|
};
|
|
3647
3705
|
let result = await doGenerate();
|
|
3648
3706
|
let parsed = parseMultiThreadObserverOutput(result.text);
|
|
3707
|
+
let retriedDueToDegenerate = false;
|
|
3649
3708
|
if (parsed.degenerate) {
|
|
3650
3709
|
omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once`);
|
|
3651
3710
|
result = await doGenerate();
|
|
3652
3711
|
parsed = parseMultiThreadObserverOutput(result.text);
|
|
3712
|
+
retriedDueToDegenerate = true;
|
|
3653
3713
|
if (parsed.degenerate) {
|
|
3654
3714
|
omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing`);
|
|
3655
3715
|
throw new Error("Multi-thread observer produced degenerate output after retry");
|
|
3656
3716
|
}
|
|
3657
3717
|
}
|
|
3718
|
+
const systemPrompt = buildObserverSystemPrompt(
|
|
3719
|
+
true,
|
|
3720
|
+
this.observationConfig.instruction,
|
|
3721
|
+
this.observationConfig.threadTitle
|
|
3722
|
+
);
|
|
3723
|
+
this.lastExchange = {
|
|
3724
|
+
systemPrompt,
|
|
3725
|
+
observerMessages,
|
|
3726
|
+
rawOutput: result.text,
|
|
3727
|
+
parsedResult: {
|
|
3728
|
+
observations: Array.from(parsed.threads.values()).map((t) => t.observations).join("\n"),
|
|
3729
|
+
threadTitle: Array.from(parsed.threads.values()).map((t) => t.threadTitle).filter(Boolean).join(", "),
|
|
3730
|
+
degenerate: parsed.degenerate
|
|
3731
|
+
},
|
|
3732
|
+
model: String(resolvedModel.model),
|
|
3733
|
+
inputTokens,
|
|
3734
|
+
isMultiThread: true,
|
|
3735
|
+
retriedDueToDegenerate
|
|
3736
|
+
};
|
|
3658
3737
|
const results = /* @__PURE__ */ new Map();
|
|
3659
3738
|
for (const [threadId, threadResult] of parsed.threads) {
|
|
3660
3739
|
results.set(threadId, {
|
|
@@ -6715,7 +6794,7 @@ ${suggestedResponse}
|
|
|
6715
6794
|
* In resource scope mode, loads messages for the entire resource (all threads).
|
|
6716
6795
|
* In thread scope mode, loads messages for just the current thread.
|
|
6717
6796
|
*/
|
|
6718
|
-
async
|
|
6797
|
+
async loadMessagesFromStorage(threadId, resourceId, lastObservedAt) {
|
|
6719
6798
|
const startDate = lastObservedAt ? new Date(lastObservedAt.getTime() + 1) : void 0;
|
|
6720
6799
|
let result;
|
|
6721
6800
|
if (this.scope === "resource" && resourceId) {
|
|
@@ -7403,7 +7482,7 @@ ${grouped}` : grouped;
|
|
|
7403
7482
|
if (opts.messages) {
|
|
7404
7483
|
unobservedMessages = this.getUnobservedMessages(opts.messages, record);
|
|
7405
7484
|
} else {
|
|
7406
|
-
const rawMessages = await this.
|
|
7485
|
+
const rawMessages = await this.loadMessagesFromStorage(
|
|
7407
7486
|
threadId,
|
|
7408
7487
|
resourceId,
|
|
7409
7488
|
record.lastObservedAt ? new Date(record.lastObservedAt) : void 0
|
|
@@ -7516,6 +7595,27 @@ ${grouped}` : grouped;
|
|
|
7516
7595
|
const record = await this.getOrCreateRecord(threadId, resourceId);
|
|
7517
7596
|
return this.getUnobservedMessages(messages, record);
|
|
7518
7597
|
}
|
|
7598
|
+
/**
|
|
7599
|
+
* Load unobserved messages from storage for a thread/resource.
|
|
7600
|
+
*
|
|
7601
|
+
* Fetches the OM record, queries storage for messages after the
|
|
7602
|
+
* lastObservedAt cursor, then applies part-level filtering so
|
|
7603
|
+
* partially-observed messages only include their unobserved parts.
|
|
7604
|
+
*
|
|
7605
|
+
* Use this when you need to load stored conversation history that
|
|
7606
|
+
* hasn't been observed yet (e.g. in a stateless gateway proxy that
|
|
7607
|
+
* only receives the latest message from the HTTP request).
|
|
7608
|
+
*/
|
|
7609
|
+
async loadUnobservedMessages(opts) {
|
|
7610
|
+
const { threadId, resourceId } = opts;
|
|
7611
|
+
const record = await this.getOrCreateRecord(threadId, resourceId);
|
|
7612
|
+
const rawMessages = await this.loadMessagesFromStorage(
|
|
7613
|
+
threadId,
|
|
7614
|
+
resourceId,
|
|
7615
|
+
record.lastObservedAt ? new Date(record.lastObservedAt) : void 0
|
|
7616
|
+
);
|
|
7617
|
+
return this.getUnobservedMessages(rawMessages, record);
|
|
7618
|
+
}
|
|
7519
7619
|
/**
|
|
7520
7620
|
* Create a buffered observation chunk without merging into active observations.
|
|
7521
7621
|
*
|
|
@@ -7577,7 +7677,7 @@ ${grouped}` : grouped;
|
|
|
7577
7677
|
if (opts.messages) {
|
|
7578
7678
|
candidateMessages = this.getUnobservedMessages(opts.messages, record, { excludeBuffered: true });
|
|
7579
7679
|
} else {
|
|
7580
|
-
const rawMessages = await this.
|
|
7680
|
+
const rawMessages = await this.loadMessagesFromStorage(
|
|
7581
7681
|
threadId,
|
|
7582
7682
|
resourceId,
|
|
7583
7683
|
record.lastObservedAt ? new Date(record.lastObservedAt) : void 0
|
|
@@ -7782,13 +7882,18 @@ ${grouped}` : grouped;
|
|
|
7782
7882
|
const activatedChunks = freshChunks.filter((c) => activationResult.activatedCycleIds.includes(c.cycleId));
|
|
7783
7883
|
const lastActivated = activatedChunks[activatedChunks.length - 1];
|
|
7784
7884
|
if (lastActivated) {
|
|
7885
|
+
const chunkThreadTitle = lastActivated.threadTitle;
|
|
7785
7886
|
const newMetadata = memory.setThreadOMMetadata(thread.metadata, {
|
|
7786
7887
|
suggestedResponse: lastActivated.suggestedContinuation,
|
|
7787
|
-
currentTask: lastActivated.currentTask
|
|
7888
|
+
currentTask: lastActivated.currentTask,
|
|
7889
|
+
threadTitle: chunkThreadTitle
|
|
7788
7890
|
});
|
|
7891
|
+
const oldTitle = thread.title?.trim();
|
|
7892
|
+
const newTitle = chunkThreadTitle?.trim();
|
|
7893
|
+
const shouldUpdateThreadTitle = !!newTitle && newTitle.length >= 3 && newTitle !== oldTitle;
|
|
7789
7894
|
await this.storage.updateThread({
|
|
7790
7895
|
id: threadId,
|
|
7791
|
-
title: thread.title ?? "",
|
|
7896
|
+
title: shouldUpdateThreadTitle ? newTitle : thread.title ?? "",
|
|
7792
7897
|
metadata: newMetadata
|
|
7793
7898
|
});
|
|
7794
7899
|
}
|
|
@@ -7819,7 +7924,7 @@ ${grouped}` : grouped;
|
|
|
7819
7924
|
await this.withLock(lockKey, async () => {
|
|
7820
7925
|
const freshRecord = await this.getOrCreateRecord(threadId, resourceId);
|
|
7821
7926
|
generationBefore = freshRecord.generationCount;
|
|
7822
|
-
const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.
|
|
7927
|
+
const unobservedMessages = messages ? this.getUnobservedMessages(messages, freshRecord) : await this.loadMessagesFromStorage(
|
|
7823
7928
|
threadId,
|
|
7824
7929
|
resourceId,
|
|
7825
7930
|
freshRecord.lastObservedAt ? new Date(freshRecord.lastObservedAt) : void 0
|
|
@@ -8223,6 +8328,20 @@ function writeProcessInputStepReproCapture(params) {
|
|
|
8223
8328
|
`
|
|
8224
8329
|
);
|
|
8225
8330
|
}
|
|
8331
|
+
if (params.observerExchange) {
|
|
8332
|
+
const serialized = safeCaptureJsonOrError(params.observerExchange);
|
|
8333
|
+
if (serialized.ok) {
|
|
8334
|
+
fs.writeFileSync(path.join(captureDir, "observer-exchange.json"), `${JSON.stringify(serialized.value, null, 2)}
|
|
8335
|
+
`);
|
|
8336
|
+
} else {
|
|
8337
|
+
captureErrors.push({ fileName: "observer-exchange.json", error: serialized.error });
|
|
8338
|
+
fs.writeFileSync(
|
|
8339
|
+
path.join(captureDir, "observer-exchange.json"),
|
|
8340
|
+
`${JSON.stringify({ __captureError: serialized.error }, null, 2)}
|
|
8341
|
+
`
|
|
8342
|
+
);
|
|
8343
|
+
}
|
|
8344
|
+
}
|
|
8226
8345
|
if (captureErrors.length > 0) {
|
|
8227
8346
|
fs.writeFileSync(path.join(captureDir, "capture-error.json"), `${JSON.stringify(captureErrors, null, 2)}
|
|
8228
8347
|
`);
|
|
@@ -8387,7 +8506,8 @@ var ObservationalMemoryProcessor = class {
|
|
|
8387
8506
|
postBufferedChunks: [],
|
|
8388
8507
|
postContextTokenCount: finalTotalPending,
|
|
8389
8508
|
messageList,
|
|
8390
|
-
details: {}
|
|
8509
|
+
details: {},
|
|
8510
|
+
observerExchange: ctx.observerExchange
|
|
8391
8511
|
});
|
|
8392
8512
|
}
|
|
8393
8513
|
}
|
|
@@ -8475,5 +8595,5 @@ exports.stripEphemeralAnchorIds = stripEphemeralAnchorIds;
|
|
|
8475
8595
|
exports.stripObservationGroups = stripObservationGroups;
|
|
8476
8596
|
exports.truncateStringByTokens = truncateStringByTokens;
|
|
8477
8597
|
exports.wrapInObservationGroup = wrapInObservationGroup;
|
|
8478
|
-
//# sourceMappingURL=chunk-
|
|
8479
|
-
//# sourceMappingURL=chunk-
|
|
8598
|
+
//# sourceMappingURL=chunk-4FMHSWZD.cjs.map
|
|
8599
|
+
//# sourceMappingURL=chunk-4FMHSWZD.cjs.map
|