@mastra/memory 1.8.4-alpha.0 → 1.9.0-alpha.1
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 +30 -0
- package/dist/{chunk-4KPXPQX3.js → chunk-5SMKVGJP.js} +205 -37
- package/dist/chunk-5SMKVGJP.js.map +1 -0
- package/dist/{chunk-LGCREJMO.cjs → chunk-AR52LM55.cjs} +205 -37
- package/dist/chunk-AR52LM55.cjs.map +1 -0
- package/dist/docs/SKILL.md +1 -1
- package/dist/docs/assets/SOURCE_MAP.json +27 -27
- package/dist/docs/references/docs-memory-observational-memory.md +2 -0
- package/dist/docs/references/reference-memory-observational-memory.md +2 -0
- package/dist/index.cjs +5 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/{observational-memory-UEDVTWS2.js → observational-memory-5NFPG6M3.js} +3 -3
- package/dist/{observational-memory-UEDVTWS2.js.map → observational-memory-5NFPG6M3.js.map} +1 -1
- package/dist/{observational-memory-4TV5KKFV.cjs → observational-memory-NH7VDTXM.cjs} +18 -18
- package/dist/{observational-memory-4TV5KKFV.cjs.map → observational-memory-NH7VDTXM.cjs.map} +1 -1
- package/dist/processors/index.cjs +16 -16
- package/dist/processors/index.js +1 -1
- package/dist/processors/observational-memory/markers.d.ts +10 -1
- package/dist/processors/observational-memory/markers.d.ts.map +1 -1
- package/dist/processors/observational-memory/observational-memory.d.ts +2 -0
- package/dist/processors/observational-memory/observational-memory.d.ts.map +1 -1
- package/dist/processors/observational-memory/observer-agent.d.ts +16 -6
- package/dist/processors/observational-memory/observer-agent.d.ts.map +1 -1
- package/dist/processors/observational-memory/reflector-agent.d.ts.map +1 -1
- package/dist/processors/observational-memory/types.d.ts +27 -1
- package/dist/processors/observational-memory/types.d.ts.map +1 -1
- package/package.json +5 -5
- package/dist/chunk-4KPXPQX3.js.map +0 -1
- package/dist/chunk-LGCREJMO.cjs.map +0 -1
|
@@ -307,6 +307,18 @@ function createActivationMarker(params) {
|
|
|
307
307
|
}
|
|
308
308
|
};
|
|
309
309
|
}
|
|
310
|
+
function createThreadUpdateMarker(params) {
|
|
311
|
+
return {
|
|
312
|
+
type: "data-om-thread-update",
|
|
313
|
+
data: {
|
|
314
|
+
cycleId: params.cycleId,
|
|
315
|
+
threadId: params.threadId,
|
|
316
|
+
oldTitle: params.oldTitle,
|
|
317
|
+
newTitle: params.newTitle,
|
|
318
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
}
|
|
310
322
|
var ENCRYPTED_CONTENT_KEY = "encryptedContent";
|
|
311
323
|
var ENCRYPTED_CONTENT_REDACTION_THRESHOLD = 256;
|
|
312
324
|
var DEFAULT_OBSERVER_TOOL_RESULT_MAX_TOKENS = 1e4;
|
|
@@ -616,17 +628,60 @@ Only add a new observation for a repeated action if the NEW result changes the p
|
|
|
616
628
|
ACTIONABLE INSIGHTS:
|
|
617
629
|
- What worked well in explanations
|
|
618
630
|
- What needs follow-up or clarification
|
|
619
|
-
- 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)
|
|
620
|
-
|
|
621
|
-
|
|
631
|
+
- 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)
|
|
632
|
+
|
|
633
|
+
COMPLETION TRACKING:
|
|
634
|
+
Completion observations are not just summaries. They are explicit memory signals to the assistant that a task, question, or subtask has been resolved.
|
|
635
|
+
Without clear completion markers, the assistant may forget that work is already finished and may repeat, reopen, or continue an already-completed task.
|
|
636
|
+
|
|
637
|
+
Use \u2705 to answer: "What exactly is now done?"
|
|
638
|
+
Choose completion observations that help the assistant know what is finished and should not be reworked unless new information appears.
|
|
639
|
+
|
|
640
|
+
Use \u2705 when:
|
|
641
|
+
- The user explicitly confirms something worked or was answered ("thanks, that fixed it", "got it", "perfect")
|
|
642
|
+
- The assistant provided a definitive, complete answer to a factual question and the user moved on
|
|
643
|
+
- A multi-step task reached its stated goal
|
|
644
|
+
- The user acknowledged receipt of requested information
|
|
645
|
+
- A concrete subtask, fix, deliverable, or implementation step became complete during ongoing work
|
|
646
|
+
|
|
647
|
+
Do NOT use \u2705 when:
|
|
648
|
+
- The assistant merely responded \u2014 the user might follow up with corrections
|
|
649
|
+
- The topic is paused but not resolved ("I'll try that later")
|
|
650
|
+
- The user's reaction is ambiguous
|
|
651
|
+
|
|
652
|
+
FORMAT:
|
|
653
|
+
As a sub-bullet under the related observation group:
|
|
654
|
+
* \u{1F534} (14:30) User asked how to configure auth middleware
|
|
655
|
+
* -> Agent explained JWT setup with code example
|
|
656
|
+
* \u2705 User confirmed auth is working
|
|
657
|
+
|
|
658
|
+
Or as a standalone observation when closing out a broader task:
|
|
659
|
+
* \u2705 (14:45) Auth configuration task completed \u2014 user confirmed middleware is working
|
|
660
|
+
|
|
661
|
+
Completion observations should be terse but specific about WHAT was completed.
|
|
662
|
+
Prefer concrete resolved outcomes over abstract workflow status so the assistant remembers what is already done.`;
|
|
663
|
+
var OBSERVER_OUTPUT_FORMAT_BASE = buildObserverOutputFormat();
|
|
664
|
+
function buildObserverOutputFormat(includeThreadTitle = false) {
|
|
665
|
+
const threadTitleSection = includeThreadTitle ? `
|
|
666
|
+
<thread-title>
|
|
667
|
+
A short, noun-phrase title for this conversation (2-5 words). Examples:
|
|
668
|
+
- "Auth bug fix" \u2014 not "Fixing the auth bug"
|
|
669
|
+
- "Dark mode toggle" \u2014 not "User wants dark mode toggle added"
|
|
670
|
+
- "Deployment pipeline setup" \u2014 not "Setting up deployment pipeline for project"
|
|
671
|
+
Only update when the topic meaningfully changes.
|
|
672
|
+
</thread-title>` : "";
|
|
673
|
+
return `Use priority levels:
|
|
674
|
+
- \u{1F534} High: explicit user facts, preferences, unresolved goals, critical context
|
|
622
675
|
- \u{1F7E1} Medium: project details, learned information, tool results
|
|
623
676
|
- \u{1F7E2} Low: minor details, uncertain observations
|
|
677
|
+
- \u2705 Completed: concrete task finished, question answered, issue resolved, goal achieved, or subtask completed in a way that helps the assistant know it is done
|
|
624
678
|
|
|
625
679
|
Group related observations (like tool sequences) by indenting:
|
|
626
680
|
* \u{1F534} (14:33) Agent debugging auth issue
|
|
627
681
|
* -> ran git status, found 3 modified files
|
|
628
682
|
* -> viewed auth.ts:45-60, found missing null check
|
|
629
683
|
* -> applied fix, tests now pass
|
|
684
|
+
* \u2705 Tests passing, auth issue resolved
|
|
630
685
|
|
|
631
686
|
Group observations by date, then list each with 24-hour time.
|
|
632
687
|
|
|
@@ -653,7 +708,8 @@ Hint for the agent's immediate next message. Examples:
|
|
|
653
708
|
- "I've updated the navigation model. Let me walk you through the changes..."
|
|
654
709
|
- "The assistant should wait for the user to respond before continuing."
|
|
655
710
|
- Call the view tool on src/example.ts to continue debugging.
|
|
656
|
-
</suggested-response
|
|
711
|
+
</suggested-response>${threadTitleSection}`;
|
|
712
|
+
}
|
|
657
713
|
var OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
|
|
658
714
|
- Good: "User prefers short, direct answers without lengthy explanations"
|
|
659
715
|
- Bad: "User stated a preference" (too vague)
|
|
@@ -663,12 +719,21 @@ var OBSERVER_GUIDELINES = `- Be specific enough for the assistant to act on
|
|
|
663
719
|
- If the agent calls tools, observe what was called, why, and what was learned
|
|
664
720
|
- When observing files with line numbers, include the line number if useful
|
|
665
721
|
- If the agent provides a detailed response, observe the contents so it could be repeated
|
|
666
|
-
- Make sure you start each observation with a priority emoji (\u{1F534}, \u{1F7E1}, \u{1F7E2})
|
|
667
|
-
-
|
|
722
|
+
- Make sure you start each observation with a priority emoji (\u{1F534}, \u{1F7E1}, \u{1F7E2}) or a completion marker (\u2705)
|
|
723
|
+
- Capture the user's words closely \u2014 short/medium messages near-verbatim, long messages summarized with key quotes. User confirmations or explicit resolved outcomes should be \u2705 when they clearly signal something is done; unresolved or critical user facts remain \u{1F534}
|
|
724
|
+
- Treat \u2705 as a memory signal that tells the assistant something is finished and should not be repeated unless new information changes it
|
|
725
|
+
- Make completion observations answer "What exactly is now done?"
|
|
726
|
+
- Prefer concrete resolved outcomes over meta-level workflow or bookkeeping updates
|
|
727
|
+
- When multiple concrete things were completed, capture the concrete completed work rather than collapsing it into a vague progress summary
|
|
668
728
|
- Observe WHAT the agent did and WHAT it means
|
|
669
729
|
- If the user provides detailed messages or code snippets, observe all important details`;
|
|
670
|
-
function buildObserverSystemPrompt(multiThread = false, instruction) {
|
|
671
|
-
const outputFormat =
|
|
730
|
+
function buildObserverSystemPrompt(multiThread = false, instruction, includeThreadTitle = false) {
|
|
731
|
+
const outputFormat = buildObserverOutputFormat(includeThreadTitle);
|
|
732
|
+
const multiThreadTitleInstruction = includeThreadTitle ? ` Each thread's observations, current-task, suggested-response, and thread-title should be nested inside a <thread id="..."> block within <observations>.` : ` Each thread's observations, current-task, and suggested-response should be nested inside a <thread id="..."> block within <observations>.`;
|
|
733
|
+
const multiThreadTitleExample = includeThreadTitle ? `
|
|
734
|
+
<thread-title>Feature X implementation</thread-title>` : "";
|
|
735
|
+
const multiThreadSecondTitleExample = includeThreadTitle ? `
|
|
736
|
+
<thread-title>Deployment setup</thread-title>` : "";
|
|
672
737
|
if (multiThread) {
|
|
673
738
|
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.
|
|
674
739
|
|
|
@@ -683,7 +748,13 @@ Process each thread separately and output observations for each thread.
|
|
|
683
748
|
|
|
684
749
|
=== OUTPUT FORMAT ===
|
|
685
750
|
|
|
686
|
-
Your output MUST use XML tags to structure the response
|
|
751
|
+
Your output MUST use XML tags to structure the response.${multiThreadTitleInstruction}
|
|
752
|
+
|
|
753
|
+
Use this observation format inside each thread block:
|
|
754
|
+
|
|
755
|
+
${outputFormat}
|
|
756
|
+
|
|
757
|
+
For multi-thread output, wrap each thread's observations like this:
|
|
687
758
|
|
|
688
759
|
<observations>
|
|
689
760
|
<thread id="thread_id_1">
|
|
@@ -697,7 +768,7 @@ What the agent is currently working on in this thread
|
|
|
697
768
|
|
|
698
769
|
<suggested-response>
|
|
699
770
|
Hint for the agent's next message in this thread
|
|
700
|
-
</suggested-response
|
|
771
|
+
</suggested-response>${multiThreadTitleExample}
|
|
701
772
|
</thread>
|
|
702
773
|
|
|
703
774
|
<thread id="thread_id_2">
|
|
@@ -710,15 +781,10 @@ Current task for this thread
|
|
|
710
781
|
|
|
711
782
|
<suggested-response>
|
|
712
783
|
Suggested response for this thread
|
|
713
|
-
</suggested-response
|
|
784
|
+
</suggested-response>${multiThreadSecondTitleExample}
|
|
714
785
|
</thread>
|
|
715
786
|
</observations>
|
|
716
787
|
|
|
717
|
-
Use priority levels:
|
|
718
|
-
- \u{1F534} High: explicit user facts, preferences, goals achieved, critical context, user messages
|
|
719
|
-
- \u{1F7E1} Medium: project details, learned information, tool results
|
|
720
|
-
- \u{1F7E2} Low: minor details, uncertain observations
|
|
721
|
-
|
|
722
788
|
=== GUIDELINES ===
|
|
723
789
|
|
|
724
790
|
${OBSERVER_GUIDELINES}
|
|
@@ -998,7 +1064,7 @@ The following messages are from ${threadOrder.length} different conversation thr
|
|
|
998
1064
|
content
|
|
999
1065
|
};
|
|
1000
1066
|
}
|
|
1001
|
-
function buildMultiThreadObserverTaskPrompt(existingObservations, threadOrder, priorMetadataByThread, wasTruncated) {
|
|
1067
|
+
function buildMultiThreadObserverTaskPrompt(existingObservations, threadOrder, priorMetadataByThread, wasTruncated, includeThreadTitle) {
|
|
1002
1068
|
let prompt = "";
|
|
1003
1069
|
if (existingObservations) {
|
|
1004
1070
|
prompt += `## Previous Observations
|
|
@@ -1013,7 +1079,8 @@ ${existingObservations}
|
|
|
1013
1079
|
const hasTruncatedObservations = wasTruncated ?? false;
|
|
1014
1080
|
const threadMetadataLines = threadOrder?.map((threadId) => {
|
|
1015
1081
|
const metadata = priorMetadataByThread?.get(threadId);
|
|
1016
|
-
|
|
1082
|
+
const hasRelevantMetadata = metadata?.currentTask || metadata?.suggestedResponse || includeThreadTitle && metadata?.threadTitle;
|
|
1083
|
+
if (!hasRelevantMetadata) {
|
|
1017
1084
|
return "";
|
|
1018
1085
|
}
|
|
1019
1086
|
const lines = [`- thread ${threadId}`];
|
|
@@ -1023,6 +1090,9 @@ ${existingObservations}
|
|
|
1023
1090
|
if (metadata.suggestedResponse) {
|
|
1024
1091
|
lines.push(` - prior suggested-response: ${metadata.suggestedResponse}`);
|
|
1025
1092
|
}
|
|
1093
|
+
if (includeThreadTitle && metadata.threadTitle) {
|
|
1094
|
+
lines.push(` - prior thread-title: ${metadata.threadTitle}`);
|
|
1095
|
+
}
|
|
1026
1096
|
return lines.join("\n");
|
|
1027
1097
|
}).filter(Boolean).join("\n");
|
|
1028
1098
|
if (threadMetadataLines) {
|
|
@@ -1037,7 +1107,8 @@ ${threadMetadataLines}
|
|
|
1037
1107
|
prompt += `The main agent still has full memory context outside this observer window.
|
|
1038
1108
|
`;
|
|
1039
1109
|
}
|
|
1040
|
-
|
|
1110
|
+
const titleHint = includeThreadTitle ? ", and thread-title" : "";
|
|
1111
|
+
prompt += `Use each thread's prior current-task, suggested-response${titleHint} as continuity hints, then update them based on that thread's new messages.
|
|
1041
1112
|
|
|
1042
1113
|
---
|
|
1043
1114
|
|
|
@@ -1046,7 +1117,8 @@ ${threadMetadataLines}
|
|
|
1046
1117
|
prompt += `## Your Task
|
|
1047
1118
|
|
|
1048
1119
|
`;
|
|
1049
|
-
|
|
1120
|
+
const titleInstruction = includeThreadTitle ? ", and thread-title" : "";
|
|
1121
|
+
prompt += `Extract new observations from each thread. Output your observations grouped by thread using <thread id="..."> tags inside your <observations> block. Each thread block should contain that thread's observations, current-task, suggested-response${titleInstruction}.
|
|
1050
1122
|
|
|
1051
1123
|
`;
|
|
1052
1124
|
prompt += `Example output format:
|
|
@@ -1062,6 +1134,8 @@ ${threadMetadataLines}
|
|
|
1062
1134
|
prompt += `<current-task>Working on feature X</current-task>
|
|
1063
1135
|
`;
|
|
1064
1136
|
prompt += `<suggested-response>Continue with the implementation</suggested-response>
|
|
1137
|
+
`;
|
|
1138
|
+
if (includeThreadTitle) prompt += `<thread-title>Feature X implementation</thread-title>
|
|
1065
1139
|
`;
|
|
1066
1140
|
prompt += `</thread>
|
|
1067
1141
|
`;
|
|
@@ -1074,6 +1148,8 @@ ${threadMetadataLines}
|
|
|
1074
1148
|
prompt += `<current-task>Discussing deployment options</current-task>
|
|
1075
1149
|
`;
|
|
1076
1150
|
prompt += `<suggested-response>Explain the deployment process</suggested-response>
|
|
1151
|
+
`;
|
|
1152
|
+
if (includeThreadTitle) prompt += `<thread-title>Deployment setup</thread-title>
|
|
1077
1153
|
`;
|
|
1078
1154
|
prompt += `</thread>
|
|
1079
1155
|
`;
|
|
@@ -1106,11 +1182,18 @@ function parseMultiThreadObserverOutput(output) {
|
|
|
1106
1182
|
suggestedContinuation = suggestedMatch[1].trim();
|
|
1107
1183
|
observations = observations.replace(/<suggested-response>[\s\S]*?<\/suggested-response>/i, "");
|
|
1108
1184
|
}
|
|
1185
|
+
let threadTitle;
|
|
1186
|
+
const threadTitleMatch = threadContent.match(/<thread-title>([\s\S]*?)<\/thread-title>/i);
|
|
1187
|
+
if (threadTitleMatch?.[1]) {
|
|
1188
|
+
threadTitle = threadTitleMatch[1].trim();
|
|
1189
|
+
observations = observations.replace(/<thread-title>[\s\S]*?<\/thread-title>/i, "");
|
|
1190
|
+
}
|
|
1109
1191
|
observations = sanitizeObservationLines(observations.trim());
|
|
1110
1192
|
threads.set(threadId, {
|
|
1111
1193
|
observations,
|
|
1112
1194
|
currentTask,
|
|
1113
1195
|
suggestedContinuation,
|
|
1196
|
+
threadTitle,
|
|
1114
1197
|
rawOutput: threadContent
|
|
1115
1198
|
});
|
|
1116
1199
|
}
|
|
@@ -1139,6 +1222,9 @@ ${existingObservations}
|
|
|
1139
1222
|
if (options?.priorSuggestedResponse) {
|
|
1140
1223
|
priorMetadataLines.push(`- prior suggested-response: ${options.priorSuggestedResponse}`);
|
|
1141
1224
|
}
|
|
1225
|
+
if (options?.includeThreadTitle && options?.priorThreadTitle) {
|
|
1226
|
+
priorMetadataLines.push(`- prior thread-title: ${options.priorThreadTitle}`);
|
|
1227
|
+
}
|
|
1142
1228
|
if (priorMetadataLines.length > 0) {
|
|
1143
1229
|
prompt += `## Prior Thread Metadata
|
|
1144
1230
|
|
|
@@ -1151,7 +1237,8 @@ ${priorMetadataLines.join("\n")}
|
|
|
1151
1237
|
prompt += `The main agent still has full memory context outside this observer window.
|
|
1152
1238
|
`;
|
|
1153
1239
|
}
|
|
1154
|
-
|
|
1240
|
+
const titleHint = options?.includeThreadTitle ? ", and thread-title" : "";
|
|
1241
|
+
prompt += `Use the prior current-task, suggested-response${titleHint} as continuity hints, then update them based on the new messages.
|
|
1155
1242
|
|
|
1156
1243
|
---
|
|
1157
1244
|
|
|
@@ -1161,10 +1248,15 @@ ${priorMetadataLines.join("\n")}
|
|
|
1161
1248
|
|
|
1162
1249
|
`;
|
|
1163
1250
|
prompt += `Extract new observations from the message history above. Do not repeat observations that are already in the previous observations. Add your new observations in the format specified in your instructions.`;
|
|
1251
|
+
if (options?.includeThreadTitle) {
|
|
1252
|
+
prompt += `
|
|
1253
|
+
|
|
1254
|
+
Also output a <thread-title> \u2014 a short noun-phrase label for this conversation (2-5 words). Write it like a file name or PR title: "Auth bug fix", "Memory config refactor", "RAG pipeline setup". Avoid verbs/sentences ("Fixing the auth bug"), filler ("Working on stuff"), and generic labels ("Code review"). Only change it from the prior title if the topic meaningfully shifted.`;
|
|
1255
|
+
}
|
|
1164
1256
|
if (options?.skipContinuationHints) {
|
|
1165
1257
|
prompt += `
|
|
1166
1258
|
|
|
1167
|
-
IMPORTANT: Do NOT include <current-task> or <suggested-response> sections in your output. Only output <observations
|
|
1259
|
+
IMPORTANT: Do NOT include <current-task> or <suggested-response> sections in your output. Only output <observations>${options?.includeThreadTitle ? " and <thread-title>" : ""}.`;
|
|
1168
1260
|
}
|
|
1169
1261
|
return prompt;
|
|
1170
1262
|
}
|
|
@@ -1192,6 +1284,7 @@ function parseObserverOutput(output) {
|
|
|
1192
1284
|
observations,
|
|
1193
1285
|
currentTask: parsed.currentTask || void 0,
|
|
1194
1286
|
suggestedContinuation: parsed.suggestedResponse || void 0,
|
|
1287
|
+
threadTitle: parsed.threadTitle || void 0,
|
|
1195
1288
|
rawOutput: output
|
|
1196
1289
|
};
|
|
1197
1290
|
}
|
|
@@ -1199,7 +1292,8 @@ function parseMemorySectionXml(content) {
|
|
|
1199
1292
|
const result = {
|
|
1200
1293
|
observations: "",
|
|
1201
1294
|
currentTask: "",
|
|
1202
|
-
suggestedResponse: ""
|
|
1295
|
+
suggestedResponse: "",
|
|
1296
|
+
threadTitle: ""
|
|
1203
1297
|
};
|
|
1204
1298
|
const observationsRegex = /^[ \t]*<observations>([\s\S]*?)^[ \t]*<\/observations>/gim;
|
|
1205
1299
|
const observationsMatches = [...content.matchAll(observationsRegex)];
|
|
@@ -1216,6 +1310,10 @@ function parseMemorySectionXml(content) {
|
|
|
1216
1310
|
if (suggestedResponseMatch?.[1]) {
|
|
1217
1311
|
result.suggestedResponse = suggestedResponseMatch[1].trim();
|
|
1218
1312
|
}
|
|
1313
|
+
const threadTitleMatch = content.match(/^[ \t]*<thread-title>([\s\S]*?)<\/thread-title>/im);
|
|
1314
|
+
if (threadTitleMatch?.[1]) {
|
|
1315
|
+
result.threadTitle = threadTitleMatch[1].trim();
|
|
1316
|
+
}
|
|
1219
1317
|
return result;
|
|
1220
1318
|
}
|
|
1221
1319
|
function extractListItemsOnly(content) {
|
|
@@ -1353,6 +1451,8 @@ When consolidating observations:
|
|
|
1353
1451
|
- Preserve and include dates/times when present (temporal context is critical)
|
|
1354
1452
|
- Retain the most relevant timestamps (start times, completion times, significant events)
|
|
1355
1453
|
- Combine related items where it makes sense (e.g., "agent called view tool 5 times on file x")
|
|
1454
|
+
- Preserve \u2705 completion markers \u2014 they are memory signals that tell the assistant what is already resolved and help prevent repeated work
|
|
1455
|
+
- Preserve the concrete resolved outcome captured by \u2705 markers so the assistant knows what exactly is done
|
|
1356
1456
|
- Condense older observations more aggressively, retain more detail for recent ones
|
|
1357
1457
|
|
|
1358
1458
|
CRITICAL: USER ASSERTIONS vs QUESTIONS
|
|
@@ -1433,6 +1533,8 @@ Please re-process with slightly more compression:
|
|
|
1433
1533
|
- Closer to the end, retain more fine details (recent context matters more)
|
|
1434
1534
|
- Memory is getting long - use a more condensed style throughout
|
|
1435
1535
|
- Combine related items more aggressively but do not lose important specific details of names, places, events, and people
|
|
1536
|
+
- Preserve \u2705 completion markers \u2014 they are memory signals that tell the assistant what is already resolved and help prevent repeated work
|
|
1537
|
+
- Preserve the concrete resolved outcome captured by \u2705 markers so the assistant knows what exactly is done
|
|
1436
1538
|
- For example if there is a long nested observation list about repeated tool calls, you can combine those into a single line and observe that the tool was called multiple times for x reason, and finally y outcome happened.
|
|
1437
1539
|
|
|
1438
1540
|
Your current detail level was a 10/10, lets aim for a 8/10 detail level.
|
|
@@ -1447,6 +1549,8 @@ Please re-process with much more aggressive compression:
|
|
|
1447
1549
|
- Closer to the end, retain fine details (recent context matters more)
|
|
1448
1550
|
- Memory is getting very long - use a significantly more condensed style throughout
|
|
1449
1551
|
- Combine related items aggressively but do not lose important specific details of names, places, events, and people
|
|
1552
|
+
- Preserve \u2705 completion markers \u2014 they are memory signals that tell the assistant what is already resolved and help prevent repeated work
|
|
1553
|
+
- Preserve the concrete resolved outcome captured by \u2705 markers so the assistant knows what exactly is done
|
|
1450
1554
|
- For example if there is a long nested observation list about repeated tool calls, you can combine those into a single line and observe that the tool was called multiple times for x reason, and finally y outcome happened.
|
|
1451
1555
|
- Remove redundant information and merge overlapping observations
|
|
1452
1556
|
|
|
@@ -1463,6 +1567,8 @@ Please re-process with maximum compression:
|
|
|
1463
1567
|
- Ruthlessly merge related observations \u2014 if 10 observations are about the same topic, combine into 1-2 lines
|
|
1464
1568
|
- Drop procedural details (tool calls, retries, intermediate steps) \u2014 keep only final outcomes
|
|
1465
1569
|
- Drop observations that are no longer relevant or have been superseded by newer information
|
|
1570
|
+
- Preserve \u2705 completion markers \u2014 they are memory signals that tell the assistant what is already resolved and help prevent repeated work
|
|
1571
|
+
- Preserve the concrete resolved outcome captured by \u2705 markers so the assistant knows what exactly is done
|
|
1466
1572
|
- Preserve: names, dates, decisions, errors, user preferences, and architectural choices
|
|
1467
1573
|
|
|
1468
1574
|
Your current detail level was a 10/10, lets aim for a 4/10 detail level.
|
|
@@ -3443,7 +3549,8 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
|
|
|
3443
3549
|
config.observation?.messageTokens ?? OBSERVATIONAL_MEMORY_DEFAULTS.observation.messageTokens
|
|
3444
3550
|
),
|
|
3445
3551
|
previousObserverTokens: config.observation?.previousObserverTokens ?? 2e3,
|
|
3446
|
-
instruction: config.observation?.instruction
|
|
3552
|
+
instruction: config.observation?.instruction,
|
|
3553
|
+
threadTitle: config.observation?.threadTitle ?? false
|
|
3447
3554
|
};
|
|
3448
3555
|
this.reflectionConfig = {
|
|
3449
3556
|
model: reflectionModel,
|
|
@@ -3669,7 +3776,11 @@ Async buffering is enabled by default \u2014 this opt-out is only needed when us
|
|
|
3669
3776
|
*/
|
|
3670
3777
|
getObserverAgent() {
|
|
3671
3778
|
if (!this.observerAgent) {
|
|
3672
|
-
const systemPrompt = buildObserverSystemPrompt(
|
|
3779
|
+
const systemPrompt = buildObserverSystemPrompt(
|
|
3780
|
+
false,
|
|
3781
|
+
this.observationConfig.instruction,
|
|
3782
|
+
this.observationConfig.threadTitle
|
|
3783
|
+
);
|
|
3673
3784
|
this.observerAgent = new agent.Agent({
|
|
3674
3785
|
id: "observational-memory-observer",
|
|
3675
3786
|
name: "Observer",
|
|
@@ -4091,7 +4202,7 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4091
4202
|
const isImportant = new Array(totalCount);
|
|
4092
4203
|
for (let i = 0; i < totalCount; i++) {
|
|
4093
4204
|
lineTokens[i] = this.tokenCounter.countString(lines[i]);
|
|
4094
|
-
isImportant[i] = lines[i].includes("\u{1F534}");
|
|
4205
|
+
isImportant[i] = lines[i].includes("\u{1F534}") || lines[i].includes("\u2705");
|
|
4095
4206
|
}
|
|
4096
4207
|
const suffixTokens = new Array(totalCount + 1);
|
|
4097
4208
|
suffixTokens[totalCount] = 0;
|
|
@@ -4177,7 +4288,9 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4177
4288
|
skipContinuationHints: options?.skipContinuationHints,
|
|
4178
4289
|
priorCurrentTask: options?.priorCurrentTask,
|
|
4179
4290
|
priorSuggestedResponse: options?.priorSuggestedResponse,
|
|
4180
|
-
|
|
4291
|
+
priorThreadTitle: options?.priorThreadTitle,
|
|
4292
|
+
wasTruncated: options?.wasTruncated,
|
|
4293
|
+
includeThreadTitle: this.observationConfig.threadTitle
|
|
4181
4294
|
})
|
|
4182
4295
|
},
|
|
4183
4296
|
buildObserverHistoryMessage(messagesToObserve)
|
|
@@ -4212,6 +4325,7 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4212
4325
|
observations: parsed.observations,
|
|
4213
4326
|
currentTask: parsed.currentTask,
|
|
4214
4327
|
suggestedContinuation: parsed.suggestedContinuation,
|
|
4328
|
+
threadTitle: parsed.threadTitle,
|
|
4215
4329
|
usage: usage ? {
|
|
4216
4330
|
inputTokens: usage.inputTokens,
|
|
4217
4331
|
outputTokens: usage.outputTokens,
|
|
@@ -4226,7 +4340,11 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4226
4340
|
* plus the total usage for the batch.
|
|
4227
4341
|
*/
|
|
4228
4342
|
async callMultiThreadObserver(existingObservations, messagesByThread, threadOrder, priorMetadataByThread, abortSignal, requestContext, wasTruncated) {
|
|
4229
|
-
const systemPrompt = buildObserverSystemPrompt(
|
|
4343
|
+
const systemPrompt = buildObserverSystemPrompt(
|
|
4344
|
+
true,
|
|
4345
|
+
this.observationConfig.instruction,
|
|
4346
|
+
this.observationConfig.threadTitle
|
|
4347
|
+
);
|
|
4230
4348
|
const agent$1 = new agent.Agent({
|
|
4231
4349
|
id: "multi-thread-observer",
|
|
4232
4350
|
name: "multi-thread-observer",
|
|
@@ -4240,7 +4358,8 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4240
4358
|
existingObservations,
|
|
4241
4359
|
threadOrder,
|
|
4242
4360
|
priorMetadataByThread,
|
|
4243
|
-
wasTruncated
|
|
4361
|
+
wasTruncated,
|
|
4362
|
+
this.observationConfig.threadTitle
|
|
4244
4363
|
)
|
|
4245
4364
|
},
|
|
4246
4365
|
buildMultiThreadObserverHistoryMessage(messagesByThread, threadOrder)
|
|
@@ -4282,7 +4401,8 @@ ${unreflectedContent}` : bufferedReflection;
|
|
|
4282
4401
|
results.set(threadId, {
|
|
4283
4402
|
observations: threadResult.observations,
|
|
4284
4403
|
currentTask: threadResult.currentTask,
|
|
4285
|
-
suggestedContinuation: threadResult.suggestedContinuation
|
|
4404
|
+
suggestedContinuation: threadResult.suggestedContinuation,
|
|
4405
|
+
threadTitle: threadResult.threadTitle
|
|
4286
4406
|
});
|
|
4287
4407
|
}
|
|
4288
4408
|
for (const threadId of threadOrder) {
|
|
@@ -5725,6 +5845,7 @@ ${threadClose}`;
|
|
|
5725
5845
|
requestContext,
|
|
5726
5846
|
priorCurrentTask: threadOMMetadata?.currentTask,
|
|
5727
5847
|
priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
|
|
5848
|
+
priorThreadTitle: thread?.title,
|
|
5728
5849
|
wasTruncated
|
|
5729
5850
|
});
|
|
5730
5851
|
const lastObservedAt = this.getMaxMessageTimestamp(messagesToObserve);
|
|
@@ -5755,10 +5876,31 @@ ${threadClose}`;
|
|
|
5755
5876
|
});
|
|
5756
5877
|
await this.storage.updateThread({
|
|
5757
5878
|
id: threadId,
|
|
5758
|
-
title: threadForMetadata.title
|
|
5879
|
+
title: threadForMetadata.title || "",
|
|
5759
5880
|
metadata: newMetadata
|
|
5760
5881
|
});
|
|
5761
5882
|
}
|
|
5883
|
+
if (this.observationConfig.threadTitle && threadForMetadata && result.threadTitle) {
|
|
5884
|
+
const oldTitle = threadForMetadata.title;
|
|
5885
|
+
const newTitle = result.threadTitle;
|
|
5886
|
+
if (newTitle.trim().length >= 3 && newTitle !== oldTitle) {
|
|
5887
|
+
await this.storage.updateThread({
|
|
5888
|
+
id: threadId,
|
|
5889
|
+
title: newTitle,
|
|
5890
|
+
metadata: threadForMetadata.metadata ?? {}
|
|
5891
|
+
});
|
|
5892
|
+
if (writer) {
|
|
5893
|
+
const threadUpdateMarker = createThreadUpdateMarker({
|
|
5894
|
+
cycleId,
|
|
5895
|
+
threadId,
|
|
5896
|
+
oldTitle: oldTitle ?? void 0,
|
|
5897
|
+
newTitle
|
|
5898
|
+
});
|
|
5899
|
+
await writer.custom(threadUpdateMarker).catch(() => {
|
|
5900
|
+
});
|
|
5901
|
+
}
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5762
5904
|
await this.storage.updateActiveObservations({
|
|
5763
5905
|
id: record.id,
|
|
5764
5906
|
observations: newObservations,
|
|
@@ -6002,6 +6144,7 @@ ${threadClose}`;
|
|
|
6002
6144
|
requestContext,
|
|
6003
6145
|
priorCurrentTask: threadOMMetadata?.currentTask,
|
|
6004
6146
|
priorSuggestedResponse: threadOMMetadata?.suggestedResponse,
|
|
6147
|
+
priorThreadTitle: thread?.title,
|
|
6005
6148
|
wasTruncated
|
|
6006
6149
|
}
|
|
6007
6150
|
);
|
|
@@ -6009,6 +6152,22 @@ ${threadClose}`;
|
|
|
6009
6152
|
omDebug(`[OM:doAsyncBufferedObservation] empty observations returned, skipping buffer storage`);
|
|
6010
6153
|
return;
|
|
6011
6154
|
}
|
|
6155
|
+
if (this.observationConfig.threadTitle && result.threadTitle) {
|
|
6156
|
+
const newTitle = result.threadTitle;
|
|
6157
|
+
if (newTitle.length >= 3 && newTitle !== thread?.title) {
|
|
6158
|
+
await this.storage.updateThread({ id: threadId, title: newTitle, metadata: thread?.metadata ?? {} });
|
|
6159
|
+
if (writer) {
|
|
6160
|
+
const marker = createThreadUpdateMarker({
|
|
6161
|
+
cycleId,
|
|
6162
|
+
threadId,
|
|
6163
|
+
oldTitle: thread?.title,
|
|
6164
|
+
newTitle
|
|
6165
|
+
});
|
|
6166
|
+
void writer.custom(marker).catch(() => {
|
|
6167
|
+
});
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
6170
|
+
}
|
|
6012
6171
|
let newObservations;
|
|
6013
6172
|
if (this.scope === "resource") {
|
|
6014
6173
|
newObservations = await this.wrapWithThreadTag(threadId, result.observations);
|
|
@@ -6432,7 +6591,8 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
|
|
|
6432
6591
|
threadMetadataMap.set(thread.id, {
|
|
6433
6592
|
lastObservedAt: omMetadata?.lastObservedAt,
|
|
6434
6593
|
currentTask: omMetadata?.currentTask,
|
|
6435
|
-
suggestedResponse: omMetadata?.suggestedResponse
|
|
6594
|
+
suggestedResponse: omMetadata?.suggestedResponse,
|
|
6595
|
+
threadTitle: thread.title
|
|
6436
6596
|
});
|
|
6437
6597
|
}
|
|
6438
6598
|
const messagesByThread = /* @__PURE__ */ new Map();
|
|
@@ -6585,10 +6745,11 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
|
|
|
6585
6745
|
const batchPriorMetadata = /* @__PURE__ */ new Map();
|
|
6586
6746
|
for (const threadId of batch.threadIds) {
|
|
6587
6747
|
const metadata = threadMetadataMap.get(threadId);
|
|
6588
|
-
if (metadata?.currentTask || metadata?.suggestedResponse) {
|
|
6748
|
+
if (metadata?.currentTask || metadata?.suggestedResponse || metadata?.threadTitle) {
|
|
6589
6749
|
batchPriorMetadata.set(threadId, {
|
|
6590
6750
|
currentTask: metadata.currentTask,
|
|
6591
|
-
suggestedResponse: metadata.suggestedResponse
|
|
6751
|
+
suggestedResponse: metadata.suggestedResponse,
|
|
6752
|
+
threadTitle: metadata.threadTitle
|
|
6592
6753
|
});
|
|
6593
6754
|
}
|
|
6594
6755
|
}
|
|
@@ -6646,6 +6807,13 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
|
|
|
6646
6807
|
);
|
|
6647
6808
|
const thread = await this.storage.getThreadById({ threadId });
|
|
6648
6809
|
if (thread) {
|
|
6810
|
+
let titleForUpdate = thread.title ?? "";
|
|
6811
|
+
if (this.observationConfig.threadTitle && result.threadTitle) {
|
|
6812
|
+
const newTitle = result.threadTitle.trim();
|
|
6813
|
+
if (newTitle.length >= 3 && newTitle !== thread.title) {
|
|
6814
|
+
titleForUpdate = newTitle;
|
|
6815
|
+
}
|
|
6816
|
+
}
|
|
6649
6817
|
const newMetadata = memory.setThreadOMMetadata(thread.metadata, {
|
|
6650
6818
|
lastObservedAt: threadLastObservedAt.toISOString(),
|
|
6651
6819
|
suggestedResponse: result.suggestedContinuation,
|
|
@@ -6654,7 +6822,7 @@ ${unreflectedContent}` : freshRecord.bufferedReflection;
|
|
|
6654
6822
|
});
|
|
6655
6823
|
await this.storage.updateThread({
|
|
6656
6824
|
id: threadId,
|
|
6657
|
-
title:
|
|
6825
|
+
title: titleForUpdate,
|
|
6658
6826
|
metadata: newMetadata
|
|
6659
6827
|
});
|
|
6660
6828
|
}
|
|
@@ -7127,5 +7295,5 @@ exports.getObservationsAsOf = getObservationsAsOf;
|
|
|
7127
7295
|
exports.hasCurrentTaskSection = hasCurrentTaskSection;
|
|
7128
7296
|
exports.optimizeObservationsForContext = optimizeObservationsForContext;
|
|
7129
7297
|
exports.parseObserverOutput = parseObserverOutput;
|
|
7130
|
-
//# sourceMappingURL=chunk-
|
|
7131
|
-
//# sourceMappingURL=chunk-
|
|
7298
|
+
//# sourceMappingURL=chunk-AR52LM55.cjs.map
|
|
7299
|
+
//# sourceMappingURL=chunk-AR52LM55.cjs.map
|