@@ -20,15 +20,16 @@ class ExploreTrajectoryBlockTaxonomy(str, enum.Enum):
2020 THINKING_RECALL = "thinking_recall"
2121 THINKING_UNDERSTAND = "thinking_understand"
2222 THINKING_HYPOTHESIZE = "thinking_hypothesize"
23- THINKING_DIAGNOSE = "thinking_diagnose "
23+ THINKING_CORRECTION = "thinking_correction "
2424
2525
2626class ImplementTrajectoryBlockTaxonomy (str , enum .Enum ):
2727 IMPLEMENTING = "implementing"
28+ IMPLEMENTING_CORRECTION = "implementing_correction"
2829 WRITING_TESTS = "writing_tests"
2930 TESTING_PUBLIC = "testing_public"
3031 TESTING_CUSTOM = "testing_custom"
31- TESTING_CUSTOM_EDGE_CASES = "testing_custom_edge_cases "
32+ TESTING_EDGE_CASES = "testing_edge_cases "
3233 DEBUGGING = "debugging"
3334
3435
@@ -84,8 +85,12 @@ def _drop_bad_elements(cls, data):
8485 return data
8586 data = dict (data )
8687 data ["summary" ] = str (data .get ("summary" ) or "" )
87- data ["highlights" ] = [h for h in (data .get ("highlights" ) or []) if isinstance (h , dict )]
88- data ["components" ] = [c for c in (data .get ("components" ) or []) if isinstance (c , dict )]
88+ data ["highlights" ] = [
89+ h for h in (data .get ("highlights" ) or []) if isinstance (h , dict )
90+ ]
91+ data ["components" ] = [
92+ c for c in (data .get ("components" ) or []) if isinstance (c , dict )
93+ ]
8994 return data
9095
9196
@@ -134,7 +139,9 @@ class TrajectoryBlock(Block):
134139
135140 output_schema = TrajectoryOutput
136141
137- def __init__ (self , trajectory_input : TrajectoryInput , * , instructions_template : str ) -> None :
142+ def __init__ (
143+ self , trajectory_input : TrajectoryInput , * , instructions_template : str
144+ ) -> None :
138145 self .trajectory_input = trajectory_input
139146 self ._instructions_template = instructions_template
140147
@@ -143,37 +150,66 @@ def sections(self) -> list[dict]:
143150 ti = self .trajectory_input
144151 taxonomy_values = [m .value for m in TrajectoryBlockTaxonomy ]
145152 return [
146- {"name" : "preamble" , "raw_input" : {}, "schema" : _PreambleIn ,
147- "formatter" : lambda _d : tp .PREAMBLE },
148- {"name" : "task" ,
149- "raw_input" : {"task_name" : ti .task_name , "instruction" : ti .instruction },
150- "schema" : _TaskIn , "formatter" : self ._fmt_task },
151- {"name" : "outcome" ,
152- "raw_input" : {"final_reward" : ti .final_reward , "model_used" : ti .model_used ,
153- "verifier_output" : ti .verifier_output },
154- "schema" : _OutcomeIn , "formatter" : self ._fmt_outcome },
155- {"name" : "instructions" , "raw_input" : {}, "schema" : _InstructionsIn ,
156- "formatter" : lambda _d : tp .instructions_section (
157- self ._instructions_template , taxonomy_values )},
158- {"name" : "trajectory" , "raw_input" : {"trajectory" : ti .trajectory },
159- "schema" : _TrajectoryIn , "formatter" : self ._fmt_trajectory },
153+ {
154+ "name" : "preamble" ,
155+ "raw_input" : {},
156+ "schema" : _PreambleIn ,
157+ "formatter" : lambda _d : tp .PREAMBLE ,
158+ },
159+ {
160+ "name" : "task" ,
161+ "raw_input" : {"task_name" : ti .task_name , "instruction" : ti .instruction },
162+ "schema" : _TaskIn ,
163+ "formatter" : self ._fmt_task ,
164+ },
165+ {
166+ "name" : "outcome" ,
167+ "raw_input" : {
168+ "final_reward" : ti .final_reward ,
169+ "model_used" : ti .model_used ,
170+ "verifier_output" : ti .verifier_output ,
171+ },
172+ "schema" : _OutcomeIn ,
173+ "formatter" : self ._fmt_outcome ,
174+ },
175+ {
176+ "name" : "instructions" ,
177+ "raw_input" : {},
178+ "schema" : _InstructionsIn ,
179+ "formatter" : lambda _d : tp .instructions_section (
180+ self ._instructions_template , taxonomy_values
181+ ),
182+ },
183+ {
184+ "name" : "trajectory" ,
185+ "raw_input" : {"trajectory" : ti .trajectory },
186+ "schema" : _TrajectoryIn ,
187+ "formatter" : self ._fmt_trajectory ,
188+ },
160189 ]
161190
162191 @staticmethod
163192 def _fmt_task (d : _TaskIn ) -> str :
164- instruction = _truncate (d .instruction ) if d .instruction is not None else "[unavailable]"
193+ instruction = (
194+ _truncate (d .instruction ) if d .instruction is not None else "[unavailable]"
195+ )
165196 return tp .task_section (d .task_name , instruction )
166197
167198 @staticmethod
168199 def _fmt_outcome (d : _OutcomeIn ) -> str :
169200 reward = f"{ d .final_reward } " if d .final_reward is not None else "[unavailable]"
170- verifier = _truncate (d .verifier_output ) if d .verifier_output is not None else "[unavailable]"
201+ verifier = (
202+ _truncate (d .verifier_output )
203+ if d .verifier_output is not None
204+ else "[unavailable]"
205+ )
171206 model = d .model_used or "[unavailable]"
172207 return tp .outcome_section (reward , verifier , model )
173208
174209 @staticmethod
175210 def _fmt_trajectory (d : _TrajectoryIn ) -> str :
176211 from api .services .summarize_trajectory import preprocess
212+
177213 return tp .trajectory_section (json .dumps (preprocess (d .trajectory )))
178214
179215 # ---- parsing (parse is inherited; this filters elements) ----
@@ -187,10 +223,15 @@ def _valid_step_ids(self) -> set[int]:
187223 def filter_output (self , parsed : TrajectoryOutput ) -> TrajectoryOutput :
188224 valid = self ._valid_step_ids ()
189225 highlights = [
190- {"step_id" : h ["step_id" ], "title" : str (h .get ("title" ) or "" ).strip (),
191- "why" : str (h .get ("why" ) or "" ).strip ()}
226+ {
227+ "step_id" : h ["step_id" ],
228+ "title" : str (h .get ("title" ) or "" ).strip (),
229+ "why" : str (h .get ("why" ) or "" ).strip (),
230+ }
192231 for h in parsed .highlights
193- if isinstance (h , dict ) and isinstance (h .get ("step_id" ), int ) and h ["step_id" ] in valid
232+ if isinstance (h , dict )
233+ and isinstance (h .get ("step_id" ), int )
234+ and h ["step_id" ] in valid
194235 ]
195236 components : list [dict ] = []
196237 for c in parsed .components :
@@ -202,11 +243,13 @@ def filter_output(self, parsed: TrajectoryOutput) -> TrajectoryOutput:
202243 ids = [s for s in m .step_ids if s in valid ]
203244 if not ids :
204245 continue
205- components .append ({
206- "step_ids" : ids ,
207- "trajectory_component" : m .trajectory_component .value ,
208- "summary" : m .summary ,
209- })
246+ components .append (
247+ {
248+ "step_ids" : ids ,
249+ "trajectory_component" : m .trajectory_component .value ,
250+ "summary" : m .summary ,
251+ }
252+ )
210253 return TrajectoryOutput (
211254 summary = str (parsed .summary or "" ).strip (),
212255 highlights = highlights ,
@@ -227,15 +270,22 @@ def timestamp_ms(step: dict) -> float | None:
227270 if not isinstance (value , str ):
228271 return None
229272 try :
230- return datetime .fromisoformat (value .replace ("Z" , "+00:00" )).timestamp () * 1000
273+ return (
274+ datetime .fromisoformat (value .replace ("Z" , "+00:00" )).timestamp ()
275+ * 1000
276+ )
231277 except ValueError :
232278 return None
233279
234280 def duration_ms (index : int , step : dict ) -> int :
235281 if index == 0 :
236282 return 0
237283 current = timestamp_ms (step )
238- previous = timestamp_ms (steps [index - 1 ]) if isinstance (steps [index - 1 ], dict ) else None
284+ previous = (
285+ timestamp_ms (steps [index - 1 ])
286+ if isinstance (steps [index - 1 ], dict )
287+ else None
288+ )
239289 if current is None or previous is None :
240290 return 0
241291 return max (0 , round (current - previous ))
@@ -247,17 +297,21 @@ def duration_ms(index: int, step: dict) -> int:
247297 for step_id in component ["step_ids" ]
248298 if step_id in step_by_id
249299 ]
250- components .append ({
251- ** component ,
252- # These fields are derived from the immutable trajectory rather
253- # than supplied by the LLM, so consumers can safely aggregate them.
254- "tool_count" : sum (
255- len (step .get ("tool_calls" ) or [])
256- for _ , step in component_steps
257- if isinstance (step .get ("tool_calls" ), list )
258- ),
259- "duration_ms" : sum (duration_ms (index , step ) for index , step in component_steps ),
260- })
300+ components .append (
301+ {
302+ ** component ,
303+ # These fields are derived from the immutable trajectory rather
304+ # than supplied by the LLM, so consumers can safely aggregate them.
305+ "tool_count" : sum (
306+ len (step .get ("tool_calls" ) or [])
307+ for _ , step in component_steps
308+ if isinstance (step .get ("tool_calls" ), list )
309+ ),
310+ "duration_ms" : sum (
311+ duration_ms (index , step ) for index , step in component_steps
312+ ),
313+ }
314+ )
261315 return {
262316 "schema_version" : "5" ,
263317 "model" : model ,
0 commit comments