1+ use chrono:: Local ;
12use os_info:: Type as OsType ;
23use os_info:: Version ;
34use serde:: Deserialize ;
@@ -40,6 +41,7 @@ pub(crate) struct EnvironmentContext {
4041 pub operating_system : Option < OperatingSystemInfo > ,
4142 pub common_tools : Option < Vec < String > > ,
4243 pub shell : Option < Shell > ,
44+ pub current_date : Option < String > ,
4345}
4446
4547#[ derive( Debug , Clone , Serialize , Deserialize , PartialEq , Eq ) ]
@@ -152,6 +154,7 @@ impl EnvironmentContext {
152154 operating_system : detect_operating_system_info ( ) ,
153155 common_tools : detect_common_tools ( ) ,
154156 shell,
157+ current_date : Some ( Local :: now ( ) . format ( "%Y-%m-%d" ) . to_string ( ) ) ,
155158 }
156159 }
157160
@@ -168,6 +171,7 @@ impl EnvironmentContext {
168171 writable_roots,
169172 operating_system,
170173 common_tools,
174+ current_date,
171175 // should compare all fields except shell
172176 shell : _,
173177 } = other;
@@ -179,6 +183,7 @@ impl EnvironmentContext {
179183 && self . writable_roots == * writable_roots
180184 && self . operating_system == * operating_system
181185 && self . common_tools == * common_tools
186+ && self . current_date == * current_date
182187 }
183188}
184189
@@ -256,6 +261,9 @@ impl EnvironmentContext {
256261 lines. push ( " </common_tools>" . to_string ( ) ) ;
257262 }
258263 }
264+ if let Some ( current_date) = self . current_date {
265+ lines. push ( format ! ( " <current_date>{current_date}</current_date>" ) ) ;
266+ }
259267 if let Some ( shell) = self . shell
260268 && let Some ( shell_name) = shell. name ( )
261269 {
@@ -852,6 +860,7 @@ mod tests {
852860 ) ;
853861 context. operating_system = None ;
854862 context. common_tools = None ;
863+ context. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
855864
856865 let expected = r#"<environment_context>
857866 <cwd>/repo</cwd>
@@ -862,6 +871,7 @@ mod tests {
862871 <root>/repo</root>
863872 <root>/tmp</root>
864873 </writable_roots>
874+ <current_date>2025-01-02</current_date>
865875</environment_context>"# ;
866876
867877 assert_eq ! ( context. serialize_to_xml( ) , expected) ;
@@ -877,11 +887,13 @@ mod tests {
877887 ) ;
878888 context. operating_system = None ;
879889 context. common_tools = None ;
890+ context. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
880891
881892 let expected = r#"<environment_context>
882893 <approval_policy>never</approval_policy>
883894 <sandbox_mode>read-only</sandbox_mode>
884895 <network_access>restricted</network_access>
896+ <current_date>2025-01-02</current_date>
885897</environment_context>"# ;
886898
887899 assert_eq ! ( context. serialize_to_xml( ) , expected) ;
@@ -897,11 +909,13 @@ mod tests {
897909 ) ;
898910 context. operating_system = None ;
899911 context. common_tools = None ;
912+ context. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
900913
901914 let expected = r#"<environment_context>
902915 <approval_policy>on-failure</approval_policy>
903916 <sandbox_mode>danger-full-access</sandbox_mode>
904917 <network_access>enabled</network_access>
918+ <current_date>2025-01-02</current_date>
905919</environment_context>"# ;
906920
907921 assert_eq ! ( context. serialize_to_xml( ) , expected) ;
@@ -921,6 +935,7 @@ mod tests {
921935 architecture : Some ( "aarch64" . to_string ( ) ) ,
922936 } ) ;
923937 context. common_tools = Some ( vec ! [ "rg" . to_string( ) , "git" . to_string( ) ] ) ;
938+ context. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
924939
925940 let xml = context. serialize_to_xml ( ) ;
926941 assert ! ( xml. contains( "<operating_system>" ) ) ;
@@ -930,6 +945,7 @@ mod tests {
930945 assert ! ( xml. contains( "<common_tools>" ) ) ;
931946 assert ! ( xml. contains( "<tool>rg</tool>" ) ) ;
932947 assert ! ( xml. contains( "<tool>git</tool>" ) ) ;
948+ assert ! ( xml. contains( "<current_date>2025-01-02</current_date>" ) ) ;
933949 }
934950
935951 fn message_text ( item : & ResponseItem ) -> & str {
@@ -1026,6 +1042,12 @@ mod tests {
10261042 Some ( workspace_write_policy ( vec ! [ "/repo" ] , true ) ) ,
10271043 None ,
10281044 ) ;
1045+ // ensure current_date doesn't influence this comparison
1046+ let fixed_date = Some ( "2025-01-02" . to_string ( ) ) ;
1047+ let mut context1 = context1;
1048+ context1. current_date = fixed_date. clone ( ) ;
1049+ let mut context2 = context2;
1050+ context2. current_date = fixed_date;
10291051 assert ! ( !context1. equals_except_shell( & context2) ) ;
10301052 }
10311053
@@ -1043,6 +1065,10 @@ mod tests {
10431065 Some ( SandboxPolicy :: new_workspace_write_policy ( ) ) ,
10441066 None ,
10451067 ) ;
1068+ let mut context1 = context1;
1069+ context1. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
1070+ let mut context2 = context2;
1071+ context2. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
10461072
10471073 assert ! ( !context1. equals_except_shell( & context2) ) ;
10481074 }
@@ -1061,6 +1087,10 @@ mod tests {
10611087 Some ( workspace_write_policy ( vec ! [ "/repo" , "/tmp" ] , true ) ) ,
10621088 None ,
10631089 ) ;
1090+ let mut context1 = context1;
1091+ context1. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
1092+ let mut context2 = context2;
1093+ context2. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
10641094
10651095 assert ! ( !context1. equals_except_shell( & context2) ) ;
10661096 }
@@ -1110,6 +1140,10 @@ mod tests {
11101140 zshrc_path : "/home/user/.zshrc" . into ( ) ,
11111141 } ) ) ,
11121142 ) ;
1143+ let mut context1 = context1;
1144+ context1. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
1145+ let mut context2 = context2;
1146+ context2. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
11131147
11141148 assert ! ( context1. equals_except_shell( & context2) ) ;
11151149 }
@@ -1193,4 +1227,24 @@ mod tests {
11931227 let second = tracker. observe ( snapshot) ;
11941228 assert ! ( second. is_none( ) , "unchanged snapshot should not emit" ) ;
11951229 }
1230+
1231+ #[ test]
1232+ fn serialize_environment_context_includes_current_date ( ) {
1233+ let mut context = EnvironmentContext :: new ( None , None , None , None ) ;
1234+ context. current_date = Some ( "2025-01-02" . to_string ( ) ) ;
1235+
1236+ let xml = context. serialize_to_xml ( ) ;
1237+ assert ! ( xml. contains( "<current_date>2025-01-02</current_date>" ) ) ;
1238+ }
1239+
1240+ #[ test]
1241+ fn current_date_format_is_iso8601 ( ) {
1242+ let context = EnvironmentContext :: new ( None , None , None , None ) ;
1243+ let date = context
1244+ . current_date
1245+ . expect ( "current_date should be populated" ) ;
1246+ assert_eq ! ( date. len( ) , 10 ) ;
1247+ assert_eq ! ( date. chars( ) . nth( 4 ) , Some ( '-' ) ) ;
1248+ assert_eq ! ( date. chars( ) . nth( 7 ) , Some ( '-' ) ) ;
1249+ }
11961250}
0 commit comments