@@ -290,6 +290,27 @@ describe("active-memory plugin", () => {
290290 ( result as { prependContext ?: unknown } | undefined ) ?. prependContext ,
291291 "expected prependContext" ,
292292 ) ;
293+ const runRecallWithSummary = async ( params : {
294+ prompt : string ;
295+ summary : string ;
296+ memoryText ?: string ;
297+ } ) : Promise < string > => {
298+ runEmbeddedAgent . mockImplementationOnce ( async ( runParams : { sessionFile : string } ) => {
299+ await writeUsableMemoryTranscript ( runParams . sessionFile , params . memoryText ?? params . summary ) ;
300+ return { payloads : [ { text : params . summary } ] } ;
301+ } ) ;
302+ return requirePrependContext (
303+ await hooks . before_prompt_build (
304+ { prompt : params . prompt , messages : [ ] } ,
305+ {
306+ agentId : "main" ,
307+ trigger : "user" ,
308+ sessionKey : "agent:main:main" ,
309+ messageProvider : "webchat" ,
310+ } ,
311+ ) ,
312+ ) ;
313+ } ;
293314 const expectPrependContextContains = ( result : unknown , text : string ) => {
294315 expect ( requirePrependContext ( result ) ) . toContain ( text ) ;
295316 } ;
@@ -5335,34 +5356,45 @@ describe("active-memory plugin", () => {
53355356 maxSummaryChars : 40 ,
53365357 } ;
53375358 plugin . register ( api as unknown as OpenClawPluginApi ) ;
5338- runEmbeddedAgent . mockImplementationOnce ( async ( params : { sessionFile : string } ) => {
5339- await writeUsableMemoryTranscript ( params . sessionFile , "alpha beta gamma" ) ;
5340- return {
5341- payloads : [
5342- {
5343- text : "alpha beta gamma delta epsilon zetalongword" ,
5344- } ,
5345- ] ,
5346- } ;
5359+ const prependContext = await runRecallWithSummary ( {
5360+ prompt : "what wings should i order? word-boundary-truncation-40" ,
5361+ summary : "alpha beta gamma delta epsilon zetalongword" ,
5362+ memoryText : "alpha beta gamma" ,
53475363 } ) ;
5348-
5349- const result = await hooks . before_prompt_build (
5350- { prompt : "what wings should i order? word-boundary-truncation-40" , messages : [ ] } ,
5351- {
5352- agentId : "main" ,
5353- trigger : "user" ,
5354- sessionKey : "agent:main:main" ,
5355- messageProvider : "webchat" ,
5356- } ,
5357- ) ;
5358-
5359- const prependContext = requirePrependContext ( result ) ;
53605364 expect ( prependContext ) . toContain ( "alpha beta gamma" ) ;
53615365 expect ( prependContext ) . toContain ( "alpha beta gamma delta epsilon…" ) ;
53625366 expect ( prependContext ) . not . toContain ( "zetalo" ) ;
53635367 expect ( prependContext ) . not . toContain ( "zetalongword" ) ;
53645368 } ) ;
53655369
5370+ it . each ( [
5371+ {
5372+ name : "split surrogate" ,
5373+ summary : `${ "a" . repeat ( 38 ) } 🎉TAILWORD` ,
5374+ expected : `${ "a" . repeat ( 38 ) } …` ,
5375+ } ,
5376+ {
5377+ name : "whitespace before a split surrogate" ,
5378+ summary : `alpha beta ${ "c" . repeat ( 26 ) } 🎉TAILWORD` ,
5379+ expected : `alpha beta ${ "c" . repeat ( 26 ) } …` ,
5380+ } ,
5381+ ] ) ( "keeps $name truncation UTF-16 safe" , async ( { name, summary, expected } ) => {
5382+ api . pluginConfig = {
5383+ agents : [ "main" ] ,
5384+ maxSummaryChars : 40 ,
5385+ } ;
5386+ plugin . register ( api as unknown as OpenClawPluginApi ) ;
5387+
5388+ const prependContext = await runRecallWithSummary ( {
5389+ prompt : `recall summary boundary: ${ name } ` ,
5390+ summary,
5391+ memoryText : expected ,
5392+ } ) ;
5393+
5394+ expect ( prependContext ) . toContain ( expected ) ;
5395+ expect ( prependContext ) . not . toContain ( "TAILWORD" ) ;
5396+ } ) ;
5397+
53665398 it ( "asks recall subagents to mark mutable operational facts stale unless source status is current" , async ( ) => {
53675399 await hooks . before_prompt_build (
53685400 { prompt : "is autonomous pickup running?" , messages : [ ] } ,
0 commit comments