@@ -1106,22 +1106,18 @@ describe("session.compaction.process", () => {
11061106 { git : true } ,
11071107 )
11081108
1109- test ( "falls back to full summary when retained tail media exceeds preserve token budget" , async ( ) => {
1110- await using tmp = await tmpdir ( { git : true } )
1111- const stub = llm ( )
1112- let captured = ""
1113- stub . push (
1114- reply ( "summary" , ( input ) => {
1115- captured = JSON . stringify ( input . messages )
1116- } ) ,
1117- )
1118- await WithInstance . provide ( {
1119- directory : tmp . path ,
1120- fn : async ( ) => {
1121- const session = await svc . create ( { } )
1122- await user ( session . id , "older" )
1123- const recent = await user ( session . id , "recent image turn" )
1124- await svc . updatePart ( {
1109+ itProcess . instance (
1110+ "falls back to full summary when retained tail media exceeds preserve token budget" ,
1111+ ( ) => {
1112+ const stub = llm ( )
1113+ let captured = ""
1114+ stub . push ( reply ( "summary" , ( input ) => ( captured = JSON . stringify ( input . messages ) ) ) )
1115+ return Effect . gen ( function * ( ) {
1116+ const ssn = yield * SessionNs . Service
1117+ const session = yield * ssn . create ( { } )
1118+ yield * createUserMessage ( session . id , "older" )
1119+ const recent = yield * createUserMessage ( session . id , "recent image turn" )
1120+ yield * ssn . updatePart ( {
11251121 id : PartID . ascending ( ) ,
11261122 messageID : recent . id ,
11271123 sessionID : session . id ,
@@ -1130,112 +1126,81 @@ describe("session.compaction.process", () => {
11301126 filename : "big.png" ,
11311127 url : `data:image/png;base64,${ "a" . repeat ( 4_000 ) } ` ,
11321128 } )
1133- await SessionCompaction . create ( {
1134- sessionID : session . id ,
1135- agent : "build" ,
1136- model : ref ,
1137- auto : false ,
1138- } )
1129+ yield * createSummaryCompaction ( session . id )
11391130
1140- const rt = liveRuntime ( stub . layer , wide ( ) , cfg ( { tail_turns : 1 , preserve_recent_tokens : 100 } ) )
1141- try {
1142- const msgs = await svc . messages ( { sessionID : session . id } )
1143- const parent = msgs . at ( - 1 ) ?. info . id
1144- expect ( parent ) . toBeTruthy ( )
1145- await rt . runPromise (
1146- SessionCompaction . Service . use ( ( svc ) =>
1147- svc . process ( {
1148- parentID : parent ! ,
1149- messages : msgs ,
1150- sessionID : session . id ,
1151- auto : false ,
1152- } ) ,
1153- ) ,
1154- )
1131+ const msgs = yield * ssn . messages ( { sessionID : session . id } )
1132+ const parent = msgs . at ( - 1 ) ?. info . id
1133+ expect ( parent ) . toBeTruthy ( )
1134+ yield * SessionCompaction . use . process ( { parentID : parent ! , messages : msgs , sessionID : session . id , auto : false } )
11551135
1156- const part = await lastCompactionPart ( session . id )
1157- expect ( part ?. type ) . toBe ( "compaction" )
1158- expect ( part ?. tail_start_id ) . toBeUndefined ( )
1159- expect ( captured ) . toContain ( "recent image turn" )
1160- expect ( captured ) . toContain ( "Attached image/png: big.png" )
1161- } finally {
1162- await rt . dispose ( )
1163- }
1164- } ,
1165- } )
1166- } )
1136+ const part = yield * readCompactionPart ( session . id )
1137+ expect ( part ?. type ) . toBe ( "compaction" )
1138+ expect ( part ?. tail_start_id ) . toBeUndefined ( )
1139+ expect ( captured ) . toContain ( "recent image turn" )
1140+ expect ( captured ) . toContain ( "Attached image/png: big.png" )
1141+ } ) . pipe (
1142+ Effect . provide (
1143+ compactionProcessLayer ( { llm : stub . layer , config : cfg ( { tail_turns : 1 , preserve_recent_tokens : 100 } ) } ) ,
1144+ ) ,
1145+ )
1146+ } ,
1147+ { git : true } ,
1148+ )
11671149
1168- test ( "retains a split turn suffix when a later message fits the preserve token budget" , async ( ) => {
1169- await using tmp = await tmpdir ( { git : true } )
1170- const stub = llm ( )
1171- let captured = ""
1172- stub . push (
1173- reply ( "summary" , ( input ) => {
1174- captured = JSON . stringify ( input . messages )
1175- } ) ,
1176- )
1177- await WithInstance . provide ( {
1178- directory : tmp . path ,
1179- fn : async ( ) => {
1180- const session = await svc . create ( { } )
1181- await user ( session . id , "older" )
1182- const recent = await user ( session . id , "recent turn" )
1183- const large = await assistant ( session . id , recent . id , tmp . path )
1184- await svc . updatePart ( {
1150+ itProcess . instance (
1151+ "retains a split turn suffix when a later message fits the preserve token budget" ,
1152+ ( ) => {
1153+ const stub = llm ( )
1154+ let captured = ""
1155+ stub . push ( reply ( "summary" , ( input ) => ( captured = JSON . stringify ( input . messages ) ) ) )
1156+ return Effect . gen ( function * ( ) {
1157+ const test = yield * TestInstance
1158+ const ssn = yield * SessionNs . Service
1159+ const session = yield * ssn . create ( { } )
1160+ yield * createUserMessage ( session . id , "older" )
1161+ const recent = yield * createUserMessage ( session . id , "recent turn" )
1162+ const large = yield * createAssistantMessage ( session . id , recent . id , test . directory )
1163+ yield * ssn . updatePart ( {
11851164 id : PartID . ascending ( ) ,
11861165 messageID : large . id ,
11871166 sessionID : session . id ,
11881167 type : "text" ,
11891168 text : "z" . repeat ( 2_000 ) ,
11901169 } )
1191- const keep = await assistant ( session . id , recent . id , tmp . path )
1192- await svc . updatePart ( {
1170+ const keep = yield * createAssistantMessage ( session . id , recent . id , test . directory )
1171+ yield * ssn . updatePart ( {
11931172 id : PartID . ascending ( ) ,
11941173 messageID : keep . id ,
11951174 sessionID : session . id ,
11961175 type : "text" ,
11971176 text : "keep tail" ,
11981177 } )
1199- await SessionCompaction . create ( {
1200- sessionID : session . id ,
1201- agent : "build" ,
1202- model : ref ,
1203- auto : false ,
1204- } )
1205-
1206- const rt = liveRuntime ( stub . layer , wide ( ) , cfg ( { tail_turns : 1 , preserve_recent_tokens : 100 } ) )
1207- try {
1208- const msgs = await svc . messages ( { sessionID : session . id } )
1209- const parent = msgs . at ( - 1 ) ?. info . id
1210- expect ( parent ) . toBeTruthy ( )
1211- await rt . runPromise (
1212- SessionCompaction . Service . use ( ( svc ) =>
1213- svc . process ( {
1214- parentID : parent ! ,
1215- messages : msgs ,
1216- sessionID : session . id ,
1217- auto : false ,
1218- } ) ,
1219- ) ,
1220- )
1178+ yield * createSummaryCompaction ( session . id )
12211179
1222- const part = await lastCompactionPart ( session . id )
1223- expect ( part ?. type ) . toBe ( "compaction" )
1224- expect ( part ?. tail_start_id ) . toBe ( keep . id )
1225- expect ( captured ) . toContain ( "zzzz" )
1226- expect ( captured ) . not . toContain ( "keep tail" )
1180+ const msgs = yield * ssn . messages ( { sessionID : session . id } )
1181+ const parent = msgs . at ( - 1 ) ?. info . id
1182+ expect ( parent ) . toBeTruthy ( )
1183+ yield * SessionCompaction . use . process ( { parentID : parent ! , messages : msgs , sessionID : session . id , auto : false } )
12271184
1228- const filtered = MessageV2 . filterCompacted ( MessageV2 . stream ( session . id ) )
1229- expect ( filtered . map ( ( msg ) => msg . info . id ) . slice ( 0 , 3 ) ) . toEqual ( [ parent ! , expect . any ( String ) , keep . id ] )
1230- expect ( filtered [ 1 ] ?. info . role ) . toBe ( "assistant" )
1231- expect ( filtered [ 1 ] ?. info . role === "assistant" ? filtered [ 1 ] . info . summary : false ) . toBe ( true )
1232- expect ( filtered . map ( ( msg ) => msg . info . id ) ) . not . toContain ( large . id )
1233- } finally {
1234- await rt . dispose ( )
1235- }
1236- } ,
1237- } )
1238- } )
1185+ const part = yield * readCompactionPart ( session . id )
1186+ expect ( part ?. type ) . toBe ( "compaction" )
1187+ expect ( part ?. tail_start_id ) . toBe ( keep . id )
1188+ expect ( captured ) . toContain ( "zzzz" )
1189+ expect ( captured ) . not . toContain ( "keep tail" )
1190+
1191+ const filtered = MessageV2 . filterCompacted ( MessageV2 . stream ( session . id ) )
1192+ expect ( filtered . map ( ( msg ) => msg . info . id ) . slice ( 0 , 3 ) ) . toEqual ( [ parent ! , expect . any ( String ) , keep . id ] )
1193+ expect ( filtered [ 1 ] ?. info . role ) . toBe ( "assistant" )
1194+ expect ( filtered [ 1 ] ?. info . role === "assistant" ? filtered [ 1 ] . info . summary : false ) . toBe ( true )
1195+ expect ( filtered . map ( ( msg ) => msg . info . id ) ) . not . toContain ( large . id )
1196+ } ) . pipe (
1197+ Effect . provide (
1198+ compactionProcessLayer ( { llm : stub . layer , config : cfg ( { tail_turns : 1 , preserve_recent_tokens : 100 } ) } ) ,
1199+ ) ,
1200+ )
1201+ } ,
1202+ { git : true } ,
1203+ )
12391204
12401205 test ( "allows plugins to disable synthetic continue prompt" , async ( ) => {
12411206 await using tmp = await tmpdir ( )
0 commit comments