kodit 0.5.4__py3-none-any.whl → 0.5.5__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 (54) hide show
  1. kodit/_version.py +2 -2
  2. kodit/application/factories/server_factory.py +54 -32
  3. kodit/application/services/code_search_application_service.py +89 -12
  4. kodit/application/services/commit_indexing_application_service.py +314 -195
  5. kodit/application/services/enrichment_query_service.py +274 -43
  6. kodit/application/services/indexing_worker_service.py +1 -1
  7. kodit/application/services/queue_service.py +15 -10
  8. kodit/application/services/sync_scheduler.py +2 -1
  9. kodit/domain/enrichments/architecture/architecture.py +1 -1
  10. kodit/domain/enrichments/architecture/physical/physical.py +1 -1
  11. kodit/domain/enrichments/development/development.py +1 -1
  12. kodit/domain/enrichments/development/snippet/snippet.py +12 -5
  13. kodit/domain/enrichments/enrichment.py +31 -4
  14. kodit/domain/enrichments/usage/api_docs.py +1 -1
  15. kodit/domain/enrichments/usage/usage.py +1 -1
  16. kodit/domain/entities/git.py +30 -25
  17. kodit/domain/factories/git_repo_factory.py +20 -5
  18. kodit/domain/protocols.py +56 -125
  19. kodit/domain/services/embedding_service.py +14 -16
  20. kodit/domain/services/git_repository_service.py +60 -38
  21. kodit/domain/services/git_service.py +18 -11
  22. kodit/domain/tracking/resolution_service.py +6 -16
  23. kodit/domain/value_objects.py +2 -9
  24. kodit/infrastructure/api/v1/dependencies.py +12 -3
  25. kodit/infrastructure/api/v1/query_params.py +27 -0
  26. kodit/infrastructure/api/v1/routers/commits.py +91 -85
  27. kodit/infrastructure/api/v1/routers/repositories.py +53 -37
  28. kodit/infrastructure/api/v1/routers/search.py +1 -1
  29. kodit/infrastructure/api/v1/schemas/enrichment.py +14 -0
  30. kodit/infrastructure/api/v1/schemas/repository.py +1 -1
  31. kodit/infrastructure/slicing/api_doc_extractor.py +0 -2
  32. kodit/infrastructure/sqlalchemy/embedding_repository.py +44 -34
  33. kodit/infrastructure/sqlalchemy/enrichment_association_repository.py +73 -0
  34. kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +116 -97
  35. kodit/infrastructure/sqlalchemy/entities.py +12 -116
  36. kodit/infrastructure/sqlalchemy/git_branch_repository.py +52 -244
  37. kodit/infrastructure/sqlalchemy/git_commit_repository.py +35 -324
  38. kodit/infrastructure/sqlalchemy/git_file_repository.py +70 -0
  39. kodit/infrastructure/sqlalchemy/git_repository.py +60 -230
  40. kodit/infrastructure/sqlalchemy/git_tag_repository.py +53 -240
  41. kodit/infrastructure/sqlalchemy/query.py +331 -0
  42. kodit/infrastructure/sqlalchemy/repository.py +203 -0
  43. kodit/infrastructure/sqlalchemy/task_repository.py +79 -58
  44. kodit/infrastructure/sqlalchemy/task_status_repository.py +45 -52
  45. kodit/migrations/versions/4b1a3b2c8fa5_refactor_git_tracking.py +190 -0
  46. {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/METADATA +1 -1
  47. {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/RECORD +50 -48
  48. kodit/infrastructure/mappers/enrichment_mapper.py +0 -83
  49. kodit/infrastructure/mappers/git_mapper.py +0 -193
  50. kodit/infrastructure/mappers/snippet_mapper.py +0 -104
  51. kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +0 -479
  52. {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/WHEEL +0 -0
  53. {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/entry_points.txt +0 -0
  54. {kodit-0.5.4.dist-info → kodit-0.5.5.dist-info}/licenses/LICENSE +0 -0
@@ -3,12 +3,20 @@
3
3
  from typing import Annotated
4
4
 
5
5
  from fastapi import APIRouter, Depends, HTTPException, Query
6
+ from fastapi.responses import RedirectResponse
6
7
 
8
+ from kodit.domain.enrichments.development.development import ENRICHMENT_TYPE_DEVELOPMENT
9
+ from kodit.domain.enrichments.development.snippet.snippet import (
10
+ ENRICHMENT_SUBTYPE_SNIPPET,
11
+ )
12
+ from kodit.domain.entities.git import GitFile
7
13
  from kodit.infrastructure.api.middleware.auth import api_key_auth
8
14
  from kodit.infrastructure.api.v1.dependencies import (
9
15
  GitCommitRepositoryDep,
16
+ GitFileRepositoryDep,
10
17
  ServerFactoryDep,
11
18
  )
19
+ from kodit.infrastructure.api.v1.query_params import PaginationParamsDep
12
20
  from kodit.infrastructure.api.v1.schemas.commit import (
13
21
  CommitAttributes,
14
22
  CommitData,
@@ -23,17 +31,18 @@ from kodit.infrastructure.api.v1.schemas.commit import (
23
31
  FileResponse,
24
32
  )
25
33
  from kodit.infrastructure.api.v1.schemas.enrichment import (
34
+ EnrichmentAssociationData,
26
35
  EnrichmentAttributes,
27
36
  EnrichmentData,
28
37
  EnrichmentListResponse,
38
+ EnrichmentRelationships,
29
39
  )
30
- from kodit.infrastructure.api.v1.schemas.snippet import (
31
- EnrichmentSchema,
32
- GitFileSchema,
33
- SnippetAttributes,
34
- SnippetContentSchema,
35
- SnippetData,
36
- SnippetListResponse,
40
+ from kodit.infrastructure.sqlalchemy.query import (
41
+ EnrichmentAssociationQueryBuilder,
42
+ EnrichmentQueryBuilder,
43
+ FilterOperator,
44
+ GitFileQueryBuilder,
45
+ QueryBuilder,
37
46
  )
38
47
 
39
48
  router = APIRouter(
@@ -49,12 +58,19 @@ router = APIRouter(
49
58
 
50
59
  @router.get("/{repo_id}/commits", summary="List repository commits")
51
60
  async def list_repository_commits(
52
- repo_id: str, git_commit_repository: GitCommitRepositoryDep
61
+ repo_id: str,
62
+ git_commit_repository: GitCommitRepositoryDep,
63
+ pagination_params: PaginationParamsDep,
53
64
  ) -> CommitListResponse:
54
65
  """List all commits for a repository."""
55
66
  try:
56
67
  # Get all commits for the repository directly from commit repository
57
- commits = await git_commit_repository.get_by_repo_id(int(repo_id))
68
+ commits = await git_commit_repository.find(
69
+ QueryBuilder()
70
+ .filter("repo_id", FilterOperator.EQ, int(repo_id))
71
+ .paginate(pagination_params)
72
+ .sort("date", descending=True)
73
+ )
58
74
  except ValueError as e:
59
75
  raise HTTPException(status_code=404, detail="Repository not found") from e
60
76
 
@@ -89,7 +105,7 @@ async def get_repository_commit(
89
105
  """Get a specific commit for a repository."""
90
106
  try:
91
107
  # Get the specific commit directly from commit repository
92
- commit = await git_commit_repository.get_by_sha(commit_sha)
108
+ commit = await git_commit_repository.get(commit_sha)
93
109
  except ValueError as e:
94
110
  raise HTTPException(status_code=404, detail="Commit not found") from e
95
111
 
@@ -112,19 +128,17 @@ async def get_repository_commit(
112
128
  async def list_commit_files(
113
129
  repo_id: str, # noqa: ARG001
114
130
  commit_sha: str,
115
- git_commit_repository: GitCommitRepositoryDep,
131
+ git_file_repository: GitFileRepositoryDep,
132
+ pagination: PaginationParamsDep,
116
133
  ) -> FileListResponse:
117
134
  """List all files in a specific commit."""
118
- try:
119
- # Get the specific commit directly from commit repository
120
- commit = await git_commit_repository.get_by_sha(commit_sha)
121
- except ValueError as e:
122
- raise HTTPException(status_code=404, detail="Commit not found") from e
123
-
135
+ files = await git_file_repository.find(
136
+ GitFileQueryBuilder().for_commit_sha(commit_sha).paginate(pagination)
137
+ )
124
138
  return FileListResponse(
125
139
  data=[
126
140
  FileData(
127
- type="file",
141
+ type=GitFile.__name__,
128
142
  id=file.blob_sha,
129
143
  attributes=FileAttributes(
130
144
  blob_sha=file.blob_sha,
@@ -134,7 +148,7 @@ async def list_commit_files(
134
148
  extension=file.extension,
135
149
  ),
136
150
  )
137
- for file in commit.files
151
+ for file in files
138
152
  ]
139
153
  )
140
154
 
@@ -148,20 +162,17 @@ async def get_commit_file(
148
162
  repo_id: str, # noqa: ARG001
149
163
  commit_sha: str,
150
164
  blob_sha: str,
151
- git_commit_repository: GitCommitRepositoryDep,
165
+ git_file_repository: GitFileRepositoryDep,
152
166
  ) -> FileResponse:
153
167
  """Get a specific file from a commit."""
154
- try:
155
- # Get the specific commit directly from commit repository
156
- commit = await git_commit_repository.get_by_sha(commit_sha)
157
- except ValueError as e:
158
- raise HTTPException(status_code=404, detail="Commit not found") from e
159
-
160
- # Find the specific file
161
- file = next((f for f in commit.files if f.blob_sha == blob_sha), None)
162
- if not file:
168
+ files = await git_file_repository.find(
169
+ GitFileQueryBuilder().for_commit_sha(commit_sha).for_blob_sha(blob_sha)
170
+ )
171
+ if not files:
163
172
  raise HTTPException(status_code=404, detail="File not found")
164
-
173
+ if len(files) > 1:
174
+ raise HTTPException(status_code=422, detail="Multiple files found")
175
+ file = files[0]
165
176
  return FileResponse(
166
177
  data=FileData(
167
178
  type="file",
@@ -185,45 +196,11 @@ async def get_commit_file(
185
196
  async def list_commit_snippets(
186
197
  repo_id: str,
187
198
  commit_sha: str,
188
- server_factory: ServerFactoryDep,
189
- ) -> SnippetListResponse:
199
+ ) -> RedirectResponse:
190
200
  """List all snippets in a specific commit."""
191
- _ = repo_id # Required by FastAPI route path but not used in function
192
- snippet_repository = server_factory.snippet_v2_repository()
193
- snippets = await snippet_repository.get_snippets_for_commit(commit_sha)
194
-
195
- return SnippetListResponse(
196
- data=[
197
- SnippetData(
198
- type="snippet",
199
- id=snippet.sha,
200
- attributes=SnippetAttributes(
201
- created_at=snippet.created_at,
202
- updated_at=snippet.updated_at,
203
- derives_from=[
204
- GitFileSchema(
205
- blob_sha=file.blob_sha,
206
- path=file.path,
207
- mime_type=file.mime_type,
208
- size=file.size,
209
- )
210
- for file in snippet.derives_from
211
- ],
212
- content=SnippetContentSchema(
213
- value=snippet.content,
214
- language=snippet.extension,
215
- ),
216
- enrichments=[
217
- EnrichmentSchema(
218
- type=enrichment.type.value,
219
- content=enrichment.content,
220
- )
221
- for enrichment in snippet.enrichments
222
- ],
223
- ),
224
- )
225
- for snippet in snippets
226
- ]
201
+ return RedirectResponse(
202
+ status_code=308,
203
+ url=f"/api/v1/repositories/{repo_id}/commits/{commit_sha}/enrichments?enrichment_type={ENRICHMENT_TYPE_DEVELOPMENT}&enrichment_subtype={ENRICHMENT_SUBTYPE_SNIPPET}",
227
204
  )
228
205
 
229
206
 
@@ -247,14 +224,12 @@ async def list_commit_embeddings(
247
224
  ) -> EmbeddingListResponse:
248
225
  """List all embeddings for snippets in a specific commit."""
249
226
  _ = repo_id # Required by FastAPI route path but not used in function
250
- snippet_repository = server_factory.snippet_v2_repository()
251
- snippets = await snippet_repository.get_snippets_for_commit(commit_sha)
252
227
 
253
- if not snippets:
254
- return EmbeddingListResponse(data=[])
228
+ enrichment_query_service = server_factory.enrichment_query_service()
229
+ snippets = await enrichment_query_service.get_all_snippets_for_commit(commit_sha)
255
230
 
256
231
  # Get snippet SHAs
257
- snippet_shas = [snippet.sha for snippet in snippets]
232
+ snippet_shas = [str(snippet.id) for snippet in snippets]
258
233
 
259
234
  # Get embeddings for all snippets in the commit
260
235
  embedding_repository = server_factory.embedding_repository()
@@ -285,15 +260,18 @@ async def list_commit_enrichments(
285
260
  repo_id: str, # noqa: ARG001
286
261
  commit_sha: str,
287
262
  server_factory: ServerFactoryDep,
263
+ pagination_params: PaginationParamsDep,
264
+ enrichment_type: str | None = None,
288
265
  ) -> EnrichmentListResponse:
289
266
  """List all enrichments for a specific commit."""
290
267
  # TODO(Phil): Should use repo too, it's confusing to the user when they specify the
291
268
  # wrong commit and another repo. It's like they are seeing results from the other
292
269
  # repo.
293
- enrichment_v2_repository = server_factory.enrichment_v2_repository()
294
- enrichments = await enrichment_v2_repository.enrichments_for_entity_type(
295
- entity_type="git_commit",
296
- entity_ids=[commit_sha],
270
+ enrichment_query_service = server_factory.enrichment_query_service()
271
+ enrichments = await enrichment_query_service.all_enrichments_for_commit(
272
+ commit_sha=commit_sha,
273
+ pagination=pagination_params,
274
+ enrichment_type=enrichment_type,
297
275
  )
298
276
 
299
277
  return EnrichmentListResponse(
@@ -308,8 +286,17 @@ async def list_commit_enrichments(
308
286
  created_at=enrichment.created_at,
309
287
  updated_at=enrichment.updated_at,
310
288
  ),
289
+ relationships=EnrichmentRelationships(
290
+ associations=[
291
+ EnrichmentAssociationData(
292
+ id=association.entity_id,
293
+ type=association.entity_type,
294
+ )
295
+ for association in associations
296
+ ],
297
+ ),
311
298
  )
312
- for enrichment in enrichments
299
+ for enrichment, associations in enrichments.items()
313
300
  ]
314
301
  )
315
302
 
@@ -327,9 +314,26 @@ async def delete_all_commit_enrichments(
327
314
  ) -> None:
328
315
  """Delete all enrichments for a specific commit."""
329
316
  enrichment_v2_repository = server_factory.enrichment_v2_repository()
330
- await enrichment_v2_repository.bulk_delete_enrichments(
331
- entity_type="git_commit",
332
- entity_ids=[commit_sha],
317
+ enrichment_association_repository = (
318
+ server_factory.enrichment_association_repository()
319
+ )
320
+ associations = await enrichment_association_repository.find(
321
+ EnrichmentAssociationQueryBuilder().for_commit(commit_sha)
322
+ )
323
+ enrichments = await enrichment_v2_repository.find(
324
+ EnrichmentQueryBuilder().for_ids(
325
+ enrichment_ids=[association.enrichment_id for association in associations]
326
+ )
327
+ )
328
+ await enrichment_association_repository.delete_by_query(
329
+ EnrichmentAssociationQueryBuilder().for_enrichments(enrichments)
330
+ )
331
+ await enrichment_v2_repository.delete_by_query(
332
+ EnrichmentQueryBuilder().for_ids(
333
+ enrichment_ids=[
334
+ enrichment.id for enrichment in enrichments if enrichment.id
335
+ ]
336
+ )
333
337
  )
334
338
 
335
339
 
@@ -346,7 +350,9 @@ async def delete_commit_enrichment(
346
350
  server_factory: ServerFactoryDep,
347
351
  ) -> None:
348
352
  """Delete a specific enrichment for a commit."""
349
- enrichment_v2_repository = server_factory.enrichment_v2_repository()
350
- deleted = await enrichment_v2_repository.delete_enrichment(enrichment_id)
351
- if not deleted:
352
- raise HTTPException(status_code=404, detail="Enrichment not found")
353
+ try:
354
+ enrichment_v2_repository = server_factory.enrichment_v2_repository()
355
+ enrichment = await enrichment_v2_repository.get(enrichment_id)
356
+ await enrichment_v2_repository.delete(enrichment)
357
+ except ValueError as e:
358
+ raise HTTPException(status_code=404, detail="Enrichment not found") from e
@@ -1,6 +1,8 @@
1
1
  """Repository management router for the REST API."""
2
2
 
3
- from fastapi import APIRouter, Depends, HTTPException
3
+ from typing import Annotated
4
+
5
+ from fastapi import APIRouter, Depends, HTTPException, Query
4
6
 
5
7
  from kodit.domain.tracking.trackable import Trackable, TrackableReferenceType
6
8
  from kodit.infrastructure.api.middleware.auth import api_key_auth
@@ -13,6 +15,7 @@ from kodit.infrastructure.api.v1.dependencies import (
13
15
  GitTagRepositoryDep,
14
16
  TaskStatusQueryServiceDep,
15
17
  )
18
+ from kodit.infrastructure.api.v1.query_params import PaginationParamsDep
16
19
  from kodit.infrastructure.api.v1.schemas.enrichment import (
17
20
  EnrichmentAttributes,
18
21
  EnrichmentData,
@@ -38,6 +41,7 @@ from kodit.infrastructure.api.v1.schemas.task_status import (
38
41
  TaskStatusData,
39
42
  TaskStatusListResponse,
40
43
  )
44
+ from kodit.infrastructure.sqlalchemy.query import FilterOperator, QueryBuilder
41
45
 
42
46
  router = APIRouter(
43
47
  prefix="/api/v1/repositories",
@@ -60,7 +64,7 @@ async def list_repositories(
60
64
  git_repository: GitRepositoryDep,
61
65
  ) -> RepositoryListResponse:
62
66
  """List all cloned repositories."""
63
- repos = await git_repository.get_all()
67
+ repos = await git_repository.find(QueryBuilder())
64
68
  return RepositoryListResponse(
65
69
  data=[RepositoryData.from_git_repo(repo) for repo in repos]
66
70
  )
@@ -99,36 +103,47 @@ async def get_repository(
99
103
  git_branch_repository: GitBranchRepositoryDep,
100
104
  ) -> RepositoryDetailsResponse:
101
105
  """Get repository details including branches and recent commits."""
102
- repo = await git_repository.get_by_id(int(repo_id))
106
+ repo = await git_repository.get(int(repo_id))
103
107
  if not repo:
104
108
  raise HTTPException(status_code=404, detail="Repository not found")
105
109
 
110
+ # Get branches for the repository using the branch repository
111
+ repo_branches = await git_branch_repository.find(
112
+ QueryBuilder().filter("repo_id", FilterOperator.EQ, int(repo_id))
113
+ )
114
+
106
115
  # Get all commits for this repository from the commit repository
107
- repo_commits = await git_commit_repository.get_by_repo_id(int(repo_id))
116
+ repo_commits = await git_commit_repository.find(
117
+ QueryBuilder().filter("repo_id", FilterOperator.EQ, int(repo_id))
118
+ )
108
119
  commits_by_sha = {commit.commit_sha: commit for commit in repo_commits}
109
120
 
110
121
  # Get recent commits from the tracking branch's head commit
111
122
  recent_commits = []
112
- if repo.tracking_branch and repo.tracking_branch.head_commit:
123
+ # Get the tracking branch from the branch repository
124
+ tracking_branch = next(
125
+ (b for b in repo_branches if b.name == repo.tracking_config.name), None
126
+ )
127
+ if tracking_branch and tracking_branch.head_commit_sha:
113
128
  # For simplicity, just show the head commit and traverse back if needed
114
- current_commit = repo.tracking_branch.head_commit
115
- recent_commits = [current_commit]
116
-
117
- # Traverse parent commits for more recent commits (up to 10)
118
- current_sha = current_commit.parent_commit_sha
119
- while current_sha and len(recent_commits) < 10:
120
- parent_commit = commits_by_sha.get(current_sha)
121
- if parent_commit:
122
- recent_commits.append(parent_commit)
123
- current_sha = parent_commit.parent_commit_sha
124
- else:
125
- break
129
+ current_commit = commits_by_sha.get(tracking_branch.head_commit_sha)
130
+ if current_commit:
131
+ recent_commits = [current_commit]
132
+
133
+ # Traverse parent commits for more recent commits (up to 10)
134
+ current_sha = current_commit.parent_commit_sha
135
+ while current_sha and len(recent_commits) < 10:
136
+ parent_commit = commits_by_sha.get(current_sha)
137
+ if parent_commit:
138
+ recent_commits.append(parent_commit)
139
+ current_sha = parent_commit.parent_commit_sha
140
+ else:
141
+ break
126
142
 
127
143
  # Get commit count for the repository using the commit repository
128
- commit_count = await git_commit_repository.count_by_repo_id(int(repo_id))
129
-
130
- # Get branches for the repository using the branch repository
131
- repo_branches = await git_branch_repository.get_by_repo_id(int(repo_id))
144
+ commit_count = await git_commit_repository.count(
145
+ QueryBuilder().filter("repo_id", FilterOperator.EQ, int(repo_id))
146
+ )
132
147
 
133
148
  # Get commit counts for all branches using the commit repository
134
149
  branch_data = []
@@ -140,9 +155,7 @@ async def get_repository(
140
155
  branch_data.append(
141
156
  RepositoryBranchData(
142
157
  name=branch.name,
143
- is_default=branch.name == repo.tracking_branch.name
144
- if repo.tracking_branch
145
- else False,
158
+ is_default=branch.name == repo.tracking_config.name,
146
159
  commit_count=branch_commit_count,
147
160
  )
148
161
  )
@@ -208,7 +221,7 @@ async def list_repository_tags(
208
221
  git_tag_repository: GitTagRepositoryDep,
209
222
  ) -> TagListResponse:
210
223
  """List all tags for a repository."""
211
- repo = await git_repository.get_by_id(int(repo_id))
224
+ repo = await git_repository.get(int(repo_id))
212
225
  if not repo:
213
226
  raise HTTPException(status_code=404, detail="Repository not found")
214
227
 
@@ -222,7 +235,7 @@ async def list_repository_tags(
222
235
  id=tag.id,
223
236
  attributes=TagAttributes(
224
237
  name=tag.name,
225
- target_commit_sha=tag.target_commit.commit_sha,
238
+ target_commit_sha=tag.target_commit_sha,
226
239
  is_version_tag=tag.is_version_tag,
227
240
  ),
228
241
  )
@@ -243,7 +256,7 @@ async def get_repository_tag(
243
256
  git_tag_repository: GitTagRepositoryDep,
244
257
  ) -> TagResponse:
245
258
  """Get a specific tag for a repository."""
246
- repo = await git_repository.get_by_id(int(repo_id))
259
+ repo = await git_repository.get(int(repo_id))
247
260
  if not repo:
248
261
  raise HTTPException(status_code=404, detail="Repository not found")
249
262
 
@@ -259,7 +272,7 @@ async def get_repository_tag(
259
272
  id=tag.id,
260
273
  attributes=TagAttributes(
261
274
  name=tag.name,
262
- target_commit_sha=tag.target_commit.commit_sha,
275
+ target_commit_sha=tag.target_commit_sha,
263
276
  is_version_tag=tag.is_version_tag,
264
277
  ),
265
278
  )
@@ -275,10 +288,16 @@ async def list_repository_enrichments( # noqa: PLR0913
275
288
  repo_id: str,
276
289
  git_repository: GitRepositoryDep,
277
290
  enrichment_query_service: EnrichmentQueryServiceDep,
291
+ pagination: PaginationParamsDep,
278
292
  ref_type: str = "branch",
279
293
  ref_name: str | None = None,
280
294
  enrichment_type: str | None = None,
281
- limit: int = 10,
295
+ max_commits_to_check: Annotated[
296
+ int,
297
+ Query(
298
+ description="Number of recent commits to search for recent enriched commits"
299
+ ),
300
+ ] = 10,
282
301
  ) -> EnrichmentListResponse:
283
302
  """List the most recent enrichments for a repository.
284
303
 
@@ -289,7 +308,7 @@ async def list_repository_enrichments( # noqa: PLR0913
289
308
  - limit: Maximum number of enrichments to return. Defaults to 10.
290
309
  """
291
310
  # Get repository
292
- repo = await git_repository.get_by_id(int(repo_id))
311
+ repo = await git_repository.get(int(repo_id))
293
312
  if not repo:
294
313
  raise HTTPException(status_code=404, detail="Repository not found")
295
314
 
@@ -297,11 +316,7 @@ async def list_repository_enrichments( # noqa: PLR0913
297
316
  if ref_name is None:
298
317
  if ref_type == "branch":
299
318
  # Default to tracking branch
300
- if not repo.tracking_branch:
301
- raise HTTPException(
302
- status_code=400, detail="No tracking branch configured"
303
- )
304
- ref_name = repo.tracking_branch.name
319
+ ref_name = repo.tracking_config.name
305
320
  else:
306
321
  raise HTTPException(
307
322
  status_code=400,
@@ -326,7 +341,7 @@ async def list_repository_enrichments( # noqa: PLR0913
326
341
  enriched_commit = await enrichment_query_service.find_latest_enriched_commit(
327
342
  trackable=trackable,
328
343
  enrichment_type=enrichment_type,
329
- max_commits_to_check=limit * 10, # Check more commits to find enriched ones
344
+ max_commits_to_check=max_commits_to_check,
330
345
  )
331
346
 
332
347
  # If no enriched commit found, return empty list
@@ -334,9 +349,10 @@ async def list_repository_enrichments( # noqa: PLR0913
334
349
  return EnrichmentListResponse(data=[])
335
350
 
336
351
  # Get enrichments for the commit
337
- enrichments = await enrichment_query_service.get_enrichments_for_commit(
352
+ enrichments = await enrichment_query_service.all_enrichments_for_commit(
338
353
  commit_sha=enriched_commit,
339
354
  enrichment_type=enrichment_type,
355
+ pagination=pagination,
340
356
  )
341
357
 
342
358
  # Map enrichments to API response format
@@ -78,7 +78,7 @@ async def search_snippets(
78
78
  ),
79
79
  enrichments=[
80
80
  EnrichmentSchema(
81
- type=enrichment.type.value,
81
+ type=enrichment.type,
82
82
  content=enrichment.content,
83
83
  )
84
84
  for enrichment in result.snippet.enrichments
@@ -15,12 +15,26 @@ class EnrichmentAttributes(BaseModel):
15
15
  updated_at: datetime | None
16
16
 
17
17
 
18
+ class EnrichmentAssociationData(BaseModel):
19
+ """Enrichment association data for JSON-API spec."""
20
+
21
+ id: str
22
+ type: str
23
+
24
+
25
+ class EnrichmentRelationships(BaseModel):
26
+ """Enrichment relationships for JSON-API spec."""
27
+
28
+ associations: list[EnrichmentAssociationData] | None = None
29
+
30
+
18
31
  class EnrichmentData(BaseModel):
19
32
  """Enrichment data following JSON-API spec."""
20
33
 
21
34
  type: str = "enrichment"
22
35
  id: str
23
36
  attributes: EnrichmentAttributes
37
+ relationships: EnrichmentRelationships | None = None
24
38
 
25
39
 
26
40
  class EnrichmentListResponse(BaseModel):
@@ -30,7 +30,7 @@ class RepositoryAttributes(BaseModel):
30
30
  created_at=repo.created_at,
31
31
  updated_at=repo.updated_at,
32
32
  last_scanned_at=repo.last_scanned_at,
33
- tracking_branch=repo.tracking_branch.name if repo.tracking_branch else None,
33
+ tracking_branch=repo.tracking_config.name,
34
34
  num_commits=repo.num_commits,
35
35
  num_branches=repo.num_branches,
36
36
  num_tags=repo.num_tags,
@@ -39,7 +39,6 @@ class APIDocExtractor:
39
39
  self,
40
40
  files: list[GitFile],
41
41
  language: str,
42
- commit_sha: str,
43
42
  include_private: bool = False, # noqa: FBT001, FBT002
44
43
  ) -> list[APIDocEnrichment]:
45
44
  """Extract API documentation enrichments from files.
@@ -93,7 +92,6 @@ class APIDocExtractor:
93
92
  )
94
93
 
95
94
  enrichment = APIDocEnrichment(
96
- entity_id=commit_sha,
97
95
  language=language,
98
96
  content=markdown_content,
99
97
  )