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.
- kodit/_version.py +2 -2
- kodit/app.py +51 -23
- kodit/application/factories/reporting_factory.py +6 -2
- kodit/application/factories/server_factory.py +353 -0
- kodit/application/services/code_search_application_service.py +144 -0
- kodit/application/services/commit_indexing_application_service.py +700 -0
- kodit/application/services/indexing_worker_service.py +13 -44
- kodit/application/services/queue_service.py +24 -3
- kodit/application/services/reporting.py +0 -2
- kodit/application/services/sync_scheduler.py +15 -31
- kodit/cli.py +2 -753
- kodit/cli_utils.py +2 -9
- kodit/config.py +4 -97
- kodit/database.py +38 -1
- kodit/domain/enrichments/__init__.py +1 -0
- kodit/domain/enrichments/architecture/__init__.py +1 -0
- kodit/domain/enrichments/architecture/architecture.py +20 -0
- kodit/domain/enrichments/architecture/physical/__init__.py +1 -0
- kodit/domain/enrichments/architecture/physical/discovery_notes.py +14 -0
- kodit/domain/enrichments/architecture/physical/formatter.py +11 -0
- kodit/domain/enrichments/architecture/physical/physical.py +17 -0
- kodit/domain/enrichments/development/__init__.py +1 -0
- kodit/domain/enrichments/development/development.py +18 -0
- kodit/domain/enrichments/development/snippet/__init__.py +1 -0
- kodit/domain/enrichments/development/snippet/snippet.py +21 -0
- kodit/domain/enrichments/enricher.py +17 -0
- kodit/domain/enrichments/enrichment.py +39 -0
- kodit/domain/enrichments/request.py +12 -0
- kodit/domain/enrichments/response.py +11 -0
- kodit/domain/enrichments/usage/__init__.py +1 -0
- kodit/domain/enrichments/usage/api_docs.py +19 -0
- kodit/domain/enrichments/usage/usage.py +18 -0
- kodit/domain/{entities.py → entities/__init__.py} +50 -195
- kodit/domain/entities/git.py +190 -0
- kodit/domain/factories/__init__.py +1 -0
- kodit/domain/factories/git_repo_factory.py +76 -0
- kodit/domain/protocols.py +264 -64
- kodit/domain/services/bm25_service.py +5 -1
- kodit/domain/services/embedding_service.py +3 -0
- kodit/domain/services/enrichment_service.py +9 -30
- kodit/domain/services/git_repository_service.py +429 -0
- kodit/domain/services/git_service.py +300 -0
- kodit/domain/services/physical_architecture_service.py +182 -0
- kodit/domain/services/task_status_query_service.py +2 -2
- kodit/domain/value_objects.py +87 -135
- kodit/infrastructure/api/client/__init__.py +0 -2
- kodit/infrastructure/api/v1/__init__.py +0 -4
- kodit/infrastructure/api/v1/dependencies.py +92 -46
- kodit/infrastructure/api/v1/routers/__init__.py +0 -6
- kodit/infrastructure/api/v1/routers/commits.py +352 -0
- kodit/infrastructure/api/v1/routers/queue.py +2 -2
- kodit/infrastructure/api/v1/routers/repositories.py +282 -0
- kodit/infrastructure/api/v1/routers/search.py +31 -14
- kodit/infrastructure/api/v1/schemas/__init__.py +0 -24
- kodit/infrastructure/api/v1/schemas/commit.py +96 -0
- kodit/infrastructure/api/v1/schemas/context.py +2 -0
- kodit/infrastructure/api/v1/schemas/enrichment.py +29 -0
- kodit/infrastructure/api/v1/schemas/repository.py +128 -0
- kodit/infrastructure/api/v1/schemas/search.py +12 -9
- kodit/infrastructure/api/v1/schemas/snippet.py +58 -0
- kodit/infrastructure/api/v1/schemas/tag.py +31 -0
- kodit/infrastructure/api/v1/schemas/task_status.py +2 -0
- kodit/infrastructure/bm25/local_bm25_repository.py +16 -4
- kodit/infrastructure/bm25/vectorchord_bm25_repository.py +68 -52
- kodit/infrastructure/cloning/git/git_python_adaptor.py +534 -0
- kodit/infrastructure/cloning/git/working_copy.py +1 -1
- kodit/infrastructure/embedding/embedding_factory.py +3 -2
- kodit/infrastructure/embedding/local_vector_search_repository.py +1 -1
- kodit/infrastructure/embedding/vectorchord_vector_search_repository.py +111 -84
- kodit/infrastructure/enricher/__init__.py +1 -0
- kodit/infrastructure/enricher/enricher_factory.py +53 -0
- kodit/infrastructure/{enrichment/litellm_enrichment_provider.py → enricher/litellm_enricher.py} +36 -56
- kodit/infrastructure/{enrichment/local_enrichment_provider.py → enricher/local_enricher.py} +19 -24
- kodit/infrastructure/enricher/null_enricher.py +36 -0
- kodit/infrastructure/indexing/fusion_service.py +1 -1
- kodit/infrastructure/mappers/enrichment_mapper.py +83 -0
- kodit/infrastructure/mappers/git_mapper.py +193 -0
- kodit/infrastructure/mappers/snippet_mapper.py +104 -0
- kodit/infrastructure/mappers/task_mapper.py +5 -44
- kodit/infrastructure/physical_architecture/__init__.py +1 -0
- kodit/infrastructure/physical_architecture/detectors/__init__.py +1 -0
- kodit/infrastructure/physical_architecture/detectors/docker_compose_detector.py +336 -0
- kodit/infrastructure/physical_architecture/formatters/__init__.py +1 -0
- kodit/infrastructure/physical_architecture/formatters/narrative_formatter.py +149 -0
- kodit/infrastructure/reporting/log_progress.py +8 -5
- kodit/infrastructure/reporting/telemetry_progress.py +21 -0
- kodit/infrastructure/slicing/api_doc_extractor.py +836 -0
- kodit/infrastructure/slicing/ast_analyzer.py +1128 -0
- kodit/infrastructure/slicing/slicer.py +87 -421
- kodit/infrastructure/sqlalchemy/embedding_repository.py +43 -23
- kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +118 -0
- kodit/infrastructure/sqlalchemy/entities.py +402 -158
- kodit/infrastructure/sqlalchemy/git_branch_repository.py +274 -0
- kodit/infrastructure/sqlalchemy/git_commit_repository.py +346 -0
- kodit/infrastructure/sqlalchemy/git_repository.py +262 -0
- kodit/infrastructure/sqlalchemy/git_tag_repository.py +268 -0
- kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +479 -0
- kodit/infrastructure/sqlalchemy/task_repository.py +29 -23
- kodit/infrastructure/sqlalchemy/task_status_repository.py +24 -12
- kodit/infrastructure/sqlalchemy/unit_of_work.py +10 -14
- kodit/mcp.py +12 -30
- kodit/migrations/env.py +1 -0
- kodit/migrations/versions/04b80f802e0c_foreign_key_review.py +100 -0
- kodit/migrations/versions/19f8c7faf8b9_add_generic_enrichment_type.py +260 -0
- kodit/migrations/versions/7f15f878c3a1_add_new_git_entities.py +690 -0
- kodit/migrations/versions/f9e5ef5e688f_add_git_commits_number.py +43 -0
- kodit/py.typed +0 -0
- kodit/utils/dump_config.py +361 -0
- kodit/utils/dump_openapi.py +6 -4
- kodit/utils/path_utils.py +29 -0
- {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/METADATA +3 -3
- kodit-0.5.1.dist-info/RECORD +168 -0
- kodit/application/factories/code_indexing_factory.py +0 -195
- kodit/application/services/auto_indexing_service.py +0 -99
- kodit/application/services/code_indexing_application_service.py +0 -410
- kodit/domain/services/index_query_service.py +0 -70
- kodit/domain/services/index_service.py +0 -269
- kodit/infrastructure/api/client/index_client.py +0 -57
- kodit/infrastructure/api/v1/routers/indexes.py +0 -164
- kodit/infrastructure/api/v1/schemas/index.py +0 -101
- kodit/infrastructure/bm25/bm25_factory.py +0 -28
- kodit/infrastructure/cloning/__init__.py +0 -1
- kodit/infrastructure/cloning/metadata.py +0 -98
- kodit/infrastructure/enrichment/__init__.py +0 -1
- kodit/infrastructure/enrichment/enrichment_factory.py +0 -52
- kodit/infrastructure/enrichment/null_enrichment_provider.py +0 -19
- kodit/infrastructure/mappers/index_mapper.py +0 -345
- kodit/infrastructure/reporting/tdqm_progress.py +0 -38
- kodit/infrastructure/slicing/language_detection_service.py +0 -18
- kodit/infrastructure/sqlalchemy/index_repository.py +0 -646
- kodit-0.4.3.dist-info/RECORD +0 -125
- /kodit/infrastructure/{enrichment → enricher}/utils.py +0 -0
- {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/WHEEL +0 -0
- {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/entry_points.txt +0 -0
- {kodit-0.4.3.dist-info → kodit-0.5.1.dist-info}/licenses/LICENSE +0 -0
kodit/domain/protocols.py
CHANGED
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
"""Repository protocol interfaces for the domain layer."""
|
|
2
2
|
|
|
3
|
-
from
|
|
4
|
-
from
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from typing import Any, Protocol
|
|
5
6
|
|
|
6
7
|
from pydantic import AnyUrl
|
|
7
8
|
|
|
8
9
|
from kodit.domain.entities import (
|
|
9
|
-
Index,
|
|
10
|
-
Snippet,
|
|
11
|
-
SnippetWithContext,
|
|
12
10
|
Task,
|
|
13
11
|
TaskStatus,
|
|
14
|
-
WorkingCopy,
|
|
15
12
|
)
|
|
16
|
-
from kodit.domain.
|
|
13
|
+
from kodit.domain.entities.git import (
|
|
14
|
+
GitBranch,
|
|
15
|
+
GitCommit,
|
|
16
|
+
GitRepo,
|
|
17
|
+
GitTag,
|
|
18
|
+
SnippetV2,
|
|
19
|
+
)
|
|
20
|
+
from kodit.domain.value_objects import (
|
|
21
|
+
FusionRequest,
|
|
22
|
+
FusionResult,
|
|
23
|
+
MultiSearchRequest,
|
|
24
|
+
TaskOperation,
|
|
25
|
+
)
|
|
17
26
|
|
|
18
27
|
|
|
19
28
|
class TaskRepository(Protocol):
|
|
@@ -30,96 +39,287 @@ class TaskRepository(Protocol):
|
|
|
30
39
|
"""Get a task by ID."""
|
|
31
40
|
...
|
|
32
41
|
|
|
33
|
-
async def
|
|
42
|
+
async def next(self) -> Task | None:
|
|
34
43
|
"""Take a task for processing."""
|
|
35
44
|
...
|
|
36
45
|
|
|
46
|
+
async def remove(self, task: Task) -> None:
|
|
47
|
+
"""Remove a task."""
|
|
48
|
+
...
|
|
49
|
+
|
|
37
50
|
async def update(self, task: Task) -> None:
|
|
38
51
|
"""Update a task."""
|
|
39
52
|
...
|
|
40
53
|
|
|
41
|
-
async def list(self,
|
|
54
|
+
async def list(self, task_operation: TaskOperation | None = None) -> list[Task]:
|
|
42
55
|
"""List tasks with optional status filter."""
|
|
43
56
|
...
|
|
44
57
|
|
|
45
58
|
|
|
46
|
-
class
|
|
47
|
-
"""
|
|
59
|
+
class ReportingModule(Protocol):
|
|
60
|
+
"""Reporting module."""
|
|
48
61
|
|
|
49
|
-
async def
|
|
50
|
-
"""
|
|
62
|
+
async def on_change(self, progress: TaskStatus) -> None:
|
|
63
|
+
"""On step changed."""
|
|
51
64
|
...
|
|
52
65
|
|
|
53
|
-
async def update(self, index: Index) -> None:
|
|
54
|
-
"""Update an index."""
|
|
55
|
-
...
|
|
56
66
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
...
|
|
67
|
+
class TaskStatusRepository(Protocol):
|
|
68
|
+
"""Repository interface for persisting progress state only."""
|
|
60
69
|
|
|
61
|
-
async def
|
|
62
|
-
"""
|
|
70
|
+
async def save(self, status: TaskStatus) -> None:
|
|
71
|
+
"""Save a progress state."""
|
|
63
72
|
...
|
|
64
73
|
|
|
65
|
-
async def
|
|
66
|
-
|
|
74
|
+
async def load_with_hierarchy(
|
|
75
|
+
self, trackable_type: str, trackable_id: int
|
|
76
|
+
) -> list[TaskStatus]:
|
|
77
|
+
"""Load progress states with IDs and parent IDs from database."""
|
|
67
78
|
...
|
|
68
79
|
|
|
69
|
-
async def
|
|
70
|
-
"""
|
|
80
|
+
async def delete(self, status: TaskStatus) -> None:
|
|
81
|
+
"""Delete a progress state."""
|
|
71
82
|
...
|
|
72
83
|
|
|
73
|
-
async def update_index_timestamp(self, index_id: int) -> None:
|
|
74
|
-
"""Update the timestamp of an index."""
|
|
75
|
-
...
|
|
76
84
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
...
|
|
85
|
+
class GitCommitRepository(ABC):
|
|
86
|
+
"""Repository for Git commits."""
|
|
80
87
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
88
|
+
@abstractmethod
|
|
89
|
+
async def get_by_sha(self, commit_sha: str) -> GitCommit:
|
|
90
|
+
"""Get a commit by its SHA."""
|
|
84
91
|
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
92
|
+
@abstractmethod
|
|
93
|
+
async def get_by_repo_id(self, repo_id: int) -> list[GitCommit]:
|
|
94
|
+
"""Get all commits for a repository."""
|
|
88
95
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
96
|
+
@abstractmethod
|
|
97
|
+
async def save(self, commit: GitCommit, repo_id: int) -> GitCommit:
|
|
98
|
+
"""Save a commit to a repository."""
|
|
92
99
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
100
|
+
@abstractmethod
|
|
101
|
+
async def save_bulk(self, commits: list[GitCommit], repo_id: int) -> None:
|
|
102
|
+
"""Bulk save commits to a repository."""
|
|
96
103
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
104
|
+
@abstractmethod
|
|
105
|
+
async def exists(self, commit_sha: str) -> bool:
|
|
106
|
+
"""Check if a commit exists."""
|
|
100
107
|
|
|
108
|
+
@abstractmethod
|
|
109
|
+
async def delete_by_repo_id(self, repo_id: int) -> None:
|
|
110
|
+
"""Delete all commits for a repository."""
|
|
101
111
|
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
@abstractmethod
|
|
113
|
+
async def count_by_repo_id(self, repo_id: int) -> int:
|
|
114
|
+
"""Count the number of commits for a repository."""
|
|
104
115
|
|
|
105
|
-
async def on_change(self, progress: TaskStatus) -> None:
|
|
106
|
-
"""On step changed."""
|
|
107
|
-
...
|
|
108
116
|
|
|
117
|
+
class GitBranchRepository(ABC):
|
|
118
|
+
"""Repository for Git branches."""
|
|
109
119
|
|
|
110
|
-
|
|
111
|
-
|
|
120
|
+
@abstractmethod
|
|
121
|
+
async def get_by_name(self, branch_name: str, repo_id: int) -> GitBranch:
|
|
122
|
+
"""Get a branch by name and repository ID."""
|
|
112
123
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
124
|
+
@abstractmethod
|
|
125
|
+
async def get_by_repo_id(self, repo_id: int) -> list[GitBranch]:
|
|
126
|
+
"""Get all branches for a repository."""
|
|
116
127
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
"""Load progress states with IDs and parent IDs from database."""
|
|
121
|
-
...
|
|
128
|
+
@abstractmethod
|
|
129
|
+
async def save(self, branch: GitBranch, repo_id: int) -> GitBranch:
|
|
130
|
+
"""Save a branch to a repository."""
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
132
|
+
@abstractmethod
|
|
133
|
+
async def save_bulk(self, branches: list[GitBranch], repo_id: int) -> None:
|
|
134
|
+
"""Bulk save branches to a repository."""
|
|
135
|
+
|
|
136
|
+
@abstractmethod
|
|
137
|
+
async def exists(self, branch_name: str, repo_id: int) -> bool:
|
|
138
|
+
"""Check if a branch exists."""
|
|
139
|
+
|
|
140
|
+
@abstractmethod
|
|
141
|
+
async def delete_by_repo_id(self, repo_id: int) -> None:
|
|
142
|
+
"""Delete all branches for a repository."""
|
|
143
|
+
|
|
144
|
+
@abstractmethod
|
|
145
|
+
async def count_by_repo_id(self, repo_id: int) -> int:
|
|
146
|
+
"""Count the number of branches for a repository."""
|
|
147
|
+
|
|
148
|
+
|
|
149
|
+
class GitTagRepository(ABC):
|
|
150
|
+
"""Repository for Git tags."""
|
|
151
|
+
|
|
152
|
+
@abstractmethod
|
|
153
|
+
async def get_by_name(self, tag_name: str, repo_id: int) -> GitTag:
|
|
154
|
+
"""Get a tag by name and repository ID."""
|
|
155
|
+
|
|
156
|
+
@abstractmethod
|
|
157
|
+
async def get_by_repo_id(self, repo_id: int) -> list[GitTag]:
|
|
158
|
+
"""Get all tags for a repository."""
|
|
159
|
+
|
|
160
|
+
@abstractmethod
|
|
161
|
+
async def save(self, tag: GitTag, repo_id: int) -> GitTag:
|
|
162
|
+
"""Save a tag to a repository."""
|
|
163
|
+
|
|
164
|
+
@abstractmethod
|
|
165
|
+
async def save_bulk(self, tags: list[GitTag], repo_id: int) -> None:
|
|
166
|
+
"""Bulk save tags to a repository."""
|
|
167
|
+
|
|
168
|
+
@abstractmethod
|
|
169
|
+
async def exists(self, tag_name: str, repo_id: int) -> bool:
|
|
170
|
+
"""Check if a tag exists."""
|
|
171
|
+
|
|
172
|
+
@abstractmethod
|
|
173
|
+
async def delete_by_repo_id(self, repo_id: int) -> None:
|
|
174
|
+
"""Delete all tags for a repository."""
|
|
175
|
+
|
|
176
|
+
@abstractmethod
|
|
177
|
+
async def count_by_repo_id(self, repo_id: int) -> int:
|
|
178
|
+
"""Count the number of tags for a repository."""
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
class GitRepoRepository(ABC):
|
|
182
|
+
"""Repository pattern for GitRepo aggregate.
|
|
183
|
+
|
|
184
|
+
GitRepo is the aggregate root that owns branches, commits, and tags.
|
|
185
|
+
This repository handles persistence of the entire aggregate.
|
|
186
|
+
"""
|
|
187
|
+
|
|
188
|
+
@abstractmethod
|
|
189
|
+
async def save(self, repo: GitRepo) -> GitRepo:
|
|
190
|
+
"""Save or update a repository with all its branches, commits, and tags.
|
|
191
|
+
|
|
192
|
+
This method persists the entire aggregate:
|
|
193
|
+
- The GitRepo entity itself
|
|
194
|
+
- All associated branches
|
|
195
|
+
- All associated commits
|
|
196
|
+
- All associated tags
|
|
197
|
+
"""
|
|
198
|
+
|
|
199
|
+
@abstractmethod
|
|
200
|
+
async def get_by_id(self, repo_id: int) -> GitRepo:
|
|
201
|
+
"""Get repository by ID with all associated data."""
|
|
202
|
+
|
|
203
|
+
@abstractmethod
|
|
204
|
+
async def get_by_uri(self, sanitized_uri: AnyUrl) -> GitRepo:
|
|
205
|
+
"""Get repository by sanitized URI with all associated data."""
|
|
206
|
+
|
|
207
|
+
@abstractmethod
|
|
208
|
+
async def get_by_commit(self, commit_sha: str) -> GitRepo:
|
|
209
|
+
"""Get repository by commit SHA with all associated data."""
|
|
210
|
+
|
|
211
|
+
@abstractmethod
|
|
212
|
+
async def get_all(self) -> list[GitRepo]:
|
|
213
|
+
"""Get all repositories."""
|
|
214
|
+
|
|
215
|
+
@abstractmethod
|
|
216
|
+
async def delete(self, sanitized_uri: AnyUrl) -> bool:
|
|
217
|
+
"""Delete a repository."""
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
class GitAdapter(ABC):
|
|
221
|
+
"""Abstract interface for Git operations."""
|
|
222
|
+
|
|
223
|
+
@abstractmethod
|
|
224
|
+
async def clone_repository(self, remote_uri: str, local_path: Path) -> None:
|
|
225
|
+
"""Clone a repository to local path."""
|
|
226
|
+
|
|
227
|
+
@abstractmethod
|
|
228
|
+
async def pull_repository(self, local_path: Path) -> None:
|
|
229
|
+
"""Pull latest changes for existing repository."""
|
|
230
|
+
|
|
231
|
+
@abstractmethod
|
|
232
|
+
async def get_all_branches(self, local_path: Path) -> list[dict[str, Any]]:
|
|
233
|
+
"""Get all branches in repository."""
|
|
234
|
+
|
|
235
|
+
@abstractmethod
|
|
236
|
+
async def get_branch_commits(
|
|
237
|
+
self, local_path: Path, branch_name: str
|
|
238
|
+
) -> list[dict[str, Any]]:
|
|
239
|
+
"""Get commit history for a specific branch."""
|
|
240
|
+
|
|
241
|
+
@abstractmethod
|
|
242
|
+
async def get_commit_files(
|
|
243
|
+
self, local_path: Path, commit_sha: str
|
|
244
|
+
) -> list[dict[str, Any]]:
|
|
245
|
+
"""Get all files in a specific commit from the git tree."""
|
|
246
|
+
|
|
247
|
+
@abstractmethod
|
|
248
|
+
async def get_commit_file_data(
|
|
249
|
+
self, local_path: Path, commit_sha: str
|
|
250
|
+
) -> list[dict[str, Any]]:
|
|
251
|
+
"""Get file metadata for a commit, with files checked out to disk."""
|
|
252
|
+
|
|
253
|
+
@abstractmethod
|
|
254
|
+
async def repository_exists(self, local_path: Path) -> bool:
|
|
255
|
+
"""Check if repository exists at local path."""
|
|
256
|
+
|
|
257
|
+
@abstractmethod
|
|
258
|
+
async def get_commit_details(
|
|
259
|
+
self, local_path: Path, commit_sha: str
|
|
260
|
+
) -> dict[str, Any]:
|
|
261
|
+
"""Get details of a specific commit."""
|
|
262
|
+
|
|
263
|
+
@abstractmethod
|
|
264
|
+
async def ensure_repository(self, remote_uri: str, local_path: Path) -> None:
|
|
265
|
+
"""Ensure repository exists at local path."""
|
|
266
|
+
|
|
267
|
+
@abstractmethod
|
|
268
|
+
async def get_file_content(
|
|
269
|
+
self, local_path: Path, commit_sha: str, file_path: str
|
|
270
|
+
) -> bytes:
|
|
271
|
+
"""Get file content at specific commit."""
|
|
272
|
+
|
|
273
|
+
@abstractmethod
|
|
274
|
+
async def get_latest_commit_sha(
|
|
275
|
+
self, local_path: Path, branch_name: str = "HEAD"
|
|
276
|
+
) -> str:
|
|
277
|
+
"""Get the latest commit SHA for a branch."""
|
|
278
|
+
|
|
279
|
+
@abstractmethod
|
|
280
|
+
async def get_all_tags(self, local_path: Path) -> list[dict[str, Any]]:
|
|
281
|
+
"""Get all tags in repository."""
|
|
282
|
+
|
|
283
|
+
@abstractmethod
|
|
284
|
+
async def get_all_commits_bulk(self, local_path: Path) -> dict[str, dict[str, Any]]:
|
|
285
|
+
"""Get all commits from all branches in bulk for efficiency."""
|
|
286
|
+
|
|
287
|
+
@abstractmethod
|
|
288
|
+
async def get_branch_commit_shas(
|
|
289
|
+
self, local_path: Path, branch_name: str
|
|
290
|
+
) -> list[str]:
|
|
291
|
+
"""Get only commit SHAs for a branch (much faster than full commit data)."""
|
|
292
|
+
|
|
293
|
+
|
|
294
|
+
class SnippetRepositoryV2(ABC):
|
|
295
|
+
"""Repository for snippet operations."""
|
|
296
|
+
|
|
297
|
+
@abstractmethod
|
|
298
|
+
async def save_snippets(self, commit_sha: str, snippets: list[SnippetV2]) -> None:
|
|
299
|
+
"""Batch save snippets for a commit."""
|
|
300
|
+
|
|
301
|
+
@abstractmethod
|
|
302
|
+
async def get_snippets_for_commit(self, commit_sha: str) -> list[SnippetV2]:
|
|
303
|
+
"""Get all snippets for a specific commit."""
|
|
304
|
+
|
|
305
|
+
@abstractmethod
|
|
306
|
+
async def delete_snippets_for_commit(self, commit_sha: str) -> None:
|
|
307
|
+
"""Delete all snippet associations for a commit."""
|
|
308
|
+
|
|
309
|
+
@abstractmethod
|
|
310
|
+
async def search(self, request: MultiSearchRequest) -> list[SnippetV2]:
|
|
311
|
+
"""Search snippets with filters."""
|
|
312
|
+
|
|
313
|
+
@abstractmethod
|
|
314
|
+
async def get_by_ids(self, ids: list[str]) -> list[SnippetV2]:
|
|
315
|
+
"""Get snippets by their IDs."""
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
class FusionService(ABC):
|
|
319
|
+
"""Abstract fusion service interface."""
|
|
320
|
+
|
|
321
|
+
@abstractmethod
|
|
322
|
+
def reciprocal_rank_fusion(
|
|
323
|
+
self, rankings: list[list[FusionRequest]], k: float = 60
|
|
324
|
+
) -> list[FusionResult]:
|
|
325
|
+
"""Perform reciprocal rank fusion on search results."""
|
|
@@ -105,7 +105,11 @@ class BM25DomainService:
|
|
|
105
105
|
valid_ids = [
|
|
106
106
|
snippet_id
|
|
107
107
|
for snippet_id in request.snippet_ids
|
|
108
|
-
if
|
|
108
|
+
if (
|
|
109
|
+
snippet_id is not None
|
|
110
|
+
and snippet_id != "0"
|
|
111
|
+
and not snippet_id.startswith("-")
|
|
112
|
+
)
|
|
109
113
|
]
|
|
110
114
|
|
|
111
115
|
if not valid_ids:
|
|
@@ -91,6 +91,9 @@ class EmbeddingDomainService:
|
|
|
91
91
|
if not valid_documents:
|
|
92
92
|
return
|
|
93
93
|
|
|
94
|
+
# TODO(Phil): We should handle the embedding of the documents here, then use the
|
|
95
|
+
# repo to simply store the embeddings.
|
|
96
|
+
|
|
94
97
|
# Domain logic: create new request with validated documents
|
|
95
98
|
validated_request = IndexRequest(documents=valid_documents)
|
|
96
99
|
async for result in self.vector_search_repository.index_documents(
|
|
@@ -1,48 +1,27 @@
|
|
|
1
1
|
"""Domain service for enrichment operations."""
|
|
2
2
|
|
|
3
|
-
from abc import ABC, abstractmethod
|
|
4
3
|
from collections.abc import AsyncGenerator
|
|
5
4
|
|
|
6
|
-
from kodit.domain.
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
EnrichmentResponse,
|
|
10
|
-
)
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class EnrichmentProvider(ABC):
|
|
14
|
-
"""Abstract enrichment provider interface."""
|
|
15
|
-
|
|
16
|
-
@abstractmethod
|
|
17
|
-
def enrich(
|
|
18
|
-
self, requests: list[EnrichmentRequest]
|
|
19
|
-
) -> AsyncGenerator[EnrichmentResponse, None]:
|
|
20
|
-
"""Enrich a list of requests."""
|
|
5
|
+
from kodit.domain.enrichments.enricher import Enricher
|
|
6
|
+
from kodit.domain.enrichments.request import EnrichmentRequest
|
|
7
|
+
from kodit.domain.enrichments.response import EnrichmentResponse
|
|
21
8
|
|
|
22
9
|
|
|
23
10
|
class EnrichmentDomainService:
|
|
24
11
|
"""Domain service for enrichment operations."""
|
|
25
12
|
|
|
26
|
-
def __init__(self,
|
|
27
|
-
"""Initialize the enrichment domain service.
|
|
28
|
-
|
|
29
|
-
Args:
|
|
30
|
-
enrichment_provider: The enrichment provider to use.
|
|
31
|
-
|
|
32
|
-
"""
|
|
33
|
-
self.enrichment_provider = enrichment_provider
|
|
13
|
+
def __init__(self, enricher: Enricher) -> None:
|
|
14
|
+
"""Initialize the enrichment domain service."""
|
|
15
|
+
self.enricher = enricher
|
|
34
16
|
|
|
35
17
|
async def enrich_documents(
|
|
36
|
-
self,
|
|
18
|
+
self, requests: list[EnrichmentRequest]
|
|
37
19
|
) -> AsyncGenerator[EnrichmentResponse, None]:
|
|
38
|
-
"""Enrich documents using the
|
|
39
|
-
|
|
40
|
-
Args:
|
|
41
|
-
request: The enrichment index request.
|
|
20
|
+
"""Enrich documents using the enricher.
|
|
42
21
|
|
|
43
22
|
Yields:
|
|
44
23
|
Enrichment responses as they are processed.
|
|
45
24
|
|
|
46
25
|
"""
|
|
47
|
-
async for response in self.
|
|
26
|
+
async for response in self.enricher.enrich(requests):
|
|
48
27
|
yield response
|