kodit 0.5.5__py3-none-any.whl → 0.5.6__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.
- kodit/_version.py +2 -2
- kodit/app.py +2 -0
- kodit/application/factories/server_factory.py +4 -0
- kodit/application/services/commit_indexing_application_service.py +213 -0
- kodit/application/services/enrichment_query_service.py +37 -0
- kodit/domain/enrichments/architecture/database_schema/__init__.py +1 -0
- kodit/domain/enrichments/architecture/database_schema/database_schema.py +17 -0
- kodit/domain/enrichments/history/__init__.py +1 -0
- kodit/domain/enrichments/history/commit_description/__init__.py +1 -0
- kodit/domain/enrichments/history/commit_description/commit_description.py +17 -0
- kodit/domain/enrichments/history/history.py +18 -0
- kodit/domain/protocols.py +4 -0
- kodit/domain/value_objects.py +4 -0
- kodit/infrastructure/cloning/git/git_python_adaptor.py +41 -0
- kodit/infrastructure/database_schema/__init__.py +1 -0
- kodit/infrastructure/database_schema/database_schema_detector.py +268 -0
- kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +29 -0
- {kodit-0.5.5.dist-info → kodit-0.5.6.dist-info}/METADATA +1 -1
- {kodit-0.5.5.dist-info → kodit-0.5.6.dist-info}/RECORD +22 -14
- {kodit-0.5.5.dist-info → kodit-0.5.6.dist-info}/WHEEL +0 -0
- {kodit-0.5.5.dist-info → kodit-0.5.6.dist-info}/entry_points.txt +0 -0
- {kodit-0.5.5.dist-info → kodit-0.5.6.dist-info}/licenses/LICENSE +0 -0
kodit/_version.py
CHANGED
|
@@ -28,7 +28,7 @@ version_tuple: VERSION_TUPLE
|
|
|
28
28
|
commit_id: COMMIT_ID
|
|
29
29
|
__commit_id__: COMMIT_ID
|
|
30
30
|
|
|
31
|
-
__version__ = version = '0.5.
|
|
32
|
-
__version_tuple__ = version_tuple = (0, 5,
|
|
31
|
+
__version__ = version = '0.5.6'
|
|
32
|
+
__version_tuple__ = version_tuple = (0, 5, 6)
|
|
33
33
|
|
|
34
34
|
__commit_id__ = commit_id = None
|
kodit/app.py
CHANGED
|
@@ -50,6 +50,9 @@ from kodit.infrastructure.bm25.vectorchord_bm25_repository import (
|
|
|
50
50
|
VectorChordBM25Repository,
|
|
51
51
|
)
|
|
52
52
|
from kodit.infrastructure.cloning.git.git_python_adaptor import GitPythonAdapter
|
|
53
|
+
from kodit.infrastructure.database_schema.database_schema_detector import (
|
|
54
|
+
DatabaseSchemaDetector,
|
|
55
|
+
)
|
|
53
56
|
from kodit.infrastructure.embedding.embedding_factory import (
|
|
54
57
|
embedding_domain_service_factory,
|
|
55
58
|
)
|
|
@@ -255,6 +258,7 @@ class ServerFactory:
|
|
|
255
258
|
text_search_service=self.text_search_service(),
|
|
256
259
|
embedding_repository=self.embedding_repository(),
|
|
257
260
|
architecture_service=self.architecture_service(),
|
|
261
|
+
database_schema_detector=DatabaseSchemaDetector(),
|
|
258
262
|
enrichment_v2_repository=self.enrichment_v2_repository(),
|
|
259
263
|
enricher_service=self.enricher(),
|
|
260
264
|
enrichment_association_repository=self.enrichment_association_repository(),
|
|
@@ -14,6 +14,9 @@ if TYPE_CHECKING:
|
|
|
14
14
|
from kodit.application.services.enrichment_query_service import (
|
|
15
15
|
EnrichmentQueryService,
|
|
16
16
|
)
|
|
17
|
+
from kodit.domain.enrichments.architecture.database_schema.database_schema import (
|
|
18
|
+
DatabaseSchemaEnrichment,
|
|
19
|
+
)
|
|
17
20
|
from kodit.domain.enrichments.architecture.physical.physical import (
|
|
18
21
|
PhysicalArchitectureEnrichment,
|
|
19
22
|
)
|
|
@@ -27,6 +30,9 @@ from kodit.domain.enrichments.enrichment import (
|
|
|
27
30
|
EnrichmentAssociation,
|
|
28
31
|
EnrichmentV2,
|
|
29
32
|
)
|
|
33
|
+
from kodit.domain.enrichments.history.commit_description.commit_description import (
|
|
34
|
+
CommitDescriptionEnrichment,
|
|
35
|
+
)
|
|
30
36
|
from kodit.domain.enrichments.request import (
|
|
31
37
|
EnrichmentRequest as GenericEnrichmentRequest,
|
|
32
38
|
)
|
|
@@ -63,6 +69,9 @@ from kodit.domain.value_objects import (
|
|
|
63
69
|
TaskOperation,
|
|
64
70
|
TrackableType,
|
|
65
71
|
)
|
|
72
|
+
from kodit.infrastructure.database_schema.database_schema_detector import (
|
|
73
|
+
DatabaseSchemaDetector,
|
|
74
|
+
)
|
|
66
75
|
from kodit.infrastructure.slicing.api_doc_extractor import APIDocExtractor
|
|
67
76
|
from kodit.infrastructure.slicing.slicer import Slicer
|
|
68
77
|
from kodit.infrastructure.sqlalchemy import entities as db_entities
|
|
@@ -82,6 +91,73 @@ You are a professional software developer. You will be given a snippet of code.
|
|
|
82
91
|
Please provide a concise explanation of the code.
|
|
83
92
|
"""
|
|
84
93
|
|
|
94
|
+
COMMIT_DESCRIPTION_SYSTEM_PROMPT = """
|
|
95
|
+
You are a professional software developer. You will be given a git commit diff.
|
|
96
|
+
Please provide a concise description of what changes were made and why.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
DATABASE_SCHEMA_SYSTEM_PROMPT = """
|
|
100
|
+
You are an expert database architect and documentation specialist.
|
|
101
|
+
Your task is to create clear, visual documentation of database schemas.
|
|
102
|
+
"""
|
|
103
|
+
|
|
104
|
+
DATABASE_SCHEMA_TASK_PROMPT = """
|
|
105
|
+
You will be provided with a database schema discovery report.
|
|
106
|
+
Please create comprehensive database schema documentation.
|
|
107
|
+
|
|
108
|
+
<schema_report>
|
|
109
|
+
{schema_report}
|
|
110
|
+
</schema_report>
|
|
111
|
+
|
|
112
|
+
**Return the following:**
|
|
113
|
+
|
|
114
|
+
## Entity List
|
|
115
|
+
|
|
116
|
+
For each table/entity, write one line:
|
|
117
|
+
- **[Table Name]**: [brief description of what it stores]
|
|
118
|
+
|
|
119
|
+
## Mermaid ERD
|
|
120
|
+
|
|
121
|
+
Create a Mermaid Entity Relationship Diagram showing:
|
|
122
|
+
- All entities (tables)
|
|
123
|
+
- Key relationships between entities (if apparent from names or common patterns)
|
|
124
|
+
- Use standard ERD notation
|
|
125
|
+
|
|
126
|
+
Example format:
|
|
127
|
+
```mermaid
|
|
128
|
+
erDiagram
|
|
129
|
+
User ||--o{{ Order : places
|
|
130
|
+
User {{
|
|
131
|
+
int id PK
|
|
132
|
+
string email
|
|
133
|
+
string name
|
|
134
|
+
}}
|
|
135
|
+
Order {{
|
|
136
|
+
int id PK
|
|
137
|
+
int user_id FK
|
|
138
|
+
datetime created_at
|
|
139
|
+
}}
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
If specific field details aren't available, show just the entity boxes and
|
|
143
|
+
relationships.
|
|
144
|
+
|
|
145
|
+
## Key Observations
|
|
146
|
+
|
|
147
|
+
Answer these questions in 1-2 sentences each:
|
|
148
|
+
1. What is the primary data model pattern (e.g., user-centric,
|
|
149
|
+
event-sourced, multi-tenant)?
|
|
150
|
+
2. What migration strategy is being used?
|
|
151
|
+
3. Are there any notable database design patterns or concerns?
|
|
152
|
+
|
|
153
|
+
## Rules:
|
|
154
|
+
- Be concise and focus on the high-level structure
|
|
155
|
+
- Infer reasonable relationships from table names when explicit information
|
|
156
|
+
isn't available
|
|
157
|
+
- If no database schema is found, state that clearly
|
|
158
|
+
- Keep entity descriptions to 10 words or less
|
|
159
|
+
"""
|
|
160
|
+
|
|
85
161
|
|
|
86
162
|
class CommitIndexingApplicationService:
|
|
87
163
|
"""Application service for commit indexing operations."""
|
|
@@ -103,6 +179,7 @@ class CommitIndexingApplicationService:
|
|
|
103
179
|
text_search_service: EmbeddingDomainService,
|
|
104
180
|
embedding_repository: SqlAlchemyEmbeddingRepository,
|
|
105
181
|
architecture_service: PhysicalArchitectureService,
|
|
182
|
+
database_schema_detector: DatabaseSchemaDetector,
|
|
106
183
|
enricher_service: Enricher,
|
|
107
184
|
enrichment_v2_repository: EnrichmentV2Repository,
|
|
108
185
|
enrichment_association_repository: EnrichmentAssociationRepository,
|
|
@@ -124,6 +201,7 @@ class CommitIndexingApplicationService:
|
|
|
124
201
|
self.text_search_service = text_search_service
|
|
125
202
|
self.embedding_repository = embedding_repository
|
|
126
203
|
self.architecture_service = architecture_service
|
|
204
|
+
self.database_schema_detector = database_schema_detector
|
|
127
205
|
self.enrichment_v2_repository = enrichment_v2_repository
|
|
128
206
|
self.enrichment_association_repository = enrichment_association_repository
|
|
129
207
|
self.enricher_service = enricher_service
|
|
@@ -191,6 +269,10 @@ class CommitIndexingApplicationService:
|
|
|
191
269
|
await self.process_architecture_discovery(repository_id, commit_sha)
|
|
192
270
|
elif task.type == TaskOperation.CREATE_PUBLIC_API_DOCS_FOR_COMMIT:
|
|
193
271
|
await self.process_api_docs(repository_id, commit_sha)
|
|
272
|
+
elif task.type == TaskOperation.CREATE_COMMIT_DESCRIPTION_FOR_COMMIT:
|
|
273
|
+
await self.process_commit_description(repository_id, commit_sha)
|
|
274
|
+
elif task.type == TaskOperation.CREATE_DATABASE_SCHEMA_FOR_COMMIT:
|
|
275
|
+
await self.process_database_schema(repository_id, commit_sha)
|
|
194
276
|
else:
|
|
195
277
|
raise ValueError(f"Unknown task type: {task.type}")
|
|
196
278
|
else:
|
|
@@ -798,6 +880,137 @@ class CommitIndexingApplicationService:
|
|
|
798
880
|
]
|
|
799
881
|
)
|
|
800
882
|
|
|
883
|
+
async def process_commit_description(
|
|
884
|
+
self, repository_id: int, commit_sha: str
|
|
885
|
+
) -> None:
|
|
886
|
+
"""Handle COMMIT_DESCRIPTION task - generate commit descriptions."""
|
|
887
|
+
async with self.operation.create_child(
|
|
888
|
+
TaskOperation.CREATE_COMMIT_DESCRIPTION_FOR_COMMIT,
|
|
889
|
+
trackable_type=TrackableType.KODIT_REPOSITORY,
|
|
890
|
+
trackable_id=repository_id,
|
|
891
|
+
) as step:
|
|
892
|
+
# Check if commit description already exists for this commit
|
|
893
|
+
if await self.enrichment_query_service.has_commit_description_for_commit(
|
|
894
|
+
commit_sha
|
|
895
|
+
):
|
|
896
|
+
await step.skip("Commit description already exists for commit")
|
|
897
|
+
return
|
|
898
|
+
|
|
899
|
+
# Get repository path
|
|
900
|
+
repo = await self.repo_repository.get(repository_id)
|
|
901
|
+
if not repo.cloned_path:
|
|
902
|
+
raise ValueError(f"Repository {repository_id} has never been cloned")
|
|
903
|
+
|
|
904
|
+
await step.set_total(3)
|
|
905
|
+
await step.set_current(1, "Getting commit diff")
|
|
906
|
+
|
|
907
|
+
# Get the diff for this commit
|
|
908
|
+
diff = await self.scanner.git_adapter.get_commit_diff(
|
|
909
|
+
repo.cloned_path, commit_sha
|
|
910
|
+
)
|
|
911
|
+
|
|
912
|
+
if not diff or len(diff.strip()) == 0:
|
|
913
|
+
await step.skip("No diff found for commit")
|
|
914
|
+
return
|
|
915
|
+
|
|
916
|
+
await step.set_current(2, "Enriching commit description with LLM")
|
|
917
|
+
|
|
918
|
+
# Enrich the diff through the enricher
|
|
919
|
+
enrichment_request = GenericEnrichmentRequest(
|
|
920
|
+
id=commit_sha,
|
|
921
|
+
text=diff,
|
|
922
|
+
system_prompt=COMMIT_DESCRIPTION_SYSTEM_PROMPT,
|
|
923
|
+
)
|
|
924
|
+
|
|
925
|
+
enriched_content = ""
|
|
926
|
+
async for response in self.enricher_service.enrich([enrichment_request]):
|
|
927
|
+
enriched_content = response.text
|
|
928
|
+
|
|
929
|
+
# Create and save commit description enrichment
|
|
930
|
+
enrichment = await self.enrichment_v2_repository.save(
|
|
931
|
+
CommitDescriptionEnrichment(
|
|
932
|
+
content=enriched_content,
|
|
933
|
+
)
|
|
934
|
+
)
|
|
935
|
+
if not enrichment or not enrichment.id:
|
|
936
|
+
raise ValueError(
|
|
937
|
+
f"Failed to save commit description enrichment for commit "
|
|
938
|
+
f"{commit_sha}"
|
|
939
|
+
)
|
|
940
|
+
await self.enrichment_association_repository.save(
|
|
941
|
+
CommitEnrichmentAssociation(
|
|
942
|
+
enrichment_id=enrichment.id,
|
|
943
|
+
entity_id=commit_sha,
|
|
944
|
+
)
|
|
945
|
+
)
|
|
946
|
+
|
|
947
|
+
await step.set_current(3, "Commit description enrichment completed")
|
|
948
|
+
|
|
949
|
+
async def process_database_schema(
|
|
950
|
+
self, repository_id: int, commit_sha: str
|
|
951
|
+
) -> None:
|
|
952
|
+
"""Handle DATABASE_SCHEMA task - discover and document database schemas."""
|
|
953
|
+
async with self.operation.create_child(
|
|
954
|
+
TaskOperation.CREATE_DATABASE_SCHEMA_FOR_COMMIT,
|
|
955
|
+
trackable_type=TrackableType.KODIT_REPOSITORY,
|
|
956
|
+
trackable_id=repository_id,
|
|
957
|
+
) as step:
|
|
958
|
+
# Check if database schema already exists for this commit
|
|
959
|
+
if await self.enrichment_query_service.has_database_schema_for_commit(
|
|
960
|
+
commit_sha
|
|
961
|
+
):
|
|
962
|
+
await step.skip("Database schema already exists for commit")
|
|
963
|
+
return
|
|
964
|
+
|
|
965
|
+
# Get repository path
|
|
966
|
+
repo = await self.repo_repository.get(repository_id)
|
|
967
|
+
if not repo.cloned_path:
|
|
968
|
+
raise ValueError(f"Repository {repository_id} has never been cloned")
|
|
969
|
+
|
|
970
|
+
await step.set_total(3)
|
|
971
|
+
await step.set_current(1, "Discovering database schemas")
|
|
972
|
+
|
|
973
|
+
# Discover database schemas
|
|
974
|
+
schema_report = await self.database_schema_detector.discover_schemas(
|
|
975
|
+
repo.cloned_path
|
|
976
|
+
)
|
|
977
|
+
|
|
978
|
+
if "No database schemas detected" in schema_report:
|
|
979
|
+
await step.skip("No database schemas found in repository")
|
|
980
|
+
return
|
|
981
|
+
|
|
982
|
+
await step.set_current(2, "Enriching schema documentation with LLM")
|
|
983
|
+
|
|
984
|
+
# Enrich the schema report through the enricher
|
|
985
|
+
enrichment_request = GenericEnrichmentRequest(
|
|
986
|
+
id=commit_sha,
|
|
987
|
+
text=DATABASE_SCHEMA_TASK_PROMPT.format(schema_report=schema_report),
|
|
988
|
+
system_prompt=DATABASE_SCHEMA_SYSTEM_PROMPT,
|
|
989
|
+
)
|
|
990
|
+
|
|
991
|
+
enriched_content = ""
|
|
992
|
+
async for response in self.enricher_service.enrich([enrichment_request]):
|
|
993
|
+
enriched_content = response.text
|
|
994
|
+
|
|
995
|
+
# Create and save database schema enrichment
|
|
996
|
+
enrichment = await self.enrichment_v2_repository.save(
|
|
997
|
+
DatabaseSchemaEnrichment(
|
|
998
|
+
content=enriched_content,
|
|
999
|
+
)
|
|
1000
|
+
)
|
|
1001
|
+
if not enrichment or not enrichment.id:
|
|
1002
|
+
raise ValueError(
|
|
1003
|
+
f"Failed to save database schema enrichment for commit {commit_sha}"
|
|
1004
|
+
)
|
|
1005
|
+
await self.enrichment_association_repository.save(
|
|
1006
|
+
CommitEnrichmentAssociation(
|
|
1007
|
+
enrichment_id=enrichment.id,
|
|
1008
|
+
entity_id=commit_sha,
|
|
1009
|
+
)
|
|
1010
|
+
)
|
|
1011
|
+
|
|
1012
|
+
await step.set_current(3, "Database schema enrichment completed")
|
|
1013
|
+
|
|
801
1014
|
async def _new_snippets_for_type(
|
|
802
1015
|
self, all_snippets: list[EnrichmentV2], embedding_type: EmbeddingType
|
|
803
1016
|
) -> list[EnrichmentV2]:
|
|
@@ -5,6 +5,9 @@ import structlog
|
|
|
5
5
|
from kodit.domain.enrichments.architecture.architecture import (
|
|
6
6
|
ENRICHMENT_TYPE_ARCHITECTURE,
|
|
7
7
|
)
|
|
8
|
+
from kodit.domain.enrichments.architecture.database_schema.database_schema import (
|
|
9
|
+
ENRICHMENT_SUBTYPE_DATABASE_SCHEMA,
|
|
10
|
+
)
|
|
8
11
|
from kodit.domain.enrichments.architecture.physical.physical import (
|
|
9
12
|
ENRICHMENT_SUBTYPE_PHYSICAL,
|
|
10
13
|
)
|
|
@@ -14,6 +17,10 @@ from kodit.domain.enrichments.development.snippet.snippet import (
|
|
|
14
17
|
ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY,
|
|
15
18
|
)
|
|
16
19
|
from kodit.domain.enrichments.enrichment import EnrichmentAssociation, EnrichmentV2
|
|
20
|
+
from kodit.domain.enrichments.history.commit_description.commit_description import (
|
|
21
|
+
ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION,
|
|
22
|
+
)
|
|
23
|
+
from kodit.domain.enrichments.history.history import ENRICHMENT_TYPE_HISTORY
|
|
17
24
|
from kodit.domain.enrichments.usage.api_docs import ENRICHMENT_SUBTYPE_API_DOCS
|
|
18
25
|
from kodit.domain.enrichments.usage.usage import ENRICHMENT_TYPE_USAGE
|
|
19
26
|
from kodit.domain.protocols import (
|
|
@@ -215,6 +222,36 @@ class EnrichmentQueryService:
|
|
|
215
222
|
api_docs = await self.get_api_docs_for_commit(commit_sha)
|
|
216
223
|
return len(api_docs) > 0
|
|
217
224
|
|
|
225
|
+
async def get_commit_description_for_commit(
|
|
226
|
+
self, commit_sha: str
|
|
227
|
+
) -> list[EnrichmentV2]:
|
|
228
|
+
"""Get commit description enrichments for a commit."""
|
|
229
|
+
return await self.get_enrichments_for_commit(
|
|
230
|
+
commit_sha,
|
|
231
|
+
enrichment_type=ENRICHMENT_TYPE_HISTORY,
|
|
232
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION,
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
async def has_commit_description_for_commit(self, commit_sha: str) -> bool:
|
|
236
|
+
"""Check if a commit has commit description enrichments."""
|
|
237
|
+
commit_descriptions = await self.get_commit_description_for_commit(commit_sha)
|
|
238
|
+
return len(commit_descriptions) > 0
|
|
239
|
+
|
|
240
|
+
async def get_database_schema_for_commit(
|
|
241
|
+
self, commit_sha: str
|
|
242
|
+
) -> list[EnrichmentV2]:
|
|
243
|
+
"""Get database schema enrichments for a commit."""
|
|
244
|
+
return await self.get_enrichments_for_commit(
|
|
245
|
+
commit_sha,
|
|
246
|
+
enrichment_type=ENRICHMENT_TYPE_ARCHITECTURE,
|
|
247
|
+
enrichment_subtype=ENRICHMENT_SUBTYPE_DATABASE_SCHEMA,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
async def has_database_schema_for_commit(self, commit_sha: str) -> bool:
|
|
251
|
+
"""Check if a commit has database schema enrichments."""
|
|
252
|
+
database_schemas = await self.get_database_schema_for_commit(commit_sha)
|
|
253
|
+
return len(database_schemas) > 0
|
|
254
|
+
|
|
218
255
|
async def associations_for_enrichments(
|
|
219
256
|
self, enrichments: list[EnrichmentV2]
|
|
220
257
|
) -> list[EnrichmentAssociation]:
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Database schema enrichments."""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Database schema enrichment domain entity."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from kodit.domain.enrichments.architecture.architecture import ArchitectureEnrichment
|
|
6
|
+
|
|
7
|
+
ENRICHMENT_SUBTYPE_DATABASE_SCHEMA = "database_schema"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class DatabaseSchemaEnrichment(ArchitectureEnrichment):
|
|
12
|
+
"""Enrichment containing database schema information for a commit."""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def subtype(self) -> str | None:
|
|
16
|
+
"""Return the enrichment subtype."""
|
|
17
|
+
return ENRICHMENT_SUBTYPE_DATABASE_SCHEMA
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""History enrichments."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Commit description enrichments."""
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"""Commit description enrichment domain entity."""
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
from kodit.domain.enrichments.history.history import HistoryEnrichment
|
|
6
|
+
|
|
7
|
+
ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION = "commit_description"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@dataclass(frozen=True)
|
|
11
|
+
class CommitDescriptionEnrichment(HistoryEnrichment):
|
|
12
|
+
"""Enrichment containing a description of what a commit did."""
|
|
13
|
+
|
|
14
|
+
@property
|
|
15
|
+
def subtype(self) -> str | None:
|
|
16
|
+
"""Return the enrichment subtype."""
|
|
17
|
+
return ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"""History enrichment domain entity."""
|
|
2
|
+
|
|
3
|
+
from abc import ABC
|
|
4
|
+
from dataclasses import dataclass
|
|
5
|
+
|
|
6
|
+
from kodit.domain.enrichments.enrichment import CommitEnrichment
|
|
7
|
+
|
|
8
|
+
ENRICHMENT_TYPE_HISTORY = "history"
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True)
|
|
12
|
+
class HistoryEnrichment(CommitEnrichment, ABC):
|
|
13
|
+
"""Enrichment containing historical information for a commit."""
|
|
14
|
+
|
|
15
|
+
@property
|
|
16
|
+
def type(self) -> str:
|
|
17
|
+
"""Return the enrichment type."""
|
|
18
|
+
return ENRICHMENT_TYPE_HISTORY
|
kodit/domain/protocols.py
CHANGED
|
@@ -213,6 +213,10 @@ class GitAdapter(ABC):
|
|
|
213
213
|
) -> list[str]:
|
|
214
214
|
"""Get only commit SHAs for a branch (much faster than full commit data)."""
|
|
215
215
|
|
|
216
|
+
@abstractmethod
|
|
217
|
+
async def get_commit_diff(self, local_path: Path, commit_sha: str) -> str:
|
|
218
|
+
"""Get the diff for a specific commit."""
|
|
219
|
+
|
|
216
220
|
|
|
217
221
|
class SnippetRepositoryV2(ABC):
|
|
218
222
|
"""Repository for snippet operations."""
|
kodit/domain/value_objects.py
CHANGED
|
@@ -614,6 +614,8 @@ class TaskOperation(StrEnum):
|
|
|
614
614
|
"kodit.commit.create_architecture_enrichment"
|
|
615
615
|
)
|
|
616
616
|
CREATE_PUBLIC_API_DOCS_FOR_COMMIT = "kodit.commit.create_public_api_docs"
|
|
617
|
+
CREATE_COMMIT_DESCRIPTION_FOR_COMMIT = "kodit.commit.create_commit_description"
|
|
618
|
+
CREATE_DATABASE_SCHEMA_FOR_COMMIT = "kodit.commit.create_database_schema"
|
|
617
619
|
|
|
618
620
|
def is_repository_operation(self) -> bool:
|
|
619
621
|
"""Check if the task operation is a repository operation."""
|
|
@@ -639,6 +641,8 @@ class PrescribedOperations:
|
|
|
639
641
|
TaskOperation.CREATE_SUMMARY_EMBEDDINGS_FOR_COMMIT,
|
|
640
642
|
TaskOperation.CREATE_ARCHITECTURE_ENRICHMENT_FOR_COMMIT,
|
|
641
643
|
TaskOperation.CREATE_PUBLIC_API_DOCS_FOR_COMMIT,
|
|
644
|
+
TaskOperation.CREATE_COMMIT_DESCRIPTION_FOR_COMMIT,
|
|
645
|
+
TaskOperation.CREATE_DATABASE_SCHEMA_FOR_COMMIT,
|
|
642
646
|
]
|
|
643
647
|
SYNC_REPOSITORY: ClassVar[list[TaskOperation]] = [
|
|
644
648
|
TaskOperation.SCAN_REPOSITORY,
|
|
@@ -532,3 +532,44 @@ class GitPythonAdapter(GitAdapter):
|
|
|
532
532
|
raise
|
|
533
533
|
|
|
534
534
|
return await asyncio.get_event_loop().run_in_executor(self.executor, _get_tags)
|
|
535
|
+
|
|
536
|
+
async def get_commit_diff(self, local_path: Path, commit_sha: str) -> str:
|
|
537
|
+
"""Get the diff for a specific commit."""
|
|
538
|
+
|
|
539
|
+
def _get_diff() -> str:
|
|
540
|
+
try:
|
|
541
|
+
repo = Repo(local_path)
|
|
542
|
+
commit = repo.commit(commit_sha)
|
|
543
|
+
|
|
544
|
+
# If this is the first commit (no parents), show diff against empty tree
|
|
545
|
+
if not commit.parents:
|
|
546
|
+
diffs = commit.diff(None, create_patch=True)
|
|
547
|
+
if not diffs:
|
|
548
|
+
return ""
|
|
549
|
+
first_diff = diffs[0]
|
|
550
|
+
diff_bytes = first_diff.diff
|
|
551
|
+
if isinstance(diff_bytes, bytes):
|
|
552
|
+
return diff_bytes.decode("utf-8")
|
|
553
|
+
return str(diff_bytes) if diff_bytes is not None else ""
|
|
554
|
+
|
|
555
|
+
# For commits with parents, show diff against first parent
|
|
556
|
+
parent = commit.parents[0]
|
|
557
|
+
diffs = parent.diff(commit, create_patch=True)
|
|
558
|
+
|
|
559
|
+
# Combine all diffs into a single string
|
|
560
|
+
diff_text = ""
|
|
561
|
+
for diff in diffs:
|
|
562
|
+
diff_bytes = diff.diff
|
|
563
|
+
if diff_bytes and isinstance(diff_bytes, bytes):
|
|
564
|
+
diff_text += diff_bytes.decode("utf-8")
|
|
565
|
+
except Exception as e:
|
|
566
|
+
self._log.error(
|
|
567
|
+
f"Failed to get diff for commit {commit_sha} in {local_path}: {e}"
|
|
568
|
+
)
|
|
569
|
+
raise
|
|
570
|
+
else:
|
|
571
|
+
return diff_text
|
|
572
|
+
|
|
573
|
+
return await asyncio.get_event_loop().run_in_executor(
|
|
574
|
+
self.executor, _get_diff
|
|
575
|
+
)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Database schema detection infrastructure."""
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""Database schema detector for discovering database schemas in a repository."""
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import ClassVar
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class DatabaseSchemaDetector:
|
|
9
|
+
"""Detects database schemas from various sources in a repository."""
|
|
10
|
+
|
|
11
|
+
# File patterns to look for
|
|
12
|
+
MIGRATION_PATTERNS: ClassVar[list[str]] = [
|
|
13
|
+
"**/migrations/**/*.sql",
|
|
14
|
+
"**/migrations/**/*.py",
|
|
15
|
+
"**/migrate/**/*.sql",
|
|
16
|
+
"**/migrate/**/*.go",
|
|
17
|
+
"**/db/migrate/**/*.rb",
|
|
18
|
+
"**/alembic/versions/**/*.py",
|
|
19
|
+
"**/liquibase/**/*.xml",
|
|
20
|
+
"**/flyway/**/*.sql",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
SQL_FILE_PATTERNS: ClassVar[list[str]] = [
|
|
24
|
+
"**/*.sql",
|
|
25
|
+
"**/schema/**/*.sql",
|
|
26
|
+
"**/schemas/**/*.sql",
|
|
27
|
+
"**/database/**/*.sql",
|
|
28
|
+
"**/db/**/*.sql",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
ORM_MODEL_PATTERNS: ClassVar[list[str]] = [
|
|
32
|
+
"**/models/**/*.py", # SQLAlchemy, Django
|
|
33
|
+
"**/models/**/*.go", # GORM
|
|
34
|
+
"**/entities/**/*.py", # SQLAlchemy
|
|
35
|
+
"**/entities/**/*.ts", # TypeORM
|
|
36
|
+
"**/entities/**/*.js", # TypeORM/Sequelize
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
# Regex patterns for schema detection
|
|
40
|
+
CREATE_TABLE_PATTERN = re.compile(
|
|
41
|
+
r"CREATE\s+TABLE\s+(?:IF\s+NOT\s+EXISTS\s+)?[`\"]?(\w+)[`\"]?",
|
|
42
|
+
re.IGNORECASE,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
SQLALCHEMY_MODEL_PATTERN = re.compile(
|
|
46
|
+
r"class\s+(\w+)\s*\([^)]*(?:Base|Model|db\.Model)[^)]*\):",
|
|
47
|
+
re.MULTILINE,
|
|
48
|
+
)
|
|
49
|
+
|
|
50
|
+
GORM_MODEL_PATTERN = re.compile(
|
|
51
|
+
r"type\s+(\w+)\s+struct\s*{[^}]*gorm\.Model",
|
|
52
|
+
re.MULTILINE | re.DOTALL,
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
TYPEORM_ENTITY_PATTERN = re.compile(
|
|
56
|
+
r"@Entity\([^)]*\)\s*(?:export\s+)?class\s+(\w+)",
|
|
57
|
+
re.MULTILINE,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
async def discover_schemas(self, repo_path: Path) -> str:
|
|
61
|
+
"""Discover database schemas and generate a structured report."""
|
|
62
|
+
findings: dict[str, set[str] | list[str] | list[dict] | None] = {
|
|
63
|
+
"tables": set(),
|
|
64
|
+
"migration_files": [],
|
|
65
|
+
"sql_files": [],
|
|
66
|
+
"orm_models": [],
|
|
67
|
+
"orm_type": None,
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
# Detect migration files
|
|
71
|
+
await self._detect_migrations(repo_path, findings)
|
|
72
|
+
|
|
73
|
+
# Detect SQL schema files
|
|
74
|
+
await self._detect_sql_files(repo_path, findings)
|
|
75
|
+
|
|
76
|
+
# Detect ORM models
|
|
77
|
+
await self._detect_orm_models(repo_path, findings)
|
|
78
|
+
|
|
79
|
+
# Generate report
|
|
80
|
+
return self._generate_report(findings)
|
|
81
|
+
|
|
82
|
+
async def _detect_migrations(self, repo_path: Path, findings: dict) -> None:
|
|
83
|
+
"""Detect migration files."""
|
|
84
|
+
for pattern in self.MIGRATION_PATTERNS:
|
|
85
|
+
for file_path in repo_path.glob(pattern):
|
|
86
|
+
if file_path.is_file():
|
|
87
|
+
findings["migration_files"].append(str(file_path.relative_to(repo_path)))
|
|
88
|
+
# Try to extract table names from migrations
|
|
89
|
+
await self._extract_tables_from_file(file_path, findings)
|
|
90
|
+
|
|
91
|
+
async def _detect_sql_files(self, repo_path: Path, findings: dict) -> None:
|
|
92
|
+
"""Detect SQL schema files."""
|
|
93
|
+
migration_paths = set(findings["migration_files"])
|
|
94
|
+
|
|
95
|
+
for pattern in self.SQL_FILE_PATTERNS:
|
|
96
|
+
for file_path in repo_path.glob(pattern):
|
|
97
|
+
if file_path.is_file():
|
|
98
|
+
rel_path = str(file_path.relative_to(repo_path))
|
|
99
|
+
# Skip if already counted as migration
|
|
100
|
+
if rel_path not in migration_paths:
|
|
101
|
+
findings["sql_files"].append(rel_path)
|
|
102
|
+
await self._extract_tables_from_file(file_path, findings)
|
|
103
|
+
|
|
104
|
+
async def _detect_orm_models(self, repo_path: Path, findings: dict) -> None:
|
|
105
|
+
"""Detect ORM model files."""
|
|
106
|
+
for pattern in self.ORM_MODEL_PATTERNS:
|
|
107
|
+
for file_path in repo_path.glob(pattern):
|
|
108
|
+
if file_path.is_file():
|
|
109
|
+
rel_path = str(file_path.relative_to(repo_path))
|
|
110
|
+
models = await self._extract_orm_models(file_path)
|
|
111
|
+
if models:
|
|
112
|
+
findings["orm_models"].append({
|
|
113
|
+
"file": rel_path,
|
|
114
|
+
"models": models,
|
|
115
|
+
})
|
|
116
|
+
findings["tables"].update(models)
|
|
117
|
+
|
|
118
|
+
async def _extract_tables_from_file(self, file_path: Path, findings: dict) -> None:
|
|
119
|
+
"""Extract table names from SQL or migration files."""
|
|
120
|
+
try:
|
|
121
|
+
content = file_path.read_text(encoding="utf-8", errors="ignore")
|
|
122
|
+
|
|
123
|
+
# Look for CREATE TABLE statements
|
|
124
|
+
for match in self.CREATE_TABLE_PATTERN.finditer(content):
|
|
125
|
+
table_name = match.group(1)
|
|
126
|
+
findings["tables"].add(table_name)
|
|
127
|
+
|
|
128
|
+
except (OSError, UnicodeDecodeError):
|
|
129
|
+
pass
|
|
130
|
+
|
|
131
|
+
async def _extract_orm_models(self, file_path: Path) -> list[str]:
|
|
132
|
+
"""Extract ORM model names from model files."""
|
|
133
|
+
models: list[str] = []
|
|
134
|
+
|
|
135
|
+
try:
|
|
136
|
+
content = file_path.read_text(encoding="utf-8", errors="ignore")
|
|
137
|
+
suffix = file_path.suffix
|
|
138
|
+
|
|
139
|
+
if suffix == ".py":
|
|
140
|
+
# SQLAlchemy or Django models
|
|
141
|
+
models.extend(
|
|
142
|
+
match.group(1)
|
|
143
|
+
for match in self.SQLALCHEMY_MODEL_PATTERN.finditer(content)
|
|
144
|
+
)
|
|
145
|
+
|
|
146
|
+
elif suffix == ".go":
|
|
147
|
+
# GORM models
|
|
148
|
+
models.extend(
|
|
149
|
+
match.group(1)
|
|
150
|
+
for match in self.GORM_MODEL_PATTERN.finditer(content)
|
|
151
|
+
)
|
|
152
|
+
|
|
153
|
+
elif suffix in [".ts", ".js"]:
|
|
154
|
+
# TypeORM entities
|
|
155
|
+
models.extend(
|
|
156
|
+
match.group(1)
|
|
157
|
+
for match in self.TYPEORM_ENTITY_PATTERN.finditer(content)
|
|
158
|
+
)
|
|
159
|
+
|
|
160
|
+
except (OSError, UnicodeDecodeError):
|
|
161
|
+
pass
|
|
162
|
+
|
|
163
|
+
return models
|
|
164
|
+
|
|
165
|
+
def _generate_report(self, findings: dict) -> str: # noqa: PLR0915, C901, PLR0912
|
|
166
|
+
"""Generate a structured report of database schema findings."""
|
|
167
|
+
lines = []
|
|
168
|
+
|
|
169
|
+
# Summary
|
|
170
|
+
lines.append("# Database Schema Discovery Report")
|
|
171
|
+
lines.append("")
|
|
172
|
+
|
|
173
|
+
has_findings = (
|
|
174
|
+
findings["tables"]
|
|
175
|
+
or findings["migration_files"]
|
|
176
|
+
or findings["sql_files"]
|
|
177
|
+
or findings["orm_models"]
|
|
178
|
+
)
|
|
179
|
+
if not has_findings:
|
|
180
|
+
lines.append("No database schemas detected in this repository.")
|
|
181
|
+
return "\n".join(lines)
|
|
182
|
+
|
|
183
|
+
# Tables/Entities found
|
|
184
|
+
if findings["tables"]:
|
|
185
|
+
lines.append(f"## Detected Tables/Entities ({len(findings['tables'])})")
|
|
186
|
+
lines.append("")
|
|
187
|
+
lines.extend(f"- {table}" for table in sorted(findings["tables"]))
|
|
188
|
+
lines.append("")
|
|
189
|
+
|
|
190
|
+
# Migration files
|
|
191
|
+
if findings["migration_files"]:
|
|
192
|
+
lines.append(f"## Migration Files ({len(findings['migration_files'])})")
|
|
193
|
+
lines.append("")
|
|
194
|
+
lines.append(
|
|
195
|
+
"Database migrations detected, suggesting schema evolution over time:"
|
|
196
|
+
)
|
|
197
|
+
lines.extend(
|
|
198
|
+
f"- {mig_file}" for mig_file in findings["migration_files"][:10]
|
|
199
|
+
)
|
|
200
|
+
if len(findings["migration_files"]) > 10:
|
|
201
|
+
lines.append(f"- ... and {len(findings['migration_files']) - 10} more")
|
|
202
|
+
lines.append("")
|
|
203
|
+
|
|
204
|
+
# SQL files
|
|
205
|
+
if findings["sql_files"]:
|
|
206
|
+
lines.append(f"## SQL Schema Files ({len(findings['sql_files'])})")
|
|
207
|
+
lines.append("")
|
|
208
|
+
lines.extend(f"- {sql_file}" for sql_file in findings["sql_files"][:10])
|
|
209
|
+
if len(findings["sql_files"]) > 10:
|
|
210
|
+
lines.append(f"- ... and {len(findings['sql_files']) - 10} more")
|
|
211
|
+
lines.append("")
|
|
212
|
+
|
|
213
|
+
# ORM models
|
|
214
|
+
if findings["orm_models"]:
|
|
215
|
+
lines.append(f"## ORM Models ({len(findings['orm_models'])} files)")
|
|
216
|
+
lines.append("")
|
|
217
|
+
lines.append(
|
|
218
|
+
"ORM models detected, suggesting object-relational mapping:"
|
|
219
|
+
)
|
|
220
|
+
for orm_info in findings["orm_models"][:10]: # Limit to first 10
|
|
221
|
+
model_names = ", ".join(orm_info["models"][:5])
|
|
222
|
+
lines.append(f"- {orm_info['file']}: {model_names}")
|
|
223
|
+
if len(orm_info["models"]) > 5:
|
|
224
|
+
lines.append(f" (and {len(orm_info['models']) - 5} more models)")
|
|
225
|
+
if len(findings["orm_models"]) > 10:
|
|
226
|
+
lines.append(f"- ... and {len(findings['orm_models']) - 10} more files")
|
|
227
|
+
lines.append("")
|
|
228
|
+
|
|
229
|
+
# Inferred database type
|
|
230
|
+
lines.append("## Inferred Information")
|
|
231
|
+
lines.append("")
|
|
232
|
+
|
|
233
|
+
mig_files_str = str(findings.get("migration_files", []))
|
|
234
|
+
mig_files = findings.get("migration_files", [])
|
|
235
|
+
|
|
236
|
+
if "alembic" in mig_files_str:
|
|
237
|
+
lines.append("- Migration framework: Alembic (Python/SQLAlchemy)")
|
|
238
|
+
elif "django" in mig_files_str or any(
|
|
239
|
+
"migrations" in f and f.endswith(".py") for f in mig_files
|
|
240
|
+
):
|
|
241
|
+
lines.append("- Migration framework: Django Migrations")
|
|
242
|
+
elif any(".go" in f for f in mig_files):
|
|
243
|
+
lines.append(
|
|
244
|
+
"- Migration framework: Go-based migrations (golang-migrate)"
|
|
245
|
+
)
|
|
246
|
+
elif "flyway" in mig_files_str:
|
|
247
|
+
lines.append("- Migration framework: Flyway")
|
|
248
|
+
elif "liquibase" in mig_files_str:
|
|
249
|
+
lines.append("- Migration framework: Liquibase")
|
|
250
|
+
|
|
251
|
+
if findings["orm_models"]:
|
|
252
|
+
orm_models = findings["orm_models"]
|
|
253
|
+
py_models = sum(1 for m in orm_models if m["file"].endswith(".py"))
|
|
254
|
+
go_models = sum(1 for m in orm_models if m["file"].endswith(".go"))
|
|
255
|
+
ts_models = sum(
|
|
256
|
+
1 for m in orm_models if m["file"].endswith((".ts", ".js"))
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
if py_models > 0:
|
|
260
|
+
lines.append("- ORM: Python (likely SQLAlchemy or Django ORM)")
|
|
261
|
+
if go_models > 0:
|
|
262
|
+
lines.append("- ORM: Go (likely GORM)")
|
|
263
|
+
if ts_models > 0:
|
|
264
|
+
lines.append(
|
|
265
|
+
"- ORM: TypeScript/JavaScript (likely TypeORM or Sequelize)"
|
|
266
|
+
)
|
|
267
|
+
|
|
268
|
+
return "\n".join(lines)
|
|
@@ -7,6 +7,10 @@ from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
7
7
|
from kodit.domain.enrichments.architecture.architecture import (
|
|
8
8
|
ENRICHMENT_TYPE_ARCHITECTURE,
|
|
9
9
|
)
|
|
10
|
+
from kodit.domain.enrichments.architecture.database_schema.database_schema import (
|
|
11
|
+
ENRICHMENT_SUBTYPE_DATABASE_SCHEMA,
|
|
12
|
+
DatabaseSchemaEnrichment,
|
|
13
|
+
)
|
|
10
14
|
from kodit.domain.enrichments.architecture.physical.physical import (
|
|
11
15
|
ENRICHMENT_SUBTYPE_PHYSICAL,
|
|
12
16
|
PhysicalArchitectureEnrichment,
|
|
@@ -19,6 +23,11 @@ from kodit.domain.enrichments.development.snippet.snippet import (
|
|
|
19
23
|
SnippetEnrichmentSummary,
|
|
20
24
|
)
|
|
21
25
|
from kodit.domain.enrichments.enrichment import EnrichmentV2
|
|
26
|
+
from kodit.domain.enrichments.history.commit_description.commit_description import (
|
|
27
|
+
ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION,
|
|
28
|
+
CommitDescriptionEnrichment,
|
|
29
|
+
)
|
|
30
|
+
from kodit.domain.enrichments.history.history import ENRICHMENT_TYPE_HISTORY
|
|
22
31
|
from kodit.domain.enrichments.usage.api_docs import (
|
|
23
32
|
ENRICHMENT_SUBTYPE_API_DOCS,
|
|
24
33
|
APIDocEnrichment,
|
|
@@ -131,6 +140,26 @@ class SQLAlchemyEnrichmentV2Repository(
|
|
|
131
140
|
created_at=db_entity.created_at,
|
|
132
141
|
updated_at=db_entity.updated_at,
|
|
133
142
|
)
|
|
143
|
+
if (
|
|
144
|
+
db_entity.type == ENRICHMENT_TYPE_HISTORY
|
|
145
|
+
and db_entity.subtype == ENRICHMENT_SUBTYPE_COMMIT_DESCRIPTION
|
|
146
|
+
):
|
|
147
|
+
return CommitDescriptionEnrichment(
|
|
148
|
+
id=db_entity.id,
|
|
149
|
+
content=db_entity.content,
|
|
150
|
+
created_at=db_entity.created_at,
|
|
151
|
+
updated_at=db_entity.updated_at,
|
|
152
|
+
)
|
|
153
|
+
if (
|
|
154
|
+
db_entity.type == ENRICHMENT_TYPE_ARCHITECTURE
|
|
155
|
+
and db_entity.subtype == ENRICHMENT_SUBTYPE_DATABASE_SCHEMA
|
|
156
|
+
):
|
|
157
|
+
return DatabaseSchemaEnrichment(
|
|
158
|
+
id=db_entity.id,
|
|
159
|
+
content=db_entity.content,
|
|
160
|
+
created_at=db_entity.created_at,
|
|
161
|
+
updated_at=db_entity.updated_at,
|
|
162
|
+
)
|
|
134
163
|
|
|
135
164
|
raise ValueError(
|
|
136
165
|
f"Unknown enrichment type: {db_entity.type}/{db_entity.subtype}"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
kodit/.gitignore,sha256=ztkjgRwL9Uud1OEi36hGQeDGk3OLK1NfDEO8YqGYy8o,11
|
|
2
2
|
kodit/__init__.py,sha256=aEKHYninUq1yh6jaNfvJBYg-6fenpN132nJt1UU6Jxs,59
|
|
3
|
-
kodit/_version.py,sha256=
|
|
4
|
-
kodit/app.py,sha256=
|
|
3
|
+
kodit/_version.py,sha256=cK44j3gESPDerYNsAlInZd36FaFcP1dYcSF1jeRDXF8,704
|
|
4
|
+
kodit/app.py,sha256=7WxSQcktnpYBmjO1skIjMeBu55rVVRf4lotBEq55pAM,5846
|
|
5
5
|
kodit/cli.py,sha256=QSTXIUDxZo3anIONY-grZi9_VSehWoS8QoVJZyOmWPQ,3086
|
|
6
6
|
kodit/cli_utils.py,sha256=umkvt4kWNapk6db6RGz6bmn7oxgDpsW2Vo09MZ37OGg,2430
|
|
7
7
|
kodit/config.py,sha256=x_67lawaejOenJvl8yMxzXgdIkeWx8Yyc2ISO37GCvc,8031
|
|
@@ -13,19 +13,19 @@ kodit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
|
13
13
|
kodit/application/__init__.py,sha256=mH50wTpgP9dhbKztFsL8Dda9Hi18TSnMVxXtpp4aGOA,35
|
|
14
14
|
kodit/application/factories/__init__.py,sha256=bU5CvEnaBePZ7JbkCOp1MGTNP752bnU2uEqmfy5FdRk,37
|
|
15
15
|
kodit/application/factories/reporting_factory.py,sha256=3IpRiAw_olM69db-jbDAtjyGtd6Nh5o8jUJX3-rXCA8,1421
|
|
16
|
-
kodit/application/factories/server_factory.py,sha256=
|
|
16
|
+
kodit/application/factories/server_factory.py,sha256=dr0X_zQRUlEybtGZ3NS-kkwTU-K96u2D1Qw5xhWkd88,17409
|
|
17
17
|
kodit/application/services/__init__.py,sha256=p5UQNw-H5sxQvs5Etfte93B3cJ1kKW6DNxK34uFvU1E,38
|
|
18
18
|
kodit/application/services/code_search_application_service.py,sha256=ceyv5TTN-jvlOFOupGa9XwfTTraLNN2GU55kFeulVXY,7763
|
|
19
|
-
kodit/application/services/commit_indexing_application_service.py,sha256=
|
|
20
|
-
kodit/application/services/enrichment_query_service.py,sha256=
|
|
19
|
+
kodit/application/services/commit_indexing_application_service.py,sha256=CIJdBdAIdere6fEJ1KytQgDu0jNXoDiE748aFcEiOmQ,42631
|
|
20
|
+
kodit/application/services/enrichment_query_service.py,sha256=RMVze-DzS5zAki1iC96Kid7tbg-nHSv0z8eqPsiURqc,15002
|
|
21
21
|
kodit/application/services/indexing_worker_service.py,sha256=59cZthlzViOVrAWEoZqUTCfLzxx2OO_FOGdM3pYf9Mc,4065
|
|
22
22
|
kodit/application/services/queue_service.py,sha256=pIHTS8M65FzAhZH5kn54BTiZ43sCbsALYdCFTz9wdqE,2692
|
|
23
23
|
kodit/application/services/reporting.py,sha256=cwe-S-UpSOE6xSAEhoD1hi4hSWk1bW3YRLJ7463fIvM,3518
|
|
24
24
|
kodit/application/services/sync_scheduler.py,sha256=hVT3dlmvfbqXKOV_KU5ZQ5gEKBGPJTlvJcF9gP2ZHQM,2853
|
|
25
25
|
kodit/domain/__init__.py,sha256=TCpg4Xx-oF4mKV91lo4iXqMEfBT1OoRSYnbG-zVWolA,66
|
|
26
26
|
kodit/domain/errors.py,sha256=yIsgCjM_yOFIg8l7l-t7jM8pgeAX4cfPq0owf7iz3DA,106
|
|
27
|
-
kodit/domain/protocols.py,sha256=
|
|
28
|
-
kodit/domain/value_objects.py,sha256=
|
|
27
|
+
kodit/domain/protocols.py,sha256=KxTHnYbECvMoXdbvXNHVF-l-OEr2kzQsoxlVXbatgwg,7814
|
|
28
|
+
kodit/domain/value_objects.py,sha256=FW0sTMtcl0Q1qej7vzEg7-Gsv86Z01IbPrDdudsgU3g,18097
|
|
29
29
|
kodit/domain/enrichments/__init__.py,sha256=UpQMnMEHqaK3u3K-eJZOC28kfBPHALLAjFMdyYBXSPE,33
|
|
30
30
|
kodit/domain/enrichments/enricher.py,sha256=jnZ5X9RmZA8Acy-RBS2TbEoBg9QSm8AgleqwS9h5WlY,512
|
|
31
31
|
kodit/domain/enrichments/enrichment.py,sha256=_4lAOFibvSRN-01HB7it61k38IGQsub0gVERqRrhWPs,1776
|
|
@@ -33,6 +33,8 @@ kodit/domain/enrichments/request.py,sha256=6zBQhliDcdw8vS4sYPG2mqZSDSbQ5VzY1YQ-4
|
|
|
33
33
|
kodit/domain/enrichments/response.py,sha256=NzoMAKgs7c2yo9vvgWjQDo1yO0koKHbbY_SrsqsalAk,205
|
|
34
34
|
kodit/domain/enrichments/architecture/__init__.py,sha256=hBSliXMuixUZKtF-_zvcgQjnqrdyc4_SjYG2PTRFYpg,39
|
|
35
35
|
kodit/domain/enrichments/architecture/architecture.py,sha256=_3nF9qdBdcA8rTXPkb1KO2F7OXTcH9SajqNYB-ICaZA,507
|
|
36
|
+
kodit/domain/enrichments/architecture/database_schema/__init__.py,sha256=xS5UGMfHqOXjpr4ZZQup3IUtevJxBDXMH4fO7wuH5vM,35
|
|
37
|
+
kodit/domain/enrichments/architecture/database_schema/database_schema.py,sha256=OOiG5SrN4Jyw_L6_-UVg4DaGWNo5JLiii7e21ZLtDvY,529
|
|
36
38
|
kodit/domain/enrichments/architecture/physical/__init__.py,sha256=4jc89cGxALWo8d3Xzfb5t-YjcCyDb1dDVGwTqVYBFmc,48
|
|
37
39
|
kodit/domain/enrichments/architecture/physical/discovery_notes.py,sha256=Wdv41rkUcMgRqXWB5Q9roaGMGFznH4V_I7mELUvDShw,636
|
|
38
40
|
kodit/domain/enrichments/architecture/physical/formatter.py,sha256=V_JvHsGDPPJ-TqGS-G61P3OS3xe0QpS2NLBEk5jX6Yc,351
|
|
@@ -41,6 +43,10 @@ kodit/domain/enrichments/development/__init__.py,sha256=ls7zlKUpSpyLZRl-WTuaow9C
|
|
|
41
43
|
kodit/domain/enrichments/development/development.py,sha256=amzcheLEtXbOyhhmjlay_yt1Z2FRyW2CrR8wZWkpC0g,483
|
|
42
44
|
kodit/domain/enrichments/development/snippet/__init__.py,sha256=M5XVnlDgfqSE5UiAqkQwE1Mbr5Rg8zQpcspHKC3k_xU,34
|
|
43
45
|
kodit/domain/enrichments/development/snippet/snippet.py,sha256=A1f385Bu3_ZBaDKQrGHZMb6GIiQoo-hORFSw2ca56yQ,791
|
|
46
|
+
kodit/domain/enrichments/history/__init__.py,sha256=OXS0MOFEjD76rBOmLl8yA2L3Q8NYebBkoGhAmgbO2O0,27
|
|
47
|
+
kodit/domain/enrichments/history/history.py,sha256=pdmkU2ZZGFBsZDQ7kKo1hj-GaVKUd0v4Q2Fu15WE2A8,464
|
|
48
|
+
kodit/domain/enrichments/history/commit_description/__init__.py,sha256=j0fVMIkao9RzkLa6JakBPP40KrELl1eb-dfOLvfADMQ,38
|
|
49
|
+
kodit/domain/enrichments/history/commit_description/commit_description.py,sha256=96yKz-YsyWPfUu7zFtnT9AhRe7DjLmky9z0jy7oreFo,518
|
|
44
50
|
kodit/domain/enrichments/usage/__init__.py,sha256=7W36rvCF6DH-VqW2RiqU6GMlkYYHZy9Wm0DL_3_fbRc,40
|
|
45
51
|
kodit/domain/enrichments/usage/api_docs.py,sha256=5cvkNXUfAWDb0HJGIViAzIEZDGEnBnWYhkacs4lHCYA,470
|
|
46
52
|
kodit/domain/enrichments/usage/usage.py,sha256=U_JrxwXWlFtOzCP7fbfMd-NH75W44MwVFliONMzYB4U,453
|
|
@@ -89,8 +95,10 @@ kodit/infrastructure/bm25/__init__.py,sha256=DmGbrEO34FOJy4e685BbyxLA7gPW1eqs2gA
|
|
|
89
95
|
kodit/infrastructure/bm25/local_bm25_repository.py,sha256=YE3pUkPS5n1JNu6oSM_HRBOXM8U04HiY8dMMZCf9CMQ,5197
|
|
90
96
|
kodit/infrastructure/bm25/vectorchord_bm25_repository.py,sha256=LjbUPj4nPMb9pdEudThUbZTmQjhxvpN314EzKGpXfi0,8621
|
|
91
97
|
kodit/infrastructure/cloning/git/__init__.py,sha256=20ePcp0qE6BuLsjsv4KYB1DzKhMIMsPXwEqIEZtjTJs,34
|
|
92
|
-
kodit/infrastructure/cloning/git/git_python_adaptor.py,sha256=
|
|
98
|
+
kodit/infrastructure/cloning/git/git_python_adaptor.py,sha256=GCBdswC5txbt8_TWbMEbhvRvlmOvPCLwb6qBlx7b3XU,21594
|
|
93
99
|
kodit/infrastructure/cloning/git/working_copy.py,sha256=sPKQN-A1gDVV_QJISNNP4PqxRWxyj5owv5tvWfXMl44,3909
|
|
100
|
+
kodit/infrastructure/database_schema/__init__.py,sha256=jgejYX70fjV69zCuOBiNw3oCQlCKYzxTkjnUUUU7DY0,48
|
|
101
|
+
kodit/infrastructure/database_schema/database_schema_detector.py,sha256=zXU7HqrZU4_EYckloKDbH0gZvZ3_TJG5-Bd5PAkEkXc,10167
|
|
94
102
|
kodit/infrastructure/embedding/__init__.py,sha256=F-8nLlWAerYJ0MOIA4tbXHLan8bW5rRR84vzxx6tRKI,39
|
|
95
103
|
kodit/infrastructure/embedding/embedding_factory.py,sha256=6nP8HKKlNWmDE8ATT5tNQHgPqeTDUMpRuWwn2rsfrOQ,3446
|
|
96
104
|
kodit/infrastructure/embedding/local_vector_search_repository.py,sha256=urccvadIF-uizmYuzK7ii7hl2HaV7swHCiS8P6n7U18,3507
|
|
@@ -134,7 +142,7 @@ kodit/infrastructure/slicing/slicer.py,sha256=EDYkoLf6RsTVloudZUq6LS5X10JJAHWcKW
|
|
|
134
142
|
kodit/infrastructure/sqlalchemy/__init__.py,sha256=UXPMSF_hgWaqr86cawRVqM8XdVNumQyyK5B8B97GnlA,33
|
|
135
143
|
kodit/infrastructure/sqlalchemy/embedding_repository.py,sha256=OhSIuNEQ725WoxaIpK3jcZvUVPW-b95HKRXr1HjurmI,8824
|
|
136
144
|
kodit/infrastructure/sqlalchemy/enrichment_association_repository.py,sha256=mjlGH4vkIv1cPfhkZ4SUyGWpMbgeS7QljsK54yQvV4g,2615
|
|
137
|
-
kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py,sha256=
|
|
145
|
+
kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py,sha256=9C7y6aRzHHkKJYTTAFxU5p0kwJVBjhqHvs-wUZDWsmk,6350
|
|
138
146
|
kodit/infrastructure/sqlalchemy/entities.py,sha256=kvZqUPCN2TNgovdNAT_0h4Y8zrgFWwkk-OecvcHIz-A,14852
|
|
139
147
|
kodit/infrastructure/sqlalchemy/git_branch_repository.py,sha256=dW9kBr8aDBXXVmw1zEux2mueiKhTcpG0JxnLuz5yZ3w,3106
|
|
140
148
|
kodit/infrastructure/sqlalchemy/git_commit_repository.py,sha256=jzYpFV1gjI-Wfgai-hxesglYn6XD384mqIorV1AtNCA,1991
|
|
@@ -169,8 +177,8 @@ kodit/utils/dump_config.py,sha256=dd5uPgqh6ATk02Zt59t2JFKR9X17YWjHudV0nE8VktE,11
|
|
|
169
177
|
kodit/utils/dump_openapi.py,sha256=EasYOnnpeabwb_sTKQUBrrOLHjPcOFQ7Zx0YKpx9fmM,1239
|
|
170
178
|
kodit/utils/generate_api_paths.py,sha256=TMtx9v55podDfUmiWaHgJHLtEWLV2sLL-5ejGFMPzAo,3569
|
|
171
179
|
kodit/utils/path_utils.py,sha256=UB_81rx7Y1G1jalVv2PX8miwaprBbcqEdtoQ3hPT3kU,2451
|
|
172
|
-
kodit-0.5.
|
|
173
|
-
kodit-0.5.
|
|
174
|
-
kodit-0.5.
|
|
175
|
-
kodit-0.5.
|
|
176
|
-
kodit-0.5.
|
|
180
|
+
kodit-0.5.6.dist-info/METADATA,sha256=7G7BfnWWbmDkwSSiKribmesiUY5NlzjcxwqsZiTJjUw,7703
|
|
181
|
+
kodit-0.5.6.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
182
|
+
kodit-0.5.6.dist-info/entry_points.txt,sha256=hoTn-1aKyTItjnY91fnO-rV5uaWQLQ-Vi7V5et2IbHY,40
|
|
183
|
+
kodit-0.5.6.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
184
|
+
kodit-0.5.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|