@mastra/memory 1.4.0 → 1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/CHANGELOG.md +48 -0
  2. package/dist/{chunk-D4AWAGLM.js → chunk-DF7NDDSM.js} +282 -190
  3. package/dist/chunk-DF7NDDSM.js.map +1 -0
  4. package/dist/{chunk-QRKB5I2S.cjs → chunk-LLTHE64H.cjs} +281 -189
  5. package/dist/chunk-LLTHE64H.cjs.map +1 -0
  6. package/dist/docs/SKILL.md +1 -1
  7. package/dist/docs/assets/SOURCE_MAP.json +25 -25
  8. package/dist/docs/references/docs-memory-observational-memory.md +2 -0
  9. package/dist/docs/references/reference-memory-memory-class.md +1 -1
  10. package/dist/docs/references/reference-memory-observational-memory.md +1 -0
  11. package/dist/index.cjs +3 -3
  12. package/dist/index.cjs.map +1 -1
  13. package/dist/index.js +3 -3
  14. package/dist/index.js.map +1 -1
  15. package/dist/{observational-memory-UCOMAMSF.cjs → observational-memory-4PCXEZIS.cjs} +17 -17
  16. package/dist/{observational-memory-UCOMAMSF.cjs.map → observational-memory-4PCXEZIS.cjs.map} +1 -1
  17. package/dist/{observational-memory-53AFLLSH.js → observational-memory-ZNTAIUGT.js} +3 -3
  18. package/dist/{observational-memory-53AFLLSH.js.map → observational-memory-ZNTAIUGT.js.map} +1 -1
  19. package/dist/processors/index.cjs +15 -15
  20. package/dist/processors/index.js +1 -1
  21. package/dist/processors/observational-memory/observational-memory.d.ts +17 -1
  22. package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
  23. package/dist/processors/observational-memory/observer-agent.d.ts +26 -5
  24. package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
  25. package/dist/processors/observational-memory/reflector-agent.d.ts.map +1 -1
  26. package/dist/processors/observational-memory/types.d.ts +14 -3
  27. package/dist/processors/observational-memory/types.d.ts.map +1 -1
  28. package/package.json +11 -11
  29. package/dist/chunk-D4AWAGLM.js.map +0 -1
  30. package/dist/chunk-QRKB5I2S.cjs.map +0 -1
@@ -2,7 +2,7 @@ import { appendFileSync } from 'fs';
2
2
  import { join } from 'path';
3
3
  import { Agent } from '@mastra/core/agent';
4
4
  import { resolveModelConfig } from '@mastra/core/llm';
5
- import { getThreadOMMetadata, parseMemoryRequestContext, setThreadOMMetadata } from '@mastra/core/memory';
5
+ import { setThreadOMMetadata, getThreadOMMetadata, parseMemoryRequestContext } from '@mastra/core/memory';
6
6
  import { MessageHistory } from '@mastra/core/processors';
7
7
  import xxhash from 'xxhash-wasm';
8
8
  import { Tiktoken } from 'js-tiktoken/lite';
@@ -11,54 +11,7 @@ import o200k_base from 'js-tiktoken/ranks/o200k_base';
11
11
  // src/processors/observational-memory/observational-memory.ts
12
12
 
13
13
  // src/processors/observational-memory/observer-agent.ts
14
- var USE_CONDENSED_PROMPT = process.env.OM_USE_CONDENSED_PROMPT === "1" || process.env.OM_USE_CONDENSED_PROMPT === "true";
15
- var CONDENSED_OBSERVER_EXTRACTION_INSTRUCTIONS = `You are the memory consciousness of an AI assistant. Your observations will be the ONLY information the assistant has about past interactions with this user.
16
-
17
- CORE PRINCIPLES:
18
-
19
- 1. BE SPECIFIC - Vague observations are useless. Capture details that distinguish and identify.
20
- 2. ANCHOR IN TIME - Note when things happened and when they were said.
21
- 3. TRACK STATE CHANGES - When information updates or supersedes previous info, make it explicit.
22
- 4. USE COMMON SENSE - If it would help the assistant remember later, observe it.
23
-
24
- ASSERTIONS VS QUESTIONS:
25
- - User TELLS you something \u2192 \u{1F534} "User stated [fact]"
26
- - User ASKS something \u2192 \u{1F7E1} "User asked [question]"
27
- - User assertions are authoritative. They are the source of truth about their own life.
28
-
29
- TEMPORAL ANCHORING:
30
- - Always include message time at the start: (14:30) User stated...
31
- - Add estimated date at the END only for relative time references:
32
- "User will visit parents this weekend. (meaning Jan 18-19)"
33
- - Don't add end dates for present-moment statements or vague terms like "recently"
34
- - Split multi-event statements into separate observations, each with its own date
35
-
36
- DETAILS TO ALWAYS PRESERVE:
37
- - Names, handles, usernames, titles (@username, "Dr. Smith")
38
- - Numbers, counts, quantities (4 items, 3 sessions, 27th in list)
39
- - Measurements, percentages, statistics (5kg, 20% improvement, 85% accuracy)
40
- - Sequences and orderings (steps 1-5, chord progression, lucky numbers)
41
- - Prices, dates, times, durations ($50, March 15, 2 hours)
42
- - Locations and distinguishing attributes (near X, based in Y, specializes in Z)
43
- - User's specific role (presenter, volunteer, organizer - not just "attended")
44
- - Exact phrasing when unusual ("movement session" for exercise)
45
- - Verbatim text being collaborated on (code, formatted text, ASCII art)
46
-
47
- WHEN ASSISTANT PROVIDES LISTS/RECOMMENDATIONS:
48
- Don't just say "Assistant recommended 5 hotels." Capture what distinguishes each:
49
- "Assistant recommended: Hotel A (near station), Hotel B (pet-friendly), Hotel C (has pool)..."
50
-
51
- STATE CHANGES:
52
- When user updates information, note what changed:
53
- "User will use the new method (replacing the old approach)"
54
-
55
- WHO/WHAT/WHERE/WHEN:
56
- Capture all dimensions. Not just "User went on a trip" but who with, where, when, and what happened.
57
-
58
- Don't repeat observations that have already been captured in previous sessions.
59
-
60
- REMEMBER: These observations are your ENTIRE memory. Any detail you fail to observe is permanently forgotten. Use common sense - if something seems like it might be important to remember, it probably is. When in doubt, observe it.`;
61
- var CURRENT_OBSERVER_EXTRACTION_INSTRUCTIONS = `CRITICAL: DISTINGUISH USER ASSERTIONS FROM QUESTIONS
14
+ var OBSERVER_EXTRACTION_INSTRUCTIONS = `CRITICAL: DISTINGUISH USER ASSERTIONS FROM QUESTIONS
62
15
 
63
16
  When the user TELLS you something about themselves, mark it as an assertion:
64
17
  - "I have two kids" \u2192 \u{1F534} (14:30) User stated has two kids
@@ -66,8 +19,8 @@ When the user TELLS you something about themselves, mark it as an assertion:
66
19
  - "I graduated in 2019" \u2192 \u{1F534} (14:32) User stated graduated in 2019
67
20
 
68
21
  When the user ASKS about something, mark it as a question/request:
69
- - "Can you help me with X?" \u2192 \u{1F7E1} (15:00) User asked help with X
70
- - "What's the best way to do Y?" \u2192 \u{1F7E1} (15:01) User asked best way to do Y
22
+ - "Can you help me with X?" \u2192 \u{1F534} (15:00) User asked help with X
23
+ - "What's the best way to do Y?" \u2192 \u{1F534} (15:01) User asked best way to do Y
71
24
 
72
25
  Distinguish between QUESTIONS and STATEMENTS OF INTENT:
73
26
  - "Can you recommend..." \u2192 Question (extract as "User asked...")
@@ -249,60 +202,39 @@ CONVERSATION CONTEXT:
249
202
  - When who/what/where/when is mentioned, note that in the observation. Example: if the user received went on a trip with someone, observe who that someone was, where the trip was, when it happened, and what happened, not just that the user went on the trip.
250
203
  - For any described entity (like a person, place, thing, etc), preserve the attributes that would help identify or describe the specific entity later: location ("near X"), specialty ("focuses on Y"), unique feature ("has Z"), relationship ("owned by W"), or other details. The entity's name is important, but so are any additional details that distinguish it. If there are a list of entities, preserve these details for each of them.
251
204
 
252
- ACTIONABLE INSIGHTS:
253
- - What worked well in explanations
254
- - What needs follow-up or clarification
255
- - User's stated goals or next steps (note if the user tells you not to do a next step, or asks for something specific, other next steps besides the users request should be marked as "waiting for user", unless the user explicitly says to continue all next steps)`;
256
- var OBSERVER_EXTRACTION_INSTRUCTIONS = USE_CONDENSED_PROMPT ? CONDENSED_OBSERVER_EXTRACTION_INSTRUCTIONS : CURRENT_OBSERVER_EXTRACTION_INSTRUCTIONS;
257
- var CONDENSED_OBSERVER_OUTPUT_FORMAT = `Use priority levels:
258
- - \u{1F534} High: explicit user facts, preferences, goals achieved, critical context
259
- - \u{1F7E1} Medium: project details, learned information, tool results
260
- - \u{1F7E2} Low: minor details, uncertain observations
205
+ USER MESSAGE CAPTURE:
206
+ - Short and medium-length user messages should be captured nearly verbatim in your own words.
207
+ - For very long user messages, summarize but quote key phrases that carry specific intent or meaning.
208
+ - This is critical for continuity: when the conversation window shrinks, the observations are the only record of what the user said.
261
209
 
262
- Group observations by date, then list each with 24-hour time.
263
- Group related observations (like tool sequences) by indenting.
210
+ AVOIDING REPETITIVE OBSERVATIONS:
211
+ - Do NOT repeat the same observation across multiple turns if there is no new information.
212
+ - When the agent performs repeated similar actions (e.g., browsing files, running the same tool type multiple times), group them into a single parent observation with sub-bullets for each new result.
264
213
 
265
- <observations>
266
- Date: Dec 4, 2025
267
- * \u{1F534} (09:15) User stated they have 3 kids: Emma (12), Jake (9), and Lily (5)
268
- * \u{1F534} (09:16) User's anniversary is March 15
269
- * \u{1F7E1} (09:20) User asked how to optimize database queries
270
- * \u{1F7E1} (10:30) User working on auth refactor - targeting 50% latency reduction
271
- * \u{1F7E1} (10:45) Assistant recommended hotels: Grand Plaza (downtown, $180/night), Seaside Inn (near beach, pet-friendly), Mountain Lodge (has pool, free breakfast)
272
- * \u{1F534} (11:00) User's friend @maria_dev recommended using Redis for caching
273
- * \u{1F7E1} (11:15) User attended the tech conference as a speaker (presented on microservices)
274
- * \u{1F534} (11:30) User will visit parents this weekend (meaning Dec 7-8, 2025)
275
- * \u{1F7E1} (14:00) Agent debugging auth issue
276
- * -> ran git status, found 3 modified files
277
- * -> viewed auth.ts:45-60, found missing null check
278
- * -> applied fix, tests now pass
279
- * \u{1F7E1} (14:30) Assistant provided dataset stats: 7,342 samples, 89.6% accuracy, 23ms inference time
280
- * \u{1F534} (15:00) User's lucky numbers from fortune cookie: 7, 14, 23, 38, 42, 49
214
+ Example \u2014 BAD (repetitive):
215
+ * \u{1F7E1} (14:30) Agent used view tool on src/auth.ts
216
+ * \u{1F7E1} (14:31) Agent used view tool on src/users.ts
217
+ * \u{1F7E1} (14:32) Agent used view tool on src/routes.ts
281
218
 
282
- Date: Dec 5, 2025
283
- * \u{1F534} (09:00) User switched from Python to TypeScript for the project (no longer using Python)
284
- * \u{1F7E1} (09:30) User bought running shoes for $120 at SportMart (downtown location)
285
- * \u{1F534} (10:00) User prefers morning meetings, not afternoon (updating previous preference)
286
- * \u{1F7E1} (10:30) User went to Italy with their sister last summer (meaning July 2025), visited Rome and Florence for 2 weeks
287
- * \u{1F534} (10:45) User's dentist appointment is next Tuesday (meaning Dec 10, 2025)
288
- * \u{1F7E2} (11:00) User mentioned they might try the new coffee shop
289
- </observations>
219
+ Example \u2014 GOOD (grouped):
220
+ * \u{1F7E1} (14:30) Agent browsed source files for auth flow
221
+ * -> viewed src/auth.ts \u2014 found token validation logic
222
+ * -> viewed src/users.ts \u2014 found user lookup by email
223
+ * -> viewed src/routes.ts \u2014 found middleware chain
290
224
 
291
- <current-task>
292
- Primary: Implementing OAuth2 flow for the auth refactor
293
- Secondary: Waiting for user to confirm database schema changes
294
- </current-task>
225
+ Only add a new observation for a repeated action if the NEW result changes the picture.
295
226
 
296
- <suggested-response>
297
- The OAuth2 implementation is ready for testing. Would you like me to walk through the flow?
298
- </suggested-response>`;
227
+ ACTIONABLE INSIGHTS:
228
+ - What worked well in explanations
229
+ - What needs follow-up or clarification
230
+ - User's stated goals or next steps (note if the user tells you not to do a next step, or asks for something specific, other next steps besides the users request should be marked as "waiting for user", unless the user explicitly says to continue all next steps)`;
299
231
  var OBSERVER_OUTPUT_FORMAT_BASE = `Use priority levels:
300
232
  - \u{1F534} High: explicit user facts, preferences, goals achieved, critical context
301
233
  - \u{1F7E1} Medium: project details, learned information, tool results
302
234
  - \u{1F7E2} Low: minor details, uncertain observations
303
235
 
304
236
  Group related observations (like tool sequences) by indenting:
305
- * \u{1F7E1} (14:33) Agent debugging auth issue
237
+ * \u{1F534} (14:33) Agent debugging auth issue
306
238
  * -> ran git status, found 3 modified files
307
239
  * -> viewed auth.ts:45-60, found missing null check
308
240
  * -> applied fix, tests now pass
@@ -312,11 +244,11 @@ Group observations by date, then list each with 24-hour time.
312
244
  <observations>
313
245
  Date: Dec 4, 2025
314
246
  * \u{1F534} (14:30) User prefers direct answers
315
- * \u{1F7E1} (14:31) Working on feature X
316
- * \u{1F7E2} (14:32) User might prefer dark mode
247
+ * \u{1F534} (14:31) Working on feature X
248
+ * \u{1F7E1} (14:32) User might prefer dark mode
317
249
 
318
250
  Date: Dec 5, 2025
319
- * \u{1F7E1} (09:15) Continued work on feature X
251
+ * \u{1F534} (09:15) Continued work on feature X
320
252
  </observations>
321
253
 
322
254
  <current-task>
@@ -333,29 +265,21 @@ Hint for the agent's immediate next message. Examples:
333
265
  - "The assistant should wait for the user to respond before continuing."
334
266
  - Call the view tool on src/example.ts to continue debugging.
335
267
  </suggested-response>`;
336
- var CONDENSED_OBSERVER_GUIDELINES = `- Be specific: "User prefers short answers without lengthy explanations" not "User stated a preference"
337
- - Use terse language - dense sentences without unnecessary words
338
- - Don't repeat observations that have already been captured
339
- - When the agent calls tools, observe what was called, why, and what was learned
340
- - Include line numbers when observing code files
341
- - If the agent provides a detailed response, observe the key points so it could be repeated
342
- - Start each observation with a priority emoji (\u{1F534}, \u{1F7E1}, \u{1F7E2})
343
- - Observe WHAT happened and WHAT it means, not HOW well it was done
344
- - If the user provides detailed messages or code snippets, observe all important details`;
345
- var OBSERVER_GUIDELINES = USE_CONDENSED_PROMPT ? CONDENSED_OBSERVER_GUIDELINES : `- Be specific enough for the assistant to act on
268
+ var OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
346
269
  - Good: "User prefers short, direct answers without lengthy explanations"
347
270
  - Bad: "User stated a preference" (too vague)
348
271
  - Add 1 to 5 observations per exchange
349
- - Use terse language to save tokens. Sentences should be dense without unnecessary words.
350
- - Do not add repetitive observations that have already been observed.
351
- - If the agent calls tools, observe what was called, why, and what was learned.
352
- - When observing files with line numbers, include the line number if useful.
353
- - If the agent provides a detailed response, observe the contents so it could be repeated.
272
+ - Use terse language to save tokens. Sentences should be dense without unnecessary words
273
+ - Do not add repetitive observations that have already been observed. Group repeated similar actions (tool calls, file browsing) under a single parent with sub-bullets for new results
274
+ - If the agent calls tools, observe what was called, why, and what was learned
275
+ - When observing files with line numbers, include the line number if useful
276
+ - If the agent provides a detailed response, observe the contents so it could be repeated
354
277
  - Make sure you start each observation with a priority emoji (\u{1F534}, \u{1F7E1}, \u{1F7E2})
355
- - Observe WHAT the agent did and WHAT it means, not HOW well it did it.
356
- - If the user provides detailed messages or code snippets, observe all important details.`;
278
+ - User messages are always \u{1F534} priority, so are the completions of tasks. Capture the user's words closely \u2014 short/medium messages near-verbatim, long messages summarized with key quotes
279
+ - Observe WHAT the agent did and WHAT it means
280
+ - If the user provides detailed messages or code snippets, observe all important details`;
357
281
  function buildObserverSystemPrompt(multiThread = false, instruction) {
358
- const outputFormat = USE_CONDENSED_PROMPT ? CONDENSED_OBSERVER_OUTPUT_FORMAT : OBSERVER_OUTPUT_FORMAT_BASE;
282
+ const outputFormat = OBSERVER_OUTPUT_FORMAT_BASE;
359
283
  if (multiThread) {
360
284
  return `You are the memory consciousness of an AI assistant. Your observations will be the ONLY information the assistant has about past interactions with this user.
361
285
 
@@ -376,7 +300,7 @@ Your output MUST use XML tags to structure the response. Each thread's observati
376
300
  <thread id="thread_id_1">
377
301
  Date: Dec 4, 2025
378
302
  * \u{1F534} (14:30) User prefers direct answers
379
- * \u{1F7E1} (14:31) Working on feature X
303
+ * \u{1F534} (14:31) Working on feature X
380
304
 
381
305
  <current-task>
382
306
  What the agent is currently working on in this thread
@@ -389,7 +313,7 @@ Hint for the agent's next message in this thread
389
313
 
390
314
  <thread id="thread_id_2">
391
315
  Date: Dec 5, 2025
392
- * \u{1F7E1} (09:15) User asked about deployment
316
+ * \u{1F534} (09:15) User asked about deployment
393
317
 
394
318
  <current-task>
395
319
  Current task for this thread
@@ -402,7 +326,7 @@ Suggested response for this thread
402
326
  </observations>
403
327
 
404
328
  Use priority levels:
405
- - \u{1F534} High: explicit user facts, preferences, goals achieved, critical context
329
+ - \u{1F534} High: explicit user facts, preferences, goals achieved, critical context, user messages
406
330
  - \u{1F7E1} Medium: project details, learned information, tool results
407
331
  - \u{1F7E2} Low: minor details, uncertain observations
408
332
 
@@ -556,7 +480,7 @@ ${formattedMessages}
556
480
  `;
557
481
  prompt += `Date: Dec 5, 2025
558
482
  `;
559
- prompt += `* \u{1F7E1} (09:15) User asked about deployment
483
+ prompt += `* \u{1F534} (09:15) User asked about deployment
560
484
  `;
561
485
  prompt += `<current-task>Discussing deployment options</current-task>
562
486
  `;
@@ -569,6 +493,9 @@ ${formattedMessages}
569
493
  }
570
494
  function parseMultiThreadObserverOutput(output) {
571
495
  const threads = /* @__PURE__ */ new Map();
496
+ if (detectDegenerateRepetition(output)) {
497
+ return { threads, rawOutput: output, degenerate: true };
498
+ }
572
499
  const observationsMatch = output.match(/^[ \t]*<observations>([\s\S]*?)^[ \t]*<\/observations>/im);
573
500
  const observationsContent = observationsMatch?.[1] ?? output;
574
501
  const threadRegex = /<thread\s+id="([^"]+)">([\s\S]*?)<\/thread>/gi;
@@ -590,7 +517,7 @@ function parseMultiThreadObserverOutput(output) {
590
517
  suggestedContinuation = suggestedMatch[1].trim();
591
518
  observations = observations.replace(/<suggested-response>[\s\S]*?<\/suggested-response>/i, "");
592
519
  }
593
- observations = observations.trim();
520
+ observations = sanitizeObservationLines(observations.trim());
594
521
  threads.set(threadId, {
595
522
  observations,
596
523
  currentTask,
@@ -635,8 +562,15 @@ IMPORTANT: Do NOT include <current-task> or <suggested-response> sections in you
635
562
  return prompt;
636
563
  }
637
564
  function parseObserverOutput(output) {
565
+ if (detectDegenerateRepetition(output)) {
566
+ return {
567
+ observations: "",
568
+ rawOutput: output,
569
+ degenerate: true
570
+ };
571
+ }
638
572
  const parsed = parseMemorySectionXml(output);
639
- const observations = parsed.observations || "";
573
+ const observations = sanitizeObservationLines(parsed.observations || "");
640
574
  return {
641
575
  observations,
642
576
  currentTask: parsed.currentTask || void 0,
@@ -677,6 +611,42 @@ function extractListItemsOnly(content) {
677
611
  }
678
612
  return listLines.join("\n").trim();
679
613
  }
614
+ var MAX_OBSERVATION_LINE_CHARS = 1e4;
615
+ function sanitizeObservationLines(observations) {
616
+ if (!observations) return observations;
617
+ const lines = observations.split("\n");
618
+ let changed = false;
619
+ for (let i = 0; i < lines.length; i++) {
620
+ if (lines[i].length > MAX_OBSERVATION_LINE_CHARS) {
621
+ lines[i] = lines[i].slice(0, MAX_OBSERVATION_LINE_CHARS) + " \u2026 [truncated]";
622
+ changed = true;
623
+ }
624
+ }
625
+ return changed ? lines.join("\n") : observations;
626
+ }
627
+ function detectDegenerateRepetition(text) {
628
+ if (!text || text.length < 2e3) return false;
629
+ const windowSize = 200;
630
+ const step = Math.max(1, Math.floor(text.length / 50));
631
+ const seen = /* @__PURE__ */ new Map();
632
+ let duplicateWindows = 0;
633
+ let totalWindows = 0;
634
+ for (let i = 0; i + windowSize <= text.length; i += step) {
635
+ const window = text.slice(i, i + windowSize);
636
+ totalWindows++;
637
+ const count = (seen.get(window) ?? 0) + 1;
638
+ seen.set(window, count);
639
+ if (count > 1) duplicateWindows++;
640
+ }
641
+ if (totalWindows > 5 && duplicateWindows / totalWindows > 0.4) {
642
+ return true;
643
+ }
644
+ const lines = text.split("\n");
645
+ for (const line of lines) {
646
+ if (line.length > 5e4) return true;
647
+ }
648
+ return false;
649
+ }
680
650
  function hasCurrentTaskSection(observations) {
681
651
  if (/<current-task>/i.test(observations)) {
682
652
  return true;
@@ -888,8 +858,14 @@ IMPORTANT: Do NOT include <current-task> or <suggested-response> sections in you
888
858
  return prompt;
889
859
  }
890
860
  function parseReflectorOutput(output) {
861
+ if (detectDegenerateRepetition(output)) {
862
+ return {
863
+ observations: "",
864
+ degenerate: true
865
+ };
866
+ }
891
867
  const parsed = parseReflectorSectionXml(output);
892
- const observations = parsed.observations || "";
868
+ const observations = sanitizeObservationLines(parsed.observations || "");
893
869
  return {
894
870
  observations,
895
871
  suggestedContinuation: parsed.suggestedResponse || void 0
@@ -1269,7 +1245,9 @@ var OBSERVATION_CONTEXT_INSTRUCTIONS = `IMPORTANT: When responding, reference sp
1269
1245
 
1270
1246
  KNOWLEDGE UPDATES: When asked about current state (e.g., "where do I currently...", "what is my current..."), always prefer the MOST RECENT information. Observations include dates - if you see conflicting information, the newer observation supersedes the older one. Look for phrases like "will start", "is switching", "changed to", "moved to" as indicators that previous information has been updated.
1271
1247
 
1272
- PLANNED ACTIONS: If the user stated they planned to do something (e.g., "I'm going to...", "I'm looking forward to...", "I will...") and the date they planned to do it is now in the past (check the relative time like "3 weeks ago"), assume they completed the action unless there's evidence they didn't. For example, if someone said "I'll start my new diet on Monday" and that was 2 weeks ago, assume they started the diet.`;
1248
+ PLANNED ACTIONS: If the user stated they planned to do something (e.g., "I'm going to...", "I'm looking forward to...", "I will...") and the date they planned to do it is now in the past (check the relative time like "3 weeks ago"), assume they completed the action unless there's evidence they didn't. For example, if someone said "I'll start my new diet on Monday" and that was 2 weeks ago, assume they started the diet.
1249
+
1250
+ MOST RECENT USER INPUT: Treat the most recent user message as the highest-priority signal for what to do next. Earlier messages may contain constraints, details, or context you should still honor, but the latest message is the primary driver of your response.`;
1273
1251
  var ObservationalMemory = class _ObservationalMemory {
1274
1252
  id = "observational-memory";
1275
1253
  name = "Observational Memory";
@@ -1439,41 +1417,65 @@ var ObservationalMemory = class _ObservationalMemory {
1439
1417
  }
1440
1418
  return [];
1441
1419
  }
1420
+ /**
1421
+ * Resolve bufferActivation config into an absolute retention floor (tokens to keep).
1422
+ * - Value in (0, 1]: ratio → retentionFloor = threshold * (1 - value)
1423
+ * - Value >= 1000: absolute token count → retentionFloor = value
1424
+ */
1425
+ resolveRetentionFloor(bufferActivation, messageTokensThreshold) {
1426
+ if (bufferActivation >= 1e3) return bufferActivation;
1427
+ return messageTokensThreshold * (1 - bufferActivation);
1428
+ }
1429
+ /**
1430
+ * Convert bufferActivation to the equivalent ratio (0-1) for the storage layer.
1431
+ * When bufferActivation >= 1000, it's an absolute retention target, so we compute
1432
+ * the equivalent ratio: 1 - (bufferActivation / threshold).
1433
+ */
1434
+ resolveActivationRatio(bufferActivation, messageTokensThreshold) {
1435
+ if (bufferActivation >= 1e3) {
1436
+ return Math.max(0, Math.min(1, 1 - bufferActivation / messageTokensThreshold));
1437
+ }
1438
+ return bufferActivation;
1439
+ }
1442
1440
  /**
1443
1441
  * Calculate the projected message tokens that would be removed if activation happened now.
1444
1442
  * This replicates the chunk boundary logic in swapBufferedToActive without actually activating.
1445
1443
  */
1446
- calculateProjectedMessageRemoval(chunks, activationRatio, messageTokensThreshold, currentPendingTokens) {
1444
+ calculateProjectedMessageRemoval(chunks, bufferActivation, messageTokensThreshold, currentPendingTokens) {
1447
1445
  if (chunks.length === 0) return 0;
1448
- const retentionFloor = messageTokensThreshold * (1 - activationRatio);
1446
+ const retentionFloor = this.resolveRetentionFloor(bufferActivation, messageTokensThreshold);
1449
1447
  const targetMessageTokens = Math.max(0, currentPendingTokens - retentionFloor);
1450
1448
  let cumulativeMessageTokens = 0;
1451
- let bestBoundary = 0;
1452
- let bestBoundaryMessageTokens = 0;
1449
+ let bestOverBoundary = 0;
1450
+ let bestOverTokens = 0;
1451
+ let bestUnderBoundary = 0;
1452
+ let bestUnderTokens = 0;
1453
1453
  for (let i = 0; i < chunks.length; i++) {
1454
1454
  cumulativeMessageTokens += chunks[i].messageTokens ?? 0;
1455
1455
  const boundary = i + 1;
1456
- const isUnder = cumulativeMessageTokens <= targetMessageTokens;
1457
- const bestIsUnder = bestBoundaryMessageTokens <= targetMessageTokens;
1458
- if (bestBoundary === 0) {
1459
- bestBoundary = boundary;
1460
- bestBoundaryMessageTokens = cumulativeMessageTokens;
1461
- } else if (isUnder && !bestIsUnder) {
1462
- bestBoundary = boundary;
1463
- bestBoundaryMessageTokens = cumulativeMessageTokens;
1464
- } else if (isUnder && bestIsUnder) {
1465
- if (cumulativeMessageTokens > bestBoundaryMessageTokens) {
1466
- bestBoundary = boundary;
1467
- bestBoundaryMessageTokens = cumulativeMessageTokens;
1456
+ if (cumulativeMessageTokens >= targetMessageTokens) {
1457
+ if (bestOverBoundary === 0 || cumulativeMessageTokens < bestOverTokens) {
1458
+ bestOverBoundary = boundary;
1459
+ bestOverTokens = cumulativeMessageTokens;
1468
1460
  }
1469
- } else if (!isUnder && !bestIsUnder) {
1470
- if (cumulativeMessageTokens < bestBoundaryMessageTokens) {
1471
- bestBoundary = boundary;
1472
- bestBoundaryMessageTokens = cumulativeMessageTokens;
1461
+ } else {
1462
+ if (cumulativeMessageTokens > bestUnderTokens) {
1463
+ bestUnderBoundary = boundary;
1464
+ bestUnderTokens = cumulativeMessageTokens;
1473
1465
  }
1474
1466
  }
1475
1467
  }
1476
- if (bestBoundary === 0) {
1468
+ const maxOvershoot = retentionFloor * 0.95;
1469
+ const overshoot = bestOverTokens - targetMessageTokens;
1470
+ const remainingAfterOver = currentPendingTokens - bestOverTokens;
1471
+ let bestBoundaryMessageTokens;
1472
+ if (bestOverBoundary > 0 && overshoot <= maxOvershoot && (remainingAfterOver >= 1e3 || retentionFloor === 0)) {
1473
+ bestBoundaryMessageTokens = bestOverTokens;
1474
+ } else if (bestUnderBoundary > 0) {
1475
+ bestBoundaryMessageTokens = bestUnderTokens;
1476
+ } else if (bestOverBoundary > 0) {
1477
+ bestBoundaryMessageTokens = bestOverTokens;
1478
+ } else {
1477
1479
  return chunks[0]?.messageTokens ?? 0;
1478
1480
  }
1479
1481
  return bestBoundaryMessageTokens;
@@ -1481,8 +1483,12 @@ var ObservationalMemory = class _ObservationalMemory {
1481
1483
  /**
1482
1484
  * Check if we've crossed a new bufferTokens interval boundary.
1483
1485
  * Returns true if async buffering should be triggered.
1486
+ *
1487
+ * When pending tokens are within ~1 bufferTokens of the observation threshold,
1488
+ * the buffer interval is halved to produce finer-grained chunks right before
1489
+ * activation. This improves chunk boundary selection, reducing overshoot.
1484
1490
  */
1485
- shouldTriggerAsyncObservation(currentTokens, lockKey, record) {
1491
+ shouldTriggerAsyncObservation(currentTokens, lockKey, record, messageTokensThreshold) {
1486
1492
  if (!this.isAsyncObservationEnabled()) return false;
1487
1493
  if (record.isBufferingObservation) {
1488
1494
  if (isOpActiveInProcess(record.id, "bufferingObservation")) return false;
@@ -1496,11 +1502,13 @@ var ObservationalMemory = class _ObservationalMemory {
1496
1502
  const dbBoundary = record.lastBufferedAtTokens ?? 0;
1497
1503
  const memBoundary = _ObservationalMemory.lastBufferedBoundary.get(bufferKey) ?? 0;
1498
1504
  const lastBoundary = Math.max(dbBoundary, memBoundary);
1499
- const currentInterval = Math.floor(currentTokens / bufferTokens);
1500
- const lastInterval = Math.floor(lastBoundary / bufferTokens);
1505
+ const rampPoint = messageTokensThreshold ? messageTokensThreshold - bufferTokens * 1.1 : Infinity;
1506
+ const effectiveBufferTokens = currentTokens >= rampPoint ? bufferTokens / 2 : bufferTokens;
1507
+ const currentInterval = Math.floor(currentTokens / effectiveBufferTokens);
1508
+ const lastInterval = Math.floor(lastBoundary / effectiveBufferTokens);
1501
1509
  const shouldTrigger = currentInterval > lastInterval;
1502
1510
  omDebug(
1503
- `[OM:shouldTriggerAsyncObs] tokens=${currentTokens}, bufferTokens=${bufferTokens}, currentInterval=${currentInterval}, lastInterval=${lastInterval}, lastBoundary=${lastBoundary} (db=${dbBoundary}, mem=${memBoundary}), shouldTrigger=${shouldTrigger}`
1511
+ `[OM:shouldTriggerAsyncObs] tokens=${currentTokens}, bufferTokens=${bufferTokens}, effectiveBufferTokens=${effectiveBufferTokens}, rampPoint=${rampPoint}, currentInterval=${currentInterval}, lastInterval=${lastInterval}, lastBoundary=${lastBoundary} (db=${dbBoundary}, mem=${memBoundary}), shouldTrigger=${shouldTrigger}`
1504
1512
  );
1505
1513
  return shouldTrigger;
1506
1514
  }
@@ -1761,9 +1769,17 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
1761
1769
  }
1762
1770
  }
1763
1771
  if (this.observationConfig.bufferActivation !== void 0) {
1764
- if (this.observationConfig.bufferActivation <= 0 || this.observationConfig.bufferActivation > 1) {
1772
+ if (this.observationConfig.bufferActivation <= 0) {
1773
+ throw new Error(`observation.bufferActivation must be > 0, got ${this.observationConfig.bufferActivation}`);
1774
+ }
1775
+ if (this.observationConfig.bufferActivation > 1 && this.observationConfig.bufferActivation < 1e3) {
1776
+ throw new Error(
1777
+ `observation.bufferActivation must be <= 1 (ratio) or >= 1000 (absolute token retention), got ${this.observationConfig.bufferActivation}`
1778
+ );
1779
+ }
1780
+ if (this.observationConfig.bufferActivation >= 1e3 && this.observationConfig.bufferActivation >= observationThreshold) {
1765
1781
  throw new Error(
1766
- `observation.bufferActivation must be in range (0, 1], got ${this.observationConfig.bufferActivation}`
1782
+ `observation.bufferActivation as absolute retention (${this.observationConfig.bufferActivation}) must be less than messageTokens (${observationThreshold})`
1767
1783
  );
1768
1784
  }
1769
1785
  }
@@ -2378,18 +2394,31 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
2378
2394
  async callObserver(existingObservations, messagesToObserve, abortSignal, options) {
2379
2395
  const agent = this.getObserverAgent();
2380
2396
  const prompt = buildObserverPrompt(existingObservations, messagesToObserve, options);
2381
- const result = await this.withAbortCheck(
2382
- () => agent.generate(prompt, {
2383
- modelSettings: {
2384
- ...this.observationConfig.modelSettings
2385
- },
2386
- providerOptions: this.observationConfig.providerOptions,
2387
- ...abortSignal ? { abortSignal } : {},
2388
- ...options?.requestContext ? { requestContext: options.requestContext } : {}
2389
- }),
2390
- abortSignal
2391
- );
2392
- const parsed = parseObserverOutput(result.text);
2397
+ const doGenerate = async () => {
2398
+ const result2 = await this.withAbortCheck(
2399
+ () => agent.generate(prompt, {
2400
+ modelSettings: {
2401
+ ...this.observationConfig.modelSettings
2402
+ },
2403
+ providerOptions: this.observationConfig.providerOptions,
2404
+ ...abortSignal ? { abortSignal } : {},
2405
+ ...options?.requestContext ? { requestContext: options.requestContext } : {}
2406
+ }),
2407
+ abortSignal
2408
+ );
2409
+ return result2;
2410
+ };
2411
+ let result = await doGenerate();
2412
+ let parsed = parseObserverOutput(result.text);
2413
+ if (parsed.degenerate) {
2414
+ omDebug(`[OM:callObserver] degenerate repetition detected, retrying once`);
2415
+ result = await doGenerate();
2416
+ parsed = parseObserverOutput(result.text);
2417
+ if (parsed.degenerate) {
2418
+ omDebug(`[OM:callObserver] degenerate repetition on retry, failing`);
2419
+ throw new Error("Observer produced degenerate output after retry");
2420
+ }
2421
+ }
2393
2422
  const usage = result.totalUsage ?? result.usage;
2394
2423
  return {
2395
2424
  observations: parsed.observations,
@@ -2423,18 +2452,30 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
2423
2452
  for (const msg of allMessages) {
2424
2453
  this.observedMessageIds.add(msg.id);
2425
2454
  }
2426
- const result = await this.withAbortCheck(
2427
- () => agent.generate(prompt, {
2428
- modelSettings: {
2429
- ...this.observationConfig.modelSettings
2430
- },
2431
- providerOptions: this.observationConfig.providerOptions,
2432
- ...abortSignal ? { abortSignal } : {},
2433
- ...requestContext ? { requestContext } : {}
2434
- }),
2435
- abortSignal
2436
- );
2437
- const parsed = parseMultiThreadObserverOutput(result.text);
2455
+ const doGenerate = async () => {
2456
+ return this.withAbortCheck(
2457
+ () => agent.generate(prompt, {
2458
+ modelSettings: {
2459
+ ...this.observationConfig.modelSettings
2460
+ },
2461
+ providerOptions: this.observationConfig.providerOptions,
2462
+ ...abortSignal ? { abortSignal } : {},
2463
+ ...requestContext ? { requestContext } : {}
2464
+ }),
2465
+ abortSignal
2466
+ );
2467
+ };
2468
+ let result = await doGenerate();
2469
+ let parsed = parseMultiThreadObserverOutput(result.text);
2470
+ if (parsed.degenerate) {
2471
+ omDebug(`[OM:callMultiThreadObserver] degenerate repetition detected, retrying once`);
2472
+ result = await doGenerate();
2473
+ parsed = parseMultiThreadObserverOutput(result.text);
2474
+ if (parsed.degenerate) {
2475
+ omDebug(`[OM:callMultiThreadObserver] degenerate repetition on retry, failing`);
2476
+ throw new Error("Multi-thread observer produced degenerate output after retry");
2477
+ }
2478
+ }
2438
2479
  const results = /* @__PURE__ */ new Map();
2439
2480
  for (const [threadId, threadResult] of parsed.threads) {
2440
2481
  results.set(threadId, {
@@ -2521,11 +2562,22 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
2521
2562
  totalUsage.totalTokens += usage.totalTokens ?? 0;
2522
2563
  }
2523
2564
  parsed = parseReflectorOutput(result.text);
2524
- reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
2565
+ if (parsed.degenerate) {
2566
+ omDebug(
2567
+ `[OM:callReflector] attempt #${attemptNumber}: degenerate repetition detected, treating as compression failure`
2568
+ );
2569
+ reflectedTokens = originalTokens;
2570
+ } else {
2571
+ reflectedTokens = this.tokenCounter.countObservations(parsed.observations);
2572
+ }
2525
2573
  omDebug(
2526
- `[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}`
2574
+ `[OM:callReflector] attempt #${attemptNumber} parsed: reflectedTokens=${reflectedTokens}, targetThreshold=${targetThreshold}, compressionValid=${validateCompression(reflectedTokens, targetThreshold)}, parsedObsLen=${parsed.observations?.length}, degenerate=${parsed.degenerate ?? false}`
2527
2575
  );
2528
- if (validateCompression(reflectedTokens, targetThreshold) || currentLevel >= maxLevel) {
2576
+ if (!parsed.degenerate && (validateCompression(reflectedTokens, targetThreshold) || currentLevel >= maxLevel)) {
2577
+ break;
2578
+ }
2579
+ if (parsed.degenerate && currentLevel >= maxLevel) {
2580
+ omDebug(`[OM:callReflector] degenerate output persists at maxLevel=${maxLevel}, breaking`);
2529
2581
  break;
2530
2582
  }
2531
2583
  if (streamContext?.writer) {
@@ -2833,6 +2885,20 @@ ${suggestedResponse}
2833
2885
  omDebug(
2834
2886
  `[OM:threshold] activation succeeded, obsTokens=${updatedRecord.observationTokenCount}, activeObsLen=${updatedRecord.activeObservations?.length}`
2835
2887
  );
2888
+ if (activationResult.suggestedContinuation || activationResult.currentTask) {
2889
+ const thread = await this.storage.getThreadById({ threadId });
2890
+ if (thread) {
2891
+ const newMetadata = setThreadOMMetadata(thread.metadata, {
2892
+ suggestedResponse: activationResult.suggestedContinuation,
2893
+ currentTask: activationResult.currentTask
2894
+ });
2895
+ await this.storage.updateThread({
2896
+ id: threadId,
2897
+ title: thread.title ?? "",
2898
+ metadata: newMetadata
2899
+ });
2900
+ }
2901
+ }
2836
2902
  await this.maybeAsyncReflect(
2837
2903
  updatedRecord,
2838
2904
  updatedRecord.observationTokenCount ?? 0,
@@ -3171,6 +3237,20 @@ ${suggestedResponse}
3171
3237
  _ObservationalMemory.lastBufferedBoundary.set(bufKey, 0);
3172
3238
  this.storage.setBufferingObservationFlag(record.id, false, 0).catch(() => {
3173
3239
  });
3240
+ if (activationResult.suggestedContinuation || activationResult.currentTask) {
3241
+ const thread = await this.storage.getThreadById({ threadId });
3242
+ if (thread) {
3243
+ const newMetadata = setThreadOMMetadata(thread.metadata, {
3244
+ suggestedResponse: activationResult.suggestedContinuation,
3245
+ currentTask: activationResult.currentTask
3246
+ });
3247
+ await this.storage.updateThread({
3248
+ id: threadId,
3249
+ title: thread.title ?? "",
3250
+ metadata: newMetadata
3251
+ });
3252
+ }
3253
+ }
3174
3254
  await this.maybeReflect({
3175
3255
  record,
3176
3256
  observationTokens: record.observationTokenCount ?? 0,
@@ -3229,7 +3309,7 @@ ${suggestedResponse}
3229
3309
  state.sealedIds = sealedIds;
3230
3310
  const lockKey = this.getLockKey(threadId, resourceId);
3231
3311
  if (this.isAsyncObservationEnabled() && totalPendingTokens < threshold) {
3232
- const shouldTrigger = this.shouldTriggerAsyncObservation(unbufferedPendingTokens, lockKey, record);
3312
+ const shouldTrigger = this.shouldTriggerAsyncObservation(unbufferedPendingTokens, lockKey, record, threshold);
3233
3313
  omDebug(
3234
3314
  `[OM:async-obs] belowThreshold: pending=${totalPendingTokens}, unbuffered=${unbufferedPendingTokens}, threshold=${threshold}, shouldTrigger=${shouldTrigger}, isBufferingObs=${record.isBufferingObservation}, lastBufferedAt=${record.lastBufferedAtTokens}`
3235
3315
  );
@@ -3245,7 +3325,7 @@ ${suggestedResponse}
3245
3325
  );
3246
3326
  }
3247
3327
  } else if (this.isAsyncObservationEnabled()) {
3248
- const shouldTrigger = this.shouldTriggerAsyncObservation(unbufferedPendingTokens, lockKey, record);
3328
+ const shouldTrigger = this.shouldTriggerAsyncObservation(unbufferedPendingTokens, lockKey, record, threshold);
3249
3329
  omDebug(
3250
3330
  `[OM:async-obs] atOrAboveThreshold: pending=${totalPendingTokens}, unbuffered=${unbufferedPendingTokens}, threshold=${threshold}, step=${stepNumber}, shouldTrigger=${shouldTrigger}`
3251
3331
  );
@@ -3927,8 +4007,12 @@ ${result.observations}` : result.observations;
3927
4007
  messagesToBuffer,
3928
4008
  void 0,
3929
4009
  // No abort signal for background ops
3930
- { skipContinuationHints: true, requestContext }
4010
+ { requestContext }
3931
4011
  );
4012
+ if (!result.observations) {
4013
+ omDebug(`[OM:doAsyncBufferedObservation] empty observations returned, skipping buffer storage`);
4014
+ return;
4015
+ }
3932
4016
  let newObservations;
3933
4017
  if (this.scope === "resource") {
3934
4018
  newObservations = await this.wrapWithThreadTag(threadId, result.observations);
@@ -3948,7 +4032,9 @@ ${result.observations}` : result.observations;
3948
4032
  tokenCount: newTokenCount,
3949
4033
  messageIds: newMessageIds,
3950
4034
  messageTokens,
3951
- lastObservedAt
4035
+ lastObservedAt,
4036
+ suggestedContinuation: result.suggestedContinuation,
4037
+ currentTask: result.currentTask
3952
4038
  },
3953
4039
  lastBufferedAtTime: lastObservedAt
3954
4040
  });
@@ -4027,24 +4113,28 @@ ${bufferedObservations}`;
4027
4113
  return { success: false };
4028
4114
  }
4029
4115
  const messageTokensThreshold = this.getMaxThreshold(this.observationConfig.messageTokens);
4116
+ let effectivePendingTokens = currentPendingTokens;
4030
4117
  if (messageList) {
4031
- const freshPendingTokens = this.tokenCounter.countMessages(messageList.get.all.db());
4032
- if (freshPendingTokens < messageTokensThreshold) {
4118
+ effectivePendingTokens = this.tokenCounter.countMessages(messageList.get.all.db());
4119
+ if (effectivePendingTokens < messageTokensThreshold) {
4033
4120
  omDebug(
4034
- `[OM:tryActivate] skipping activation: freshPendingTokens=${freshPendingTokens} < threshold=${messageTokensThreshold}`
4121
+ `[OM:tryActivate] skipping activation: freshPendingTokens=${effectivePendingTokens} < threshold=${messageTokensThreshold}`
4035
4122
  );
4036
4123
  return { success: false };
4037
4124
  }
4038
4125
  }
4039
- const activationRatio = this.observationConfig.bufferActivation ?? 0.7;
4126
+ const bufferActivation = this.observationConfig.bufferActivation ?? 0.7;
4127
+ const activationRatio = this.resolveActivationRatio(bufferActivation, messageTokensThreshold);
4128
+ const forceMaxActivation = !!(this.observationConfig.blockAfter && effectivePendingTokens >= this.observationConfig.blockAfter);
4040
4129
  omDebug(
4041
- `[OM:tryActivate] swapping: freshChunks=${freshChunks.length}, activationRatio=${activationRatio}, totalChunkTokens=${freshChunks.reduce((s, c) => s + (c.tokenCount ?? 0), 0)}`
4130
+ `[OM:tryActivate] swapping: freshChunks=${freshChunks.length}, bufferActivation=${bufferActivation}, activationRatio=${activationRatio}, forceMax=${forceMaxActivation}, totalChunkTokens=${freshChunks.reduce((s, c) => s + (c.tokenCount ?? 0), 0)}`
4042
4131
  );
4043
4132
  const activationResult = await this.storage.swapBufferedToActive({
4044
4133
  id: freshRecord.id,
4045
4134
  activationRatio,
4046
4135
  messageTokensThreshold,
4047
- currentPendingTokens
4136
+ currentPendingTokens: effectivePendingTokens,
4137
+ forceMaxActivation
4048
4138
  });
4049
4139
  omDebug(
4050
4140
  `[OM:tryActivate] swapResult: chunksActivated=${activationResult.chunksActivated}, tokensActivated=${activationResult.messageTokensActivated}, obsTokensActivated=${activationResult.observationTokensActivated}, activatedCycleIds=${activationResult.activatedCycleIds.join(",")}`
@@ -4083,7 +4173,9 @@ ${bufferedObservations}`;
4083
4173
  success: true,
4084
4174
  updatedRecord: updatedRecord ?? void 0,
4085
4175
  messageTokensActivated: activationResult.messageTokensActivated,
4086
- activatedMessageIds: activationResult.activatedMessageIds
4176
+ activatedMessageIds: activationResult.activatedMessageIds,
4177
+ suggestedContinuation: activationResult.suggestedContinuation,
4178
+ currentTask: activationResult.currentTask
4087
4179
  };
4088
4180
  }
4089
4181
  /**
@@ -4956,5 +5048,5 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
4956
5048
  };
4957
5049
 
4958
5050
  export { OBSERVATIONAL_MEMORY_DEFAULTS, OBSERVATION_CONTEXT_INSTRUCTIONS, OBSERVATION_CONTEXT_PROMPT, OBSERVATION_CONTINUATION_HINT, OBSERVER_SYSTEM_PROMPT, ObservationalMemory, TokenCounter, buildObserverPrompt, buildObserverSystemPrompt, extractCurrentTask, formatMessagesForObserver, hasCurrentTaskSection, optimizeObservationsForContext, parseObserverOutput };
4959
- //# sourceMappingURL=chunk-D4AWAGLM.js.map
4960
- //# sourceMappingURL=chunk-D4AWAGLM.js.map
5051
+ //# sourceMappingURL=chunk-DF7NDDSM.js.map
5052
+ //# sourceMappingURL=chunk-DF7NDDSM.js.map