@@ -864,6 +864,66 @@ it('rejects an already-aborted tool call without invoking the MCP SDK', async ()
864864 }
865865} , 30_000 ) ;
866866
867+ it ( 'rejects a tool call aborted while its epoch availability probe is pending' , async ( ) => {
868+ const root = await mkdtemp ( join ( tmpdir ( ) , 'agent-bundle-persistent-mcp-probe-abort-' ) ) ;
869+ const pluginData = await mkdtemp ( join ( tmpdir ( ) , 'agent-bundle-persistent-mcp-probe-abort-data-' ) ) ;
870+ try {
871+ let allowProbe : ( ( ) => void ) | undefined ;
872+ const probeBlocked = new Promise < void > ( ( resolvePromise ) => {
873+ allowProbe = resolvePromise ;
874+ } ) ;
875+ let probeStarted : ( ( ) => void ) | undefined ;
876+ const probeStartedPromise = new Promise < void > ( ( resolvePromise ) => {
877+ probeStarted = resolvePromise ;
878+ } ) ;
879+ let calls = 0 ;
880+ const session = new McpSession ( {
881+ assertEpochAvailable : async ( ) => {
882+ probeStarted ?.( ) ;
883+ await probeBlocked ;
884+ } ,
885+ binding : { epochId : 'epoch-probe-abort' , serverName : 'fixture' , target : 'portable' } ,
886+ createClient : ( ) => ( {
887+ callTool : async ( ) => {
888+ calls += 1 ;
889+ return { content : [ ] } ;
890+ } ,
891+ close : async ( ) => undefined ,
892+ connect : async ( ) => undefined ,
893+ ...mcpCatalogStub ( ) ,
894+ } ) ,
895+ createStdioTransport : ( ) => stdioTransportStub ( ) as never ,
896+ createStreamableHttpTransport : ( ) => ( { } ) as never ,
897+ epochReference : { close : async ( ) => undefined , root } as never ,
898+ id : 'session-probe-abort' ,
899+ onClose : ( ) => undefined ,
900+ pluginData,
901+ resolved : {
902+ runtime : runtimeFor ( 'portable' ) ,
903+ server : { args : [ ] , command : 'node' , kind : 'stdio' } ,
904+ target : 'portable' ,
905+ targetRoot : root ,
906+ } ,
907+ workspaceRoot : root ,
908+ } ) ;
909+ await session . initialize ( ) ;
910+ const aborted = new AbortController ( ) ;
911+ const reason = new Error ( 'cancelled during epoch probe' ) ;
912+
913+ const pending = session . callTool ( { arguments : { } , name : 'fixture' , signal : aborted . signal } ) ;
914+ await probeStartedPromise ;
915+ aborted . abort ( reason ) ;
916+ allowProbe ?.( ) ;
917+
918+ await expect ( pending ) . rejects . toBe ( reason ) ;
919+ expect ( calls ) . toBe ( 0 ) ;
920+ await session . close ( ) ;
921+ } finally {
922+ await rm ( root , { force : true , recursive : true } ) ;
923+ await rm ( pluginData , { force : true , recursive : true } ) ;
924+ }
925+ } , 30_000 ) ;
926+
867927it ( 'bounds frame and event retention with an explicit replay overflow cursor' , async ( ) => {
868928 const root = await mkdtemp ( join ( tmpdir ( ) , 'agent-bundle-persistent-mcp-retention-' ) ) ;
869929 try {
0 commit comments