butler/mcp/github_tool_aliases.py
Rama main · réplica de lectura del repositorio original.
"""Resolve common LLM mis-names for GitHub MCP tools (EXT-4)."""
from __future__ import annotations
import os
import re
from typing import Any
from butler.defaults.env_defaults import GITHUB_DEFAULT_OWNER_DEFAULT
_GITHUB_TOOL_ALIASES: dict[str, str] = {
"mcp_github_get_issues": "mcp_github_lst_repo_issues",
"mcp_github_list_issues": "mcp_github_lst_repo_issues",
"mcp_github_list_repo_issues": "mcp_github_lst_repo_issues",
"mcp_github_get_repository_issues": "mcp_github_lst_repo_issues",
"mcp_github_list_repos": "mcp_github_lst_repos_authenticated_usr",
"mcp_github_list_repositories": "mcp_github_lst_repos_authenticated_usr",
}
def resolve_github_mcp_tool_name(name: str) -> str:
key = str(name or "").strip()
if key in _GITHUB_TOOL_ALIASES:
return _GITHUB_TOOL_ALIASES[key]
from butler.mcp.github_tool_aliases_ops import resolve_mcp_tool_alias_safe
resolved = resolve_mcp_tool_alias_safe(key)
if resolved != key:
return str(resolved)
return key
def default_github_owner() -> str:
return os.getenv("BUTLER_GITHUB_DEFAULT_OWNER", GITHUB_DEFAULT_OWNER_DEFAULT).strip() or GITHUB_DEFAULT_OWNER_DEFAULT
def parse_github_owner_repo(
text: str,
args: dict[str, Any] | None = None,
) -> tuple[str, str]:
"""Best-effort owner/repo from tool args or user text."""
raw_args = dict(args or {})
owner = str(raw_args.get("owner") or "").strip()
repo = str(raw_args.get("repo") or raw_args.get("repository") or "").strip()
if owner and repo:
return owner, repo
if repo and "/" in repo:
left, right = repo.split("/", 1)
return left.strip(), right.strip()
user_text = str(text or "").strip()
slash = re.search(r"([\w.-]+)/([\w.-]+)", user_text)
if slash:
return slash.group(1), slash.group(2)
if not repo:
m = re.search(
r"(?:列出|list|查看|查|看看)\s*([\w.-]+)\s*的\s*issues?",
user_text,
re.IGNORECASE,
)
if m:
repo = m.group(1)
else:
m2 = re.search(r"\b([\w.-]+)\s*的\s*issues?\b", user_text, re.IGNORECASE)
if m2:
repo = m2.group(1)
if not owner:
owner = default_github_owner()
return owner, repo
def normalize_github_mcp_args(
tool_name: str,
args: dict[str, Any],
*,
user_text: str = "",
) -> dict[str, Any]:
out = dict(args or {})
resolved = resolve_github_mcp_tool_name(tool_name)
if resolved == "mcp_github_lst_repo_issues":
owner, repo = parse_github_owner_repo(user_text, out)
if owner:
out["owner"] = owner
if repo:
out["repo"] = repo
out.pop("repository", None)
state = str(out.get("state") or "").strip().lower()
if not state:
if any(k in str(user_text or "") for k in ("全部", "所有", "all", "关闭", "closed")):
out["state"] = "all" if any(k in str(user_text or "").lower() for k in ("全部", "所有", "all")) else "closed"
else:
out["state"] = "open"
return out