@@ -1059,6 +1059,93 @@ describe("AcpSessionManager turn results", () => {
10591059 expect ( states ) . not . toContain ( "error" ) ;
10601060 } ) ;
10611061
1062+ it ( "does not retry after a persistent resume wrapper with generic Internal error without SessionResumeRequiredError" , async ( ) => {
1063+ const runtimeState = createRuntime ( ) ;
1064+ hoisted . requireAcpRuntimeBackendMock . mockReturnValue ( {
1065+ id : "acpx" ,
1066+ runtime : runtimeState . runtime ,
1067+ } ) ;
1068+ const sessionKey =
1069+ "agent:kiro:acp:binding:discord:default:no-retry-generic-internal" ;
1070+ let currentMeta : SessionAcpMeta = {
1071+ ...readySessionMeta ( {
1072+ agent : "kiro" ,
1073+ } ) ,
1074+ runtimeSessionName : sessionKey ,
1075+ identity : {
1076+ state : "resolved" ,
1077+ source : "status" ,
1078+ acpxSessionId : "acpx-sid-stale" ,
1079+ lastUpdatedAt : Date . now ( ) ,
1080+ } ,
1081+ } ;
1082+ hoisted . readAcpSessionEntryMock . mockImplementation ( ( paramsUnknown : unknown ) => {
1083+ const key = ( paramsUnknown as { sessionKey ?: string } ) . sessionKey ?? sessionKey ;
1084+ return {
1085+ sessionKey : key ,
1086+ storeSessionKey : key ,
1087+ acp : currentMeta ,
1088+ } ;
1089+ } ) ;
1090+ hoisted . upsertAcpSessionMetaMock . mockImplementation ( async ( paramsUnknown : unknown ) => {
1091+ const params = paramsUnknown as {
1092+ mutate : (
1093+ current : SessionAcpMeta | undefined ,
1094+ entry : { acp ?: SessionAcpMeta } | undefined ,
1095+ ) => SessionAcpMeta | null | undefined ;
1096+ } ;
1097+ const next = params . mutate ( currentMeta , { acp : currentMeta } ) ;
1098+ if ( next ) {
1099+ currentMeta = next ;
1100+ }
1101+ return {
1102+ sessionId : "session-kiro-1" ,
1103+ updatedAt : Date . now ( ) ,
1104+ acp : currentMeta ,
1105+ } ;
1106+ } ) ;
1107+ runtimeState . ensureSession . mockImplementation ( async ( inputUnknown : unknown ) => {
1108+ const input = inputUnknown as {
1109+ sessionKey : string ;
1110+ mode : "persistent" | "oneshot" ;
1111+ resumeSessionId ?: string ;
1112+ } ;
1113+ return {
1114+ sessionKey : input . sessionKey ,
1115+ backend : "acpx" ,
1116+ runtimeSessionName : `${ input . sessionKey } :${ input . mode } :runtime` ,
1117+ backendSessionId : input . resumeSessionId ? "acpx-sid-stale" : "acpx-sid-fresh" ,
1118+ } ;
1119+ } ) ;
1120+ runtimeState . getStatus . mockResolvedValue ( {
1121+ summary : "status=alive" ,
1122+ backendSessionId : "acpx-sid-fresh" ,
1123+ details : { status : "alive" } ,
1124+ } ) ;
1125+ runtimeState . runTurn . mockImplementationOnce ( async function * ( ) {
1126+ yield {
1127+ type : "error" as const ,
1128+ code : "NO_SESSION" ,
1129+ message :
1130+ "Persistent ACP session acpx-sid-stale could not be resumed: Internal error" ,
1131+ } ;
1132+ } ) ;
1133+
1134+ const manager = new AcpSessionManager ( ) ;
1135+ const turnPromise = manager . runTurn ( {
1136+ cfg : baseCfg ,
1137+ sessionKey,
1138+ text : "do kiro work" ,
1139+ mode : "prompt" ,
1140+ requestId : "run-kiro-generic-internal" ,
1141+ } ) ;
1142+ await expect ( turnPromise ) . rejects . toMatchObject ( {
1143+ code : "ACP_TURN_FAILED" ,
1144+ } ) ;
1145+
1146+ expect ( runtimeState . prepareFreshSession ) . not . toHaveBeenCalled ( ) ;
1147+ } ) ;
1148+
10621149 it ( "retries once with a fresh persistent session after a kiro-style SessionResumeRequiredError with Internal error" , async ( ) => {
10631150 const runtimeState = createRuntime ( ) ;
10641151 hoisted . requireAcpRuntimeBackendMock . mockReturnValue ( {
0 commit comments