@@ -1593,6 +1593,7 @@ describe("runPreparedReply media-only handling", () => {
15931593 it ( "queues active room events as followups instead of steering fake prompts" , async ( ) => {
15941594 const queueSettings = await import ( "./queue/settings-runtime.js" ) ;
15951595 const piRuntime = await import ( "../../agents/pi-embedded.runtime.js" ) ;
1596+ const abortController = new AbortController ( ) ;
15961597 vi . mocked ( queueSettings . resolveQueueSettings ) . mockReturnValueOnce ( {
15971598 mode : "steer" ,
15981599 debounceMs : 500 ,
@@ -1610,6 +1611,7 @@ describe("runPreparedReply media-only handling", () => {
16101611
16111612 await runPreparedReply (
16121613 baseParams ( {
1614+ opts : { abortSignal : abortController . signal } ,
16131615 ctx : {
16141616 Body : "ambient" ,
16151617 RawBody : "ambient" ,
@@ -1638,9 +1640,58 @@ describe("runPreparedReply media-only handling", () => {
16381640 expect ( call . resolvedQueue . mode ) . toBe ( "steer" ) ;
16391641 expect ( call . followupRun . prompt ) . toBe ( "[OpenClaw room event]" ) ;
16401642 expect ( call . followupRun . currentInboundEventKind ) . toBe ( "room_event" ) ;
1643+ expect ( call . followupRun . abortSignal ) . toBe ( abortController . signal ) ;
16411644 expect ( call . followupRun . currentInboundContext ?. text ) . toContain ( "Current event:" ) ;
16421645 } ) ;
16431646
1647+ it ( "detaches queued user requests from superseded source abort signals" , async ( ) => {
1648+ const queueSettings = await import ( "./queue/settings-runtime.js" ) ;
1649+ const piRuntime = await import ( "../../agents/pi-embedded.runtime.js" ) ;
1650+ const abortController = new AbortController ( ) ;
1651+ vi . mocked ( queueSettings . resolveQueueSettings ) . mockReturnValueOnce ( {
1652+ mode : "collect" ,
1653+ debounceMs : 500 ,
1654+ cap : 20 ,
1655+ dropPolicy : "summarize" ,
1656+ } ) ;
1657+ vi . mocked ( piRuntime . resolveActiveEmbeddedRunSessionId )
1658+ . mockReturnValueOnce ( "active-session" )
1659+ . mockReturnValueOnce ( "active-session" ) ;
1660+ vi . mocked ( piRuntime . isEmbeddedPiRunActive ) . mockReturnValueOnce ( true ) ;
1661+ vi . mocked ( piRuntime . isEmbeddedPiRunStreaming ) . mockReturnValueOnce ( true ) ;
1662+ vi . mocked ( buildInboundUserContextPrefix ) . mockReturnValueOnce ( "user request context" ) ;
1663+
1664+ await runPreparedReply (
1665+ baseParams ( {
1666+ opts : { abortSignal : abortController . signal } ,
1667+ ctx : {
1668+ Body : "@bot keep this" ,
1669+ RawBody : "@bot keep this" ,
1670+ CommandBody : "@bot keep this" ,
1671+ Provider : "telegram" ,
1672+ Surface : "telegram" ,
1673+ ChatType : "group" ,
1674+ } ,
1675+ sessionCtx : {
1676+ Body : "@bot keep this" ,
1677+ BodyStripped : "@bot keep this" ,
1678+ Provider : "telegram" ,
1679+ Surface : "telegram" ,
1680+ ChatType : "group" ,
1681+ InboundEventKind : "user_request" ,
1682+ MessageSid : "994" ,
1683+ SenderName : "Alice" ,
1684+ } ,
1685+ } ) ,
1686+ ) ;
1687+
1688+ const call = requireLastRunReplyAgentCall ( ) ;
1689+ expect ( call . shouldFollowup ) . toBe ( true ) ;
1690+ expect ( call . isActive ) . toBe ( true ) ;
1691+ expect ( call . followupRun . currentInboundEventKind ) . toBe ( "user_request" ) ;
1692+ expect ( call . followupRun . abortSignal ) . toBeUndefined ( ) ;
1693+ } ) ;
1694+
16441695 it ( "queues active room events instead of interrupting active user requests" , async ( ) => {
16451696 const queueSettings = await import ( "./queue/settings-runtime.js" ) ;
16461697 const piRuntime = await import ( "../../agents/pi-embedded.runtime.js" ) ;
0 commit comments