From c73775f19ef05b40dcb17da4fc5506960c52fe7c Mon Sep 17 00:00:00 2001 From: Owen Lin Date: Fri, 2 Oct 2026 16:45:05 +0000 Subject: [PATCH] Remove initial messages from session configuration events (#50360) ## What changed Remove `initial_messages` from `SessionConfiguredEvent` and the corresponding schema. Stop attaching replay history to startup events for resumed or rejoined threads, and remove `InitialHistory::get_event_msgs`. ## Testing Update the MCP resume test to verify persisted tool events through `load_history`, and retain coverage that resumed requests include prior conversation items. GitOrigin-RevId: 54b72bc44423c9b1ef2051891ef392c0ede32fe5 --- .../app-server-exports-stable.json.zst | Bin 157569 -> 157509 bytes .../session/extension_interruption_tests.rs | 1 - codex-rs/core/src/session/session.rs | 3 - codex-rs/core/src/thread_manager.rs | 5 +- codex-rs/core/src/thread_startup_metadata.rs | 12 +- codex-rs/core/tests/suite/client.rs | 14 +- .../core/tests/suite/mcp_turn_metadata.rs | 14 +- codex-rs/core/tests/suite/resume.rs | 145 ------------------ ...event_processor_with_human_output_tests.rs | 1 - codex-rs/exec/src/lib.rs | 1 - .../tests/event_processor_with_json_output.rs | 1 - codex-rs/history/src/lib.rs | 25 --- codex-rs/protocol/src/protocol.rs | 8 - 13 files changed, 17 insertions(+), 213 deletions(-) diff --git a/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst b/codex-rs/app-server-protocol/schema/precomputed/app-server-exports-stable.json.zst index 06c3080768a0fe35510097abd6a5c874b3629b52..04ec7af91f17bc127ae2a3b6db84b4c5ae4b2c56 100644 GIT binary patch delta 20304 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 delta 20402 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཯i!a7v}Vr;D$G;avZe`vDV9fIFR5Hn-ioRq)rSp!!YRW75b>rH8lowT6Qr{CUIQ|*DF zGI2#u526{Ju6$=k@%$GXgRW|*X4|C8MAvWkL((Z*ok~X^3vG>6aGc0WjbRS;2tJsp z`&jj8p9M9h4}C3yfPeX6NES+}D=NUKF-mSJMetoLU1*VPMkQbJnD1R4eHd;sRxFb2 zz@j+izX~;?)amfEJ;$K4&tS&ksmFD|wophx^OHZF{ZxSOkN&Ooo)%*W-14Gr0T0g< zt*ZsaeJx)>lfGyctJs5kE6kU0nGfO9`cMXlk^Do^7VaBec7K^xKU~C3vKS(!eA$hC z6%Vk~!j_e*{xFg|E!7|)c-uP{R(SD*4-Mei;HZ|K4H=P&-O^1#j6h{HH$+H(?bl)a zssH+w)vkD!UAZuTL^A~)FlI4iHaLLN;t#-a!-`mJDt5(o^Kz4^Gz!Pj=h^RI_D1+6 zjs>&GNrqX&$bW}RhGA!uzt;iNe+jO>fW=}bDL?lXh<~qSIdunqgTFmkRKs(-jwMMi zfD{&9dxIfmH!)Cb3PR||JK3|SQ8luu(YO36@+~7kAP1`79EBjrPy3p90I)#m&*=b9 z4*`Zw;(O_|qvMVJr%c!D4ErLOxi1sZUYLIj?XxYt^xG#oG1@MJM#-AdFq(IfvQzQu zF2dw}B7cm1pX-NFNIPPoDaBl0)u9pVR|#mi5ls)0F(ve3ohVaKGp-phkK(&G84BBp zU~_#NZNt|sMFGZF;z3wdRC{yW1{v!dhS0>Qc`|jLjvdHd!Z5U4P zwTn=BI(!$`G4K?IZ+q!2Onpaq3BC4Sz0S1s@cCWWbrNGZm8pS}6lCiNTCw zviDG*MEIMHz#r~AqF7R0`$uZW40E^mE9e#%s43C5RxjSj_R)Mgt*tQ+mlinStCL_P zZ(Wxv&gSHyqXIn^49;n|?{5X~L)7 z5a~6kiVF%`R$c z&DUOfB02Li!%9yLLW%im%emeptt~5_wSUquFpI88JNao@peN%06?jEu^#`b}7LFxz zEuMHU3O;Ea7jf;^oo3z_MpuNO2j-3SJhm^~d6UE>`8Z*-T*x_c@Li|LOPkzXkWPXxPJ)q)tcve5Jr)933VPPJ*Tn6)|Z3X@8haRELN>{>lFyu}QH z7Y4;t6)Jql(7Xls6|=F27)8^sg3XN-V>U|BU(4^G+gFRKyP3i1vJR!2+$ zWYFEXINeJs)@aj0AA#7G7;qk6;_=?wD`w`|t`H)2*Lx31?V8sh-l?JDFMm6a&V`^U zK+M0RQR@C>X&qxSnwmLpRfNJMZHrTq67yU54RHlj0Q)1d@(OG&i7R9n)s}$peH0%a z_91CVZJbII8B8eFDPM19ec0qzce~CL{i9M(Zh#C30_?mxc`+~+LS0sW!LAH59@|FV zGbPV34t2vS@bRe*2ckm^#eavq&`p74#6#&WjMcC$IsR${#&qh)mI@hU%g>XDS7# z@7994<)S+iO(mU-OLUxx`(aICZ6$9|CfI7qX_YkGXwCff96o%JZ}b|%iN@To3{qiv z(Co}Kso#VQk_Z@5L4TwuFWP=U{Z7|kdM`C8uFz(rsCpthJpt-hpnoS6^uVe7&%=LW z8i?kUIlc$?m=i0Qeq5j{;MHxVq?ZoecIv7R!!jm}5hpVxW(oc_CXt`5j+?68l1p8@b}%4rI;2oJHf2h7(s|6AIF@WsQwvIWP>2iX?njs>Ig!J@ot@RCG*0&mfzL$X{nAJN z5|%q@IocL6{h#Iy3Tz2i6qJg0Yh6KHAoN-SyYyEBjG9dh8w~iUm>3GOyX#vD z+|Lk7ibN;JYPNpSo-Vt;rBuR+FuiEsNegPEA# z5t2D-3`|>?J!{zI{(>BmNszP|hAOe%yiZ50(BZGsxFssNUODNzH{E$Xw#sqm@4%(m zc>!oeLMVLILBq~a26Q6oz4fnx2`(`z(bx^hB{&%*T$gN!G&&ZZs|~S~4uu{f9|%*Z zZYy}BWUcKM5r2{M0eW&SEqI6juSI5-h{RDl0KQH{c4IB=5++6DzG#V%YLkp;F@?d~ zo)#9Rcr&Q!p|v1S25(9#*xsPmE{K+c9BF9q#$GhxW~jm2x1#0X;@9BK{OlsYWE#}8 zZRi%LLCp}|9920rsO}F6Z!QP#4ysg;zI5=GyJ1wp*?+-%d0{#l4cvv$JDcjIvO%>i zV~!2?;N5)+C}?bhDq3|M3O4+~+X_fReg}j%E1)k6R}kK#b&kDx)Cl3Nh|12EU&cI{yc@)~rXSS;_wVV=H1RST1SAM??DAvFAL zE|1d27szCQgLoDf2?}n5sdq2v6Q*ZdhZl?ELQK$S5hD6DXd9-Ndd*FzRtH5c1#X)j ze_?tEUN42%4|vueb%dw5%!CF^Z-j9a6gmTQMSmc9+Yt9P^k&f4r$})?2>7QdQapXs zRBd=Ee|eOavIat4sF2kh_J(EaIT-vl`Qme5uU+zmBTsVYuGGJT{-np;;3E87q9#d> za7~Fplp+pxm0(|Rcb%74{Op%ZS$H(bqv#fuF&WgDzcuM62rVjP>ry#P49nPz&!ZaA zbbp>NoG-RgL6ku;)vQ2Mis>~vjQe?l1?^TnQOe&<3OMLn){fKoeqi`@eLe8wzUG3h zYzC@UE!7xSR^CfPluLyTM2@IG<=?6lzGr<)g=0C|$4=_f^9WJ$yU!2dqOP(=X8;fz zkr)*lzRNFiwyCfrmY{&&BqQc%L~2v4)3&+W*&){3Va0c}EMtK|iq0{TKT=0bFdQ0$^&Bl~|=%^ZoW(*au)PJxw z)e;>{pI(%vnvHe9&J-kLGjhbbmm@SNzoK5jfE8OJ0|`AnlyvfFX6Dajo&t9u;L`0BDM_D}v^tZ~nceZ- zedQi`96SwYjL>#qp^`zSo^yvTA%6<;t)MhZgsTIk{z8zV@XpY#x5{bfl%KUq!k$A??v?Cx11~Vs0=k z{~#CX%jDbG85@q7iLVrGk4PWF&>ODL#tvb-Y$6t`?m?b30_>D{!}Fe&4u#h7Ohga} zreAKpn-j6!2p}mze^oL)DFDomO_;M}!^}ZGbabXmp@yTk&}q7EJIP z7#ocdB$L78U(%hXK#GgdJb&@5y&h~k7hjuzlT!*_Z}TnAms>;Q?2?^2{@Z8;$SK}f zG^8^^K54+y?U?u#KkC`HP}2{X@RRw}+yx{n53&`io-Kh;TFc zDhER4k_I%fy(g(#Wq_~SdW4XliI3qbWamcJR71>>u`EFH=2>-5%GEfKjiX$I5CB~p zZNdCa3*ORsC0WV36Mu9m()k0RVC!HbfGs(5Lv?_~wn3xyM~HRaN49mYRsN#eC8ABc z8D=^n9Zx=9(5?DXPaSbw*0*@<_iKyJIa8g7G#Q0j>$WB<*p*4_%Yg=VM+Wz(0`hUrO2z8_;~Yq@o#yZ z&r#&vPZQoCG_%;-4n^KTBX>w>RQ9>BZwz}7J9Cxso(=%~4z$Mr=Hp`?FjX6X zWYt?rrwqfw`AFzSPTV39P3D-#qp7- z#em)|hIhwVVRN8eGB*C(UW<4G3%%Q?+vV#CjcNQ&)~xb#GG$I|vhwnd@4H$TFd~=$ zWARb_1Pd!{sJ*kkphF>nKokzHPW`jaw=az=`VHx%n17f8LXl7|j3=;Fy--GVNm43V z+kbqNj?|(0#uu;bwPXIW_X492x^n;PDm~p2wCR9(e;$15QKRy6)_9g4TNFj5rzbn9 z)T}Zlm7JZLG2iieTG2g);{Si!vV;}bQ%vjAV45a}*1x6c=$sZ$N@Sxa0 zED9L`L0}LJ1On)&*b%gJki4cOHKm^}92#`{|O!2C(lfaM%uN_|Xs2kHK{ z9mEr_7@Z{`g_IB-0-?mR^3-9r=(w%HAyeCj_#n#pXo8#Ow!o`tOn!}f|0oUy2JCT- za8$^vAg_Pn+J(fcfCt<5lT~nYKRGsk`ic9=eAC@eCeG0Jlk0m1f3nlI_oNs2lV$tI zpS*^y{K+J)&7a&r)cnaZ3G^plex^S;8j|%VV}lK$FG`)ROrCgXAS-yVRiML0EbtMi zefyJ7|G2p0brk-nE{D734XC1D=d@jLBl0C0W zenczkYKgtyT+w!NW3RE1OgQ0RxtJTe$Gfy}swi+~mPdH&ISq$O$BD}-a)27!%8Nv* z)g4|KZ%Lzn3Qo98)Hg5}4C7 z2Yr9uVmt)Y8WcWC(T-<5hWaiIuiQUb^yuzG0FVFW+jPNrCGSfTse?{804Rut{^iq& zz0wEenr_EP4fmcWLvC9_jRlC~(z1fgdk z%c1@v7leM+X&WppS>i3${d;jVC2oB0A@~1gH#VTLYnq*hhan!SZ7#3c>eJM&cXHf7e(+V@Imiq~6Z}JNCY4 zZq9$Yx6ptDMBGs1Aa5dCc&VA>_x28GK!zoCln?{vO0I7J`oW6h&sv~{jbZtXKbNS2 z$Ay=TKT}4j7WNuA8wd5;3fD)8e3@0(QroiYSbu5n2{iufS{oQbtQmi9+@XKhJ7Xv| z8Gnw#F~* z=TY1FBY-~vAn5(flL7}X3u{ew|y&P)B}up&b&{u7T_KK2hdu z6ZEa&hA@M8I*XIQ1APn8$dG@=-=E?&AB!iz)zzU#Y=m5_3RD-9M4Sqx}MV?M4wQur7*b6!d>A5u%LRuf3mt)zgdn@)kprSzf5#yN0 zx!JjOd=7e;bOezj-fQfT{+{R#49Uk3-2```_*)*h+?Z;orBALjnel(r`((q7cdceD zrwQ&QfsNo}uLD{vI~7c*^)o;V&)=&9C+X;p<|@kp2D zrEy;0da-xDXAV~11Q8v(DnL3_V@$9v$EJL9K2$D<1mtj*)3pU$Y*{-F#0_jas;#3h5GiJ>V$uSltc~GrN)7=6nwzl zKpcL_6SRMybcmkIUt3wu7$!o&d(_L7w4}GelAhl-h`%)FNpklADBTYx;Jn;x#$Kxw zFxAQ6ZU#(!P^H(frbH$Rp4=Ah3cU77H#sx^n8wT6w5y9U;{U*C1{bz=LF2849DUti zd5sg$8gyHudPRSF2?;@n{0joK36Wkvz6MvAVw=9NZ72gGsM43l~x( zTWuj#ItNnnZEFEEx;|TPlz-rJSA}LiavoR1?SF6$|Kfk@@^bJiH3Xk&5hlWFHhhq* zzvr|h*==R9&IuA@x%n7Rd$jR~(?U@ZftfYmzoAp239SJh9LisKdB7baM7U>)il-=_ z_l_xBqI|w}IPhT+<+Hf$YK)VrtSLs|o4O3E4~`7_`Irs1$t~P?sF)oCc^kh`$gey2 z@D@t4%%6Xfk$VA+YtQ#9jkj_O{np=n+-GZNF+;kxL4C`u-Wx-_ZWKQ)u4vY>P_H{HW0Gw1ZwFQhY8T}{#eB0g z*oJjJ5(CX{tvVs7#6eKIXlQ<-q{p<|+$|I&aLwXETHh&97 zOe72H7hN}3lup_CM;2K4zCPsAG@#3Ho<%H9WD`RK%Y>TIcj$71Y|s*xfai@+a2H$DN zPKx5(4Ssa165t3)1)4+h#t|uK`Q5M0mMi{GQfFYEDfrNWFW!tz$*qZwZU(Sv9YWf!`5SRKO z#F5AaWpyQ{dGFFFwW4aP4*yvEs>nm@DBJC z2_%;u*jw2&B$WK`aw00ux3u^FXgD7Z{SL%D4n&G!FXqgRs3SIpq?*7c%Y*r2M-N6N zLo{h(k)8ko#E40bpH}YD6lf#-(sYW^3mH>l8Ju4r0w|M>IA}NT+l-ZRIK2v=*RTFI$*%Uj$tiPg0NQgienc?P92IGtO*Dc zN)8y)DU9wc3~naEpYcDQ7B_!ZLesp;q97KuG=`A&CJ^xwbVy2K*NT2U4tTAOz;fy> zHTMrK2rU8#q{)ilKtO!oQsqk~ZFg9=t}d=UjXF}Lm@JEel?n?HL*ZlPUYvx8ue$nz zTF;D&s8m$tn@*5(S^1AOht~wjFVVbMJb^w~L4yD4K@g*N`=m*UIpKf9wM00e$TMcm z*#mE3@_5EBNOU~oK%}tqyj}h+(NqJ$uk$QF-A9dt<{76l*LmikX6rnk0#EBahf|w% zp25#ntn-{=_tkk8pRCn+UVf=M&x=oR&n2q!99EdA^BkfXi`046rHMMv^8!q6Svp=^ z^swBtZzrIW(7%yRUJZY!l;-cs(gnE81_8h;ro}~V=viDG%NpRQ2g?j}>Q1xoB*bVs z8@^M(Cclf8CALVpy$~3SJ~NOLuVqUbI}CbkUI>{_nFif)KM)1 z6r*P-GA7NT)O8<2nvgU!f~!(zmwyr%UCy9c&iY%U7DL2~EWm#~>AgH&12@Q#IPKp` zJLmokLM1k|aeH*?HzFQSuhO8P$bU`jkF3gQL%n!wt&ZjSVT-bGQH;v8V`F9~)TCsw zf-p&xV==6{OaioEV#TR71s%rfR7TbhN`Zm)eQLVSInxJn84~ovD8h*FAZXTcg6cwu zB9^d3kuIFmQU`w$K&A~Q&|vtN_;l$ZJ@)ET%7rGsjDIE7X9KJC@=TuVXQx}tM0^X` z)s@8}@vsX{?GhOojBz{KLV4_j5P?o&G!CDXLH}Q9{0e=W6Gc%LL5_-}id6ZSA_LUs zPKs3c@eT5T`K4%Q&>$V4TuTf3Bv-4%rI>6k7bvQ9e= z!O_Puert#)F#KCpVz?y51}m9{xCogFzjja@+Y|mZ0hTvZW*pfAQ!=M9_&*TDv+^8> z=haXOr9-IjS++f3#z+cVA`12E@>4uKt0mBL-p#$$^6;E~@3NU2$N4o*Vjm))2rw4j zfDyymfYg78RFz>Icw6-F?0uP2svtSX^MV`d;rT}8p64E(4`0$Ao{!Ew&G_&OR~Tx5a6E((9oqyek zp3)$*?#lHvAD?!476v|ITbu@)NQ5%1fKEc?j--sgoSaCW*KNe-PbuW|MJ=WN! zt;WV{A$Re@vP1^Iw~qsCsJg&1-(3dpDA^lIv3oAc2pEHPUPtYid%Pqwz=;IJY^#79 z%0#YCMc78R{^@`qSifaqjv#x*M|y6_zA??iL)%xa%9DM})^k>E`*5i86l&b)a)P7sjL8BquYb6Fv_$=VkRp1C!0 z-H%4leK1hg2+HS#X>xze;l$kfJj#Cxz}wtv%pLA48cg#?UD+`x8EDUgxMN;SF%F!n zM=#ZgKm#tp-0p6@Kg#@mf=gbo@cmxJ!N|IvM5cL-h&EG5uh) zvtmVRHsz6_kWBaml`!5k-)AicOfqwsR@~}iV{l@aGHk#sS=A9IwohRUPtAX`a1r%q zExQr}x~0b5Boh2g?02hl>vU@XzVYzF$ghCE7XGNuKKAB+nr?)~IR?Kx8QU3QcF~ns zzC?k9=l1#EA0~C;PjDHQ@P_?VOEeldP)Q)$;$Z_ij2a1xeju{K=g4Wzyo!CriK2(K3=aO0acZ9K=J|>5$5w52)aG5K>0Zi_Pjj|@sf z`?CAJVqz}F*+Fr18>nz@=I8cHc{{%1L~mR*RK5)#YwX}4&^F~oCbLqj3yd^q3kKvn z6Dk;YggL4W9cx^p1^jkPKFdBvEY|+^hj|Jc$_SU;^S+=BLo?eOsIS0x>7yO1v9|Rc( zATk6WJ`l%;1X>5+m9Bk)*rStRKfdy&+tS1@39g!<0ACFQ%v*n+WgD0y-5j%F(n)=R zP0(P?2a#AJXNU#v*5pGTxh&+(Z2r*H zt2f(%oSU@QHDQ7Mtr`X`Ikp0OPsghZg;}6{sttEzd0g_k1s2Fdjy8jBQyzIG$Ts8Q zXEabi497v~PBDMo)phY@oIqy}tOTjh5MX(&MwGBWcdh%!TKx|~cujCrn;fFWt5wAq zc6v)v42|t32?N5nDL9vE>~)JVT9v1t#MX+a5f~&&MXuPaeAHOJvM0G-b(Ktz-Ciq&o;3FjH7f0FldS_*e%0#v+RFr)qiLM6nmjF|8Z#v=+$N# z`>a*I;oG?C{Xzz(<$~vuT-5BobmsV)r9~4CxKa>2kTVIcz-W$QM>HU^5Fk%ayU&1J zVxZ`nZP?WTiNDUL-0-mh#$3!oM?FDtPatQ~uM;7dg#Q>h*HX{9vQs=N^Lim1XcE@Q z_J$RKW%qwQNWn>F%+nqFsAuVWAIT*)0{rwX7aB?;82lg5xwREj?V$L&LwJ33C4Xd~ zs3L^T40Jt&v%;;Z2-He0Am;)_Au>~&(-I1u~^Pv1A-Y)|EA1ZF* zTF&Ruj$se_|B_Un2lXEXa}My_AE|;6onp^7i9GXJaDCrtZj0>n9uIy}OJ2WTzKcqv z-^_n}q-vMn9I74`7Fr!%Z~Z&!rX9a6()P^9l{Nc>yMUqfZK1VZ6M}dqNa!hrl_Zz) ztCAmg&uJf!i4_$i;~g05@Bf-I@ACN@y1_^`|ErKwLzxhjV8QZ{ebZ#~0l4wQzLouH zibX5BCQCHENTD<>Gd{9*1Lohq>Mt~sLgs%3Q~*vN!Y;}41&X?P?`l02t<{$8ai~0O zw{TSfg16T2bP(}gH|!a~xoL@H{~z-0!YH=JMM$vc14IBqz&myZj7mHPfRTMty#<71 z|5dvLOG(qc+M^I?Jpe)Ey4If}vNT^-M)eQ!ODH>JDS`}Ls>jtBIL_U5^MAFmlzV?u zfV`H{v)G3>SncZ2M`Wjq;rBKX;4|pfMuIO?6C#qBjRxEKYA6-uZXqe_i(5u57g?86 z6AY-1AA=E?8?p~#DJkseIm6F(a-lgjqhx`T9N?P4MMN#1HG={d6J%z6LklszD^e`Y zu2Ga?!2O#W{(((dQmcQj{zx^YTY-Olm1E#pUWvF2{X|4oO{_ z1X81x8;y@^)>(Tkn@SWYpa$nuAD^s^SVy3QvIU)CCU1#C|6wMTYTcq3#rzy*hNJfZ z)&Z_c0M&i%$qAqnxuXjuR;9ZDwqs|P(oX^OH4rARntkdcloSjU2;T~-HZ)JXI~0tf>A|$Rt41Z1(;BzhT+HLMJ^})c ze@hqD834ZU*xH6cL(YT7``aZma{)HjKWLd3(REmvq!u~2k- zN2wZ&B0;-ASTHak(+kd7iKu||_v0?8d+M)8H%=$mC53ihwh0qUM8vooYB|p7kx1ea z#Ae>bK%rQ+%&VHD#Z;^w4Nd-=d4E0$9jypD){as$iVKUFvxdwWWXT}Qq;m=IzlwRs z$;X!!Q370lXolpdgB_Pml0upTLm&`HfZzZE;%F=!2}Q(%l1%FZ6M(^kqM~>dGJ?V& zAs`3{f`LFI2!bF8f}jY3APCDqBm+d^yM-}Q0m{d=ZUM?u9XS_-nv(_EANP{S9v=YO zA_!dtjcFfmhL5>I#{6X0$XTdS!R^l+gmqY|A07&ScD(x}S*-;9dKi)?AAiev;JiOn zQ>ncf9q7fFrWjtFnMgg{CA*FG^|#)#9xSS^-uy$ z*Pm8@#$ZJ0c^L1^t)qiygnb=~$u(jq9Y0km?tF76L`JSyD!{-yW0J&4K=ex^@?V=E z&8HrkjB>@P#hu3>Te@*>fiIS!xv?Q;eykZ&tYC{7Pgt#Vi`Ra!wrnarjSIv_o-%tW zCnXo-jPUduIaHF~uSh=zk3FCr&J9IN@+?Pxg0y(YBHO$RRM!t>&^``PQ@|b+GN0Oc zYQbCGEkcivqNjas;=1m$Ad~^HaE%TR2#hL-%x_2n9_&X-c4`@9LcwrcrK^5sX?E|5 zq(@+G<8IaJXh+A6##}!S;FjHe_2_hey2=BKbo@2G4s}l?N=0}yB~0|;TdZ_gLLt_F z1RbVW$Ass{Yuq-$qH=UMeqeoZUo_ZFj2;9dEpM?|007v66^#%<(CxAyJ}?zip!b7N zx)>_NP5}l`2H=nl^cE7BrH9{k4CdJ^SQac+U4*&J9aCnxGjFDL?A2|MmC@*XK~?Tg z3)`9!9re{lIZnZ>dX|I?kWeYAo~~MdS>TGK8q2bS)PaJlLdwyO1T;HnlI15IX!E4c z=bNAOMdA0PIT1&+c9+|WfZ~dk%Tp+h9N(jEe)?keKyCgsUdovypU?;*j(666=ePbCk z8fECdxw;YUYhHk`7i;mzx#b1Zbu~v4cMAf{EO5p|FLx`EU_;#X(hS~!bftA zT-Q9)WmG9k$P;#E)O3U8Q^4A(Ss&OVCt1cz|4-G+NJh`aSd+Pp6n+-}6mUFIkGwK) zW|f_uW3>dnMsVAB6P?wS^X5-~HKE27XvZ~m;4wJ1UiU5L-phlarp!m=*UT5){AgjJ zh5TBlno2ti_R3O1o63NLfZe{L*Zgz`e#;*?4N#&HE0UY|UX8Z6`;%&^4VX*4TDxD! zX}BMRWygsZpzjHX54o}eQb1APZbfyYTIH_eX|)fSusbuq9SY~V_Nfs)QT)WyOU zQAiC@NnPj*FX)mBYjX}SXwIJ&%^&n-z*#nO!{R)vByV@tm?ZYu-zp8 zY#b&~up-zvD2}o5oaA9wwKe{GDzpf^Rag1K$~a_^V=x6-6-=H{(Ly@G?gVZA8pO?u z3geWg=^0wi<%9ciYTNXG5S_FL?ah-GOuqM?tS4TtkEaOkCHw zTU*EW6~xG9gND*9vf%;n$2{XS)B|t5KYF{13B7v>w#oW`R*IoR3i9Gm{uD_; zKMD5SlSLQE`9@Meskk3Fuopje+|QcS^`f;R=D_(iu0|Zj4eXzLcV591$=BH)e4j8o4LKA{9H806MyBV|hpXK+U? zY$Zu}IZ?!6w5M}fn)3N{w@@A$$)P$;1Hf#YDHu*YP%@~4b+v>Pe^Vw?Tz*>Qpra19 zCxXR3SPw#B%K2pM#&pC3i-ki0Uc2Cv#2Zn7UB(v&Mg7-*=5qpR_gYqQQhr`|7Ku** z__w3y8lPoW=!>4Cj~W>M@~I!}M8b_!r-7CBF87m8s?Jo5*{qTx7Ve%zcx16xxT8UM zj0{4`eyf>7jm}hV8f;bCy!HQCns3W+f9Cf_Tv6u%o)2O0j)H3!NorUx2L{}2HQDa7 zq8d2pOFXOabo1(2%OF4c5-wVUIX$v3WB3%Fsk zLusP+DXa#IT=1gp8 zfauRKADR&(e`~@d+U*f)1zgKod5&WBimC|igcG-sY?k{RF_ZTg?HIf@IKlWNcI`D0 z#^a;vwb!0LBD3{-iXB%BK=#@m`LWl+pJ1B2$wO=M>+N;@*D0<$T0lHcuwQ!=2vd5= zVAO1@{R<@41V~R@+jR&2SUVf6Vc|@~zg{1Vr=$d(6*lMvIDd z4sZ|an$e#K*$NUc-j0ZHn8g`qYiN6Q_+#s%|0M=A8*J-2P947k5Nu3iogK%uTkma3 zZ>PDz=Gc=;%2O#m(mB@z4%*Spi<4)UNe2py&B^ELfdaBIi!&FCOZxpMLJWSGAIXx8 zlmUYBe|9G8G&1;1`DFgB89~4wrvV*$mu)b$=}6p-!x+p_0CheWuuF3&6njQm#JtZz zCaKvR+ZFH;Iy5cd@(fTN;FfMyjwJl|g1dBU(+=R4Vs*80 z`K^ydgN0?+;bLFV*}JpRX6?$MWI}JG-}`_Df0m!mX@(fGiwkw})-d+9Z{Ay}wEbA? zMyv|w1Nf}DwbV_n-Sd2t9l%qSO4x1zg_L+-54ii&G4Qcrysw?*_~LNE9$WKk9FW{w zT(G@}PybFi`|3}DNC`&)#=FAWy&g`_HqwXEBMkgU_uk-K6svqGZhf`@a8@-ShXPT; zfAVJ!->-)Y8egoPrJ6@doPZ8mt+c{M9XbpLW&XM?A4rGCSoJU}gQwX8&R@pLGkDG$ zJh$sge!UQTLNwWH~sM>AS2^N{`Hz3OK_Mj&~+K&{xOs}3=LdtUD6 z8qvFr(N{@h>};#0sl0~4PfJbeSH~_5e{z{9#%*2Q^HqxPPNz{zas_KZ7Jp=}9~>Xo zE5ZAJ$}JcuQ`mx3ZC7a?tdj0jq(RX~_47$5fSYpXp0SCDG31$SB2e-t1P2OmEP7>V zpZ6P^H{eimre*p50RIj31QNSVeqS7C9>2q07wZ#Qj?1cpj|)7#26nErnDPg3e?mEf zQiupYsLQN-__m$06_+M;-zRJr#?omKI}$E~0*grViT)BR1u8BBm2*srcv!~Sba4+` z{(c}`hD?tNe>EL(3>&qD2N&qJ(X6p=hJWB8?Dsab&03a$!OO}DT>Rt^X$H{SYGhkR zm`{ovKVn&XQKlVL<5XpDS@>X&f7D$94Y%*UQD{#9AAfgF2mq2iJnsXXf~D=i=ua25 z<9nWHLOLj;Rga=`^0TXPbI^|7DD&

0O6d>lTOl23_{^3=`oJp-u>y6xs@XPSWxz4(-Qu5@dsj`F}Gwn1R|ze~@hlDEW2a zuoxTQJ1LZ+$@*X39DBQzPEHsEFaz(K-mq$4h};e;S9Cah1q3Pw2BY~_QG(IWdP#b~ z*(?=bncC6RdpXrB-)rhJWZRZFbwhea!($emtzOYv8+v@{ZJh9$pssT66D0rjq)*Aq~{vie?ACX95 zdtSr}kWz9J$TO9^hNMP7?fypN?PGtVYp#7EEh^Xa zH#*v@4OWTa`SX|gh`xh^Km0?JlgQSYcAan;{LCJwPy-Y92`Hj|f1}%z{)0mWsy-aZ zp+5X_^F{;};F0q6KZzNAtrE|{mQ@HddUFA`H-z0@Q^`|3DR5<7kwM7WO=f{(nGtR` zq26@Q#DUE!YXE?QjTDZyN~d6Jq+IZX86qh*%78)kd+e0fmgDk!hs!{Y9X_3fVAY6J z3p;aY01|}(SUcasf9mAj5r$lB^A$U>v4o{u%9@m9-V>s!sUFi(HeMwe4rT*G_8Be|K}M*TYlDZT>63>S-Wg(vKQ<`ggWv;|CM5*IO zP$kHuy2Rl|@!$mFo++4MtXN2PV4kmS);T}jD#_ejJwLZTD$rb302nlM1mL~uOh3{{P^byCo+ay8O4(YKxilV+J z-JVImIiXQ&^De|EY^i(pw&WS$meZe27K!%lUgl|b!x`fzI;6HqUn#4MH-k*b z!qB#6iXZ&|V#s@@4KmDg#RVqHcSjFvAhO zuRho*e~DsO`N*RVTt_OzET;so5)x}IfPAq|S;6II5DN<`6b4x1Egb^acgO#H*IsUM zfcNuG&9;&HYRyq941X~vL(eX67yJ3Vl`cC@pp$H$7@tUvq}I3YS;M~dXz!CY7z)CY za24E)%88p_ZGgW)7NUWqhve>#tMN>A@|!{$M`?i%Onf=S3Zuk?Vu|IL6BH`>_Wax8kgjRC#0W$d1$ zf34Gu&GNZo(an<+bW}7G)JD3G*~=ib7!XLvmxo-2!`yrYP3dvgiQ~qT_r|oRq~=HQ zb5I*V2gc2f(tp!iSG^(SZb7<7{1G?+HRSDK;Sf~1=>ag!h4qutB?L8O38GyeuEvTl znb@?2-pAk$KMt^U13gF_yVm{+R))Pmf9Fl6VMkd+obq!MuzV4f$*BwM_Gvy}?o%{) zJ>NIVZtFTpytQqhVO{%~f5oFjW@)T|8}w%+paCezjjW17Kekk|To=t=zv=_{?>f_) z^`DxrGCPpOxR=W4YPNIbHrdRBa{;*aucxG7`7oo*n5;M0#SP;qMX<2HvQmqie^x?L zM$z_l(MQ|`zY4n~Nc3Hoq!gaUGQRh7&_C0xUWVMHqQ|>=D{~V%z^1_9Xqx%d!O@Q0 z6E*NDPs*c;mxA96GROTWEDpn4g1TKw9EY#-!GQE{VpQEBD(UPUD1$q^NqKGxs*?l8 zd=^Zz$|-28-u0kN=dy3U$Hai(e*&-XU$Br+>Ae8F#LS|oIP?BQ=U?4`Lhj9HwGtbM z{{0a}iNl+`-~1iw$_s?{SlXYHPi_?bm;mch85Bg@v6}HkK_$z^u{tCNRE8_1$QT_d zo@C9P@=INM=o0TMYh#KZP+do1t*YGPssiBDlEE=7qO;GWmbNL>WQmvwf4VW>OPV&- zj(k-a;QezDD7`(WC!Fj>RsB~){0pK7YKpdPPsNVCMU5RIPyqD=H|?jXJXOUk>p=#@ z0^aXClQNS$gK6a%Jn()htiW`71h7p}L)&_N(Wd6j$>bV$B4I3av4wsig_QcXODMku z7Ns(9z&t989XM=Rii4L+e{eO$7f43d6yZ}T1fMJU5w;eM;;|v-Xm)IX#Jjz`+5_zt zn+Fk*x^YJr9r=czCP~S?e2J=?#8M?<1G?8v^DIU;8Fpl?~`SaB+obh_!)3dz!p zvy>w?K+Fzg7I#fU23q8R-U^+(q5C2dfQZ?KnwFXpbjFhrLN-e5yI?`kTU=YDVhzFBH-(awP%7X zdd&0D;dw3wxEiC4r{M96?^l8hKN`&B3~j3FmO?%$TP?lB#{WzV`OpDk2&`JPly0B& z0i_kshG4CBf8$#}>(@N-I(SE9D_mTG-uc$>R+I;DG6Ak7N^BzkflVH@EnA2TKbU@y zOGZQ{^#}H|(0tZ>rhkTg5XO#!t;T2QeGCgr@v2}6OUg*?;pJe>0$A(47Y78BNcB4V zcY@+x;;F$B=^Z6KXX4)c?2>;f{5Th@syhoFQ1f#@e|=et+w`<~BXfs;)aV-@k4WYm0RJ0^E!6AQ_6zQj(nIfS0jOFA7hy2oC_`$Cv0R7eqcF zXOYjzf8n{-&!LfwC_{5iqa%!Uj{_R0X2ueaE=9|Uw@~V%5(b$k-pA4555p=!EtM|s ziEi%{IGH3z>Hx^Y_c!{c|1&@aRW*X9z!s$iSp}22mxG(mK%8-%aZ8E-w*oA;N8&NO h$>d8qg-?*hx&saLXfD?(%8lX^&^4-nL%-`{0Wf-O3}pZS diff --git a/codex-rs/core/src/session/extension_interruption_tests.rs b/codex-rs/core/src/session/extension_interruption_tests.rs index 43bade0a08..7e46b02e35 100644 --- a/codex-rs/core/src/session/extension_interruption_tests.rs +++ b/codex-rs/core/src/session/extension_interruption_tests.rs @@ -66,7 +66,6 @@ async fn interrupt_if_no_pending_input_handles_cancelled_submission() { active_permission_profile: None, cwd: turn_context.config.cwd.clone(), reasoning_effort: None, - initial_messages: None, network_proxy: None, rollout_path: None, }), diff --git a/codex-rs/core/src/session/session.rs b/codex-rs/core/src/session/session.rs index 64f93fd42b..2319e3f7ae 100644 --- a/codex-rs/core/src/session/session.rs +++ b/codex-rs/core/src/session/session.rs @@ -1857,8 +1857,6 @@ impl Session { *guard = Arc::downgrade(&sess); } // Dispatch the SessionConfiguredEvent first and then report any errors. - // If resuming, include converted initial messages in the payload so UIs can render them immediately. - let initial_messages = initial_history.get_event_msgs(); let thread_config = session_configuration.thread_config_snapshot(turn_environments.selections()); let events = std::iter::once(Event { @@ -1884,7 +1882,6 @@ impl Session { permission_profile: thread_config.permission_profile, active_permission_profile: thread_config.active_permission_profile, reasoning_effort: thread_config.reasoning_effort, - initial_messages, rollout_path, }), }) diff --git a/codex-rs/core/src/thread_manager.rs b/codex-rs/core/src/thread_manager.rs index b7d3318e28..0ebf8dacfa 100644 --- a/codex-rs/core/src/thread_manager.rs +++ b/codex-rs/core/src/thread_manager.rs @@ -2156,9 +2156,8 @@ impl ThreadManagerState { resumed.conversation_id ))); } - let session_configured = thread - .startup_metadata() - .to_session_configured_event(initial_history.get_event_msgs()); + let session_configured = + thread.startup_metadata().to_session_configured_event(); startup_state.release_membership(); if let Some(startup_guard) = startup_guard { startup_guard.disarm(); diff --git a/codex-rs/core/src/thread_startup_metadata.rs b/codex-rs/core/src/thread_startup_metadata.rs index a7f47a9f26..3e3408f2b3 100644 --- a/codex-rs/core/src/thread_startup_metadata.rs +++ b/codex-rs/core/src/thread_startup_metadata.rs @@ -1,4 +1,4 @@ -//! Retained startup metadata, separate from the replay sent in startup responses. +//! Retained startup metadata for new and resumed threads. use codex_protocol::SessionId; use codex_protocol::ThreadId; @@ -7,14 +7,13 @@ use codex_protocol::models::ActivePermissionProfile; use codex_protocol::models::PermissionProfile; use codex_protocol::openai_models::ReasoningEffort; use codex_protocol::protocol::AskForApproval; -use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::SessionConfiguredEvent; use codex_protocol::protocol::SessionNetworkProxyRuntime; use codex_protocol::protocol::ThreadSource; use codex_utils_absolute_path::AbsolutePathBuf; use std::path::PathBuf; -/// The configuration reported when a thread started, without its replay history. +/// The configuration reported when a thread started. /// Current settings are available through [`crate::CodexThread::config_snapshot`]. #[derive(Debug)] pub struct ThreadStartupMetadata { @@ -55,7 +54,6 @@ impl From<&SessionConfiguredEvent> for ThreadStartupMetadata { active_permission_profile, cwd, reasoning_effort, - initial_messages: _, network_proxy, rollout_path, } = event; @@ -82,10 +80,7 @@ impl From<&SessionConfiguredEvent> for ThreadStartupMetadata { } impl ThreadStartupMetadata { - pub(crate) fn to_session_configured_event( - &self, - initial_messages: Option>, - ) -> SessionConfiguredEvent { + pub(crate) fn to_session_configured_event(&self) -> SessionConfiguredEvent { SessionConfiguredEvent { session_id: self.session_id, thread_id: self.thread_id, @@ -102,7 +97,6 @@ impl ThreadStartupMetadata { active_permission_profile: self.active_permission_profile.clone(), cwd: self.cwd.clone(), reasoning_effort: self.reasoning_effort.clone(), - initial_messages, network_proxy: self.network_proxy.clone(), rollout_path: self.rollout_path.clone(), } diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 02b8b8acfe..16f58fb41e 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -901,7 +901,7 @@ fn non_zero_u64(value: u64) -> NonZeroU64 { } #[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn resume_includes_initial_messages_and_sends_prior_items() { +async fn resume_sends_prior_items() { skip_if_no_network!(); // Create a fake rollout session file with prior user + system + assistant messages. @@ -1016,18 +1016,8 @@ async fn resume_includes_initial_messages_and_sends_prior_items() { .await .expect("resume conversation"); let codex = test.codex.clone(); - let session_configured = test.session_configured; - // 1) Assert initial_messages only includes existing EventMsg entries; response items are not converted - let initial_msgs = session_configured - .initial_messages - .clone() - .expect("expected initial messages option for resumed session"); - let initial_json = serde_json::to_value(&initial_msgs).unwrap(); - let expected_initial_json = json!([]); - assert_eq!(initial_json, expected_initial_json); - - // 2) Submit new input; the request body must include the prior items, then initial context, then new user input. + // Submit new input; the request body must include the prior items, then initial context, then new user input. codex .start_or_steer_turn(TurnInputRequest::user_input(vec![UserInput::Text { text: "hello".into(), diff --git a/codex-rs/core/tests/suite/mcp_turn_metadata.rs b/codex-rs/core/tests/suite/mcp_turn_metadata.rs index 4fdc08065b..94b1e3c945 100644 --- a/codex-rs/core/tests/suite/mcp_turn_metadata.rs +++ b/codex-rs/core/tests/suite/mcp_turn_metadata.rs @@ -200,11 +200,17 @@ async fn mcp_app_ui_survives_tool_events_and_resume( let resumed = builder.restart(&server, &test).await?; let completed_history = resumed - .session_configured - .initial_messages - .expect("resumed history") + .codex + .load_history(/*include_archived*/ false) + .await? + .items .into_iter() - .filter(|event| matches!(event, EventMsg::McpToolCallEnd(end) if end.call_id == call_id)) + .filter_map(|item| match item { + RolloutItem::EventMsg(EventMsg::McpToolCallEnd(end)) if end.call_id == call_id => { + Some(EventMsg::McpToolCallEnd(end)) + } + _ => None, + }) .collect::>(); assert_eq!( serde_json::to_value(completed_history)?, diff --git a/codex-rs/core/tests/suite/resume.rs b/codex-rs/core/tests/suite/resume.rs index a3bdb7257a..1d3ecde41b 100644 --- a/codex-rs/core/tests/suite/resume.rs +++ b/codex-rs/core/tests/suite/resume.rs @@ -7,13 +7,10 @@ use codex_protocol::mcp::ClientMcpExtensions; use codex_protocol::protocol::EventMsg; use codex_protocol::protocol::ThreadHistoryMode; use codex_protocol::protocol::ThreadSettingsOverrides; -use codex_protocol::user_input::ByteRange; -use codex_protocol::user_input::TextElement; use codex_protocol::user_input::UserInput; use codex_thread_store::LoadThreadHistoryParams; use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; -use core_test_support::responses::ev_reasoning_item; use core_test_support::responses::ev_response_created; use core_test_support::responses::mount_sse_once; use core_test_support::responses::mount_sse_sequence; @@ -126,148 +123,6 @@ async fn resume_restores_windows_sandbox_override() -> Result<()> { Ok(()) } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> { - skip_if_no_network!(Ok(())); - - let server = start_mock_server().await; - let mut builder = test_codex(); - let initial = builder.build(&server).await?; - let codex = Arc::clone(&initial.codex); - - let initial_sse = sse(vec![ - ev_response_created("resp-initial"), - ev_assistant_message("msg-1", "Completed first turn"), - ev_completed("resp-initial"), - ]); - mount_sse_once(&server, initial_sse).await; - - let text_elements = vec![TextElement::new( - ByteRange { start: 0, end: 6 }, - Some("".into()), - )]; - - codex - .start_or_steer_turn(TurnInputRequest::user_input(vec![UserInput::Text { - text: "Record some messages".into(), - text_elements: text_elements.clone(), - }])) - .await?; - - wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; - let mut resumed = builder.restart(&server, &initial).await?; - let initial_messages = resumed - .session_configured - .initial_messages - .take() - .expect("expected initial messages to be present for resumed session"); - match initial_messages.as_slice() { - [ - EventMsg::TurnStarted(started), - EventMsg::UserMessage(first_user), - EventMsg::AgentMessage(assistant_message), - EventMsg::TokenCount(_), - EventMsg::TurnComplete(completed), - ] => { - assert_eq!(first_user.message, "Record some messages"); - assert_eq!(first_user.text_elements, text_elements); - assert_eq!(assistant_message.message, "Completed first turn"); - assert_eq!(completed.turn_id, started.turn_id); - assert_eq!( - completed.last_agent_message.as_deref(), - Some("Completed first turn") - ); - } - other => panic!("unexpected initial messages after resume: {other:#?}"), - } - - resumed.codex.flush_rollout().await?; - let mut rejoined = resumed - .thread_manager - .resume_legacy_thread_from_rollout( - resumed.config.clone(), - resumed.codex.rollout_path().expect("resumed rollout path"), - resumed.thread_manager.auth_manager(), - /*parent_trace*/ None, - ClientMcpExtensions::default(), - ) - .await?; - assert!(Arc::ptr_eq(&rejoined.thread, &resumed.codex)); - let rejoined_messages = rejoined - .session_configured - .initial_messages - .take() - .expect("rejoining a loaded thread must still provide replay messages"); - assert_eq!( - serde_json::to_value(&rejoined.session_configured)?, - serde_json::to_value(&resumed.session_configured)?, - ); - assert_eq!( - serde_json::to_value(&rejoined_messages[..initial_messages.len()])?, - serde_json::to_value(&initial_messages)?, - ); - - Ok(()) -} - -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()> { - skip_if_no_network!(Ok(())); - - let server = start_mock_server().await; - let mut builder = test_codex().with_config(|config| { - config.show_raw_agent_reasoning = true; - }); - let initial = builder.build(&server).await?; - let codex = Arc::clone(&initial.codex); - - let initial_sse = sse(vec![ - ev_response_created("resp-initial"), - ev_reasoning_item("reason-1", &["Summarized step"], &["raw detail"]), - ev_assistant_message("msg-1", "Completed reasoning turn"), - ev_completed("resp-initial"), - ]); - mount_sse_once(&server, initial_sse).await; - - codex - .start_or_steer_turn(TurnInputRequest::user_input(vec![UserInput::Text { - text: "Record reasoning messages".into(), - text_elements: Vec::new(), - }])) - .await?; - - wait_for_event(&codex, |event| matches!(event, EventMsg::TurnComplete(_))).await; - let resumed = builder.restart(&server, &initial).await?; - let initial_messages = resumed - .session_configured - .initial_messages - .expect("expected initial messages to be present for resumed session"); - match initial_messages.as_slice() { - [ - EventMsg::TurnStarted(started), - EventMsg::UserMessage(first_user), - EventMsg::AgentReasoning(reasoning), - EventMsg::AgentReasoningRawContent(raw), - EventMsg::AgentMessage(assistant_message), - EventMsg::TokenCount(_), - EventMsg::TurnComplete(completed), - ] => { - assert_eq!(first_user.message, "Record reasoning messages"); - assert_eq!(reasoning.text, "Summarized step"); - assert_eq!(raw.text, "raw detail"); - assert_eq!(assistant_message.message, "Completed reasoning turn"); - assert_eq!(completed.turn_id, started.turn_id); - assert_eq!( - completed.last_agent_message.as_deref(), - Some("Completed reasoning turn") - ); - } - other => panic!("unexpected initial messages after resume: {other:#?}"), - } - - Ok(()) -} - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn resume_switches_models_preserves_base_instructions() -> Result<()> { skip_if_no_network!(Ok(())); diff --git a/codex-rs/exec/src/event_processor_with_human_output_tests.rs b/codex-rs/exec/src/event_processor_with_human_output_tests.rs index 594e2d3bb6..eea78a58b3 100644 --- a/codex-rs/exec/src/event_processor_with_human_output_tests.rs +++ b/codex-rs/exec/src/event_processor_with_human_output_tests.rs @@ -230,7 +230,6 @@ async fn config_summary_entries_include_runtime_workspace_roots() { active_permission_profile: None, cwd, reasoning_effort: None, - initial_messages: None, network_proxy: None, rollout_path: None, }; diff --git a/codex-rs/exec/src/lib.rs b/codex-rs/exec/src/lib.rs index 22e481a890..ac3c2c6aff 100644 --- a/codex-rs/exec/src/lib.rs +++ b/codex-rs/exec/src/lib.rs @@ -1651,7 +1651,6 @@ fn session_configured_from_thread_response( active_permission_profile, cwd, reasoning_effort, - initial_messages: None, network_proxy: None, rollout_path, }) diff --git a/codex-rs/exec/tests/event_processor_with_json_output.rs b/codex-rs/exec/tests/event_processor_with_json_output.rs index 15a0015aa4..45f849c4f6 100644 --- a/codex-rs/exec/tests/event_processor_with_json_output.rs +++ b/codex-rs/exec/tests/event_processor_with_json_output.rs @@ -124,7 +124,6 @@ fn session_configured_produces_thread_started_event() { active_permission_profile: None, cwd: test_path_buf("/tmp/project").abs(), reasoning_effort: None, - initial_messages: None, network_proxy: None, rollout_path: None, }; diff --git a/codex-rs/history/src/lib.rs b/codex-rs/history/src/lib.rs index 240bd7108f..5fb8de4290 100644 --- a/codex-rs/history/src/lib.rs +++ b/codex-rs/history/src/lib.rs @@ -423,31 +423,6 @@ impl InitialHistory { } } - pub fn get_event_msgs(&self) -> Option> { - match self { - Self::New | Self::Cleared => None, - Self::Resumed(resumed) => Some( - resumed - .history - .iter() - .filter_map(|item| match item { - RolloutItem::EventMsg(event) => Some(event.clone()), - _ => None, - }) - .collect(), - ), - Self::Forked(items) => Some( - items - .iter() - .filter_map(|item| match item { - RolloutItem::EventMsg(event) => Some(event.clone()), - _ => None, - }) - .collect(), - ), - } - } - pub fn get_base_instructions(&self) -> Option { match self { Self::New | Self::Cleared => None, diff --git a/codex-rs/protocol/src/protocol.rs b/codex-rs/protocol/src/protocol.rs index abc4e90847..2ccac2bff4 100644 --- a/codex-rs/protocol/src/protocol.rs +++ b/codex-rs/protocol/src/protocol.rs @@ -4007,11 +4007,6 @@ pub struct SessionConfiguredEvent { #[serde(skip_serializing_if = "Option::is_none")] pub reasoning_effort: Option, - /// Optional initial messages (as events) for resumed sessions. - /// When present, UIs can use these to seed the history. - #[serde(skip_serializing_if = "Option::is_none")] - pub initial_messages: Option>, - /// Runtime proxy bind addresses, when the managed proxy was started for this session. #[serde(default, skip_serializing_if = "Option::is_none")] #[ts(optional)] @@ -4053,7 +4048,6 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent { active_permission_profile: Option, cwd: AbsolutePathBuf, reasoning_effort: Option, - initial_messages: Option>, network_proxy: Option, rollout_path: Option, } @@ -4086,7 +4080,6 @@ impl<'de> Deserialize<'de> for SessionConfiguredEvent { active_permission_profile: wire.active_permission_profile, cwd: wire.cwd, reasoning_effort: wire.reasoning_effort, - initial_messages: wire.initial_messages, network_proxy: wire.network_proxy, rollout_path: wire.rollout_path, }) @@ -6296,7 +6289,6 @@ mod tests { active_permission_profile: None, cwd: test_path_buf("/home/user/project").abs(), reasoning_effort: Some(ReasoningEffortConfig::default()), - initial_messages: None, network_proxy: None, rollout_path: Some(rollout_file.path().to_path_buf()), }),