empathy-framework 3.7.0__py3-none-any.whl → 3.7.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (267) hide show
  1. coach_wizards/code_reviewer_README.md +60 -0
  2. coach_wizards/code_reviewer_wizard.py +180 -0
  3. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/METADATA +20 -2
  4. empathy_framework-3.7.1.dist-info/RECORD +327 -0
  5. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/top_level.txt +5 -1
  6. empathy_healthcare_plugin/monitors/__init__.py +9 -0
  7. empathy_healthcare_plugin/monitors/clinical_protocol_monitor.py +315 -0
  8. empathy_healthcare_plugin/monitors/monitoring/__init__.py +44 -0
  9. empathy_healthcare_plugin/monitors/monitoring/protocol_checker.py +300 -0
  10. empathy_healthcare_plugin/monitors/monitoring/protocol_loader.py +214 -0
  11. empathy_healthcare_plugin/monitors/monitoring/sensor_parsers.py +306 -0
  12. empathy_healthcare_plugin/monitors/monitoring/trajectory_analyzer.py +389 -0
  13. empathy_llm_toolkit/agent_factory/__init__.py +53 -0
  14. empathy_llm_toolkit/agent_factory/adapters/__init__.py +85 -0
  15. empathy_llm_toolkit/agent_factory/adapters/autogen_adapter.py +312 -0
  16. empathy_llm_toolkit/agent_factory/adapters/crewai_adapter.py +454 -0
  17. empathy_llm_toolkit/agent_factory/adapters/haystack_adapter.py +298 -0
  18. empathy_llm_toolkit/agent_factory/adapters/langchain_adapter.py +362 -0
  19. empathy_llm_toolkit/agent_factory/adapters/langgraph_adapter.py +333 -0
  20. empathy_llm_toolkit/agent_factory/adapters/native.py +228 -0
  21. empathy_llm_toolkit/agent_factory/adapters/wizard_adapter.py +426 -0
  22. empathy_llm_toolkit/agent_factory/base.py +305 -0
  23. empathy_llm_toolkit/agent_factory/crews/__init__.py +67 -0
  24. empathy_llm_toolkit/agent_factory/crews/code_review.py +1113 -0
  25. empathy_llm_toolkit/agent_factory/crews/health_check.py +1246 -0
  26. empathy_llm_toolkit/agent_factory/crews/refactoring.py +1128 -0
  27. empathy_llm_toolkit/agent_factory/crews/security_audit.py +1018 -0
  28. empathy_llm_toolkit/agent_factory/decorators.py +286 -0
  29. empathy_llm_toolkit/agent_factory/factory.py +558 -0
  30. empathy_llm_toolkit/agent_factory/framework.py +192 -0
  31. empathy_llm_toolkit/agent_factory/memory_integration.py +324 -0
  32. empathy_llm_toolkit/agent_factory/resilient.py +320 -0
  33. empathy_llm_toolkit/cli/__init__.py +8 -0
  34. empathy_llm_toolkit/cli/sync_claude.py +487 -0
  35. empathy_llm_toolkit/code_health.py +150 -3
  36. empathy_llm_toolkit/config/__init__.py +29 -0
  37. empathy_llm_toolkit/config/unified.py +295 -0
  38. empathy_llm_toolkit/routing/__init__.py +32 -0
  39. empathy_llm_toolkit/routing/model_router.py +362 -0
  40. empathy_llm_toolkit/security/IMPLEMENTATION_SUMMARY.md +413 -0
  41. empathy_llm_toolkit/security/PHASE2_COMPLETE.md +384 -0
  42. empathy_llm_toolkit/security/PHASE2_SECRETS_DETECTOR_COMPLETE.md +271 -0
  43. empathy_llm_toolkit/security/QUICK_REFERENCE.md +316 -0
  44. empathy_llm_toolkit/security/README.md +262 -0
  45. empathy_llm_toolkit/security/__init__.py +62 -0
  46. empathy_llm_toolkit/security/audit_logger.py +929 -0
  47. empathy_llm_toolkit/security/audit_logger_example.py +152 -0
  48. empathy_llm_toolkit/security/pii_scrubber.py +640 -0
  49. empathy_llm_toolkit/security/secrets_detector.py +678 -0
  50. empathy_llm_toolkit/security/secrets_detector_example.py +304 -0
  51. empathy_llm_toolkit/security/secure_memdocs.py +1192 -0
  52. empathy_llm_toolkit/security/secure_memdocs_example.py +278 -0
  53. empathy_llm_toolkit/wizards/__init__.py +38 -0
  54. empathy_llm_toolkit/wizards/base_wizard.py +364 -0
  55. empathy_llm_toolkit/wizards/customer_support_wizard.py +190 -0
  56. empathy_llm_toolkit/wizards/healthcare_wizard.py +362 -0
  57. empathy_llm_toolkit/wizards/patient_assessment_README.md +64 -0
  58. empathy_llm_toolkit/wizards/patient_assessment_wizard.py +193 -0
  59. empathy_llm_toolkit/wizards/technology_wizard.py +194 -0
  60. empathy_os/__init__.py +52 -52
  61. empathy_os/adaptive/__init__.py +13 -0
  62. empathy_os/adaptive/task_complexity.py +127 -0
  63. empathy_os/cli.py +118 -8
  64. empathy_os/cli_unified.py +121 -1
  65. empathy_os/config/__init__.py +63 -0
  66. empathy_os/config/xml_config.py +239 -0
  67. empathy_os/dashboard/__init__.py +15 -0
  68. empathy_os/dashboard/server.py +743 -0
  69. empathy_os/memory/__init__.py +195 -0
  70. empathy_os/memory/claude_memory.py +466 -0
  71. empathy_os/memory/config.py +224 -0
  72. empathy_os/memory/control_panel.py +1298 -0
  73. empathy_os/memory/edges.py +179 -0
  74. empathy_os/memory/graph.py +567 -0
  75. empathy_os/memory/long_term.py +1193 -0
  76. empathy_os/memory/nodes.py +179 -0
  77. empathy_os/memory/redis_bootstrap.py +540 -0
  78. empathy_os/memory/security/__init__.py +31 -0
  79. empathy_os/memory/security/audit_logger.py +930 -0
  80. empathy_os/memory/security/pii_scrubber.py +640 -0
  81. empathy_os/memory/security/secrets_detector.py +678 -0
  82. empathy_os/memory/short_term.py +2119 -0
  83. empathy_os/memory/storage/__init__.py +15 -0
  84. empathy_os/memory/summary_index.py +583 -0
  85. empathy_os/memory/unified.py +619 -0
  86. empathy_os/metrics/__init__.py +12 -0
  87. empathy_os/metrics/prompt_metrics.py +190 -0
  88. empathy_os/models/__init__.py +136 -0
  89. empathy_os/models/__main__.py +13 -0
  90. empathy_os/models/cli.py +655 -0
  91. empathy_os/models/empathy_executor.py +354 -0
  92. empathy_os/models/executor.py +252 -0
  93. empathy_os/models/fallback.py +671 -0
  94. empathy_os/models/provider_config.py +563 -0
  95. empathy_os/models/registry.py +382 -0
  96. empathy_os/models/tasks.py +302 -0
  97. empathy_os/models/telemetry.py +548 -0
  98. empathy_os/models/token_estimator.py +378 -0
  99. empathy_os/models/validation.py +274 -0
  100. empathy_os/monitoring/__init__.py +52 -0
  101. empathy_os/monitoring/alerts.py +23 -0
  102. empathy_os/monitoring/alerts_cli.py +268 -0
  103. empathy_os/monitoring/multi_backend.py +271 -0
  104. empathy_os/monitoring/otel_backend.py +363 -0
  105. empathy_os/optimization/__init__.py +19 -0
  106. empathy_os/optimization/context_optimizer.py +272 -0
  107. empathy_os/plugins/__init__.py +28 -0
  108. empathy_os/plugins/base.py +361 -0
  109. empathy_os/plugins/registry.py +268 -0
  110. empathy_os/project_index/__init__.py +30 -0
  111. empathy_os/project_index/cli.py +335 -0
  112. empathy_os/project_index/crew_integration.py +430 -0
  113. empathy_os/project_index/index.py +425 -0
  114. empathy_os/project_index/models.py +501 -0
  115. empathy_os/project_index/reports.py +473 -0
  116. empathy_os/project_index/scanner.py +538 -0
  117. empathy_os/prompts/__init__.py +61 -0
  118. empathy_os/prompts/config.py +77 -0
  119. empathy_os/prompts/context.py +177 -0
  120. empathy_os/prompts/parser.py +285 -0
  121. empathy_os/prompts/registry.py +313 -0
  122. empathy_os/prompts/templates.py +208 -0
  123. empathy_os/resilience/__init__.py +56 -0
  124. empathy_os/resilience/circuit_breaker.py +256 -0
  125. empathy_os/resilience/fallback.py +179 -0
  126. empathy_os/resilience/health.py +300 -0
  127. empathy_os/resilience/retry.py +209 -0
  128. empathy_os/resilience/timeout.py +135 -0
  129. empathy_os/routing/__init__.py +43 -0
  130. empathy_os/routing/chain_executor.py +433 -0
  131. empathy_os/routing/classifier.py +217 -0
  132. empathy_os/routing/smart_router.py +234 -0
  133. empathy_os/routing/wizard_registry.py +307 -0
  134. empathy_os/trust/__init__.py +28 -0
  135. empathy_os/trust/circuit_breaker.py +579 -0
  136. empathy_os/validation/__init__.py +19 -0
  137. empathy_os/validation/xml_validator.py +281 -0
  138. empathy_os/wizard_factory_cli.py +170 -0
  139. empathy_os/workflows/__init__.py +360 -0
  140. empathy_os/workflows/base.py +1530 -0
  141. empathy_os/workflows/bug_predict.py +962 -0
  142. empathy_os/workflows/code_review.py +960 -0
  143. empathy_os/workflows/code_review_adapters.py +310 -0
  144. empathy_os/workflows/code_review_pipeline.py +720 -0
  145. empathy_os/workflows/config.py +600 -0
  146. empathy_os/workflows/dependency_check.py +648 -0
  147. empathy_os/workflows/document_gen.py +1069 -0
  148. empathy_os/workflows/documentation_orchestrator.py +1205 -0
  149. empathy_os/workflows/health_check.py +679 -0
  150. empathy_os/workflows/keyboard_shortcuts/__init__.py +39 -0
  151. empathy_os/workflows/keyboard_shortcuts/generators.py +386 -0
  152. empathy_os/workflows/keyboard_shortcuts/parsers.py +414 -0
  153. empathy_os/workflows/keyboard_shortcuts/prompts.py +295 -0
  154. empathy_os/workflows/keyboard_shortcuts/schema.py +193 -0
  155. empathy_os/workflows/keyboard_shortcuts/workflow.py +505 -0
  156. empathy_os/workflows/manage_documentation.py +804 -0
  157. empathy_os/workflows/new_sample_workflow1.py +146 -0
  158. empathy_os/workflows/new_sample_workflow1_README.md +150 -0
  159. empathy_os/workflows/perf_audit.py +687 -0
  160. empathy_os/workflows/pr_review.py +748 -0
  161. empathy_os/workflows/progress.py +445 -0
  162. empathy_os/workflows/progress_server.py +322 -0
  163. empathy_os/workflows/refactor_plan.py +691 -0
  164. empathy_os/workflows/release_prep.py +808 -0
  165. empathy_os/workflows/research_synthesis.py +404 -0
  166. empathy_os/workflows/secure_release.py +585 -0
  167. empathy_os/workflows/security_adapters.py +297 -0
  168. empathy_os/workflows/security_audit.py +1050 -0
  169. empathy_os/workflows/step_config.py +234 -0
  170. empathy_os/workflows/test5.py +125 -0
  171. empathy_os/workflows/test5_README.md +158 -0
  172. empathy_os/workflows/test_gen.py +1855 -0
  173. empathy_os/workflows/test_lifecycle.py +526 -0
  174. empathy_os/workflows/test_maintenance.py +626 -0
  175. empathy_os/workflows/test_maintenance_cli.py +590 -0
  176. empathy_os/workflows/test_maintenance_crew.py +821 -0
  177. empathy_os/workflows/xml_enhanced_crew.py +285 -0
  178. empathy_software_plugin/cli/__init__.py +120 -0
  179. empathy_software_plugin/cli/inspect.py +362 -0
  180. empathy_software_plugin/cli.py +3 -1
  181. empathy_software_plugin/wizards/__init__.py +42 -0
  182. empathy_software_plugin/wizards/advanced_debugging_wizard.py +392 -0
  183. empathy_software_plugin/wizards/agent_orchestration_wizard.py +511 -0
  184. empathy_software_plugin/wizards/ai_collaboration_wizard.py +503 -0
  185. empathy_software_plugin/wizards/ai_context_wizard.py +441 -0
  186. empathy_software_plugin/wizards/ai_documentation_wizard.py +503 -0
  187. empathy_software_plugin/wizards/base_wizard.py +288 -0
  188. empathy_software_plugin/wizards/book_chapter_wizard.py +519 -0
  189. empathy_software_plugin/wizards/code_review_wizard.py +606 -0
  190. empathy_software_plugin/wizards/debugging/__init__.py +50 -0
  191. empathy_software_plugin/wizards/debugging/bug_risk_analyzer.py +414 -0
  192. empathy_software_plugin/wizards/debugging/config_loaders.py +442 -0
  193. empathy_software_plugin/wizards/debugging/fix_applier.py +469 -0
  194. empathy_software_plugin/wizards/debugging/language_patterns.py +383 -0
  195. empathy_software_plugin/wizards/debugging/linter_parsers.py +470 -0
  196. empathy_software_plugin/wizards/debugging/verification.py +369 -0
  197. empathy_software_plugin/wizards/enhanced_testing_wizard.py +537 -0
  198. empathy_software_plugin/wizards/memory_enhanced_debugging_wizard.py +816 -0
  199. empathy_software_plugin/wizards/multi_model_wizard.py +501 -0
  200. empathy_software_plugin/wizards/pattern_extraction_wizard.py +422 -0
  201. empathy_software_plugin/wizards/pattern_retriever_wizard.py +400 -0
  202. empathy_software_plugin/wizards/performance/__init__.py +9 -0
  203. empathy_software_plugin/wizards/performance/bottleneck_detector.py +221 -0
  204. empathy_software_plugin/wizards/performance/profiler_parsers.py +278 -0
  205. empathy_software_plugin/wizards/performance/trajectory_analyzer.py +429 -0
  206. empathy_software_plugin/wizards/performance_profiling_wizard.py +305 -0
  207. empathy_software_plugin/wizards/prompt_engineering_wizard.py +425 -0
  208. empathy_software_plugin/wizards/rag_pattern_wizard.py +461 -0
  209. empathy_software_plugin/wizards/security/__init__.py +32 -0
  210. empathy_software_plugin/wizards/security/exploit_analyzer.py +290 -0
  211. empathy_software_plugin/wizards/security/owasp_patterns.py +241 -0
  212. empathy_software_plugin/wizards/security/vulnerability_scanner.py +604 -0
  213. empathy_software_plugin/wizards/security_analysis_wizard.py +322 -0
  214. empathy_software_plugin/wizards/security_learning_wizard.py +740 -0
  215. empathy_software_plugin/wizards/tech_debt_wizard.py +726 -0
  216. empathy_software_plugin/wizards/testing/__init__.py +27 -0
  217. empathy_software_plugin/wizards/testing/coverage_analyzer.py +459 -0
  218. empathy_software_plugin/wizards/testing/quality_analyzer.py +531 -0
  219. empathy_software_plugin/wizards/testing/test_suggester.py +533 -0
  220. empathy_software_plugin/wizards/testing_wizard.py +274 -0
  221. hot_reload/README.md +473 -0
  222. hot_reload/__init__.py +62 -0
  223. hot_reload/config.py +84 -0
  224. hot_reload/integration.py +228 -0
  225. hot_reload/reloader.py +298 -0
  226. hot_reload/watcher.py +179 -0
  227. hot_reload/websocket.py +176 -0
  228. scaffolding/README.md +589 -0
  229. scaffolding/__init__.py +35 -0
  230. scaffolding/__main__.py +14 -0
  231. scaffolding/cli.py +240 -0
  232. test_generator/__init__.py +38 -0
  233. test_generator/__main__.py +14 -0
  234. test_generator/cli.py +226 -0
  235. test_generator/generator.py +325 -0
  236. test_generator/risk_analyzer.py +216 -0
  237. workflow_patterns/__init__.py +33 -0
  238. workflow_patterns/behavior.py +249 -0
  239. workflow_patterns/core.py +76 -0
  240. workflow_patterns/output.py +99 -0
  241. workflow_patterns/registry.py +255 -0
  242. workflow_patterns/structural.py +288 -0
  243. workflow_scaffolding/__init__.py +11 -0
  244. workflow_scaffolding/__main__.py +12 -0
  245. workflow_scaffolding/cli.py +206 -0
  246. workflow_scaffolding/generator.py +265 -0
  247. agents/code_inspection/patterns/inspection/recurring_B112.json +0 -18
  248. agents/code_inspection/patterns/inspection/recurring_F541.json +0 -16
  249. agents/code_inspection/patterns/inspection/recurring_FORMAT.json +0 -25
  250. agents/code_inspection/patterns/inspection/recurring_bug_20250822_def456.json +0 -16
  251. agents/code_inspection/patterns/inspection/recurring_bug_20250915_abc123.json +0 -16
  252. agents/code_inspection/patterns/inspection/recurring_bug_20251212_3c5b9951.json +0 -16
  253. agents/code_inspection/patterns/inspection/recurring_bug_20251212_97c0f72f.json +0 -16
  254. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a0871d53.json +0 -16
  255. agents/code_inspection/patterns/inspection/recurring_bug_20251212_a9b6ec41.json +0 -16
  256. agents/code_inspection/patterns/inspection/recurring_bug_null_001.json +0 -16
  257. agents/code_inspection/patterns/inspection/recurring_builtin.json +0 -16
  258. agents/compliance_anticipation_agent.py +0 -1422
  259. agents/compliance_db.py +0 -339
  260. agents/epic_integration_wizard.py +0 -530
  261. agents/notifications.py +0 -291
  262. agents/trust_building_behaviors.py +0 -872
  263. empathy_framework-3.7.0.dist-info/RECORD +0 -105
  264. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/WHEEL +0 -0
  265. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/entry_points.txt +0 -0
  266. {empathy_framework-3.7.0.dist-info → empathy_framework-3.7.1.dist-info}/licenses/LICENSE +0 -0
  267. /empathy_os/{monitoring.py → agent_monitoring.py} +0 -0
@@ -0,0 +1,804 @@
1
+ """Manage_Documentation - Multi-Agent Workflow
2
+
3
+ Makes sure that new program files are fully documented and existing documents
4
+ are updated when associate program files are changed.
5
+
6
+ Pattern: Crew
7
+ - Multiple specialized AI agents collaborate on the task
8
+ - Process Type: sequential
9
+ - Agents: 4
10
+
11
+ Generated with: empathy workflow new Manage_Documentation
12
+ See: docs/guides/WORKFLOW_PATTERNS.md
13
+
14
+ Copyright 2025 Smart-AI-Memory
15
+ Licensed under Fair Source License 0.9
16
+ """
17
+
18
+ import asyncio
19
+ import os
20
+ from dataclasses import dataclass, field
21
+ from datetime import datetime
22
+ from pathlib import Path
23
+ from typing import Any
24
+
25
+ # Try to import the LLM executor for actual AI calls
26
+ EmpathyLLMExecutor = None
27
+ ExecutionContext = None
28
+ HAS_EXECUTOR = False
29
+
30
+ try:
31
+ from empathy_os.models import ExecutionContext as _ExecutionContext
32
+ from empathy_os.models.empathy_executor import EmpathyLLMExecutor as _EmpathyLLMExecutor
33
+
34
+ EmpathyLLMExecutor = _EmpathyLLMExecutor
35
+ ExecutionContext = _ExecutionContext
36
+ HAS_EXECUTOR = True
37
+ except ImportError:
38
+ pass
39
+
40
+ # Try to import the ProjectIndex for file tracking
41
+ ProjectIndex = None
42
+ HAS_PROJECT_INDEX = False
43
+
44
+ try:
45
+ from empathy_os.project_index import ProjectIndex as _ProjectIndex
46
+
47
+ ProjectIndex = _ProjectIndex
48
+ HAS_PROJECT_INDEX = True
49
+ except ImportError:
50
+ pass
51
+
52
+
53
+ @dataclass
54
+ class ManageDocumentationCrewResult:
55
+ """Result from ManageDocumentationCrew execution."""
56
+
57
+ success: bool
58
+ findings: list[dict] = field(default_factory=list)
59
+ recommendations: list[str] = field(default_factory=list)
60
+ files_analyzed: int = 0
61
+ docs_needing_update: int = 0
62
+ new_docs_needed: int = 0
63
+ confidence: float = 0.0
64
+ cost: float = 0.0
65
+ duration_ms: int = 0
66
+ formatted_report: str = ""
67
+
68
+ def to_dict(self) -> dict:
69
+ return {
70
+ "success": self.success,
71
+ "findings": self.findings,
72
+ "recommendations": self.recommendations,
73
+ "files_analyzed": self.files_analyzed,
74
+ "docs_needing_update": self.docs_needing_update,
75
+ "new_docs_needed": self.new_docs_needed,
76
+ "confidence": self.confidence,
77
+ "cost": self.cost,
78
+ "duration_ms": self.duration_ms,
79
+ "formatted_report": self.formatted_report,
80
+ }
81
+
82
+
83
+ @dataclass
84
+ class Agent:
85
+ """Agent configuration for the crew with XML-enhanced prompting."""
86
+
87
+ role: str
88
+ goal: str
89
+ backstory: str
90
+ expertise_level: str = "expert"
91
+ use_xml_structure: bool = True # Enable XML-enhanced prompting by default
92
+
93
+ def get_system_prompt(self) -> str:
94
+ """Generate XML-enhanced system prompt for this agent."""
95
+ if not self.use_xml_structure:
96
+ # Legacy format for backward compatibility
97
+ return f"""You are a {self.role} with {self.expertise_level}-level expertise.
98
+
99
+ Goal: {self.goal}
100
+
101
+ Background: {self.backstory}
102
+
103
+ Provide thorough, actionable analysis. Be specific and cite file paths when relevant."""
104
+
105
+ # XML-enhanced format (Anthropic best practice)
106
+ return f"""<agent_role>
107
+ You are a {self.role} with {self.expertise_level}-level expertise.
108
+ </agent_role>
109
+
110
+ <agent_goal>
111
+ {self.goal}
112
+ </agent_goal>
113
+
114
+ <agent_backstory>
115
+ {self.backstory}
116
+ </agent_backstory>
117
+
118
+ <instructions>
119
+ 1. Carefully review all provided context data
120
+ 2. Think through your analysis step-by-step
121
+ 3. Provide thorough, actionable analysis
122
+ 4. Be specific and cite file paths when relevant
123
+ 5. Structure your output according to the requested format
124
+ </instructions>
125
+
126
+ <output_structure>
127
+ Always structure your response as:
128
+
129
+ <thinking>
130
+ [Your step-by-step reasoning process]
131
+ - What you observe in the context
132
+ - How you analyze the situation
133
+ - What conclusions you draw
134
+ </thinking>
135
+
136
+ <answer>
137
+ [Your final output in the requested format]
138
+ </answer>
139
+ </output_structure>"""
140
+
141
+
142
+ @dataclass
143
+ class Task:
144
+ """Task configuration for the crew with XML-enhanced prompting."""
145
+
146
+ description: str
147
+ expected_output: str
148
+ agent: Agent
149
+
150
+ def get_user_prompt(self, context: dict) -> str:
151
+ """Generate XML-enhanced user prompt for this task with context."""
152
+ if not self.agent.use_xml_structure:
153
+ # Legacy format for backward compatibility
154
+ context_str = "\n".join(f"- {k}: {v}" for k, v in context.items() if v)
155
+ return f"""{self.description}
156
+
157
+ Context:
158
+ {context_str}
159
+
160
+ Expected output format: {self.expected_output}"""
161
+
162
+ # XML-enhanced format (Anthropic best practice)
163
+ # Build structured context with proper XML tags
164
+ context_sections = []
165
+ for key, value in context.items():
166
+ if value:
167
+ # Use underscores for tag names
168
+ tag_name = key.replace(" ", "_").replace("-", "_").lower()
169
+ # Wrap in appropriate tags
170
+ context_sections.append(f"<{tag_name}>\n{value}\n</{tag_name}>")
171
+
172
+ context_xml = "\n".join(context_sections)
173
+
174
+ return f"""<task_description>
175
+ {self.description}
176
+ </task_description>
177
+
178
+ <context>
179
+ {context_xml}
180
+ </context>
181
+
182
+ <expected_output>
183
+ {self.expected_output}
184
+ </expected_output>
185
+
186
+ <instructions>
187
+ 1. Review all context data in the <context> tags above
188
+ 2. Structure your response using <thinking> and <answer> tags as defined in your system prompt
189
+ 3. Match the expected output format exactly
190
+ 4. Be thorough and specific in your analysis
191
+ </instructions>"""
192
+
193
+
194
+ def parse_xml_response(response: str) -> dict:
195
+ """Parse XML-structured agent response.
196
+
197
+ Args:
198
+ response: Raw agent response potentially containing XML tags
199
+
200
+ Returns:
201
+ Dictionary with 'thinking', 'answer', and 'raw' keys
202
+ """
203
+ import re
204
+
205
+ thinking_match = re.search(r"<thinking>(.*?)</thinking>", response, re.DOTALL)
206
+ answer_match = re.search(r"<answer>(.*?)</answer>", response, re.DOTALL)
207
+
208
+ return {
209
+ "thinking": thinking_match.group(1).strip() if thinking_match else "",
210
+ "answer": answer_match.group(1).strip() if answer_match else response.strip(),
211
+ "raw": response,
212
+ "has_structure": bool(thinking_match and answer_match),
213
+ }
214
+
215
+
216
+ def format_manage_docs_report(result: ManageDocumentationCrewResult, path: str) -> str:
217
+ """Format documentation management output as a human-readable report.
218
+
219
+ Args:
220
+ result: The ManageDocumentationCrewResult
221
+ path: The path that was analyzed
222
+
223
+ Returns:
224
+ Formatted report string
225
+ """
226
+ lines = []
227
+
228
+ # Header with confidence
229
+ confidence = result.confidence
230
+ if confidence >= 0.8:
231
+ confidence_icon = "🟢"
232
+ confidence_text = "HIGH CONFIDENCE"
233
+ elif confidence >= 0.5:
234
+ confidence_icon = "🟡"
235
+ confidence_text = "MODERATE CONFIDENCE"
236
+ else:
237
+ confidence_icon = "🔴"
238
+ confidence_text = "LOW CONFIDENCE (Mock Mode)"
239
+
240
+ lines.append("=" * 60)
241
+ lines.append("DOCUMENTATION SYNC REPORT")
242
+ lines.append("=" * 60)
243
+ lines.append("")
244
+ lines.append(f"Path Analyzed: {path}")
245
+ lines.append(f"Confidence: {confidence_icon} {confidence_text} ({confidence:.0%})")
246
+ lines.append("")
247
+
248
+ # Summary
249
+ lines.append("-" * 60)
250
+ lines.append("SUMMARY")
251
+ lines.append("-" * 60)
252
+ lines.append(f"Files Analyzed: {result.files_analyzed}")
253
+ lines.append(f"Docs Needing Update: {result.docs_needing_update}")
254
+ lines.append(f"New Docs Needed: {result.new_docs_needed}")
255
+ lines.append(f"Duration: {result.duration_ms}ms ({result.duration_ms / 1000:.1f}s)")
256
+ lines.append(f"Cost: ${result.cost:.4f}")
257
+ lines.append("")
258
+
259
+ # Agent Findings
260
+ if result.findings:
261
+ lines.append("-" * 60)
262
+ lines.append("AGENT FINDINGS")
263
+ lines.append("-" * 60)
264
+ for i, finding in enumerate(result.findings, 1):
265
+ agent = finding.get("agent", f"Agent {i}")
266
+ response = finding.get("response", "")
267
+ thinking = finding.get("thinking", "")
268
+ answer = finding.get("answer", "")
269
+ has_xml = finding.get("has_xml_structure", False)
270
+ cost = finding.get("cost", 0.0)
271
+
272
+ lines.append(
273
+ f"\n{i}. {agent} (Cost: ${cost:.4f}) {'🔬 XML-Structured' if has_xml else ''}"
274
+ )
275
+ lines.append(" " + "-" * 54)
276
+
277
+ # Show thinking and answer separately if available
278
+ if has_xml and thinking:
279
+ lines.append(" 💭 Thinking:")
280
+ if len(thinking) > 300:
281
+ lines.append(f" {thinking[:300]}...")
282
+ else:
283
+ lines.append(f" {thinking}")
284
+ lines.append("")
285
+ lines.append(" ✅ Answer:")
286
+ if len(answer) > 300:
287
+ lines.append(f" {answer[:300]}...")
288
+ else:
289
+ lines.append(f" {answer}")
290
+ else:
291
+ # Fallback to original response
292
+ if len(response) > 500:
293
+ lines.append(f" {response[:500]}...")
294
+ lines.append(f" [Truncated - {len(response)} chars total]")
295
+ else:
296
+ lines.append(f" {response}")
297
+ lines.append("")
298
+
299
+ # Recommendations
300
+ if result.recommendations:
301
+ lines.append("-" * 60)
302
+ lines.append("RECOMMENDATIONS")
303
+ lines.append("-" * 60)
304
+ for i, rec in enumerate(result.recommendations, 1):
305
+ lines.append(f"{i}. {rec}")
306
+ lines.append("")
307
+
308
+ # Next Steps
309
+ lines.append("-" * 60)
310
+ lines.append("NEXT STEPS")
311
+ lines.append("-" * 60)
312
+ lines.append("1. Review agent findings above for specific files")
313
+ lines.append("2. Prioritize documentation updates based on impact")
314
+ lines.append("3. Use 'Generate Docs' workflow for auto-generation")
315
+ lines.append("4. Run this workflow periodically to keep docs in sync")
316
+ lines.append("")
317
+
318
+ # Footer
319
+ lines.append("=" * 60)
320
+ if result.success:
321
+ lines.append("✅ Documentation sync analysis complete")
322
+ else:
323
+ lines.append("❌ Documentation sync analysis failed")
324
+ lines.append("=" * 60)
325
+
326
+ return "\n".join(lines)
327
+
328
+
329
+ class ManageDocumentationCrew:
330
+ """Manage_Documentation - Documentation management crew.
331
+
332
+ Makes sure that new program files are fully documented and existing
333
+ documents are updated when associated program files are changed.
334
+
335
+ Process Type: sequential
336
+
337
+ Agents:
338
+ - Analyst: Scans codebase to identify documentation gaps
339
+ - Reviewer: Cross-checks findings and validates accuracy
340
+ - Synthesizer: Combines findings into actionable recommendations
341
+ - Manager: Coordinates actions and prioritizes work
342
+
343
+ Usage:
344
+ crew = ManageDocumentationCrew()
345
+ result = await crew.execute(path="./src", context={})
346
+ """
347
+
348
+ name = "Manage_Documentation"
349
+ description = "Makes sure that new program files are fully documented and existing documents are updated when associated program files are changed."
350
+ process_type = "sequential"
351
+
352
+ def __init__(self, project_root: str = ".", **kwargs: Any):
353
+ """Initialize the crew with configured agents."""
354
+ self.config = kwargs
355
+ self.project_root = project_root
356
+ self._executor = None
357
+ self._project_index = None
358
+ self._total_cost = 0.0
359
+ self._total_input_tokens = 0
360
+ self._total_output_tokens = 0
361
+
362
+ # Initialize executor if available
363
+ if HAS_EXECUTOR and EmpathyLLMExecutor is not None:
364
+ api_key = os.getenv("ANTHROPIC_API_KEY")
365
+ if api_key:
366
+ try:
367
+ self._executor = EmpathyLLMExecutor(
368
+ provider="anthropic",
369
+ api_key=api_key,
370
+ )
371
+ except Exception:
372
+ pass
373
+
374
+ # Initialize ProjectIndex if available
375
+ if HAS_PROJECT_INDEX and ProjectIndex is not None:
376
+ try:
377
+ self._project_index = ProjectIndex(project_root)
378
+ if not self._project_index.load():
379
+ # Index doesn't exist or is stale, refresh it
380
+ print(" [ProjectIndex] Building index (first run)...")
381
+ self._project_index.refresh()
382
+ except Exception as e:
383
+ print(f" [ProjectIndex] Warning: Could not load index: {e}")
384
+
385
+ # Define agents
386
+ self.analyst = Agent(
387
+ role="Documentation Analyst",
388
+ goal="Scan the codebase to identify files lacking documentation and find stale docs",
389
+ backstory="Expert analyst who understands code structure, docstrings, and documentation best practices. Skilled at identifying gaps between code and documentation.",
390
+ expertise_level="expert",
391
+ )
392
+
393
+ self.reviewer = Agent(
394
+ role="Documentation Reviewer",
395
+ goal="Cross-check findings and validate accuracy of the analysis",
396
+ backstory="Experienced technical writer and reviewer focused on quality, correctness, and ensuring documentation matches actual code behavior.",
397
+ expertise_level="expert",
398
+ )
399
+
400
+ self.synthesizer = Agent(
401
+ role="Documentation Synthesizer",
402
+ goal="Combine findings into actionable, prioritized recommendations",
403
+ backstory="Strategic thinker who excels at synthesis and prioritization. Creates clear action plans that developers can follow.",
404
+ expertise_level="expert",
405
+ )
406
+
407
+ self.manager = Agent(
408
+ role="Documentation Manager",
409
+ goal="Coordinate actions of other agents and prioritize documentation work",
410
+ backstory="Understands the documentation needs of the project and the capability of other agents. Makes decisions about what to document first based on impact and effort.",
411
+ expertise_level="world-class",
412
+ )
413
+
414
+ # Store all agents
415
+ self.agents = [self.analyst, self.reviewer, self.synthesizer, self.manager]
416
+
417
+ def define_tasks(self) -> list[Task]:
418
+ """Define the tasks for this crew."""
419
+ return [
420
+ Task(
421
+ description="Analyze the codebase to identify: 1) Python files without docstrings, 2) Functions/classes missing documentation, 3) README files that may be outdated, 4) Missing API documentation",
422
+ expected_output="JSON list of findings with: file_path, issue_type (missing_docstring|stale_doc|no_readme), severity (high|medium|low), details",
423
+ agent=self.analyst,
424
+ ),
425
+ Task(
426
+ description="Review and validate the analysis findings. Check if flagged files truly need documentation updates. Identify any false positives.",
427
+ expected_output="Validated findings with confidence scores (0-1) and notes on any false positives removed",
428
+ agent=self.reviewer,
429
+ ),
430
+ Task(
431
+ description="Synthesize validated findings into a prioritized action plan. Group by module/area, estimate effort, and create clear next steps.",
432
+ expected_output="Prioritized list of documentation tasks with: priority (1-5), task description, estimated effort (small|medium|large), files involved",
433
+ agent=self.synthesizer,
434
+ ),
435
+ ]
436
+
437
+ async def _call_llm(
438
+ self,
439
+ agent: Agent,
440
+ task: Task,
441
+ context: dict,
442
+ task_type: str = "code_analysis",
443
+ ) -> tuple[str, int, int, float]:
444
+ """Call the LLM with agent/task configuration.
445
+
446
+ Returns: (response_text, input_tokens, output_tokens, cost)
447
+ """
448
+ system_prompt = agent.get_system_prompt()
449
+ user_prompt = task.get_user_prompt(context)
450
+
451
+ if self._executor is not None and ExecutionContext is not None:
452
+ try:
453
+ exec_context = ExecutionContext(
454
+ workflow_name=self.name,
455
+ step_name=agent.role.lower().replace(" ", "_"),
456
+ task_type=task_type,
457
+ )
458
+
459
+ response = await self._executor.run(
460
+ task_type=task_type,
461
+ prompt=user_prompt,
462
+ system=system_prompt,
463
+ context=exec_context,
464
+ )
465
+
466
+ return (
467
+ response.content,
468
+ response.tokens_input,
469
+ response.tokens_output,
470
+ response.cost_estimate or 0.0,
471
+ )
472
+ except Exception as e:
473
+ # Fallback to mock response on error
474
+ return self._mock_response(agent, task, context, str(e))
475
+ else:
476
+ # No executor available - return mock response
477
+ return self._mock_response(agent, task, context, "No LLM executor configured")
478
+
479
+ def _mock_response(
480
+ self,
481
+ agent: Agent,
482
+ task: Task,
483
+ context: dict,
484
+ reason: str,
485
+ ) -> tuple[str, int, int, float]:
486
+ """Generate a mock response when LLM is not available."""
487
+ mock_findings = {
488
+ "Documentation Analyst": f"""[Mock Analysis - {reason}]
489
+
490
+ Based on scanning the path: {context.get("path", ".")}
491
+
492
+ Findings:
493
+ 1. {{
494
+ "file_path": "src/example.py",
495
+ "issue_type": "missing_docstring",
496
+ "severity": "medium",
497
+ "details": "Module lacks module-level docstring"
498
+ }}
499
+ 2. {{
500
+ "file_path": "README.md",
501
+ "issue_type": "stale_doc",
502
+ "severity": "low",
503
+ "details": "README may not reflect recent changes"
504
+ }}
505
+
506
+ Note: This is a mock response. Configure ANTHROPIC_API_KEY for real analysis.""",
507
+ "Documentation Reviewer": f"""[Mock Review - {reason}]
508
+
509
+ Validated Findings:
510
+ - Finding 1: VALID (confidence: 0.8) - Missing docstrings are a real issue
511
+ - Finding 2: NEEDS_VERIFICATION (confidence: 0.5) - Stale docs need manual check
512
+
513
+ False Positives Removed: 0
514
+
515
+ Note: This is a mock response. Configure ANTHROPIC_API_KEY for real analysis.""",
516
+ "Documentation Synthesizer": f"""[Mock Synthesis - {reason}]
517
+
518
+ Prioritized Action Plan:
519
+
520
+ 1. Priority 1 (High) - Add module docstrings
521
+ - Effort: small
522
+ - Files: src/example.py
523
+
524
+ 2. Priority 3 (Medium) - Review README accuracy
525
+ - Effort: medium
526
+ - Files: README.md
527
+
528
+ Note: This is a mock response. Configure ANTHROPIC_API_KEY for real analysis.""",
529
+ }
530
+
531
+ response = mock_findings.get(agent.role, f"Mock response for {agent.role}")
532
+ return (response, 0, 0, 0.0)
533
+
534
+ def _scan_directory(self, path: str) -> dict:
535
+ """Scan directory for Python files and documentation."""
536
+ path_obj = Path(path)
537
+ if not path_obj.exists():
538
+ return {"error": f"Path does not exist: {path}"}
539
+
540
+ python_files = []
541
+ doc_files = []
542
+
543
+ # Find Python files
544
+ for py_file in path_obj.rglob("*.py"):
545
+ if "__pycache__" not in str(py_file):
546
+ python_files.append(str(py_file))
547
+
548
+ # Find documentation files
549
+ for pattern in ["*.md", "*.rst", "*.txt"]:
550
+ for doc_file in path_obj.rglob(pattern):
551
+ doc_files.append(str(doc_file))
552
+
553
+ return {
554
+ "python_files": python_files[:50], # Limit for context
555
+ "python_file_count": len(python_files),
556
+ "doc_files": doc_files[:20],
557
+ "doc_file_count": len(doc_files),
558
+ }
559
+
560
+ def _get_index_context(self) -> dict[str, Any]:
561
+ """Get documentation context from ProjectIndex if available."""
562
+ if self._project_index is None:
563
+ return {}
564
+
565
+ try:
566
+ return self._project_index.get_context_for_workflow("documentation")
567
+ except Exception as e:
568
+ print(f" [ProjectIndex] Warning: Could not get context: {e}")
569
+ return {}
570
+
571
+ async def execute(
572
+ self,
573
+ path: str = ".",
574
+ context: dict | None = None,
575
+ **kwargs: Any,
576
+ ) -> ManageDocumentationCrewResult:
577
+ """Execute the documentation management crew.
578
+
579
+ Args:
580
+ path: Path to analyze for documentation gaps
581
+ context: Additional context for agents
582
+ **kwargs: Additional arguments
583
+
584
+ Returns:
585
+ ManageDocumentationCrewResult with findings and recommendations
586
+
587
+ """
588
+ started_at = datetime.now()
589
+ context = context or {}
590
+
591
+ # Try to get rich context from ProjectIndex
592
+ index_context = self._get_index_context()
593
+
594
+ if index_context:
595
+ print(" [ProjectIndex] Using indexed file data")
596
+ doc_stats = index_context.get("documentation_stats", {})
597
+
598
+ # Build context from index
599
+ agent_context = {
600
+ "path": path,
601
+ "python_files": f"{doc_stats.get('total_python_files', 0)} Python files indexed",
602
+ "files_with_docstrings": f"{doc_stats.get('files_with_docstrings', 0)} files ({doc_stats.get('docstring_coverage_pct', 0):.1f}% coverage)",
603
+ "files_without_docstrings": f"{doc_stats.get('files_without_docstrings', 0)} files need docstrings",
604
+ "type_hint_coverage": f"{doc_stats.get('type_hint_coverage_pct', 0):.1f}%",
605
+ "high_impact_undocumented": doc_stats.get("priority_files", []),
606
+ "doc_files": f"{doc_stats.get('doc_file_count', 0)} documentation files",
607
+ "total_loc_undocumented": doc_stats.get("loc_undocumented", 0),
608
+ # New: modification tracking
609
+ "recently_modified_source_count": doc_stats.get(
610
+ "recently_modified_source_count",
611
+ 0,
612
+ ),
613
+ "stale_docs_count": doc_stats.get("stale_docs_count", 0),
614
+ **context,
615
+ }
616
+
617
+ # Add sample of files needing docs
618
+ files_without_docs = index_context.get("files_without_docstrings", [])
619
+ if files_without_docs:
620
+ agent_context["sample_undocumented"] = [f["path"] for f in files_without_docs[:10]]
621
+
622
+ # Add recently modified source files (last 7 days)
623
+ recent_source = index_context.get("recently_modified_source", [])
624
+ if recent_source:
625
+ agent_context["recently_modified_source_files"] = [
626
+ {"path": f["path"], "modified": f.get("last_modified")}
627
+ for f in recent_source[:10]
628
+ ]
629
+
630
+ # Add docs that may need review (source changed after doc)
631
+ docs_needing_review = index_context.get("docs_needing_review", [])
632
+ if docs_needing_review:
633
+ stale_docs = [d for d in docs_needing_review if d.get("source_modified_after_doc")]
634
+ agent_context["stale_docs"] = [
635
+ {
636
+ "doc": d["doc_file"],
637
+ "related_source": d["related_source_files"][:3],
638
+ "days_since_update": d["days_since_doc_update"],
639
+ }
640
+ for d in stale_docs[:5]
641
+ ]
642
+
643
+ scan_results = {
644
+ "python_file_count": doc_stats.get("total_python_files", 0),
645
+ "doc_file_count": doc_stats.get("doc_file_count", 0),
646
+ "python_files": [f["path"] for f in files_without_docs[:50]],
647
+ "doc_files": [f["path"] for f in index_context.get("doc_files", [])[:20]],
648
+ "recently_modified_count": doc_stats.get("recently_modified_source_count", 0),
649
+ "stale_docs_count": doc_stats.get("stale_docs_count", 0),
650
+ }
651
+ else:
652
+ # Fallback to directory scanning
653
+ print(" [Fallback] Scanning directory manually")
654
+ scan_results = self._scan_directory(path)
655
+ if "error" in scan_results:
656
+ return ManageDocumentationCrewResult(
657
+ success=False,
658
+ findings=[{"error": scan_results["error"]}],
659
+ recommendations=["Fix the path and try again"],
660
+ )
661
+
662
+ # Build context for agents
663
+ agent_context = {
664
+ "path": path,
665
+ "python_files": f"{scan_results['python_file_count']} files found",
666
+ "sample_files": ", ".join(scan_results["python_files"][:10]),
667
+ "doc_files": f"{scan_results['doc_file_count']} doc files found",
668
+ **context,
669
+ }
670
+
671
+ # Get tasks
672
+ tasks = self.define_tasks()
673
+
674
+ # Execute tasks sequentially (crew pattern)
675
+ all_findings: list[dict] = []
676
+ all_responses: list[str] = []
677
+
678
+ for i, task in enumerate(tasks):
679
+ print(f" [{i + 1}/{len(tasks)}] {task.agent.role}: {task.description[:50]}...")
680
+
681
+ # Add previous task output to context
682
+ if all_responses:
683
+ agent_context["previous_analysis"] = all_responses[-1][:2000]
684
+
685
+ # Determine task type for routing
686
+ task_type = "code_analysis"
687
+ if "review" in task.agent.role.lower():
688
+ task_type = "code_analysis" # Could be "review" if defined
689
+ elif "synth" in task.agent.role.lower():
690
+ task_type = "summarize"
691
+
692
+ # Call LLM
693
+ response, in_tokens, out_tokens, cost = await self._call_llm(
694
+ agent=task.agent,
695
+ task=task,
696
+ context=agent_context,
697
+ task_type=task_type,
698
+ )
699
+
700
+ # Track metrics
701
+ self._total_input_tokens += in_tokens
702
+ self._total_output_tokens += out_tokens
703
+ self._total_cost += cost
704
+
705
+ # Parse XML-structured response if available
706
+ parsed = parse_xml_response(response)
707
+
708
+ # Store full response for next agent's context
709
+ all_responses.append(response)
710
+
711
+ # Store findings with parsed structure
712
+ all_findings.append(
713
+ {
714
+ "agent": task.agent.role,
715
+ "task": task.description[:100],
716
+ "response": response[:1000], # Truncate for result
717
+ "thinking": parsed["thinking"][:500] if parsed["thinking"] else "",
718
+ "answer": parsed["answer"][:500] if parsed["answer"] else response[:500],
719
+ "has_xml_structure": parsed["has_structure"],
720
+ "tokens": {"input": in_tokens, "output": out_tokens},
721
+ "cost": cost,
722
+ },
723
+ )
724
+
725
+ # Manager coordination (final synthesis)
726
+ manager_context = {
727
+ "path": path,
728
+ "analyst_findings": all_responses[0][:1500] if len(all_responses) > 0 else "",
729
+ "reviewer_validation": all_responses[1][:1500] if len(all_responses) > 1 else "",
730
+ "synthesizer_plan": all_responses[2][:1500] if len(all_responses) > 2 else "",
731
+ }
732
+
733
+ print(f" [Final] {self.manager.role}: Coordinating final output...")
734
+
735
+ manager_task = Task(
736
+ description="Review all agent outputs and create a final executive summary with the top 3-5 prioritized actions for improving documentation.",
737
+ expected_output="Executive summary with: 1) Overall documentation health score (0-100), 2) Top priorities, 3) Quick wins, 4) Estimated total effort",
738
+ agent=self.manager,
739
+ )
740
+
741
+ final_response, in_tokens, out_tokens, cost = await self._call_llm(
742
+ agent=self.manager,
743
+ task=manager_task,
744
+ context=manager_context,
745
+ task_type="summarize",
746
+ )
747
+
748
+ self._total_input_tokens += in_tokens
749
+ self._total_output_tokens += out_tokens
750
+ self._total_cost += cost
751
+
752
+ # Calculate duration
753
+ duration_ms = int((datetime.now() - started_at).total_seconds() * 1000)
754
+
755
+ # Build recommendations from final response
756
+ recommendations = [
757
+ f"Documentation analysis complete for {path}",
758
+ f"Analyzed {scan_results['python_file_count']} Python files",
759
+ f"Found {scan_results['doc_file_count']} documentation files",
760
+ ]
761
+
762
+ # Add synthesized recommendations if available
763
+ if len(all_responses) > 2:
764
+ recommendations.append("See synthesizer output for prioritized action plan")
765
+
766
+ # Create result
767
+ result = ManageDocumentationCrewResult(
768
+ success=True,
769
+ findings=all_findings,
770
+ recommendations=recommendations,
771
+ files_analyzed=scan_results["python_file_count"],
772
+ docs_needing_update=0, # Would be parsed from actual LLM response
773
+ new_docs_needed=0, # Would be parsed from actual LLM response
774
+ confidence=0.75 if self._executor else 0.3,
775
+ cost=self._total_cost,
776
+ duration_ms=duration_ms,
777
+ )
778
+
779
+ # Generate formatted report
780
+ result.formatted_report = format_manage_docs_report(result, path)
781
+
782
+ return result
783
+
784
+
785
+ # CLI entry point for testing
786
+ if __name__ == "__main__":
787
+ import sys
788
+
789
+ async def main():
790
+ path = sys.argv[1] if len(sys.argv) > 1 else "."
791
+ print(f"ManageDocumentationCrew - Analyzing: {path}\n")
792
+
793
+ crew = ManageDocumentationCrew()
794
+ print(f"Crew: {crew.name}")
795
+ print(f"Agents: {len(crew.agents)}")
796
+ print(f"LLM Executor: {'Available' if crew._executor else 'Not configured (using mocks)'}")
797
+ print()
798
+
799
+ result = await crew.execute(path=path)
800
+
801
+ # Print formatted report
802
+ print("\n" + result.formatted_report)
803
+
804
+ asyncio.run(main())