kodit 0.5.0__py3-none-any.whl → 0.5.2__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.

Potentially problematic release.


This version of kodit might be problematic. Click here for more details.

Files changed (70) hide show
  1. kodit/_version.py +2 -2
  2. kodit/app.py +10 -12
  3. kodit/application/factories/server_factory.py +78 -11
  4. kodit/application/services/commit_indexing_application_service.py +188 -31
  5. kodit/application/services/enrichment_query_service.py +95 -0
  6. kodit/config.py +3 -3
  7. kodit/domain/enrichments/__init__.py +1 -0
  8. kodit/domain/enrichments/architecture/__init__.py +1 -0
  9. kodit/domain/enrichments/architecture/architecture.py +20 -0
  10. kodit/domain/enrichments/architecture/physical/__init__.py +1 -0
  11. kodit/domain/enrichments/architecture/physical/discovery_notes.py +14 -0
  12. kodit/domain/enrichments/architecture/physical/formatter.py +11 -0
  13. kodit/domain/enrichments/architecture/physical/physical.py +17 -0
  14. kodit/domain/enrichments/development/__init__.py +1 -0
  15. kodit/domain/enrichments/development/development.py +18 -0
  16. kodit/domain/enrichments/development/snippet/__init__.py +1 -0
  17. kodit/domain/enrichments/development/snippet/snippet.py +21 -0
  18. kodit/domain/enrichments/enricher.py +17 -0
  19. kodit/domain/enrichments/enrichment.py +39 -0
  20. kodit/domain/enrichments/request.py +12 -0
  21. kodit/domain/enrichments/response.py +11 -0
  22. kodit/domain/enrichments/usage/__init__.py +1 -0
  23. kodit/domain/enrichments/usage/api_docs.py +19 -0
  24. kodit/domain/enrichments/usage/usage.py +18 -0
  25. kodit/domain/protocols.py +7 -6
  26. kodit/domain/services/enrichment_service.py +9 -30
  27. kodit/domain/services/physical_architecture_service.py +182 -0
  28. kodit/domain/tracking/__init__.py +1 -0
  29. kodit/domain/tracking/resolution_service.py +81 -0
  30. kodit/domain/tracking/trackable.py +21 -0
  31. kodit/domain/value_objects.py +6 -23
  32. kodit/infrastructure/api/v1/dependencies.py +15 -0
  33. kodit/infrastructure/api/v1/routers/commits.py +81 -0
  34. kodit/infrastructure/api/v1/routers/repositories.py +99 -0
  35. kodit/infrastructure/api/v1/schemas/enrichment.py +29 -0
  36. kodit/infrastructure/cloning/git/git_python_adaptor.py +71 -4
  37. kodit/infrastructure/enricher/__init__.py +1 -0
  38. kodit/infrastructure/enricher/enricher_factory.py +53 -0
  39. kodit/infrastructure/{enrichment/litellm_enrichment_provider.py → enricher/litellm_enricher.py} +20 -33
  40. kodit/infrastructure/{enrichment/local_enrichment_provider.py → enricher/local_enricher.py} +19 -24
  41. kodit/infrastructure/enricher/null_enricher.py +36 -0
  42. kodit/infrastructure/mappers/enrichment_mapper.py +83 -0
  43. kodit/infrastructure/mappers/snippet_mapper.py +20 -22
  44. kodit/infrastructure/physical_architecture/__init__.py +1 -0
  45. kodit/infrastructure/physical_architecture/detectors/__init__.py +1 -0
  46. kodit/infrastructure/physical_architecture/detectors/docker_compose_detector.py +336 -0
  47. kodit/infrastructure/physical_architecture/formatters/__init__.py +1 -0
  48. kodit/infrastructure/physical_architecture/formatters/narrative_formatter.py +149 -0
  49. kodit/infrastructure/slicing/api_doc_extractor.py +836 -0
  50. kodit/infrastructure/slicing/ast_analyzer.py +1128 -0
  51. kodit/infrastructure/slicing/slicer.py +56 -391
  52. kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +118 -0
  53. kodit/infrastructure/sqlalchemy/entities.py +46 -38
  54. kodit/infrastructure/sqlalchemy/git_branch_repository.py +22 -11
  55. kodit/infrastructure/sqlalchemy/git_commit_repository.py +23 -14
  56. kodit/infrastructure/sqlalchemy/git_repository.py +27 -17
  57. kodit/infrastructure/sqlalchemy/git_tag_repository.py +22 -11
  58. kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +101 -106
  59. kodit/migrations/versions/19f8c7faf8b9_add_generic_enrichment_type.py +260 -0
  60. kodit/utils/dump_config.py +361 -0
  61. kodit/utils/dump_openapi.py +5 -6
  62. {kodit-0.5.0.dist-info → kodit-0.5.2.dist-info}/METADATA +1 -1
  63. {kodit-0.5.0.dist-info → kodit-0.5.2.dist-info}/RECORD +67 -32
  64. kodit/infrastructure/enrichment/__init__.py +0 -1
  65. kodit/infrastructure/enrichment/enrichment_factory.py +0 -52
  66. kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -19
  67. /kodit/infrastructure/{enrichment → enricher}/utils.py +0 -0
  68. {kodit-0.5.0.dist-info → kodit-0.5.2.dist-info}/WHEEL +0 -0
  69. {kodit-0.5.0.dist-info → kodit-0.5.2.dist-info}/entry_points.txt +0 -0
  70. {kodit-0.5.0.dist-info → kodit-0.5.2.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,149 @@
1
+ """Narrative formatter for converting observations to LLM-optimized text."""
2
+
3
+ import re
4
+
5
+ from kodit.domain.enrichments.architecture.physical.discovery_notes import (
6
+ ArchitectureDiscoveryNotes,
7
+ )
8
+
9
+
10
+ class NarrativeFormatter:
11
+ """Formats architecture observations into narrative text optimized for LLM consumption.""" # noqa: E501
12
+
13
+ def format_for_llm(self, notes: ArchitectureDiscoveryNotes) -> str:
14
+ """Convert discovery notes into a comprehensive narrative format."""
15
+ sections = []
16
+
17
+ # Title and overview
18
+ sections.append("# Physical Architecture Discovery Report")
19
+ sections.append("")
20
+ sections.append(notes.repository_context)
21
+ sections.append("")
22
+
23
+ # Component Analysis
24
+ self._add_component_section(sections, notes.component_observations)
25
+
26
+ # Connection Analysis
27
+ self._add_connection_section(sections, notes.connection_observations)
28
+
29
+ # Infrastructure Analysis
30
+ self._add_infrastructure_section(sections, notes.infrastructure_observations)
31
+
32
+ # Methodology
33
+ sections.append("## Discovery Methodology")
34
+ sections.append(notes.discovery_metadata)
35
+ sections.append("")
36
+
37
+ # Conclusion
38
+ self._add_conclusion_section(sections, notes)
39
+
40
+ return "\n".join(sections)
41
+
42
+ def _add_component_section(
43
+ self, sections: list[str], component_observations: list[str]
44
+ ) -> None:
45
+ """Add component observations section with proper formatting."""
46
+ sections.append("## Components")
47
+ sections.append("")
48
+
49
+ if component_observations:
50
+ for i, observation in enumerate(component_observations, 1):
51
+ sections.append(f"**{i}.** {observation}")
52
+ sections.append("")
53
+
54
+ # Extract and highlight port information
55
+ port_info = self._extract_port_information(component_observations)
56
+ if port_info:
57
+ sections.append("### Port Mappings")
58
+ sections.append("")
59
+ for component, ports_desc in port_info.items():
60
+ sections.append(f"- **{component}**: {ports_desc}")
61
+ sections.append("")
62
+ else:
63
+ sections.append("None. Likely monolithic or library architecture.")
64
+ sections.append("")
65
+
66
+ def _add_connection_section(
67
+ self, sections: list[str], connection_observations: list[str]
68
+ ) -> None:
69
+ """Add connection observations section with proper formatting."""
70
+ sections.append("## Connections")
71
+ sections.append("")
72
+
73
+ if connection_observations:
74
+ for i, observation in enumerate(connection_observations, 1):
75
+ sections.append(f"**{i}.** {observation}")
76
+ sections.append("")
77
+ else:
78
+ sections.append("None. Possible monolithic or independent services.")
79
+ sections.append("")
80
+
81
+ def _add_infrastructure_section(
82
+ self, sections: list[str], infrastructure_observations: list[str]
83
+ ) -> None:
84
+ """Add infrastructure observations section with proper formatting."""
85
+ sections.append("## Infrastructure")
86
+ sections.append("")
87
+
88
+ if infrastructure_observations:
89
+ for i, observation in enumerate(infrastructure_observations, 1):
90
+ sections.append(f"**{i}.** {observation}")
91
+ sections.append("")
92
+ else:
93
+ sections.append("None. May use external or cloud-native deployment.")
94
+ sections.append("")
95
+
96
+ def _add_conclusion_section(
97
+ self, sections: list[str], notes: ArchitectureDiscoveryNotes
98
+ ) -> None:
99
+ """Add a conclusion section summarizing the findings."""
100
+ sections.append("## Summary")
101
+ sections.append("")
102
+
103
+ # Determine architecture characteristics
104
+ has_components = bool(notes.component_observations)
105
+ has_connections = bool(notes.connection_observations)
106
+ has_infrastructure = bool(notes.infrastructure_observations)
107
+
108
+ if has_components and has_connections and has_infrastructure:
109
+ arch_type = "distributed microservices"
110
+ complexity = "high"
111
+ elif has_components and (has_connections or has_infrastructure):
112
+ arch_type = "multi-component"
113
+ complexity = "medium"
114
+ elif has_components or has_infrastructure:
115
+ arch_type = "structured application"
116
+ complexity = "medium"
117
+ else:
118
+ arch_type = "monolithic"
119
+ complexity = "low"
120
+
121
+ sections.append(f"**Architecture:** {arch_type} | **Complexity:** {complexity}")
122
+ sections.append("")
123
+ sections.append("**Note:** Static analysis only. Runtime behavior may differ.")
124
+
125
+ def _extract_port_information(
126
+ self, component_observations: list[str]
127
+ ) -> dict[str, str]:
128
+ """Extract port information from component observations."""
129
+ port_info = {}
130
+
131
+ # Pattern to extract service name and port information
132
+ service_pattern = r"Found '([^']+)' service"
133
+ port_pattern = r"Exposes ports ([\d, ]+)(?: suggesting ([^.]+))?"
134
+
135
+ for observation in component_observations:
136
+ service_match = re.search(service_pattern, observation)
137
+ port_match = re.search(port_pattern, observation)
138
+
139
+ if service_match and port_match:
140
+ service_name = service_match.group(1)
141
+ ports = port_match.group(1).strip()
142
+ protocol = port_match.group(2)
143
+
144
+ if protocol:
145
+ port_info[service_name] = f"{ports} ({protocol})"
146
+ else:
147
+ port_info[service_name] = ports
148
+
149
+ return port_info