"""Canonical Ralph MCP tool naming helpers."""
from __future__ import annotations
from enum import StrEnum
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
RALPH_MCP_SERVER_NAME = "ralph"
READ_FILE_TOOL = RalphToolName.READ_FILE
WRITE_FILE_TOOL = RalphToolName.WRITE_FILE
LIST_DIRECTORY_TOOL = RalphToolName.LIST_DIRECTORY
LIST_DIRECTORY_RECURSIVE_TOOL = RalphToolName.LIST_DIRECTORY_RECURSIVE
DIRECTORY_TREE_TOOL = RalphToolName.DIRECTORY_TREE
SEARCH_FILES_TOOL = RalphToolName.SEARCH_FILES
READ_MULTIPLE_FILES_TOOL = RalphToolName.READ_MULTIPLE_FILES
STAT_PATH_TOOL = RalphToolName.STAT_PATH
LIST_ALLOWED_ROOTS_TOOL = RalphToolName.LIST_ALLOWED_ROOTS
GREP_FILES_TOOL = RalphToolName.GREP_FILES
EDIT_FILE_TOOL = RalphToolName.EDIT_FILE
APPEND_FILE_TOOL = RalphToolName.APPEND_FILE
CREATE_DIRECTORY_TOOL = RalphToolName.CREATE_DIRECTORY
MOVE_FILE_TOOL = RalphToolName.MOVE_FILE
COPY_FILE_TOOL = RalphToolName.COPY_FILE
DELETE_PATH_TOOL = RalphToolName.DELETE_PATH
GIT_STATUS_TOOL = RalphToolName.GIT_STATUS
GIT_DIFF_TOOL = RalphToolName.GIT_DIFF
GIT_LOG_TOOL = RalphToolName.GIT_LOG
GIT_SHOW_TOOL = RalphToolName.GIT_SHOW
EXEC_TOOL = RalphToolName.EXEC
UNSAFE_EXEC_TOOL = RalphToolName.UNSAFE_EXEC
RAW_EXEC_TOOL = RalphToolName.RAW_EXEC
SUBMIT_ARTIFACT_TOOL = RalphToolName.SUBMIT_ARTIFACT
SUBMIT_PLAN_SECTION_TOOL = RalphToolName.SUBMIT_PLAN_SECTION
SUBMIT_PLAN_SECTIONS_TOOL = RalphToolName.SUBMIT_PLAN_SECTIONS
INSERT_PLAN_STEP_TOOL = RalphToolName.INSERT_PLAN_STEP
REPLACE_PLAN_STEP_TOOL = RalphToolName.REPLACE_PLAN_STEP
REMOVE_PLAN_STEP_TOOL = RalphToolName.REMOVE_PLAN_STEP
MOVE_PLAN_STEP_TOOL = RalphToolName.MOVE_PLAN_STEP
PATCH_PLAN_STEP_TOOL = RalphToolName.PATCH_PLAN_STEP
FINALIZE_PLAN_TOOL = RalphToolName.FINALIZE_PLAN
GET_PLAN_DRAFT_TOOL = RalphToolName.GET_PLAN_DRAFT
DISCARD_PLAN_DRAFT_TOOL = RalphToolName.DISCARD_PLAN_DRAFT
VALIDATE_PLAN_DRAFT_TOOL = RalphToolName.VALIDATE_PLAN_DRAFT
REPORT_PROGRESS_TOOL = RalphToolName.REPORT_PROGRESS
DECLARE_COMPLETE_TOOL = RalphToolName.DECLARE_COMPLETE
COORDINATE_TOOL = RalphToolName.COORDINATE
READ_ENV_TOOL = RalphToolName.READ_ENV
WEB_SEARCH_TOOL = RalphToolName.WEB_SEARCH
VISIT_URL_TOOL = RalphToolName.VISIT_URL
DOWNLOAD_URL_TOOL = RalphToolName.DOWNLOAD_URL
READ_IMAGE_TOOL = RalphToolName.READ_IMAGE
READ_MEDIA_TOOL = RalphToolName.READ_MEDIA
WORKSPACE_READ_TOOLS: tuple[str, ...] = (
READ_FILE_TOOL,
LIST_DIRECTORY_TOOL,
LIST_DIRECTORY_RECURSIVE_TOOL,
DIRECTORY_TREE_TOOL,
SEARCH_FILES_TOOL,
READ_MULTIPLE_FILES_TOOL,
STAT_PATH_TOOL,
LIST_ALLOWED_ROOTS_TOOL,
GREP_FILES_TOOL,
)
WORKSPACE_EDIT_TOOLS: tuple[str, ...] = (
EDIT_FILE_TOOL,
APPEND_FILE_TOOL,
CREATE_DIRECTORY_TOOL,
MOVE_FILE_TOOL,
COPY_FILE_TOOL,
)
WORKSPACE_DELETE_TOOLS: tuple[str, ...] = (DELETE_PATH_TOOL,)
GIT_STATUS_READ_TOOLS: tuple[str, ...] = (GIT_STATUS_TOOL, GIT_LOG_TOOL, GIT_SHOW_TOOL)
GIT_DIFF_READ_TOOLS: tuple[str, ...] = (GIT_DIFF_TOOL,)
TRACKED_WRITE_TOOLS: tuple[str, ...] = (WRITE_FILE_TOOL,)
PROCESS_EXEC_TOOLS: tuple[str, ...] = (EXEC_TOOL,)
PROCESS_EXEC_UNBOUNDED_TOOLS: tuple[str, ...] = (UNSAFE_EXEC_TOOL, RAW_EXEC_TOOL)
ARTIFACT_SUBMIT_TOOLS: tuple[str, ...] = (SUBMIT_ARTIFACT_TOOL, DECLARE_COMPLETE_TOOL)
ARTIFACT_COORDINATE_TOOLS: tuple[str, ...] = (COORDINATE_TOOL,)
ARTIFACT_TOOLS: tuple[str, ...] = (*ARTIFACT_SUBMIT_TOOLS, *ARTIFACT_COORDINATE_TOOLS)
PLAN_DRAFT_READ_TOOLS: tuple[str, ...] = (GET_PLAN_DRAFT_TOOL, VALIDATE_PLAN_DRAFT_TOOL)
PLAN_DRAFT_WRITE_TOOLS: tuple[str, ...] = (
COORDINATE_TOOL,
SUBMIT_PLAN_SECTION_TOOL,
SUBMIT_PLAN_SECTIONS_TOOL,
INSERT_PLAN_STEP_TOOL,
REPLACE_PLAN_STEP_TOOL,
REMOVE_PLAN_STEP_TOOL,
MOVE_PLAN_STEP_TOOL,
PATCH_PLAN_STEP_TOOL,
FINALIZE_PLAN_TOOL,
DISCARD_PLAN_DRAFT_TOOL,
)
PLANNING_DRAFT_TOOLS: tuple[str, ...] = (*PLAN_DRAFT_READ_TOOLS, *PLAN_DRAFT_WRITE_TOOLS)
PROGRESS_TOOLS: tuple[str, ...] = (REPORT_PROGRESS_TOOL,)
ENV_READ_TOOLS: tuple[str, ...] = (READ_ENV_TOOL,)
WEB_SEARCH_TOOLS: tuple[str, ...] = (WEB_SEARCH_TOOL,)
WEB_VISIT_TOOLS: tuple[str, ...] = (VISIT_URL_TOOL,)
WEB_DOWNLOAD_TOOLS: tuple[str, ...] = (DOWNLOAD_URL_TOOL,)
MEDIA_READ_TOOLS: tuple[str, ...] = (READ_IMAGE_TOOL, READ_MEDIA_TOOL)
ALL_RALPH_TOOLS: tuple[str, ...] = tuple(str(member) for member in RalphToolName)
# Authoritative source: https://opencode.ai/config.json schema PermissionConfig keys
# Setting each to false physically removes the tool (unlike permission which is allow-by-default).
# Only filesystem/exec primitives are disabled — they are funneled through Ralph's MCP
# surface. Orchestration tools (sub-agents, skills, todos, web access) stay native; see
# OPENCODE_NATIVE_TOOLS_TO_KEEP. ``question`` stays disabled: it prompts the user and
# wedges headless runs.
OPENCODE_NATIVE_TOOLS_TO_DISABLE: tuple[str, ...] = (
"bash",
"codesearch",
"edit",
"glob",
"grep",
"list",
"lsp",
"patch",
"question",
"read",
"write",
)
# Native orchestration tools that MUST stay enabled when Ralph wires its MCP surface:
# sub-agent dispatch, skills, todo tracking, and web access. They are auto-allowed in
# the generated permission section so they cannot wedge a headless run on approval.
OPENCODE_NATIVE_TOOLS_TO_KEEP: tuple[str, ...] = (
"skill",
"task",
"todowrite",
"webfetch",
"websearch",
)
# Claude Code built-in tools kept available via ``--tools`` when Ralph restricts the
# native toolset (all other built-ins are funneled through Ralph's MCP surface).
# ``Task`` was renamed ``Agent`` in claude v2.1.63; unknown names in ``--tools`` are
# silently ignored, so listing both keeps every CLI version covered.
CLAUDE_NATIVE_TOOLS_TO_KEEP: tuple[str, ...] = (
"Agent",
"Task",
"Skill",
"TodoWrite",
"WebFetch",
"WebSearch",
)
# Authoritative source: https://developers.openai.com/codex/config-reference
# apply_patch and core editing primitives are NOT disableable — documented limitation.
# shell/undo/apps are funneled through Ralph's MCP surface; multi_agent (sub-agents)
# is explicitly enabled. web_search is intentionally absent: it is left at Codex's
# native default rather than force-disabled.
CODEX_NATIVE_FEATURE_OVERRIDES: tuple[tuple[str, str], ...] = (
("features.shell_tool", "false"),
("features.multi_agent", "true"),
("features.undo", "false"),
("features.apps", "false"),
)
def _coerce_tool_name(tool_name: str | RalphToolName) -> RalphToolName | None:
if isinstance(tool_name, RalphToolName):
return tool_name
try:
return RalphToolName(tool_name)
except ValueError:
return None