@@ -40,24 +40,28 @@ function latestDeliveryRequest(): DeliveryRequest {
4040 return request as DeliveryRequest ;
4141}
4242
43+ function makeIsolatedLastTargetConfig ( tmpDir : string , storePath : string ) : OpenClawConfig {
44+ return {
45+ agents : {
46+ list : [ { id : "main" , default : true } ] ,
47+ defaults : {
48+ workspace : tmpDir ,
49+ heartbeat : {
50+ every : "5m" ,
51+ target : "last" ,
52+ isolatedSession : true ,
53+ } ,
54+ } ,
55+ } ,
56+ channels : { whatsapp : { allowFrom : [ "*" ] } } ,
57+ session : { store : storePath } ,
58+ } ;
59+ }
60+
4361describe ( "runHeartbeatOnce - isolated heartbeat outbound session mirror" , ( ) => {
4462 it ( "uses the isolated run key for outbound delivery while base session owns target and state" , async ( ) => {
4563 await withTempHeartbeatSandbox ( async ( { tmpDir, storePath, replySpy } ) => {
46- const cfg : OpenClawConfig = {
47- agents : {
48- list : [ { id : "main" , default : true } ] ,
49- defaults : {
50- workspace : tmpDir ,
51- heartbeat : {
52- every : "5m" ,
53- target : "last" ,
54- isolatedSession : true ,
55- } ,
56- } ,
57- } ,
58- channels : { whatsapp : { allowFrom : [ "*" ] } } ,
59- session : { store : storePath } ,
60- } ;
64+ const cfg = makeIsolatedLastTargetConfig ( tmpDir , storePath ) ;
6165 const baseSessionKey = resolveMainSessionKey ( cfg ) ;
6266 const isolatedSessionKey = `${ baseSessionKey } :heartbeat` ;
6367 const nowMs = Date . now ( ) ;
@@ -123,4 +127,52 @@ describe("runHeartbeatOnce - isolated heartbeat outbound session mirror", () =>
123127 expect ( store [ isolatedSessionKey ] ?. lastHeartbeatText ) . toBeUndefined ( ) ;
124128 } ) ;
125129 } ) ;
130+
131+ it ( "keeps the base policy key when wake re-entry starts from the isolated key" , async ( ) => {
132+ await withTempHeartbeatSandbox ( async ( { tmpDir, storePath, replySpy } ) => {
133+ const cfg = makeIsolatedLastTargetConfig ( tmpDir , storePath ) ;
134+ const baseSessionKey = resolveMainSessionKey ( cfg ) ;
135+ const isolatedSessionKey = `${ baseSessionKey } :heartbeat` ;
136+ const nowMs = Date . now ( ) ;
137+
138+ await fs . writeFile (
139+ storePath ,
140+ JSON . stringify ( {
141+ [ isolatedSessionKey ] : {
142+ sessionId : "isolated-session" ,
143+ updatedAt : nowMs - 1_000 ,
144+ lastChannel : "whatsapp" ,
145+ lastProvider : "whatsapp" ,
146+ lastTo : "+15551234567" ,
147+ heartbeatIsolatedBaseSessionKey : baseSessionKey ,
148+ } ,
149+ } ) ,
150+ "utf-8" ,
151+ ) ;
152+ replySpy . mockResolvedValueOnce ( { text : "Wake result needs attention." } ) ;
153+
154+ const result = await runHeartbeatOnce ( {
155+ cfg,
156+ sessionKey : isolatedSessionKey ,
157+ deps : {
158+ getReplyFromConfig : replySpy ,
159+ getQueueSize : ( ) => 0 ,
160+ nowMs : ( ) => nowMs ,
161+ } ,
162+ } ) ;
163+
164+ expect ( result . status ) . toBe ( "ran" ) ;
165+ expect ( replySpy . mock . calls [ 0 ] ?. [ 0 ] ) . toMatchObject ( {
166+ SessionKey : isolatedSessionKey ,
167+ } ) ;
168+ expect ( latestDeliveryRequest ( ) ) . toMatchObject ( {
169+ channel : "whatsapp" ,
170+ to : "+15551234567" ,
171+ session : {
172+ key : isolatedSessionKey ,
173+ policyKey : baseSessionKey ,
174+ } ,
175+ } ) ;
176+ } ) ;
177+ } ) ;
126178} ) ;
0 commit comments