kodit 0.4.3__py3-none-any.whl → 0.5.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.

Potentially problematic release.


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

Files changed (135) hide show
  1. kodit/_version.py +2 -2
  2. kodit/app.py +51 -23
  3. kodit/application/factories/reporting_factory.py +6 -2
  4. kodit/application/factories/server_factory.py +353 -0
  5. kodit/application/services/code_search_application_service.py +144 -0
  6. kodit/application/services/commit_indexing_application_service.py +700 -0
  7. kodit/application/services/indexing_worker_service.py +13 -44
  8. kodit/application/services/queue_service.py +24 -3
  9. kodit/application/services/reporting.py +0 -2
  10. kodit/application/services/sync_scheduler.py +15 -31
  11. kodit/cli.py +2 -753
  12. kodit/cli_utils.py +2 -9
  13. kodit/config.py +4 -97
  14. kodit/database.py +38 -1
  15. kodit/domain/enrichments/__init__.py +1 -0
  16. kodit/domain/enrichments/architecture/__init__.py +1 -0
  17. kodit/domain/enrichments/architecture/architecture.py +20 -0
  18. kodit/domain/enrichments/architecture/physical/__init__.py +1 -0
  19. kodit/domain/enrichments/architecture/physical/discovery_notes.py +14 -0
  20. kodit/domain/enrichments/architecture/physical/formatter.py +11 -0
  21. kodit/domain/enrichments/architecture/physical/physical.py +17 -0
  22. kodit/domain/enrichments/development/__init__.py +1 -0
  23. kodit/domain/enrichments/development/development.py +18 -0
  24. kodit/domain/enrichments/development/snippet/__init__.py +1 -0
  25. kodit/domain/enrichments/development/snippet/snippet.py +21 -0
  26. kodit/domain/enrichments/enricher.py +17 -0
  27. kodit/domain/enrichments/enrichment.py +39 -0
  28. kodit/domain/enrichments/request.py +12 -0
  29. kodit/domain/enrichments/response.py +11 -0
  30. kodit/domain/enrichments/usage/__init__.py +1 -0
  31. kodit/domain/enrichments/usage/api_docs.py +19 -0
  32. kodit/domain/enrichments/usage/usage.py +18 -0
  33. kodit/domain/{entities.py → entities/__init__.py} +50 -195
  34. kodit/domain/entities/git.py +190 -0
  35. kodit/domain/factories/__init__.py +1 -0
  36. kodit/domain/factories/git_repo_factory.py +76 -0
  37. kodit/domain/protocols.py +264 -64
  38. kodit/domain/services/bm25_service.py +5 -1
  39. kodit/domain/services/embedding_service.py +3 -0
  40. kodit/domain/services/enrichment_service.py +9 -30
  41. kodit/domain/services/git_repository_service.py +429 -0
  42. kodit/domain/services/git_service.py +300 -0
  43. kodit/domain/services/physical_architecture_service.py +182 -0
  44. kodit/domain/services/task_status_query_service.py +2 -2
  45. kodit/domain/value_objects.py +87 -135
  46. kodit/infrastructure/api/client/__init__.py +0 -2
  47. kodit/infrastructure/api/v1/__init__.py +0 -4
  48. kodit/infrastructure/api/v1/dependencies.py +92 -46
  49. kodit/infrastructure/api/v1/routers/__init__.py +0 -6
  50. kodit/infrastructure/api/v1/routers/commits.py +352 -0
  51. kodit/infrastructure/api/v1/routers/queue.py +2 -2
  52. kodit/infrastructure/api/v1/routers/repositories.py +282 -0
  53. kodit/infrastructure/api/v1/routers/search.py +31 -14
  54. kodit/infrastructure/api/v1/schemas/__init__.py +0 -24
  55. kodit/infrastructure/api/v1/schemas/commit.py +96 -0
  56. kodit/infrastructure/api/v1/schemas/context.py +2 -0
  57. kodit/infrastructure/api/v1/schemas/enrichment.py +29 -0
  58. kodit/infrastructure/api/v1/schemas/repository.py +128 -0
  59. kodit/infrastructure/api/v1/schemas/search.py +12 -9
  60. kodit/infrastructure/api/v1/schemas/snippet.py +58 -0
  61. kodit/infrastructure/api/v1/schemas/tag.py +31 -0
  62. kodit/infrastructure/api/v1/schemas/task_status.py +2 -0
  63. kodit/infrastructure/bm25/local_bm25_repository.py +16 -4
  64. kodit/infrastructure/bm25/vectorchord_bm25_repository.py +68 -52
  65. kodit/infrastructure/cloning/git/git_python_adaptor.py +534 -0
  66. kodit/infrastructure/cloning/git/working_copy.py +1 -1
  67. kodit/infrastructure/embedding/embedding_factory.py +3 -2
  68. kodit/infrastructure/embedding/local_vector_search_repository.py +1 -1
  69. kodit/infrastructure/embedding/vectorchord_vector_search_repository.py +111 -84
  70. kodit/infrastructure/enricher/__init__.py +1 -0
  71. kodit/infrastructure/enricher/enricher_factory.py +53 -0
  72. kodit/infrastructure/{enrichment/litellm_enrichment_provider.py → enricher/litellm_enricher.py} +36 -56
  73. kodit/infrastructure/{enrichment/local_enrichment_provider.py → enricher/local_enricher.py} +19 -24
  74. kodit/infrastructure/enricher/null_enricher.py +36 -0
  75. kodit/infrastructure/indexing/fusion_service.py +1 -1
  76. kodit/infrastructure/mappers/enrichment_mapper.py +83 -0
  77. kodit/infrastructure/mappers/git_mapper.py +193 -0
  78. kodit/infrastructure/mappers/snippet_mapper.py +104 -0
  79. kodit/infrastructure/mappers/task_mapper.py +5 -44
  80. kodit/infrastructure/physical_architecture/__init__.py +1 -0
  81. kodit/infrastructure/physical_architecture/detectors/__init__.py +1 -0
  82. kodit/infrastructure/physical_architecture/detectors/docker_compose_detector.py +336 -0
  83. kodit/infrastructure/physical_architecture/formatters/__init__.py +1 -0
  84. kodit/infrastructure/physical_architecture/formatters/narrative_formatter.py +149 -0
  85. kodit/infrastructure/reporting/log_progress.py +8 -5
  86. kodit/infrastructure/reporting/telemetry_progress.py +21 -0
  87. kodit/infrastructure/slicing/api_doc_extractor.py +836 -0
  88. kodit/infrastructure/slicing/ast_analyzer.py +1128 -0
  89. kodit/infrastructure/slicing/slicer.py +87 -421
  90. kodit/infrastructure/sqlalchemy/embedding_repository.py +43 -23
  91. kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +118 -0
  92. kodit/infrastructure/sqlalchemy/entities.py +402 -158
  93. kodit/infrastructure/sqlalchemy/git_branch_repository.py +274 -0
  94. kodit/infrastructure/sqlalchemy/git_commit_repository.py +346 -0
  95. kodit/infrastructure/sqlalchemy/git_repository.py +262 -0
  96. kodit/infrastructure/sqlalchemy/git_tag_repository.py +268 -0
  97. kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +479 -0
  98. kodit/infrastructure/sqlalchemy/task_repository.py +29 -23
  99. kodit/infrastructure/sqlalchemy/task_status_repository.py +24 -12
  100. kodit/infrastructure/sqlalchemy/unit_of_work.py +10 -14
  101. kodit/mcp.py +12 -30
  102. kodit/migrations/env.py +1 -0
  103. kodit/migrations/versions/04b80f802e0c_foreign_key_review.py +100 -0
  104. kodit/migrations/versions/19f8c7faf8b9_add_generic_enrichment_type.py +260 -0
  105. kodit/migrations/versions/7f15f878c3a1_add_new_git_entities.py +690 -0
  106. kodit/migrations/versions/f9e5ef5e688f_add_git_commits_number.py +43 -0
  107. kodit/py.typed +0 -0
  108. kodit/utils/dump_config.py +361 -0
  109. kodit/utils/dump_openapi.py +6 -4
  110. kodit/utils/path_utils.py +29 -0
  111. {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/METADATA +3 -3
  112. kodit-0.5.1.dist-info/RECORD +168 -0
  113. kodit/application/factories/code_indexing_factory.py +0 -195
  114. kodit/application/services/auto_indexing_service.py +0 -99
  115. kodit/application/services/code_indexing_application_service.py +0 -410
  116. kodit/domain/services/index_query_service.py +0 -70
  117. kodit/domain/services/index_service.py +0 -269
  118. kodit/infrastructure/api/client/index_client.py +0 -57
  119. kodit/infrastructure/api/v1/routers/indexes.py +0 -164
  120. kodit/infrastructure/api/v1/schemas/index.py +0 -101
  121. kodit/infrastructure/bm25/bm25_factory.py +0 -28
  122. kodit/infrastructure/cloning/__init__.py +0 -1
  123. kodit/infrastructure/cloning/metadata.py +0 -98
  124. kodit/infrastructure/enrichment/__init__.py +0 -1
  125. kodit/infrastructure/enrichment/enrichment_factory.py +0 -52
  126. kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -19
  127. kodit/infrastructure/mappers/index_mapper.py +0 -345
  128. kodit/infrastructure/reporting/tdqm_progress.py +0 -38
  129. kodit/infrastructure/slicing/language_detection_service.py +0 -18
  130. kodit/infrastructure/sqlalchemy/index_repository.py +0 -646
  131. kodit-0.4.3.dist-info/RECORD +0 -125
  132. /kodit/infrastructure/{enrichment → enricher}/utils.py +0 -0
  133. {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/WHEEL +0 -0
  134. {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/entry_points.txt +0 -0
  135. {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,83 @@
1
+ """Enrichment mapper."""
2
+
3
+ from kodit.domain.enrichments.architecture.architecture import (
4
+ ENRICHMENT_TYPE_ARCHITECTURE,
5
+ )
6
+ from kodit.domain.enrichments.architecture.physical.physical import (
7
+ ENRICHMENT_SUBTYPE_PHYSICAL,
8
+ PhysicalArchitectureEnrichment,
9
+ )
10
+ from kodit.domain.enrichments.development.development import ENRICHMENT_TYPE_DEVELOPMENT
11
+ from kodit.domain.enrichments.development.snippet.snippet import (
12
+ ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY,
13
+ SnippetEnrichment,
14
+ )
15
+ from kodit.domain.enrichments.enrichment import EnrichmentV2
16
+ from kodit.domain.enrichments.usage.api_docs import (
17
+ ENRICHMENT_SUBTYPE_API_DOCS,
18
+ APIDocEnrichment,
19
+ )
20
+ from kodit.domain.enrichments.usage.usage import ENRICHMENT_TYPE_USAGE
21
+ from kodit.infrastructure.sqlalchemy import entities as db_entities
22
+
23
+
24
+ class EnrichmentMapper:
25
+ """Maps between domain enrichment entities and database entities."""
26
+
27
+ @staticmethod
28
+ def to_database(domain_enrichment: EnrichmentV2) -> db_entities.EnrichmentV2:
29
+ """Convert domain enrichment to database entity."""
30
+ return db_entities.EnrichmentV2(
31
+ id=domain_enrichment.id,
32
+ type=domain_enrichment.type,
33
+ subtype=domain_enrichment.subtype,
34
+ content=domain_enrichment.content,
35
+ created_at=domain_enrichment.created_at,
36
+ updated_at=domain_enrichment.updated_at,
37
+ )
38
+
39
+ @staticmethod
40
+ def to_domain(
41
+ db_enrichment: db_entities.EnrichmentV2,
42
+ entity_type: str, # noqa: ARG004
43
+ entity_id: str,
44
+ ) -> EnrichmentV2:
45
+ """Convert database enrichment to domain entity."""
46
+ # Use the stored type and subtype to determine the correct domain class
47
+ if (
48
+ db_enrichment.type == ENRICHMENT_TYPE_DEVELOPMENT
49
+ and db_enrichment.subtype == ENRICHMENT_SUBTYPE_SNIPPET_SUMMARY
50
+ ):
51
+ return SnippetEnrichment(
52
+ id=db_enrichment.id,
53
+ entity_id=entity_id,
54
+ content=db_enrichment.content,
55
+ created_at=db_enrichment.created_at,
56
+ updated_at=db_enrichment.updated_at,
57
+ )
58
+ if (
59
+ db_enrichment.type == ENRICHMENT_TYPE_USAGE
60
+ and db_enrichment.subtype == ENRICHMENT_SUBTYPE_API_DOCS
61
+ ):
62
+ return APIDocEnrichment(
63
+ id=db_enrichment.id,
64
+ entity_id=entity_id,
65
+ content=db_enrichment.content,
66
+ created_at=db_enrichment.created_at,
67
+ updated_at=db_enrichment.updated_at,
68
+ )
69
+ if (
70
+ db_enrichment.type == ENRICHMENT_TYPE_ARCHITECTURE
71
+ and db_enrichment.subtype == ENRICHMENT_SUBTYPE_PHYSICAL
72
+ ):
73
+ return PhysicalArchitectureEnrichment(
74
+ id=db_enrichment.id,
75
+ entity_id=entity_id,
76
+ content=db_enrichment.content,
77
+ created_at=db_enrichment.created_at,
78
+ updated_at=db_enrichment.updated_at,
79
+ )
80
+
81
+ raise ValueError(
82
+ f"Unknown enrichment type: {db_enrichment.type}/{db_enrichment.subtype}"
83
+ )
@@ -0,0 +1,193 @@
1
+ """Mapping between domain Git entities and SQLAlchemy entities."""
2
+
3
+ from collections import defaultdict
4
+ from pathlib import Path
5
+
6
+ from pydantic import AnyUrl
7
+
8
+ import kodit.domain.entities.git as domain_git_entities
9
+ from kodit.infrastructure.sqlalchemy import entities as db_entities
10
+
11
+
12
+ class GitMapper:
13
+ """Mapper for converting between domain Git entities and database entities."""
14
+
15
+ def to_domain_commits(
16
+ self,
17
+ db_commits: list[db_entities.GitCommit],
18
+ db_commit_files: list[db_entities.GitCommitFile],
19
+ ) -> list[domain_git_entities.GitCommit]:
20
+ """Convert SQLAlchemy GitCommit to domain GitCommit."""
21
+ commit_files_map = defaultdict(list)
22
+ for file in db_commit_files:
23
+ commit_files_map[file.commit_sha].append(file.blob_sha)
24
+
25
+ commit_domain_files_map = defaultdict(list)
26
+ for file in db_commit_files:
27
+ commit_domain_files_map[file.commit_sha].append(
28
+ domain_git_entities.GitFile(
29
+ created_at=file.created_at,
30
+ blob_sha=file.blob_sha,
31
+ path=file.path,
32
+ mime_type=file.mime_type,
33
+ size=file.size,
34
+ extension=file.extension,
35
+ )
36
+ )
37
+
38
+ domain_commits = []
39
+ for db_commit in db_commits:
40
+ domain_commit = domain_git_entities.GitCommit(
41
+ created_at=db_commit.created_at,
42
+ updated_at=db_commit.updated_at,
43
+ commit_sha=db_commit.commit_sha,
44
+ date=db_commit.date,
45
+ message=db_commit.message,
46
+ parent_commit_sha=db_commit.parent_commit_sha,
47
+ files=commit_domain_files_map[db_commit.commit_sha],
48
+ author=db_commit.author,
49
+ )
50
+ domain_commits.append(domain_commit)
51
+ return domain_commits
52
+
53
+ def to_domain_branches(
54
+ self,
55
+ db_branches: list[db_entities.GitBranch],
56
+ domain_commits: list[domain_git_entities.GitCommit],
57
+ ) -> list[domain_git_entities.GitBranch]:
58
+ """Convert SQLAlchemy GitBranch to domain GitBranch."""
59
+ commit_map = {commit.commit_sha: commit for commit in domain_commits}
60
+ domain_branches = []
61
+ for db_branch in db_branches:
62
+ if db_branch.head_commit_sha not in commit_map:
63
+ raise ValueError(
64
+ f"Commit {db_branch.head_commit_sha} for "
65
+ f"branch {db_branch.name} not found in commits: {commit_map.keys()}"
66
+ )
67
+ domain_branch = domain_git_entities.GitBranch(
68
+ repo_id=db_branch.repo_id,
69
+ name=db_branch.name,
70
+ created_at=db_branch.created_at,
71
+ updated_at=db_branch.updated_at,
72
+ head_commit=commit_map[db_branch.head_commit_sha],
73
+ )
74
+ domain_branches.append(domain_branch)
75
+ return domain_branches
76
+
77
+ def to_domain_tags(
78
+ self,
79
+ db_tags: list[db_entities.GitTag],
80
+ domain_commits: list[domain_git_entities.GitCommit],
81
+ ) -> list[domain_git_entities.GitTag]:
82
+ """Convert SQLAlchemy GitTag to domain GitTag."""
83
+ commit_map = {commit.commit_sha: commit for commit in domain_commits}
84
+ domain_tags = []
85
+ for db_tag in db_tags:
86
+ if db_tag.target_commit_sha not in commit_map:
87
+ raise ValueError(
88
+ f"Commit {db_tag.target_commit_sha} for tag {db_tag.name} not found"
89
+ )
90
+ domain_tag = domain_git_entities.GitTag(
91
+ created_at=db_tag.created_at,
92
+ updated_at=db_tag.updated_at,
93
+ repo_id=db_tag.repo_id,
94
+ name=db_tag.name,
95
+ target_commit=commit_map[db_tag.target_commit_sha],
96
+ )
97
+ domain_tags.append(domain_tag)
98
+ return domain_tags
99
+
100
+ def to_domain_tracking_branch(
101
+ self,
102
+ db_tracking_branch: db_entities.GitTrackingBranch | None,
103
+ db_tracking_branch_entity: db_entities.GitBranch | None,
104
+ domain_commits: list[domain_git_entities.GitCommit],
105
+ ) -> domain_git_entities.GitBranch | None:
106
+ """Convert SQLAlchemy GitTrackingBranch to domain GitBranch."""
107
+ if db_tracking_branch is None or db_tracking_branch_entity is None:
108
+ return None
109
+
110
+ commit_map = {commit.commit_sha: commit for commit in domain_commits}
111
+ if db_tracking_branch_entity.head_commit_sha not in commit_map:
112
+ raise ValueError(
113
+ f"Commit {db_tracking_branch_entity.head_commit_sha} for "
114
+ f"tracking branch {db_tracking_branch.name} not found"
115
+ )
116
+
117
+ return domain_git_entities.GitBranch(
118
+ repo_id=db_tracking_branch_entity.repo_id,
119
+ name=db_tracking_branch_entity.name,
120
+ created_at=db_tracking_branch_entity.created_at,
121
+ updated_at=db_tracking_branch_entity.updated_at,
122
+ head_commit=commit_map[db_tracking_branch_entity.head_commit_sha],
123
+ )
124
+
125
+ def to_domain_git_repo( # noqa: PLR0913
126
+ self,
127
+ db_repo: db_entities.GitRepo,
128
+ db_tracking_branch_entity: db_entities.GitBranch | None,
129
+ db_commits: list[db_entities.GitCommit],
130
+ db_tags: list[db_entities.GitTag],
131
+ db_commit_files: list[db_entities.GitCommitFile],
132
+ db_tracking_branch: db_entities.GitTrackingBranch | None,
133
+ ) -> domain_git_entities.GitRepo:
134
+ """Convert SQLAlchemy GitRepo to domain GitRepo."""
135
+ # Build commits needed for tags and tracking branch
136
+ domain_commits = self.to_domain_commits(
137
+ db_commits=db_commits, db_commit_files=db_commit_files
138
+ )
139
+ self.to_domain_tags(
140
+ db_tags=db_tags, domain_commits=domain_commits
141
+ )
142
+ tracking_branch = self.to_domain_tracking_branch(
143
+ db_tracking_branch=db_tracking_branch,
144
+ db_tracking_branch_entity=db_tracking_branch_entity,
145
+ domain_commits=domain_commits,
146
+ )
147
+
148
+ from kodit.domain.factories.git_repo_factory import GitRepoFactory
149
+
150
+ return GitRepoFactory.create_from_components(
151
+ repo_id=db_repo.id,
152
+ created_at=db_repo.created_at,
153
+ updated_at=db_repo.updated_at,
154
+ sanitized_remote_uri=AnyUrl(db_repo.sanitized_remote_uri),
155
+ remote_uri=AnyUrl(db_repo.remote_uri),
156
+ tracking_branch=tracking_branch,
157
+ cloned_path=Path(db_repo.cloned_path) if db_repo.cloned_path else None,
158
+ last_scanned_at=db_repo.last_scanned_at,
159
+ num_commits=db_repo.num_commits,
160
+ num_branches=db_repo.num_branches,
161
+ num_tags=db_repo.num_tags,
162
+ )
163
+
164
+ def to_domain_commit_index(
165
+ self,
166
+ db_commit_index: db_entities.CommitIndex,
167
+ snippets: list[domain_git_entities.SnippetV2],
168
+ ) -> domain_git_entities.CommitIndex:
169
+ """Convert SQLAlchemy CommitIndex to domain CommitIndex."""
170
+ return domain_git_entities.CommitIndex(
171
+ commit_sha=db_commit_index.commit_sha,
172
+ created_at=db_commit_index.created_at,
173
+ updated_at=db_commit_index.updated_at,
174
+ snippets=snippets,
175
+ status=domain_git_entities.IndexStatus(db_commit_index.status),
176
+ indexed_at=db_commit_index.indexed_at,
177
+ error_message=db_commit_index.error_message,
178
+ files_processed=db_commit_index.files_processed,
179
+ processing_time_seconds=float(db_commit_index.processing_time_seconds),
180
+ )
181
+
182
+ def from_domain_commit_index(
183
+ self, domain_commit_index: domain_git_entities.CommitIndex
184
+ ) -> db_entities.CommitIndex:
185
+ """Convert domain CommitIndex to SQLAlchemy CommitIndex."""
186
+ return db_entities.CommitIndex(
187
+ commit_sha=domain_commit_index.commit_sha,
188
+ status=domain_commit_index.status,
189
+ indexed_at=domain_commit_index.indexed_at,
190
+ error_message=domain_commit_index.error_message,
191
+ files_processed=domain_commit_index.files_processed,
192
+ processing_time_seconds=domain_commit_index.processing_time_seconds,
193
+ )
@@ -0,0 +1,104 @@
1
+ """Mapping between domain Git entities and SQLAlchemy entities."""
2
+
3
+ import kodit.domain.entities.git as domain_git_entities
4
+ from kodit.domain.enrichments.development.snippet.snippet import SnippetEnrichment
5
+ from kodit.domain.enrichments.enrichment import EnrichmentV2
6
+ from kodit.domain.value_objects import Enrichment, EnrichmentType
7
+ from kodit.infrastructure.sqlalchemy import entities as db_entities
8
+
9
+
10
+ class SnippetMapper:
11
+ """Mapper for converting between domain Git entities and database entities."""
12
+
13
+ def to_domain_snippet_v2(
14
+ self,
15
+ db_snippet: db_entities.SnippetV2,
16
+ db_files: list[db_entities.GitCommitFile],
17
+ db_enrichments: list[EnrichmentV2],
18
+ ) -> domain_git_entities.SnippetV2:
19
+ """Convert SQLAlchemy SnippetV2 to domain SnippetV2."""
20
+ # Convert enrichments from SnippetEnrichment to Enrichment value objects
21
+ enrichments: list[Enrichment] = [
22
+ Enrichment(
23
+ type=EnrichmentType.SUMMARIZATION,
24
+ content=enrichment.content,
25
+ )
26
+ for enrichment in db_enrichments
27
+ ]
28
+
29
+ derives_from = [
30
+ domain_git_entities.GitFile(
31
+ created_at=file.created_at,
32
+ blob_sha=file.blob_sha,
33
+ path=file.path,
34
+ mime_type=file.mime_type,
35
+ size=file.size,
36
+ extension=file.extension,
37
+ )
38
+ for file in db_files
39
+ ]
40
+
41
+ return domain_git_entities.SnippetV2(
42
+ sha=db_snippet.sha,
43
+ created_at=db_snippet.created_at,
44
+ updated_at=db_snippet.updated_at,
45
+ derives_from=derives_from,
46
+ content=db_snippet.content,
47
+ enrichments=enrichments,
48
+ extension=db_snippet.extension,
49
+ )
50
+
51
+ def from_domain_snippet_v2(
52
+ self, domain_snippet: domain_git_entities.SnippetV2
53
+ ) -> db_entities.SnippetV2:
54
+ """Convert domain SnippetV2 to SQLAlchemy SnippetV2."""
55
+ return db_entities.SnippetV2(
56
+ sha=domain_snippet.sha,
57
+ content=domain_snippet.content,
58
+ extension=domain_snippet.extension,
59
+ )
60
+
61
+ def from_domain_enrichments(
62
+ self,
63
+ snippet_sha: str,
64
+ enrichments: list[Enrichment],
65
+ ) -> list[SnippetEnrichment]:
66
+ """Convert domain enrichments to SnippetEnrichment entities."""
67
+ return [
68
+ SnippetEnrichment(
69
+ entity_id=snippet_sha,
70
+ content=enrichment.content,
71
+ )
72
+ for enrichment in enrichments
73
+ ]
74
+
75
+ def to_domain_commit_index(
76
+ self,
77
+ db_commit_index: db_entities.CommitIndex,
78
+ snippets: list[domain_git_entities.SnippetV2],
79
+ ) -> domain_git_entities.CommitIndex:
80
+ """Convert SQLAlchemy CommitIndex to domain CommitIndex."""
81
+ return domain_git_entities.CommitIndex(
82
+ commit_sha=db_commit_index.commit_sha,
83
+ created_at=db_commit_index.created_at,
84
+ updated_at=db_commit_index.updated_at,
85
+ snippets=snippets,
86
+ status=domain_git_entities.IndexStatus(db_commit_index.status),
87
+ indexed_at=db_commit_index.indexed_at,
88
+ error_message=db_commit_index.error_message,
89
+ files_processed=db_commit_index.files_processed,
90
+ processing_time_seconds=float(db_commit_index.processing_time_seconds),
91
+ )
92
+
93
+ def from_domain_commit_index(
94
+ self, domain_commit_index: domain_git_entities.CommitIndex
95
+ ) -> db_entities.CommitIndex:
96
+ """Convert domain CommitIndex to SQLAlchemy CommitIndex."""
97
+ return db_entities.CommitIndex(
98
+ commit_sha=domain_commit_index.commit_sha,
99
+ status=domain_commit_index.status,
100
+ indexed_at=domain_commit_index.indexed_at,
101
+ error_message=domain_commit_index.error_message,
102
+ files_processed=domain_commit_index.files_processed,
103
+ processing_time_seconds=domain_commit_index.processing_time_seconds,
104
+ )
@@ -1,43 +1,10 @@
1
1
  """Task mapper for the task queue."""
2
2
 
3
- from typing import ClassVar
4
-
5
3
  from kodit.domain.entities import Task
6
- from kodit.domain.value_objects import TaskType
4
+ from kodit.domain.value_objects import TaskOperation
7
5
  from kodit.infrastructure.sqlalchemy import entities as db_entities
8
6
 
9
7
 
10
- class TaskTypeMapper:
11
- """Maps between domain QueuedTaskType and SQLAlchemy TaskType."""
12
-
13
- # Map TaskType enum to QueuedTaskType
14
- TASK_TYPE_MAPPING: ClassVar[dict[db_entities.TaskType, TaskType]] = {
15
- db_entities.TaskType.INDEX_UPDATE: TaskType.INDEX_UPDATE,
16
- }
17
-
18
- @staticmethod
19
- def to_domain_type(task_type: db_entities.TaskType) -> TaskType:
20
- """Convert SQLAlchemy TaskType to domain QueuedTaskType."""
21
- if task_type not in TaskTypeMapper.TASK_TYPE_MAPPING:
22
- raise ValueError(f"Unknown task type: {task_type}")
23
- return TaskTypeMapper.TASK_TYPE_MAPPING[task_type]
24
-
25
- @staticmethod
26
- def from_domain_type(task_type: TaskType) -> db_entities.TaskType:
27
- """Convert domain QueuedTaskType to SQLAlchemy TaskType."""
28
- if task_type not in TaskTypeMapper.TASK_TYPE_MAPPING.values():
29
- raise ValueError(f"Unknown task type: {task_type}")
30
-
31
- # Find value in TASK_TYPE_MAPPING
32
- return next(
33
- (
34
- db_task_type
35
- for db_task_type, domain_task_type in TaskTypeMapper.TASK_TYPE_MAPPING.items() # noqa: E501
36
- if domain_task_type == task_type
37
- )
38
- )
39
-
40
-
41
8
  class TaskMapper:
42
9
  """Maps between domain QueuedTask and SQLAlchemy Task entities.
43
10
 
@@ -52,13 +19,12 @@ class TaskMapper:
52
19
  Since QueuedTask doesn't have status fields, we store processing
53
20
  state in the payload.
54
21
  """
55
- # Get the task type
56
- task_type = TaskTypeMapper.to_domain_type(record.type)
57
-
22
+ if record.type not in TaskOperation.__members__.values():
23
+ raise ValueError(f"Unknown operation: {record.type}")
58
24
  # The dedup_key becomes the id in the domain entity
59
25
  return Task(
60
26
  id=record.dedup_key, # Use dedup_key as the unique identifier
61
- type=task_type,
27
+ type=TaskOperation(record.type),
62
28
  priority=record.priority,
63
29
  payload=record.payload or {},
64
30
  created_at=record.created_at,
@@ -68,14 +34,9 @@ class TaskMapper:
68
34
  @staticmethod
69
35
  def from_domain_task(task: Task) -> db_entities.Task:
70
36
  """Convert domain QueuedTask to SQLAlchemy Task record."""
71
- if task.type not in TaskTypeMapper.TASK_TYPE_MAPPING.values():
72
- raise ValueError(f"Unknown task type: {task.type}")
73
-
74
- # Find value in TASK_TYPE_MAPPING
75
- task_type = TaskTypeMapper.from_domain_type(task.type)
76
37
  return db_entities.Task(
77
38
  dedup_key=task.id,
78
- type=task_type,
39
+ type=task.type.value,
79
40
  payload=task.payload,
80
41
  priority=task.priority,
81
42
  )
@@ -0,0 +1 @@
1
+ """Physical architecture discovery infrastructure."""
@@ -0,0 +1 @@
1
+ """Component detectors for physical architecture discovery."""