68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
import re
|
|
import hashlib
|
|
from typing import Iterable, List, Tuple, Any
|
|
|
|
|
|
TOOL_NAME_PATTERN = re.compile(r"^[a-zA-Z0-9_-]{1,64}$")
|
|
|
|
|
|
class ToolValidationError(Exception):
|
|
pass
|
|
|
|
|
|
def sanitize_tool_name(name: str, max_len: int = 64) -> str:
|
|
safe = re.sub(r"[^a-zA-Z0-9_-]", "_", name or "tool")
|
|
if len(safe) > max_len:
|
|
suffix = hashlib.sha1(safe.encode()).hexdigest()[:8]
|
|
safe = safe[: max_len - 9] + "_" + suffix
|
|
return safe or "tool"
|
|
|
|
|
|
def _find_illegal_chars(name: str) -> List[str]:
|
|
return sorted(list(set(re.findall(r"[^a-zA-Z0-9_-]", name))))
|
|
|
|
|
|
def _get_name(obj: Any) -> str:
|
|
return getattr(obj, "name", None) or getattr(obj, "tool_name", None) or getattr(obj, "__name__", "tool")
|
|
|
|
|
|
def validate_tool_names(
|
|
tools: Iterable[Any], *, strict: bool = True, max_len: int = 64
|
|
) -> Tuple[bool, List[str]]:
|
|
"""
|
|
Validate that tool names conform to OpenAI-compatible constraints:
|
|
- Allowed chars: a-z, A-Z, 0-9, underscore, hyphen
|
|
- Max length: 64
|
|
|
|
Returns (ok, messages). If strict=True and invalid tools exist,
|
|
raises ToolValidationError with a detailed report.
|
|
"""
|
|
messages: List[str] = []
|
|
errors: List[str] = []
|
|
for idx, t in enumerate(tools):
|
|
name = _get_name(t)
|
|
if TOOL_NAME_PATTERN.match(name or ""):
|
|
continue
|
|
parts: List[str] = [f"第{idx}个工具名称不合法: '{name}'"]
|
|
if not name:
|
|
parts.append("原因: 为空")
|
|
else:
|
|
illegal = _find_illegal_chars(name)
|
|
if illegal:
|
|
parts.append(f"包含非法字符: {''.join(illegal)} (仅允许[a-zA-Z0-9_-])")
|
|
if len(name) > max_len:
|
|
parts.append(f"长度超限: {len(name)} > {max_len}")
|
|
suggestion = sanitize_tool_name(name or "tool", max_len=max_len)
|
|
parts.append(f"建议名称: '{suggestion}'")
|
|
errors.append("; ".join(parts))
|
|
|
|
if errors:
|
|
report = "\n".join(errors)
|
|
messages.append(report)
|
|
if strict:
|
|
raise ToolValidationError(report)
|
|
return False, messages
|
|
|
|
return True, messages
|
|
|