Source code for ralph.mcp.tools.plan_draft_edit

"""Precise MCP handlers for plan draft step edits."""

from __future__ import annotations

from typing import cast

from ralph.mcp.artifacts.plan import (
    PlanArtifactValidationError,
    insert_plan_step,
    remove_plan_step,
    replace_plan_step,
)
from ralph.mcp.tools.coordination import (
    CoordinationSessionLike,
    InvalidParamsError,
    ToolContent,
    ToolResult,
    WorkspaceLike,
    require_capability,
)

from .artifact import (
    DEFAULT_ARTIFACT_HANDLER_DEPS,
    PLAN_DRAFT_WRITE_CAPABILITY,
    ArtifactHandlerDeps,
    _load_or_create_plan_draft,
    _resolve_artifact_dir,
    _save_updated_plan_draft,
)


[docs] def handle_insert_plan_step( session: CoordinationSessionLike, workspace: WorkspaceLike, params: dict[str, object], *, deps: ArtifactHandlerDeps | None = None, ) -> ToolResult: """Insert a single plan step and reindex the draft deterministically.""" require_capability(session, PLAN_DRAFT_WRITE_CAPABILITY, "Plan step insertion") index = _required_int(params, "index") step_payload = params.get("step") resolved_deps = deps or DEFAULT_ARTIFACT_HANDLER_DEPS artifact_dir = _resolve_artifact_dir(session, workspace) draft = _load_or_create_plan_draft(artifact_dir, deps=resolved_deps) current_sections = cast("dict[str, object]", draft.get("sections", {})) try: updated_sections = insert_plan_step( current_sections, index=index, step_payload=step_payload, ) except PlanArtifactValidationError as exc: raise InvalidParamsError(str(exc)) from exc draft["sections"] = updated_sections _save_updated_plan_draft(artifact_dir, draft, deps=resolved_deps) return ToolResult( content=[ToolContent.text_content(f"Plan step inserted at index {index}.")], is_error=False, )
[docs] def handle_replace_plan_step( session: CoordinationSessionLike, workspace: WorkspaceLike, params: dict[str, object], *, deps: ArtifactHandlerDeps | None = None, ) -> ToolResult: """Replace a single plan step and reindex the draft deterministically.""" require_capability(session, PLAN_DRAFT_WRITE_CAPABILITY, "Plan step replacement") step_number = _required_int(params, "step_number") step_payload = params.get("step") resolved_deps = deps or DEFAULT_ARTIFACT_HANDLER_DEPS artifact_dir = _resolve_artifact_dir(session, workspace) draft = _load_or_create_plan_draft(artifact_dir, deps=resolved_deps) current_sections = cast("dict[str, object]", draft.get("sections", {})) try: updated_sections = replace_plan_step( current_sections, step_number=step_number, step_payload=step_payload, ) except PlanArtifactValidationError as exc: raise InvalidParamsError(str(exc)) from exc draft["sections"] = updated_sections _save_updated_plan_draft(artifact_dir, draft, deps=resolved_deps) return ToolResult( content=[ToolContent.text_content(f"Plan step {step_number} replaced.")], is_error=False, )
[docs] def handle_remove_plan_step( session: CoordinationSessionLike, workspace: WorkspaceLike, params: dict[str, object], *, deps: ArtifactHandlerDeps | None = None, ) -> ToolResult: """Remove a single plan step and reindex the draft deterministically.""" require_capability(session, PLAN_DRAFT_WRITE_CAPABILITY, "Plan step removal") step_number = _required_int(params, "step_number") resolved_deps = deps or DEFAULT_ARTIFACT_HANDLER_DEPS artifact_dir = _resolve_artifact_dir(session, workspace) draft = _load_or_create_plan_draft(artifact_dir, deps=resolved_deps) current_sections = cast("dict[str, object]", draft.get("sections", {})) try: updated_sections = remove_plan_step(current_sections, step_number=step_number) except PlanArtifactValidationError as exc: raise InvalidParamsError(str(exc)) from exc draft["sections"] = updated_sections _save_updated_plan_draft(artifact_dir, draft, deps=resolved_deps) return ToolResult( content=[ToolContent.text_content(f"Plan step {step_number} removed.")], is_error=False, )
def _required_int(params: dict[str, object], name: str) -> int: value = params.get(name) if not isinstance(value, int): raise InvalidParamsError(f"Missing '{name}' parameter") return value __all__ = [ "handle_insert_plan_step", "handle_remove_plan_step", "handle_replace_plan_step", ]