Generate a YAML plan for the given task. Args: task_id: Identifier used for the output filename (e.g. "task_001"). task_description: What the task should accomplish. context_summary: Optional summary of relevant context from the orchestrat
(
self,
task_id: str,
task_description: str,
context_summary: Optional[str] = None,
hints: Optional[str] = None,
recommended_tools: Optional[list[str]] = None,
)
| 43 | self.plans_dir.mkdir(parents=True, exist_ok=True) |
| 44 | |
| 45 | def generate( |
| 46 | self, |
| 47 | task_id: str, |
| 48 | task_description: str, |
| 49 | context_summary: Optional[str] = None, |
| 50 | hints: Optional[str] = None, |
| 51 | recommended_tools: Optional[list[str]] = None, |
| 52 | ) -> Path: |
| 53 | """Generate a YAML plan for the given task. |
| 54 | |
| 55 | Args: |
| 56 | task_id: Identifier used for the output filename (e.g. "task_001"). |
| 57 | task_description: What the task should accomplish. |
| 58 | context_summary: Optional summary of relevant context from the |
| 59 | orchestrator's conversation so far. |
| 60 | hints: Optional hints for the plan generator (e.g. preferred |
| 61 | structure, tool preferences). |
| 62 | recommended_tools: Optional list of MCP tool names pre-selected |
| 63 | by the orchestrator. When provided, the plan generator is |
| 64 | instructed to use ONLY these tools. The orchestrator (more |
| 65 | capable model with full tool schemas) makes the tool selection |
| 66 | decision; the plan generator focuses on workflow structure. |
| 67 | |
| 68 | Returns: |
| 69 | Path to the generated YAML file. |
| 70 | |
| 71 | Raises: |
| 72 | ValueError: If YAML generation fails after retry. |
| 73 | """ |
| 74 | user_message = self._build_user_message( |
| 75 | task_description, |
| 76 | context_summary, |
| 77 | hints, |
| 78 | recommended_tools, |
| 79 | ) |
| 80 | |
| 81 | # First attempt |
| 82 | raw_response = self._call_llm(user_message) |
| 83 | yaml_str = self._extract_yaml(raw_response) |
| 84 | |
| 85 | parse_error = self._try_parse(yaml_str) |
| 86 | if parse_error: |
| 87 | # Retry with error feedback |
| 88 | retry_message = ( |
| 89 | f"The YAML you produced has a syntax error:\n{parse_error}\n\n" |
| 90 | f"Original YAML:\n```yaml\n{yaml_str}\n```\n\n" |
| 91 | "Please fix the error and return the corrected YAML " |
| 92 | "inside a ```yaml fenced code block." |
| 93 | ) |
| 94 | raw_response = self._call_llm(retry_message) |
| 95 | yaml_str = self._extract_yaml(raw_response) |
| 96 | parse_error = self._try_parse(yaml_str) |
| 97 | if parse_error: |
| 98 | raise ValueError( |
| 99 | f"Plan generation failed after retry. YAML error: {parse_error}" |
| 100 | ) |
| 101 | |
| 102 | # Write to disk |
no test coverage detected