""" Trajectory Correction / Editing Layout Annotators rewrite the steps of an agent trace (reasoning, tool calls, observations) and optionally the final answer, producing a *corrected* trajectory alongside the original. The corrected/original pair is exported as SFT targets and DPO preference pairs (see ``potato/export/trajectory_correction_exporter.py``). This is the editing counterpart to ``trajectory_eval`` (which *scores* steps). It reuses ``trajectory_eval``'s data-loading + per-step-card structure and ``text_edit``'s live word/char diff. Each step shows the original text read-only plus an editable textarea pre-filled with the original; a per-step "edited" flag is set automatically when the text diverges. Research / motivation: Labelbox Agent Trajectory Editor; Datadog "edited outputs"; SFT/DPO post-training from human-corrected trajectories. """ import json import logging from typing import Any, Dict, List, Tuple from .identifier_utils import ( safe_generate_layout, generate_element_identifier, generate_validation_attribute, escape_html_content, generate_layout_attributes, ) logger = logging.getLogger(__name__) DEFAULT_EDITABLE_FIELDS = ["action"] def generate_trajectory_edit_layout( annotation_scheme: Dict[str, Any], ) -> Tuple[str, List[Tuple[str, str]]]: """Generate HTML for a trajectory correction/editing interface. Args: annotation_scheme: Configuration dict. Required: ``name``, ``description``. Optional: ``steps_key``, ``step_text_key``, ``editable_fields``, ``show_diff``, ``show_edit_distance``, ``allow_reset``, ``require_reason_on_edit``, ``edit_final_answer``, ``final_answer_key``. Returns: ``(html, keybindings)`` tuple. """ return safe_generate_layout(annotation_scheme, _generate_internal) def _generate_internal( annotation_scheme: Dict[str, Any], ) -> Tuple[str, List[Tuple[str, str]]]: schema_name = annotation_scheme["name"] description = annotation_scheme["description"] steps_key = annotation_scheme.get("steps_key", "steps") step_text_key = annotation_scheme.get("step_text_key", "action") editable_fields = annotation_scheme.get("editable_fields") or [step_text_key] if not isinstance(editable_fields, list): editable_fields = [step_text_key] show_diff = annotation_scheme.get("show_diff", True) show_edit_distance = annotation_scheme.get("show_edit_distance", True) allow_reset = annotation_scheme.get("allow_reset", True) require_reason_on_edit = annotation_scheme.get("require_reason_on_edit", False) edit_final_answer = annotation_scheme.get("edit_final_answer", False) final_answer_key = annotation_scheme.get("final_answer_key", "final_answer") layout_attrs = generate_layout_attributes(annotation_scheme) validation = generate_validation_attribute(annotation_scheme) identifiers = generate_element_identifier(schema_name, schema_name, "hidden") config_json = json.dumps({ "steps_key": steps_key, "step_text_key": step_text_key, "editable_fields": editable_fields, "show_diff": show_diff, "show_edit_distance": show_edit_distance, "allow_reset": allow_reset, "require_reason_on_edit": require_reason_on_edit, "edit_final_answer": edit_final_answer, "final_answer_key": final_answer_key, }) esc_schema = escape_html_content(schema_name) html = f"""
{escape_html_content(description)}
Steps edited: 0 Total edit distance: 0
""" logger.info(f"Generated trajectory edit layout for {schema_name}") return html, []