kodit 0.4.2__py3-none-any.whl → 0.5.0__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 +59 -24
- kodit/application/factories/reporting_factory.py +16 -7
- kodit/application/factories/server_factory.py +311 -0
- kodit/application/services/code_search_application_service.py +144 -0
- kodit/application/services/commit_indexing_application_service.py +543 -0
- kodit/application/services/indexing_worker_service.py +13 -46
- kodit/application/services/queue_service.py +24 -3
- kodit/application/services/reporting.py +70 -54
- kodit/application/services/sync_scheduler.py +15 -31
- kodit/cli.py +2 -763
- kodit/cli_utils.py +2 -9
- kodit/config.py +3 -96
- kodit/database.py +38 -1
- kodit/domain/entities/__init__.py +276 -0
- 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 +270 -46
- kodit/domain/services/bm25_service.py +5 -1
- kodit/domain/services/embedding_service.py +3 -0
- kodit/domain/services/git_repository_service.py +429 -0
- kodit/domain/services/git_service.py +300 -0
- kodit/domain/services/task_status_query_service.py +19 -0
- kodit/domain/value_objects.py +113 -147
- kodit/infrastructure/api/client/__init__.py +0 -2
- kodit/infrastructure/api/v1/__init__.py +0 -4
- kodit/infrastructure/api/v1/dependencies.py +105 -44
- kodit/infrastructure/api/v1/routers/__init__.py +0 -6
- kodit/infrastructure/api/v1/routers/commits.py +271 -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/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 +41 -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 +467 -0
- kodit/infrastructure/cloning/git/working_copy.py +10 -3
- 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/enrichment/litellm_enrichment_provider.py +19 -26
- kodit/infrastructure/enrichment/local_enrichment_provider.py +41 -30
- kodit/infrastructure/indexing/fusion_service.py +1 -1
- kodit/infrastructure/mappers/git_mapper.py +193 -0
- kodit/infrastructure/mappers/snippet_mapper.py +106 -0
- kodit/infrastructure/mappers/task_mapper.py +5 -44
- kodit/infrastructure/mappers/task_status_mapper.py +85 -0
- kodit/infrastructure/reporting/db_progress.py +23 -0
- kodit/infrastructure/reporting/log_progress.py +13 -38
- kodit/infrastructure/reporting/telemetry_progress.py +21 -0
- kodit/infrastructure/slicing/slicer.py +32 -31
- kodit/infrastructure/sqlalchemy/embedding_repository.py +43 -23
- kodit/infrastructure/sqlalchemy/entities.py +428 -131
- kodit/infrastructure/sqlalchemy/git_branch_repository.py +263 -0
- kodit/infrastructure/sqlalchemy/git_commit_repository.py +337 -0
- kodit/infrastructure/sqlalchemy/git_repository.py +252 -0
- kodit/infrastructure/sqlalchemy/git_tag_repository.py +257 -0
- kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +484 -0
- kodit/infrastructure/sqlalchemy/task_repository.py +29 -23
- kodit/infrastructure/sqlalchemy/task_status_repository.py +91 -0
- kodit/infrastructure/sqlalchemy/unit_of_work.py +10 -14
- kodit/mcp.py +12 -26
- kodit/migrations/env.py +1 -1
- kodit/migrations/versions/04b80f802e0c_foreign_key_review.py +100 -0
- kodit/migrations/versions/7f15f878c3a1_add_new_git_entities.py +690 -0
- kodit/migrations/versions/b9cd1c3fd762_add_task_status.py +77 -0
- kodit/migrations/versions/f9e5ef5e688f_add_git_commits_number.py +43 -0
- kodit/py.typed +0 -0
- kodit/utils/dump_openapi.py +7 -4
- kodit/utils/path_utils.py +29 -0
- {kodit-0.4.2.dist-info → kodit-0.5.0.dist-info}/METADATA +3 -3
- kodit-0.5.0.dist-info/RECORD +137 -0
- kodit/application/factories/code_indexing_factory.py +0 -193
- kodit/application/services/auto_indexing_service.py +0 -103
- kodit/application/services/code_indexing_application_service.py +0 -393
- kodit/domain/entities.py +0 -323
- kodit/domain/services/index_query_service.py +0 -70
- kodit/domain/services/index_service.py +0 -267
- kodit/infrastructure/api/client/index_client.py +0 -57
- kodit/infrastructure/api/v1/routers/indexes.py +0 -119
- 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/mappers/index_mapper.py +0 -345
- kodit/infrastructure/reporting/tdqm_progress.py +0 -73
- kodit/infrastructure/slicing/language_detection_service.py +0 -18
- kodit/infrastructure/sqlalchemy/index_repository.py +0 -646
- kodit-0.4.2.dist-info/RECORD +0 -119
- {kodit-0.4.2.dist-info → kodit-0.5.0.dist-info}/WHEEL +0 -0
- {kodit-0.4.2.dist-info → kodit-0.5.0.dist-info}/entry_points.txt +0 -0
- {kodit-0.4.2.dist-info → kodit-0.5.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -2,13 +2,11 @@
|
|
|
2
2
|
|
|
3
3
|
from .base import BaseAPIClient
|
|
4
4
|
from .exceptions import AuthenticationError, KoditAPIError
|
|
5
|
-
from .index_client import IndexClient
|
|
6
5
|
from .search_client import SearchClient
|
|
7
6
|
|
|
8
7
|
__all__ = [
|
|
9
8
|
"AuthenticationError",
|
|
10
9
|
"BaseAPIClient",
|
|
11
|
-
"IndexClient",
|
|
12
10
|
"KoditAPIError",
|
|
13
11
|
"SearchClient",
|
|
14
12
|
]
|
|
@@ -1,22 +1,30 @@
|
|
|
1
1
|
"""FastAPI dependencies for the REST API."""
|
|
2
2
|
|
|
3
|
-
from collections.abc import
|
|
3
|
+
from collections.abc import Callable
|
|
4
4
|
from typing import Annotated, cast
|
|
5
5
|
|
|
6
6
|
from fastapi import Depends, Request
|
|
7
7
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
8
8
|
|
|
9
|
-
from kodit.application.factories.
|
|
10
|
-
|
|
9
|
+
from kodit.application.factories.server_factory import ServerFactory
|
|
10
|
+
from kodit.application.services.code_search_application_service import (
|
|
11
|
+
CodeSearchApplicationService,
|
|
11
12
|
)
|
|
12
|
-
from kodit.application.services.
|
|
13
|
-
|
|
13
|
+
from kodit.application.services.commit_indexing_application_service import (
|
|
14
|
+
CommitIndexingApplicationService,
|
|
14
15
|
)
|
|
15
16
|
from kodit.application.services.queue_service import QueueService
|
|
16
17
|
from kodit.config import AppContext
|
|
17
|
-
from kodit.domain.
|
|
18
|
-
|
|
19
|
-
|
|
18
|
+
from kodit.domain.protocols import (
|
|
19
|
+
GitBranchRepository,
|
|
20
|
+
GitCommitRepository,
|
|
21
|
+
GitRepoRepository,
|
|
22
|
+
GitTagRepository,
|
|
23
|
+
)
|
|
24
|
+
from kodit.domain.services.task_status_query_service import TaskStatusQueryService
|
|
25
|
+
from kodit.infrastructure.sqlalchemy.task_status_repository import (
|
|
26
|
+
create_task_status_repository,
|
|
27
|
+
)
|
|
20
28
|
|
|
21
29
|
|
|
22
30
|
def get_app_context(request: Request) -> AppContext:
|
|
@@ -30,24 +38,22 @@ def get_app_context(request: Request) -> AppContext:
|
|
|
30
38
|
AppContextDep = Annotated[AppContext, Depends(get_app_context)]
|
|
31
39
|
|
|
32
40
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
yield session
|
|
41
|
+
def get_server_factory(request: Request) -> ServerFactory:
|
|
42
|
+
"""Get the server factory dependency."""
|
|
43
|
+
server_factory = cast("ServerFactory", request.state.server_factory)
|
|
44
|
+
if server_factory is None:
|
|
45
|
+
raise RuntimeError("Server factory not initialized")
|
|
46
|
+
return server_factory
|
|
40
47
|
|
|
41
48
|
|
|
42
|
-
|
|
49
|
+
ServerFactoryDep = Annotated[ServerFactory, Depends(get_server_factory)]
|
|
43
50
|
|
|
44
51
|
|
|
45
52
|
async def get_db_session_factory(
|
|
46
|
-
|
|
47
|
-
) ->
|
|
53
|
+
server_factory: ServerFactoryDep,
|
|
54
|
+
) -> Callable[[], AsyncSession]:
|
|
48
55
|
"""Get database session dependency."""
|
|
49
|
-
|
|
50
|
-
yield db.session_factory
|
|
56
|
+
return server_factory.session_factory
|
|
51
57
|
|
|
52
58
|
|
|
53
59
|
DBSessionFactoryDep = Annotated[
|
|
@@ -55,42 +61,97 @@ DBSessionFactoryDep = Annotated[
|
|
|
55
61
|
]
|
|
56
62
|
|
|
57
63
|
|
|
58
|
-
async def
|
|
64
|
+
async def get_queue_service(
|
|
59
65
|
session_factory: DBSessionFactoryDep,
|
|
60
|
-
) ->
|
|
61
|
-
"""Get
|
|
62
|
-
return
|
|
63
|
-
|
|
64
|
-
fusion_service=ReciprocalRankFusionService(),
|
|
66
|
+
) -> QueueService:
|
|
67
|
+
"""Get queue service dependency."""
|
|
68
|
+
return QueueService(
|
|
69
|
+
session_factory=session_factory,
|
|
65
70
|
)
|
|
66
71
|
|
|
67
72
|
|
|
68
|
-
|
|
73
|
+
QueueServiceDep = Annotated[QueueService, Depends(get_queue_service)]
|
|
69
74
|
|
|
70
75
|
|
|
71
|
-
async def
|
|
72
|
-
app_context: AppContextDep,
|
|
73
|
-
session: DBSessionDep,
|
|
76
|
+
async def get_task_status_query_service(
|
|
74
77
|
session_factory: DBSessionFactoryDep,
|
|
75
|
-
) ->
|
|
76
|
-
"""Get
|
|
77
|
-
return
|
|
78
|
-
|
|
78
|
+
) -> TaskStatusQueryService:
|
|
79
|
+
"""Get task status query service dependency."""
|
|
80
|
+
return TaskStatusQueryService(
|
|
81
|
+
repository=create_task_status_repository(session_factory=session_factory)
|
|
79
82
|
)
|
|
80
83
|
|
|
81
84
|
|
|
82
|
-
|
|
83
|
-
|
|
85
|
+
TaskStatusQueryServiceDep = Annotated[
|
|
86
|
+
TaskStatusQueryService, Depends(get_task_status_query_service)
|
|
84
87
|
]
|
|
85
88
|
|
|
86
89
|
|
|
87
|
-
async def
|
|
88
|
-
|
|
89
|
-
) ->
|
|
90
|
-
"""Get
|
|
91
|
-
return
|
|
92
|
-
session_factory=session_factory,
|
|
93
|
-
)
|
|
90
|
+
async def get_git_repository(
|
|
91
|
+
server_factory: ServerFactoryDep,
|
|
92
|
+
) -> GitRepoRepository:
|
|
93
|
+
"""Get git repository dependency."""
|
|
94
|
+
return server_factory.repo_repository()
|
|
94
95
|
|
|
95
96
|
|
|
96
|
-
|
|
97
|
+
GitRepositoryDep = Annotated[GitRepoRepository, Depends(get_git_repository)]
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
async def get_git_commit_repository(
|
|
101
|
+
server_factory: ServerFactoryDep,
|
|
102
|
+
) -> GitCommitRepository:
|
|
103
|
+
"""Get git commit repository dependency."""
|
|
104
|
+
return server_factory.git_commit_repository()
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
GitCommitRepositoryDep = Annotated[
|
|
108
|
+
GitCommitRepository, Depends(get_git_commit_repository)
|
|
109
|
+
]
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
async def get_git_branch_repository(
|
|
113
|
+
server_factory: ServerFactoryDep,
|
|
114
|
+
) -> GitBranchRepository:
|
|
115
|
+
"""Get git branch repository dependency."""
|
|
116
|
+
return server_factory.git_branch_repository()
|
|
117
|
+
|
|
118
|
+
|
|
119
|
+
GitBranchRepositoryDep = Annotated[
|
|
120
|
+
GitBranchRepository, Depends(get_git_branch_repository)
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
async def get_git_tag_repository(
|
|
125
|
+
server_factory: ServerFactoryDep,
|
|
126
|
+
) -> GitTagRepository:
|
|
127
|
+
"""Get git tag repository dependency."""
|
|
128
|
+
return server_factory.git_tag_repository()
|
|
129
|
+
|
|
130
|
+
|
|
131
|
+
GitTagRepositoryDep = Annotated[
|
|
132
|
+
GitTagRepository, Depends(get_git_tag_repository)
|
|
133
|
+
]
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
async def get_commit_indexing_app_service(
|
|
137
|
+
server_factory: ServerFactoryDep,
|
|
138
|
+
) -> CommitIndexingApplicationService:
|
|
139
|
+
"""Get commit indexing application service dependency."""
|
|
140
|
+
return server_factory.commit_indexing_application_service()
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
CommitIndexingAppServiceDep = Annotated[
|
|
144
|
+
CommitIndexingApplicationService, Depends(get_commit_indexing_app_service)
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
async def get_code_search_app_service(
|
|
149
|
+
server_factory: ServerFactoryDep,
|
|
150
|
+
) -> CodeSearchApplicationService:
|
|
151
|
+
"""Get code search application service dependency."""
|
|
152
|
+
return server_factory.code_search_application_service()
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
CodeSearchAppServiceDep = Annotated[
|
|
156
|
+
CodeSearchApplicationService, Depends(get_code_search_app_service)
|
|
157
|
+
]
|
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
"""Commit management router for the REST API."""
|
|
2
|
+
|
|
3
|
+
from typing import Annotated
|
|
4
|
+
|
|
5
|
+
from fastapi import APIRouter, Depends, HTTPException, Query
|
|
6
|
+
|
|
7
|
+
from kodit.infrastructure.api.middleware.auth import api_key_auth
|
|
8
|
+
from kodit.infrastructure.api.v1.dependencies import (
|
|
9
|
+
GitCommitRepositoryDep,
|
|
10
|
+
ServerFactoryDep,
|
|
11
|
+
)
|
|
12
|
+
from kodit.infrastructure.api.v1.schemas.commit import (
|
|
13
|
+
CommitAttributes,
|
|
14
|
+
CommitData,
|
|
15
|
+
CommitListResponse,
|
|
16
|
+
CommitResponse,
|
|
17
|
+
EmbeddingAttributes,
|
|
18
|
+
EmbeddingData,
|
|
19
|
+
EmbeddingListResponse,
|
|
20
|
+
FileAttributes,
|
|
21
|
+
FileData,
|
|
22
|
+
FileListResponse,
|
|
23
|
+
FileResponse,
|
|
24
|
+
)
|
|
25
|
+
from kodit.infrastructure.api.v1.schemas.snippet import (
|
|
26
|
+
EnrichmentSchema,
|
|
27
|
+
GitFileSchema,
|
|
28
|
+
SnippetAttributes,
|
|
29
|
+
SnippetContentSchema,
|
|
30
|
+
SnippetData,
|
|
31
|
+
SnippetListResponse,
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
router = APIRouter(
|
|
35
|
+
prefix="/api/v1/repositories",
|
|
36
|
+
tags=["commits"],
|
|
37
|
+
dependencies=[Depends(api_key_auth)],
|
|
38
|
+
responses={
|
|
39
|
+
401: {"description": "Unauthorized"},
|
|
40
|
+
422: {"description": "Invalid request"},
|
|
41
|
+
},
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
@router.get("/{repo_id}/commits", summary="List repository commits")
|
|
46
|
+
async def list_repository_commits(
|
|
47
|
+
repo_id: str, git_commit_repository: GitCommitRepositoryDep
|
|
48
|
+
) -> CommitListResponse:
|
|
49
|
+
"""List all commits for a repository."""
|
|
50
|
+
try:
|
|
51
|
+
# Get all commits for the repository directly from commit repository
|
|
52
|
+
commits = await git_commit_repository.get_by_repo_id(int(repo_id))
|
|
53
|
+
except ValueError as e:
|
|
54
|
+
raise HTTPException(status_code=404, detail="Repository not found") from e
|
|
55
|
+
|
|
56
|
+
return CommitListResponse(
|
|
57
|
+
data=[
|
|
58
|
+
CommitData(
|
|
59
|
+
type="commit",
|
|
60
|
+
id=commit.commit_sha,
|
|
61
|
+
attributes=CommitAttributes(
|
|
62
|
+
commit_sha=commit.commit_sha,
|
|
63
|
+
date=commit.date,
|
|
64
|
+
message=commit.message,
|
|
65
|
+
parent_commit_sha=commit.parent_commit_sha or "",
|
|
66
|
+
author=commit.author,
|
|
67
|
+
),
|
|
68
|
+
)
|
|
69
|
+
for commit in commits
|
|
70
|
+
]
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
@router.get(
|
|
75
|
+
"/{repo_id}/commits/{commit_sha}",
|
|
76
|
+
summary="Get repository commit",
|
|
77
|
+
responses={404: {"description": "Repository or commit not found"}},
|
|
78
|
+
)
|
|
79
|
+
async def get_repository_commit(
|
|
80
|
+
repo_id: str, # noqa: ARG001
|
|
81
|
+
commit_sha: str,
|
|
82
|
+
git_commit_repository: GitCommitRepositoryDep,
|
|
83
|
+
) -> CommitResponse:
|
|
84
|
+
"""Get a specific commit for a repository."""
|
|
85
|
+
try:
|
|
86
|
+
# Get the specific commit directly from commit repository
|
|
87
|
+
commit = await git_commit_repository.get_by_sha(commit_sha)
|
|
88
|
+
except ValueError as e:
|
|
89
|
+
raise HTTPException(status_code=404, detail="Commit not found") from e
|
|
90
|
+
|
|
91
|
+
return CommitResponse(
|
|
92
|
+
data=CommitData(
|
|
93
|
+
type="commit",
|
|
94
|
+
id=commit.commit_sha,
|
|
95
|
+
attributes=CommitAttributes(
|
|
96
|
+
commit_sha=commit.commit_sha,
|
|
97
|
+
date=commit.date,
|
|
98
|
+
message=commit.message,
|
|
99
|
+
parent_commit_sha=commit.parent_commit_sha or "",
|
|
100
|
+
author=commit.author,
|
|
101
|
+
),
|
|
102
|
+
)
|
|
103
|
+
)
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
@router.get("/{repo_id}/commits/{commit_sha}/files", summary="List commit files")
|
|
107
|
+
async def list_commit_files(
|
|
108
|
+
repo_id: str, # noqa: ARG001
|
|
109
|
+
commit_sha: str,
|
|
110
|
+
git_commit_repository: GitCommitRepositoryDep,
|
|
111
|
+
) -> FileListResponse:
|
|
112
|
+
"""List all files in a specific commit."""
|
|
113
|
+
try:
|
|
114
|
+
# Get the specific commit directly from commit repository
|
|
115
|
+
commit = await git_commit_repository.get_by_sha(commit_sha)
|
|
116
|
+
except ValueError as e:
|
|
117
|
+
raise HTTPException(status_code=404, detail="Commit not found") from e
|
|
118
|
+
|
|
119
|
+
return FileListResponse(
|
|
120
|
+
data=[
|
|
121
|
+
FileData(
|
|
122
|
+
type="file",
|
|
123
|
+
id=file.blob_sha,
|
|
124
|
+
attributes=FileAttributes(
|
|
125
|
+
blob_sha=file.blob_sha,
|
|
126
|
+
path=file.path,
|
|
127
|
+
mime_type=file.mime_type,
|
|
128
|
+
size=file.size,
|
|
129
|
+
extension=file.extension,
|
|
130
|
+
),
|
|
131
|
+
)
|
|
132
|
+
for file in commit.files
|
|
133
|
+
]
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
|
|
137
|
+
@router.get(
|
|
138
|
+
"/{repo_id}/commits/{commit_sha}/files/{blob_sha}",
|
|
139
|
+
summary="Get commit file",
|
|
140
|
+
responses={404: {"description": "Repository, commit or file not found"}},
|
|
141
|
+
)
|
|
142
|
+
async def get_commit_file(
|
|
143
|
+
repo_id: str, # noqa: ARG001
|
|
144
|
+
commit_sha: str,
|
|
145
|
+
blob_sha: str,
|
|
146
|
+
git_commit_repository: GitCommitRepositoryDep,
|
|
147
|
+
) -> FileResponse:
|
|
148
|
+
"""Get a specific file from a commit."""
|
|
149
|
+
try:
|
|
150
|
+
# Get the specific commit directly from commit repository
|
|
151
|
+
commit = await git_commit_repository.get_by_sha(commit_sha)
|
|
152
|
+
except ValueError as e:
|
|
153
|
+
raise HTTPException(status_code=404, detail="Commit not found") from e
|
|
154
|
+
|
|
155
|
+
# Find the specific file
|
|
156
|
+
file = next((f for f in commit.files if f.blob_sha == blob_sha), None)
|
|
157
|
+
if not file:
|
|
158
|
+
raise HTTPException(status_code=404, detail="File not found")
|
|
159
|
+
|
|
160
|
+
return FileResponse(
|
|
161
|
+
data=FileData(
|
|
162
|
+
type="file",
|
|
163
|
+
id=file.blob_sha,
|
|
164
|
+
attributes=FileAttributes(
|
|
165
|
+
blob_sha=file.blob_sha,
|
|
166
|
+
path=file.path,
|
|
167
|
+
mime_type=file.mime_type,
|
|
168
|
+
size=file.size,
|
|
169
|
+
extension=file.extension,
|
|
170
|
+
),
|
|
171
|
+
)
|
|
172
|
+
)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
@router.get(
|
|
176
|
+
"/{repo_id}/commits/{commit_sha}/snippets",
|
|
177
|
+
summary="List commit snippets",
|
|
178
|
+
responses={404: {"description": "Repository or commit not found"}},
|
|
179
|
+
)
|
|
180
|
+
async def list_commit_snippets(
|
|
181
|
+
repo_id: str,
|
|
182
|
+
commit_sha: str,
|
|
183
|
+
server_factory: ServerFactoryDep,
|
|
184
|
+
) -> SnippetListResponse:
|
|
185
|
+
"""List all snippets in a specific commit."""
|
|
186
|
+
_ = repo_id # Required by FastAPI route path but not used in function
|
|
187
|
+
snippet_repository = server_factory.snippet_v2_repository()
|
|
188
|
+
snippets = await snippet_repository.get_snippets_for_commit(commit_sha)
|
|
189
|
+
|
|
190
|
+
return SnippetListResponse(
|
|
191
|
+
data=[
|
|
192
|
+
SnippetData(
|
|
193
|
+
type="snippet",
|
|
194
|
+
id=snippet.sha,
|
|
195
|
+
attributes=SnippetAttributes(
|
|
196
|
+
created_at=snippet.created_at,
|
|
197
|
+
updated_at=snippet.updated_at,
|
|
198
|
+
derives_from=[
|
|
199
|
+
GitFileSchema(
|
|
200
|
+
blob_sha=file.blob_sha,
|
|
201
|
+
path=file.path,
|
|
202
|
+
mime_type=file.mime_type,
|
|
203
|
+
size=file.size,
|
|
204
|
+
)
|
|
205
|
+
for file in snippet.derives_from
|
|
206
|
+
],
|
|
207
|
+
content=SnippetContentSchema(
|
|
208
|
+
value=snippet.content,
|
|
209
|
+
language=snippet.extension,
|
|
210
|
+
),
|
|
211
|
+
enrichments=[
|
|
212
|
+
EnrichmentSchema(
|
|
213
|
+
type=enrichment.type.value,
|
|
214
|
+
content=enrichment.content,
|
|
215
|
+
)
|
|
216
|
+
for enrichment in snippet.enrichments
|
|
217
|
+
],
|
|
218
|
+
),
|
|
219
|
+
)
|
|
220
|
+
for snippet in snippets
|
|
221
|
+
]
|
|
222
|
+
)
|
|
223
|
+
|
|
224
|
+
|
|
225
|
+
# TODO(Phil): This doesn't return vectorchord embeddings properly because it's
|
|
226
|
+
# implemented in a different repo
|
|
227
|
+
@router.get(
|
|
228
|
+
"/{repo_id}/commits/{commit_sha}/embeddings",
|
|
229
|
+
summary="List commit embeddings",
|
|
230
|
+
responses={404: {"description": "Repository or commit not found"}},
|
|
231
|
+
)
|
|
232
|
+
async def list_commit_embeddings(
|
|
233
|
+
repo_id: str,
|
|
234
|
+
commit_sha: str,
|
|
235
|
+
server_factory: ServerFactoryDep,
|
|
236
|
+
full: Annotated[ # noqa: FBT002
|
|
237
|
+
bool,
|
|
238
|
+
Query(
|
|
239
|
+
description="If true, return full vectors. If false, return first 5 values."
|
|
240
|
+
),
|
|
241
|
+
] = False,
|
|
242
|
+
) -> EmbeddingListResponse:
|
|
243
|
+
"""List all embeddings for snippets in a specific commit."""
|
|
244
|
+
_ = repo_id # Required by FastAPI route path but not used in function
|
|
245
|
+
snippet_repository = server_factory.snippet_v2_repository()
|
|
246
|
+
snippets = await snippet_repository.get_snippets_for_commit(commit_sha)
|
|
247
|
+
|
|
248
|
+
if not snippets:
|
|
249
|
+
return EmbeddingListResponse(data=[])
|
|
250
|
+
|
|
251
|
+
# Get snippet SHAs
|
|
252
|
+
snippet_shas = [snippet.sha for snippet in snippets]
|
|
253
|
+
|
|
254
|
+
# Get embeddings for all snippets in the commit
|
|
255
|
+
embedding_repository = server_factory.embedding_repository()
|
|
256
|
+
embeddings = await embedding_repository.get_embeddings_by_snippet_ids(snippet_shas)
|
|
257
|
+
|
|
258
|
+
return EmbeddingListResponse(
|
|
259
|
+
data=[
|
|
260
|
+
EmbeddingData(
|
|
261
|
+
type="embedding",
|
|
262
|
+
id=f"{embedding.snippet_id}_{embedding.type.value}",
|
|
263
|
+
attributes=EmbeddingAttributes(
|
|
264
|
+
snippet_sha=embedding.snippet_id,
|
|
265
|
+
embedding_type=embedding.type.name.lower(),
|
|
266
|
+
embedding=embedding.embedding if full else embedding.embedding[:5],
|
|
267
|
+
),
|
|
268
|
+
)
|
|
269
|
+
for embedding in embeddings
|
|
270
|
+
]
|
|
271
|
+
)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from fastapi import APIRouter, Depends, HTTPException
|
|
4
4
|
|
|
5
|
-
from kodit.domain.value_objects import
|
|
5
|
+
from kodit.domain.value_objects import TaskOperation
|
|
6
6
|
from kodit.infrastructure.api.middleware.auth import api_key_auth
|
|
7
7
|
from kodit.infrastructure.api.v1.dependencies import QueueServiceDep
|
|
8
8
|
from kodit.infrastructure.api.v1.schemas.queue import (
|
|
@@ -26,7 +26,7 @@ router = APIRouter(
|
|
|
26
26
|
@router.get("")
|
|
27
27
|
async def list_queue_tasks(
|
|
28
28
|
queue_service: QueueServiceDep,
|
|
29
|
-
task_type:
|
|
29
|
+
task_type: TaskOperation | None = None,
|
|
30
30
|
) -> TaskListResponse:
|
|
31
31
|
"""List all tasks in the queue.
|
|
32
32
|
|