@@ -1042,6 +1042,47 @@ describe('Runner.run', () => {
10421042 expect ( getFirstTextContent ( streamInput [ 0 ] ) ) . toBe ( 'Alpha' ) ;
10431043 } ) ;
10441044
1045+ it ( 'does not mutate run history when filter mutates input items' , async ( ) => {
1046+ const model = new FilterTrackingModel ( [
1047+ {
1048+ ...TEST_MODEL_RESPONSE_BASIC ,
1049+ } ,
1050+ ] ) ;
1051+ const agent = new Agent ( {
1052+ name : 'HistoryFilterAgent' ,
1053+ model,
1054+ } ) ;
1055+
1056+ const originalText = 'Top secret message' ;
1057+ const redactedText = '[redacted]' ;
1058+
1059+ const runner = new Runner ( {
1060+ callModelInputFilter : ( { modelData } ) => {
1061+ const first = modelData . input [ 0 ] ;
1062+ if (
1063+ first ?. type === 'message' &&
1064+ Array . isArray ( first . content ) &&
1065+ first . content . length > 0
1066+ ) {
1067+ const firstChunk = first . content [ 0 ] as { text ?: string } ;
1068+ if ( firstChunk ) {
1069+ firstChunk . text = redactedText ;
1070+ }
1071+ }
1072+ return modelData ;
1073+ } ,
1074+ } ) ;
1075+
1076+ const result = await runner . run ( agent , [ user ( originalText ) ] ) ;
1077+
1078+ const sentInput = model . lastRequest ?. input as AgentInputItem [ ] ;
1079+ expect ( Array . isArray ( sentInput ) ) . toBe ( true ) ;
1080+ expect ( getFirstTextContent ( sentInput [ 0 ] ) ) . toBe ( redactedText ) ;
1081+
1082+ const history = result . history ;
1083+ expect ( getFirstTextContent ( history [ 0 ] ) ) . toBe ( originalText ) ;
1084+ } ) ;
1085+
10451086 it ( 'throws when filter returns invalid data' , async ( ) => {
10461087 const model = new FilterTrackingModel ( [
10471088 {
0 commit comments