Coverage for lintro / ai / hook.py: 95%

22 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2026-04-03 18:53 +0000

1"""Post-execution hook for AI enhancement. 

2 

3Replaces inline ``if lintro_config.ai.enabled:`` checks in tool_executor 

4with a structured hook pattern. AI stays auto-invoked after check/fix 

5-- no standalone command. 

6""" 

7 

8from __future__ import annotations 

9 

10from typing import TYPE_CHECKING 

11 

12from loguru import logger 

13 

14from lintro.ai.models import AIResult 

15from lintro.enums.action import Action 

16 

17if TYPE_CHECKING: 

18 from lintro.config.lintro_config import LintroConfig 

19 from lintro.models.core.tool_result import ToolResult 

20 from lintro.utils.console.logger import ThreadSafeConsoleLogger 

21 

22 

23class AIPostExecutionHook: 

24 """Hook that runs AI enhancement after tool execution.""" 

25 

26 def __init__( 

27 self, 

28 lintro_config: LintroConfig, 

29 *, 

30 ai_fix: bool = False, 

31 ) -> None: 

32 """Initialize the hook. 

33 

34 Args: 

35 lintro_config: Full Lintro configuration. 

36 ai_fix: Whether AI fix suggestions were requested. 

37 """ 

38 self._lintro_config = lintro_config 

39 self._ai_fix = ai_fix 

40 

41 def should_run(self, action: Action) -> bool: 

42 """Check whether AI enhancement should run for this action. 

43 

44 Args: 

45 action: The action being performed (CHECK, FIX, TEST). 

46 

47 Returns: 

48 True if AI is enabled and action is CHECK or FIX. 

49 """ 

50 return self._lintro_config.ai.enabled and action in { 

51 Action.CHECK, 

52 Action.FIX, 

53 } 

54 

55 def execute( 

56 self, 

57 action: Action, 

58 all_results: list[ToolResult], 

59 *, 

60 console_logger: ThreadSafeConsoleLogger, 

61 output_format: str, 

62 ) -> AIResult: 

63 """Run AI enhancement on tool results. 

64 

65 Args: 

66 action: The action that was performed. 

67 all_results: Results from all tools. 

68 console_logger: Logger for console output. 

69 output_format: Output format string. 

70 

71 Returns: 

72 AIResult with structured outcome data. 

73 

74 Raises: 

75 Exception: Re-raised when ``fail_on_ai_error`` is enabled. 

76 """ 

77 try: 

78 from lintro.ai.orchestrator import run_ai_enhancement 

79 

80 return run_ai_enhancement( 

81 action=action, 

82 all_results=all_results, 

83 lintro_config=self._lintro_config, 

84 logger=console_logger, 

85 output_format=output_format, 

86 ai_fix=self._ai_fix, 

87 ) 

88 except Exception as e: 

89 logger.opt(exception=True).debug(f"AI post-execution hook failed: {e}") 

90 if getattr(self._lintro_config.ai, "fail_on_ai_error", False): 

91 raise 

92 if output_format.lower() not in ("json", "sarif"): 

93 console_logger.warning(f"AI enhancement unavailable: {e}") 

94 return AIResult(error=True)