fix: repair missing step_type fields in Plan validation (#653)

* fix: resolve issue #650 - repair missing step_type fields in Plan validation

- Add step_type repair logic to validate_and_fix_plan() to auto-infer missing step_type
- Infer as 'research' when need_search=true, 'processing' when need_search=false
- Add explicit CRITICAL REQUIREMENT section to planner.md emphasizing step_type mandatory for every step
- Include validation checklist and examples showing both research and processing steps
- Add 23 comprehensive unit tests for validate_and_fix_plan() covering all scenarios
- Add 4 integration tests specifically for Issue #650 with actual Plan validation
- Prevents Pydantic ValidationError: 'Field required' for missing step_type

* Update tests/unit/graph/test_plan_validation.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update tests/unit/graph/test_plan_validation.py

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* update the planner.zh_CN.md with recent changes of planner.md

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Willem Jiang
2025-10-24 21:26:48 +08:00
committed by GitHub
parent 975b344ca7
commit 36bf5c9ccd
5 changed files with 794 additions and 6 deletions

View File

@@ -100,6 +100,26 @@ def validate_and_fix_plan(plan: dict, enforce_web_search: bool = False) -> dict:
steps = plan.get("steps", [])
# ============================================================
# SECTION 1: Repair missing step_type fields (Issue #650 fix)
# ============================================================
for idx, step in enumerate(steps):
if not isinstance(step, dict):
continue
# Check if step_type is missing or empty
if "step_type" not in step or not step.get("step_type"):
# Infer step_type based on need_search value
inferred_type = "research" if step.get("need_search", False) else "processing"
step["step_type"] = inferred_type
logger.info(
f"Repaired missing step_type for step {idx} ({step.get('title', 'Untitled')}): "
f"inferred as '{inferred_type}' based on need_search={step.get('need_search', False)}"
)
# ============================================================
# SECTION 2: Enforce web search requirements
# ============================================================
if enforce_web_search:
# Check if any step has need_search=true
has_search_step = any(step.get("need_search", False) for step in steps)