Coverage for .claude/hooks/moai/lib/agent_context.py: 0.00%

96 statements  

« prev     ^ index     » next       coverage.py v7.11.3, created at 2025-11-19 08:00 +0900

1#!/usr/bin/env python3 

2"""Agent Context Engineering utilities 

3 

4Advanced JIT (Just-in-Time) Retrieval with Expert Agent Delegation 

5Intelligently analyzes user prompts to recommend specialist agents and skills 

6""" 

7 

8import json 

9import re 

10from pathlib import Path 

11from typing import Any, Dict, List, Optional, Tuple 

12 

13from .context import get_jit_context 

14 

15 

16def load_agent_skills_mapping() -> Dict[str, Any]: 

17 """Load agent-skills mapping configuration 

18 

19 Returns: 

20 Mapping configuration dictionary 

21 """ 

22 try: 

23 mapping_file = Path(__file__).parent.parent / "config" / "agent_skills_mapping.json" 

24 if mapping_file.exists(): 

25 with open(mapping_file, 'r', encoding='utf-8') as f: 

26 return json.load(f) 

27 except Exception: 

28 pass 

29 

30 return { 

31 "agent_skills_mapping": {}, 

32 "prompt_patterns": {} 

33 } 

34 

35 

36def analyze_prompt_intent(prompt: str, mapping: Dict[str, Any]) -> Optional[Dict[str, Any]]: 

37 """Analyze user prompt intent 

38 

39 Args: 

40 prompt: User prompt 

41 mapping: Agent-skills mapping 

42 

43 Returns: 

44 Analyzed intent information or None 

45 """ 

46 prompt_lower = prompt.lower() 

47 

48 # Calculate score for each pattern 

49 pattern_scores = [] 

50 

51 for pattern_name, pattern_config in mapping.get("prompt_patterns", {}).items(): 

52 score = 0 

53 matched_keywords = [] 

54 

55 # Keyword matching 

56 for keyword in pattern_config.get("keywords", []): 

57 if keyword.lower() in prompt_lower: 

58 score += 1 

59 matched_keywords.append(keyword) 

60 

61 # Regex pattern matching 

62 if pattern_config.get("regex_patterns"): 

63 for regex_pattern in pattern_config["regex_patterns"]: 

64 if re.search(regex_pattern, prompt_lower): 

65 score += 2 # Regex matching has higher weight 

66 

67 if score > 0: 

68 pattern_scores.append({ 

69 "pattern": pattern_name, 

70 "score": score, 

71 "matched_keywords": matched_keywords, 

72 "config": pattern_config 

73 }) 

74 

75 # Return pattern with highest score 

76 if pattern_scores: 

77 pattern_scores.sort(key=lambda x: x["score"], reverse=True) 

78 best_match = pattern_scores[0] 

79 

80 return { 

81 "intent": best_match["pattern"], 

82 "confidence": min(best_match["score"] / 3.0, 1.0), # Maximum 3 keyword matches 

83 "matched_keywords": best_match["matched_keywords"], 

84 "primary_agent": best_match["config"].get("primary_agent"), 

85 "secondary_agents": best_match["config"].get("secondary_agents", []), 

86 "recommended_skills": best_match["config"].get("skills", []), 

87 "context_files": best_match["config"].get("context_files", []) 

88 } 

89 

90 return None 

91 

92 

93def get_agent_delegation_context(prompt: str, cwd: str) -> Dict[str, Any]: 

94 """Create agent delegation context based on prompt 

95 

96 Args: 

97 prompt: User prompt 

98 cwd: Current working directory 

99 

100 Returns: 

101 Agent delegation context information 

102 """ 

103 mapping = load_agent_skills_mapping() 

104 intent_analysis = analyze_prompt_intent(prompt, mapping) 

105 

106 # Get existing JIT context 

107 existing_context = get_jit_context(prompt, cwd) 

108 

109 # Agent delegation information 

110 agent_context = { 

111 "intent_detected": intent_analysis is not None, 

112 "traditional_context": existing_context 

113 } 

114 

115 if intent_analysis: 

116 # Verify file existence 

117 valid_context_files = [] 

118 cwd_path = Path(cwd) 

119 

120 for context_file in intent_analysis["context_files"]: 

121 file_path = cwd_path / context_file 

122 if file_path.exists(): 

123 valid_context_files.append(context_file) 

124 

125 # Create skills reference paths 

126 skill_references = [] 

127 for skill in intent_analysis["recommended_skills"]: 

128 skill_ref = f".claude/skills/{skill}/reference.md" 

129 skill_path = cwd_path / skill_ref 

130 if skill_path.exists(): 

131 skill_references.append(skill_ref) 

132 

133 agent_context.update({ 

134 "primary_agent": intent_analysis["primary_agent"], 

135 "secondary_agents": intent_analysis["secondary_agents"], 

136 "recommended_skills": intent_analysis["recommended_skills"], 

137 "skill_references": skill_references, 

138 "context_files": valid_context_files, 

139 "confidence": intent_analysis["confidence"], 

140 "intent": intent_analysis["intent"], 

141 "matched_keywords": intent_analysis["matched_keywords"] 

142 }) 

143 

144 return agent_context 

145 

146 

147def format_agent_delegation_message(context: Dict[str, Any]) -> Optional[str]: 

148 """Format agent delegation message 

149 

150 Args: 

151 context: Agent delegation context 

152 

153 Returns: 

154 Formatted message or None 

155 """ 

156 if not context.get("intent_detected"): 

157 return None 

158 

159 messages = [] 

160 

161 # Basic information 

162 primary_agent = context.get("primary_agent") 

163 confidence = context.get("confidence", 0) 

164 intent = context.get("intent", "") 

165 matched_keywords = context.get("matched_keywords", []) 

166 

167 if primary_agent and confidence > 0.5: 

168 messages.append(f"🎯 Recommended Expert Agent: {primary_agent}") 

169 messages.append(f"📋 Task Intent: {intent}") 

170 

171 if matched_keywords: 

172 messages.append(f"🔍 Detected Keywords: {', '.join(matched_keywords)}") 

173 

174 # Recommended skills 

175 skills = context.get("recommended_skills", []) 

176 if skills: 

177 messages.append(f"⚡ Recommended Skills: {', '.join(skills[:3])}") # Display max 3 

178 

179 # Secondary agents 

180 secondary_agents = context.get("secondary_agents", []) 

181 if secondary_agents: 

182 messages.append(f"🤝 Collaboration Agents: {', '.join(secondary_agents[:2])}") # Display max 2 

183 

184 # Context files 

185 context_files = context.get("context_files", []) 

186 skill_references = context.get("skill_references", []) 

187 

188 all_files = context_files + skill_references 

189 if all_files: 

190 messages.append(f"📚 Auto-loaded Context: {len(all_files)} files") 

191 

192 return "\n".join(messages) if messages else None 

193 

194 

195def get_enhanced_jit_context(prompt: str, cwd: str) -> Tuple[List[str], Optional[str]]: 

196 """Get enhanced JIT context 

197 

198 Args: 

199 prompt: User prompt 

200 cwd: Current working directory 

201 

202 Returns: 

203 (Context file list, system message) 

204 """ 

205 agent_context = get_agent_delegation_context(prompt, cwd) 

206 

207 # Combine all context files 

208 context_files = [] 

209 

210 # Add existing context 

211 traditional_context = agent_context.get("traditional_context", []) 

212 context_files.extend(traditional_context) 

213 

214 # Add agent context files 

215 agent_context_files = agent_context.get("context_files", []) 

216 for file in agent_context_files: 

217 if file not in context_files: 

218 context_files.append(file) 

219 

220 # Add skills reference files 

221 skill_references = agent_context.get("skill_references", []) 

222 for skill_ref in skill_references: 

223 if skill_ref not in context_files: 

224 context_files.append(skill_ref) 

225 

226 # Generate system message 

227 system_message = format_agent_delegation_message(agent_context) 

228 

229 return context_files, system_message 

230 

231 

232__all__ = [ 

233 "load_agent_skills_mapping", 

234 "analyze_prompt_intent", 

235 "get_agent_delegation_context", 

236 "format_agent_delegation_message", 

237 "get_enhanced_jit_context" 

238]