mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-05 01:50:27 +08:00
171 lines
4.7 KiB
Python
171 lines
4.7 KiB
Python
"""Hook interfaces for Claude Code integration."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import logging
|
|
from pathlib import Path
|
|
from typing import Any, Dict, Optional, Callable, TYPE_CHECKING
|
|
|
|
from codexlens.mcp.schema import MCPContext
|
|
|
|
if TYPE_CHECKING:
|
|
from codexlens.mcp.provider import MCPProvider
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class HookManager:
|
|
"""Manages hook registration and execution."""
|
|
|
|
def __init__(self, mcp_provider: "MCPProvider") -> None:
|
|
self.mcp_provider = mcp_provider
|
|
self._pre_hooks: Dict[str, Callable] = {}
|
|
self._post_hooks: Dict[str, Callable] = {}
|
|
|
|
# Register default hooks
|
|
self._register_default_hooks()
|
|
|
|
def _register_default_hooks(self) -> None:
|
|
"""Register built-in hooks."""
|
|
self._pre_hooks["explain"] = self._pre_explain_hook
|
|
self._pre_hooks["refactor"] = self._pre_refactor_hook
|
|
self._pre_hooks["document"] = self._pre_document_hook
|
|
|
|
def execute_pre_hook(
|
|
self,
|
|
action: str,
|
|
params: Dict[str, Any],
|
|
) -> Optional[MCPContext]:
|
|
"""Execute pre-tool hook to gather context.
|
|
|
|
Args:
|
|
action: The action being performed (e.g., "explain", "refactor")
|
|
params: Parameters for the action
|
|
|
|
Returns:
|
|
MCPContext to inject into prompt, or None
|
|
"""
|
|
hook = self._pre_hooks.get(action)
|
|
|
|
if not hook:
|
|
logger.debug(f"No pre-hook for action: {action}")
|
|
return None
|
|
|
|
try:
|
|
return hook(params)
|
|
except Exception as e:
|
|
logger.error(f"Pre-hook failed for {action}: {e}")
|
|
return None
|
|
|
|
def execute_post_hook(
|
|
self,
|
|
action: str,
|
|
result: Any,
|
|
) -> None:
|
|
"""Execute post-tool hook for proactive caching.
|
|
|
|
Args:
|
|
action: The action that was performed
|
|
result: Result of the action
|
|
"""
|
|
hook = self._post_hooks.get(action)
|
|
|
|
if not hook:
|
|
return
|
|
|
|
try:
|
|
hook(result)
|
|
except Exception as e:
|
|
logger.error(f"Post-hook failed for {action}: {e}")
|
|
|
|
def _pre_explain_hook(self, params: Dict[str, Any]) -> Optional[MCPContext]:
|
|
"""Pre-hook for 'explain' action."""
|
|
symbol_name = params.get("symbol")
|
|
|
|
if not symbol_name:
|
|
return None
|
|
|
|
return self.mcp_provider.build_context(
|
|
symbol_name=symbol_name,
|
|
context_type="symbol_explanation",
|
|
include_references=True,
|
|
include_related=True,
|
|
)
|
|
|
|
def _pre_refactor_hook(self, params: Dict[str, Any]) -> Optional[MCPContext]:
|
|
"""Pre-hook for 'refactor' action."""
|
|
symbol_name = params.get("symbol")
|
|
|
|
if not symbol_name:
|
|
return None
|
|
|
|
return self.mcp_provider.build_context(
|
|
symbol_name=symbol_name,
|
|
context_type="refactor_context",
|
|
include_references=True,
|
|
include_related=True,
|
|
max_references=20,
|
|
)
|
|
|
|
def _pre_document_hook(self, params: Dict[str, Any]) -> Optional[MCPContext]:
|
|
"""Pre-hook for 'document' action."""
|
|
symbol_name = params.get("symbol")
|
|
file_path = params.get("file_path")
|
|
|
|
if symbol_name:
|
|
return self.mcp_provider.build_context(
|
|
symbol_name=symbol_name,
|
|
context_type="documentation_context",
|
|
include_references=False,
|
|
include_related=True,
|
|
)
|
|
elif file_path:
|
|
return self.mcp_provider.build_context_for_file(
|
|
Path(file_path),
|
|
context_type="file_documentation",
|
|
)
|
|
|
|
return None
|
|
|
|
def register_pre_hook(
|
|
self,
|
|
action: str,
|
|
hook: Callable[[Dict[str, Any]], Optional[MCPContext]],
|
|
) -> None:
|
|
"""Register a custom pre-tool hook."""
|
|
self._pre_hooks[action] = hook
|
|
|
|
def register_post_hook(
|
|
self,
|
|
action: str,
|
|
hook: Callable[[Any], None],
|
|
) -> None:
|
|
"""Register a custom post-tool hook."""
|
|
self._post_hooks[action] = hook
|
|
|
|
|
|
def create_context_for_prompt(
|
|
mcp_provider: "MCPProvider",
|
|
action: str,
|
|
params: Dict[str, Any],
|
|
) -> str:
|
|
"""Create context string for prompt injection.
|
|
|
|
This is the main entry point for Claude Code hook integration.
|
|
|
|
Args:
|
|
mcp_provider: The MCP provider instance
|
|
action: Action being performed
|
|
params: Action parameters
|
|
|
|
Returns:
|
|
Formatted context string for prompt injection
|
|
"""
|
|
manager = HookManager(mcp_provider)
|
|
context = manager.execute_pre_hook(action, params)
|
|
|
|
if context:
|
|
return context.to_prompt_injection()
|
|
|
|
return ""
|