24 files changed
@@ -0,0 +1,2 @@ | |||
| 1 | + """Lightweight orchestration helpers extracted from the legacy orchestrator.""" | ||
| 2 | + | ||
@@ -0,0 +1,35 @@ | |||
| 1 | + """Shared agent/model selection helpers for orchestration.""" | ||
| 2 | + | ||
| 3 | + from __future__ import annotations | ||
| 4 | + | ||
| 5 | + from .common_utils import pack_skill_args | ||
| 6 | + | ||
| 7 | + | ||
| 8 | + def resolve_model_tier(config: object, agent_name: str) -> tuple[str, str]: | ||
| 9 | + """Return the configured model tier and model id for an agent name.""" | ||
| 10 | + tier_key = agent_name | ||
| 11 | + if agent_name.startswith("writer_"): | ||
| 12 | + tier_key = "section_writer" | ||
| 13 | + elif agent_name.startswith("critic_") and agent_name != "critic": | ||
| 14 | + tier_key = "section_critic" | ||
| 15 | + elif "_critiques_" in agent_name: | ||
| 16 | + tier_key = "idea_critique" | ||
| 17 | + | ||
| 18 | + tier = config.agent_tier_map.get(tier_key, "standard") | ||
| 19 | + model = config.model_tiers.get(tier, config.model_tiers["standard"]) | ||
| 20 | + return tier, model | ||
| 21 | + | ||
| 22 | + | ||
| 23 | + def codex_reviewer_args(config: object, mode: str, ws: str) -> str: | ||
| 24 | + """Build reviewer args with an optional model override.""" | ||
| 25 | + if config.codex_model: | ||
| 26 | + return pack_skill_args(ws, mode, config.codex_model) | ||
| 27 | + return pack_skill_args(ws, mode) | ||
| 28 | + | ||
| 29 | + | ||
| 30 | + def codex_writer_args(config: object, ws: str) -> str: | ||
| 31 | + """Build Codex writer args with an optional model override.""" | ||
| 32 | + model = config.codex_writing_model or config.codex_model | ||
| 33 | + if model: | ||
| 34 | + return pack_skill_args(ws, model) | ||
| 35 | + return pack_skill_args(ws) | ||
@@ -0,0 +1,38 @@ | |||
| 1 | + """Checkpoint lifecycle helpers for orchestration stages.""" | ||
| 2 | + | ||
| 3 | + from __future__ import annotations | ||
| 4 | + | ||
| 5 | + from typing import Any | ||
| 6 | + | ||
| 7 | + from .constants import CHECKPOINT_DIRS | ||
| 8 | + | ||
| 9 | + | ||
| 10 | + def get_or_create_checkpoint( | ||
| 11 | + orchestrator: Any, | ||
| 12 | + stage: str, | ||
| 13 | + steps: dict[str, str], | ||
| 14 | + ) -> dict | None: | ||
| 15 | + """Get a validated checkpoint or create a fresh one for a stage.""" | ||
| 16 | + cp_dir = CHECKPOINT_DIRS.get(stage) | ||
| 17 | + if cp_dir is None: | ||
| 18 | + return None | ||
| 19 | + | ||
| 20 | + iteration = orchestrator.ws.get_status().iteration | ||
| 21 | + valid = orchestrator.ws.validate_checkpoint(cp_dir, current_iteration=iteration) | ||
| 22 | + if valid is not None: | ||
| 23 | + return { | ||
| 24 | + "resuming": True, | ||
| 25 | + "completed_steps": valid["completed"], | ||
| 26 | + "remaining_steps": valid["remaining"], | ||
| 27 | + "all_complete": not valid["remaining"], | ||
| 28 | + "checkpoint_dir": cp_dir, | ||
| 29 | + } | ||
| 30 | + | ||
| 31 | + orchestrator.ws.create_checkpoint(stage, cp_dir, steps, iteration=iteration) | ||
| 32 | + return { | ||
| 33 | + "resuming": False, | ||
| 34 | + "completed_steps": [], | ||
| 35 | + "remaining_steps": list(steps.keys()), | ||
| 36 | + "all_complete": False, | ||
| 37 | + "checkpoint_dir": cp_dir, | ||
| 38 | + } | ||
0 commit comments