kodit 0.5.0__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 +10 -12
- kodit/application/factories/server_factory.py +53 -11
- kodit/application/services/commit_indexing_application_service.py +188 -31
- kodit/config.py +3 -3
- 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/protocols.py +7 -6
- kodit/domain/services/enrichment_service.py +9 -30
- kodit/domain/services/physical_architecture_service.py +182 -0
- kodit/domain/value_objects.py +6 -23
- kodit/infrastructure/api/v1/routers/commits.py +81 -0
- kodit/infrastructure/api/v1/schemas/enrichment.py +29 -0
- kodit/infrastructure/cloning/git/git_python_adaptor.py +71 -4
- 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} +20 -33
- kodit/infrastructure/{enrichment/local_enrichment_provider.py → enricher/local_enricher.py} +19 -24
- kodit/infrastructure/enricher/null_enricher.py +36 -0
- kodit/infrastructure/mappers/enrichment_mapper.py +83 -0
- kodit/infrastructure/mappers/snippet_mapper.py +20 -22
- 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/slicing/api_doc_extractor.py +836 -0
- kodit/infrastructure/slicing/ast_analyzer.py +1128 -0
- kodit/infrastructure/slicing/slicer.py +56 -391
- kodit/infrastructure/sqlalchemy/enrichment_v2_repository.py +118 -0
- kodit/infrastructure/sqlalchemy/entities.py +46 -38
- kodit/infrastructure/sqlalchemy/git_branch_repository.py +22 -11
- kodit/infrastructure/sqlalchemy/git_commit_repository.py +23 -14
- kodit/infrastructure/sqlalchemy/git_repository.py +27 -17
- kodit/infrastructure/sqlalchemy/git_tag_repository.py +22 -11
- kodit/infrastructure/sqlalchemy/snippet_v2_repository.py +101 -106
- kodit/migrations/versions/19f8c7faf8b9_add_generic_enrichment_type.py +260 -0
- kodit/utils/dump_config.py +361 -0
- kodit/utils/dump_openapi.py +5 -6
- {kodit-0.5.0.dist-info → kodit-0.5.1.dist-info}/METADATA +1 -1
- {kodit-0.5.0.dist-info → kodit-0.5.1.dist-info}/RECORD +61 -30
- 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/{enrichment → enricher}/utils.py +0 -0
- {kodit-0.5.0.dist-info → kodit-0.5.1.dist-info}/WHEEL +0 -0
- {kodit-0.5.0.dist-info → kodit-0.5.1.dist-info}/entry_points.txt +0 -0
- {kodit-0.5.0.dist-info → kodit-0.5.1.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Enricher factory for creating generic enricher domain services."""
|
|
2
|
+
|
|
3
|
+
from kodit.config import AppContext, Endpoint
|
|
4
|
+
from kodit.domain.enrichments.enricher import Enricher
|
|
5
|
+
from kodit.infrastructure.enricher.litellm_enricher import LiteLLMEnricher
|
|
6
|
+
from kodit.infrastructure.enricher.local_enricher import LocalEnricher
|
|
7
|
+
from kodit.infrastructure.enricher.null_enricher import NullEnricher
|
|
8
|
+
from kodit.log import log_event
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _get_endpoint_configuration(app_context: AppContext) -> Endpoint | None:
|
|
12
|
+
"""Get the endpoint configuration for the enricher service.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
app_context: The application context.
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
The endpoint configuration or None.
|
|
19
|
+
|
|
20
|
+
"""
|
|
21
|
+
return app_context.enrichment_endpoint or None
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
def enricher_domain_service_factory(
|
|
25
|
+
app_context: AppContext,
|
|
26
|
+
*,
|
|
27
|
+
use_null_enricher: bool = False,
|
|
28
|
+
) -> Enricher:
|
|
29
|
+
"""Create an enricher domain service.
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
app_context: The application context.
|
|
33
|
+
use_null_enricher: Whether to use the null enricher instead.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
An enricher domain service instance.
|
|
37
|
+
|
|
38
|
+
"""
|
|
39
|
+
enricher: Enricher
|
|
40
|
+
|
|
41
|
+
if use_null_enricher:
|
|
42
|
+
log_event("kodit.enricher", {"provider": "null"})
|
|
43
|
+
enricher = NullEnricher()
|
|
44
|
+
else:
|
|
45
|
+
endpoint = _get_endpoint_configuration(app_context)
|
|
46
|
+
if endpoint:
|
|
47
|
+
log_event("kodit.enricher", {"provider": "litellm"})
|
|
48
|
+
enricher = LiteLLMEnricher(endpoint=endpoint)
|
|
49
|
+
else:
|
|
50
|
+
log_event("kodit.enricher", {"provider": "local"})
|
|
51
|
+
enricher = LocalEnricher()
|
|
52
|
+
|
|
53
|
+
return enricher
|
kodit/infrastructure/{enrichment/litellm_enrichment_provider.py → enricher/litellm_enricher.py}
RENAMED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""LiteLLM
|
|
1
|
+
"""LiteLLM enricher implementation."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
from collections.abc import AsyncGenerator
|
|
@@ -10,27 +10,22 @@ import structlog
|
|
|
10
10
|
from litellm import acompletion
|
|
11
11
|
|
|
12
12
|
from kodit.config import Endpoint
|
|
13
|
-
from kodit.domain.
|
|
14
|
-
from kodit.domain.
|
|
15
|
-
from kodit.
|
|
13
|
+
from kodit.domain.enrichments.enricher import Enricher
|
|
14
|
+
from kodit.domain.enrichments.request import EnrichmentRequest
|
|
15
|
+
from kodit.domain.enrichments.response import EnrichmentResponse
|
|
16
|
+
from kodit.infrastructure.enricher.utils import clean_thinking_tags
|
|
16
17
|
|
|
17
|
-
ENRICHMENT_SYSTEM_PROMPT = """
|
|
18
|
-
You are a professional software developer. You will be given a snippet of code.
|
|
19
|
-
Please provide a concise explanation of the code.
|
|
20
|
-
"""
|
|
21
|
-
|
|
22
|
-
# Default tuned conservatively for broad provider compatibility
|
|
23
18
|
DEFAULT_NUM_PARALLEL_TASKS = 20
|
|
24
19
|
|
|
25
20
|
|
|
26
|
-
class
|
|
27
|
-
"""LiteLLM
|
|
21
|
+
class LiteLLMEnricher(Enricher):
|
|
22
|
+
"""LiteLLM enricher that supports 100+ providers."""
|
|
28
23
|
|
|
29
24
|
def __init__(
|
|
30
25
|
self,
|
|
31
26
|
endpoint: Endpoint,
|
|
32
27
|
) -> None:
|
|
33
|
-
"""Initialize the LiteLLM
|
|
28
|
+
"""Initialize the LiteLLM enricher.
|
|
34
29
|
|
|
35
30
|
Args:
|
|
36
31
|
endpoint: The endpoint configuration containing all settings.
|
|
@@ -44,23 +39,20 @@ class LiteLLMEnrichmentProvider(EnrichmentProvider):
|
|
|
44
39
|
self.num_parallel_tasks = (
|
|
45
40
|
endpoint.num_parallel_tasks or DEFAULT_NUM_PARALLEL_TASKS
|
|
46
41
|
)
|
|
47
|
-
self.timeout = endpoint.timeout
|
|
42
|
+
self.timeout = endpoint.timeout
|
|
48
43
|
self.extra_params = endpoint.extra_params or {}
|
|
49
44
|
|
|
50
|
-
# Configure LiteLLM with custom HTTPX client for Unix socket support if needed
|
|
51
45
|
self._setup_litellm_client()
|
|
52
46
|
|
|
53
47
|
def _setup_litellm_client(self) -> None:
|
|
54
48
|
"""Set up LiteLLM with custom HTTPX client for Unix socket support."""
|
|
55
49
|
if self.socket_path:
|
|
56
|
-
# Create HTTPX client with Unix socket transport
|
|
57
50
|
transport = httpx.AsyncHTTPTransport(uds=self.socket_path)
|
|
58
51
|
unix_client = httpx.AsyncClient(
|
|
59
52
|
transport=transport,
|
|
60
|
-
base_url="http://localhost",
|
|
53
|
+
base_url="http://localhost",
|
|
61
54
|
timeout=self.timeout,
|
|
62
55
|
)
|
|
63
|
-
# Set as LiteLLM's async client session
|
|
64
56
|
litellm.aclient_session = unix_client
|
|
65
57
|
|
|
66
58
|
async def _call_chat_completion(self, messages: list[dict[str, str]]) -> Any:
|
|
@@ -79,20 +71,17 @@ class LiteLLMEnrichmentProvider(EnrichmentProvider):
|
|
|
79
71
|
"timeout": self.timeout,
|
|
80
72
|
}
|
|
81
73
|
|
|
82
|
-
# Add API key if provided
|
|
83
74
|
if self.api_key:
|
|
84
75
|
kwargs["api_key"] = self.api_key
|
|
85
76
|
|
|
86
|
-
# Add base_url if provided
|
|
87
77
|
if self.base_url:
|
|
88
78
|
kwargs["api_base"] = self.base_url
|
|
89
79
|
|
|
90
|
-
# Add extra parameters
|
|
91
80
|
kwargs.update(self.extra_params)
|
|
92
81
|
|
|
93
82
|
try:
|
|
94
|
-
# Use litellm's async completion function
|
|
95
83
|
response = await acompletion(**kwargs)
|
|
84
|
+
self.log.debug("enrichment request", request=kwargs, response=response)
|
|
96
85
|
return (
|
|
97
86
|
response.model_dump() if hasattr(response, "model_dump") else response
|
|
98
87
|
)
|
|
@@ -108,30 +97,31 @@ class LiteLLMEnrichmentProvider(EnrichmentProvider):
|
|
|
108
97
|
"""Enrich a list of requests using LiteLLM.
|
|
109
98
|
|
|
110
99
|
Args:
|
|
111
|
-
requests: List of enrichment requests.
|
|
100
|
+
requests: List of generic enrichment requests.
|
|
112
101
|
|
|
113
102
|
Yields:
|
|
114
|
-
|
|
103
|
+
Generic enrichment responses as they are processed.
|
|
115
104
|
|
|
116
105
|
"""
|
|
117
106
|
if not requests:
|
|
118
107
|
self.log.warning("No requests for enrichment")
|
|
119
108
|
return
|
|
120
109
|
|
|
121
|
-
# Process requests in parallel with a semaphore to limit concurrent requests
|
|
122
110
|
sem = asyncio.Semaphore(self.num_parallel_tasks)
|
|
123
111
|
|
|
124
|
-
async def process_request(
|
|
112
|
+
async def process_request(
|
|
113
|
+
request: EnrichmentRequest,
|
|
114
|
+
) -> EnrichmentResponse:
|
|
125
115
|
async with sem:
|
|
126
116
|
if not request.text:
|
|
127
117
|
return EnrichmentResponse(
|
|
128
|
-
|
|
118
|
+
id=request.id,
|
|
129
119
|
text="",
|
|
130
120
|
)
|
|
131
121
|
messages = [
|
|
132
122
|
{
|
|
133
123
|
"role": "system",
|
|
134
|
-
"content":
|
|
124
|
+
"content": request.system_prompt,
|
|
135
125
|
},
|
|
136
126
|
{"role": "user", "content": request.text},
|
|
137
127
|
]
|
|
@@ -141,22 +131,19 @@ class LiteLLMEnrichmentProvider(EnrichmentProvider):
|
|
|
141
131
|
.get("message", {})
|
|
142
132
|
.get("content", "")
|
|
143
133
|
)
|
|
144
|
-
# Remove thinking tags from the response
|
|
145
134
|
cleaned_content = clean_thinking_tags(content or "")
|
|
146
135
|
return EnrichmentResponse(
|
|
147
|
-
|
|
136
|
+
id=request.id,
|
|
148
137
|
text=cleaned_content,
|
|
149
138
|
)
|
|
150
139
|
|
|
151
|
-
# Create tasks for all requests
|
|
152
140
|
tasks = [process_request(request) for request in requests]
|
|
153
141
|
|
|
154
|
-
# Process all requests and yield results as they complete
|
|
155
142
|
for task in asyncio.as_completed(tasks):
|
|
156
143
|
yield await task
|
|
157
144
|
|
|
158
145
|
async def close(self) -> None:
|
|
159
|
-
"""Close the
|
|
146
|
+
"""Close the enricher and cleanup HTTPX client if using Unix sockets."""
|
|
160
147
|
if (
|
|
161
148
|
self.socket_path
|
|
162
149
|
and hasattr(litellm, "aclient_session")
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"""Local
|
|
1
|
+
"""Local enricher implementation."""
|
|
2
2
|
|
|
3
3
|
import asyncio
|
|
4
4
|
import os
|
|
@@ -8,28 +8,24 @@ from typing import Any
|
|
|
8
8
|
import structlog
|
|
9
9
|
import tiktoken
|
|
10
10
|
|
|
11
|
-
from kodit.domain.
|
|
12
|
-
from kodit.domain.
|
|
13
|
-
from kodit.
|
|
11
|
+
from kodit.domain.enrichments.enricher import Enricher
|
|
12
|
+
from kodit.domain.enrichments.request import EnrichmentRequest
|
|
13
|
+
from kodit.domain.enrichments.response import EnrichmentResponse
|
|
14
|
+
from kodit.infrastructure.enricher.utils import clean_thinking_tags
|
|
14
15
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
Please provide a concise explanation of the code.
|
|
18
|
-
"""
|
|
16
|
+
DEFAULT_ENRICHER_MODEL = "Qwen/Qwen3-0.6B"
|
|
17
|
+
DEFAULT_CONTEXT_WINDOW_SIZE = 2048
|
|
19
18
|
|
|
20
|
-
DEFAULT_ENRICHMENT_MODEL = "Qwen/Qwen3-0.6B"
|
|
21
|
-
DEFAULT_CONTEXT_WINDOW_SIZE = 2048 # Small so it works even on low-powered devices
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
"""Local enrichment provider implementation."""
|
|
20
|
+
class LocalEnricher(Enricher):
|
|
21
|
+
"""Local enricher implementation using local models."""
|
|
26
22
|
|
|
27
23
|
def __init__(
|
|
28
24
|
self,
|
|
29
|
-
model_name: str =
|
|
25
|
+
model_name: str = DEFAULT_ENRICHER_MODEL,
|
|
30
26
|
context_window: int = DEFAULT_CONTEXT_WINDOW_SIZE,
|
|
31
27
|
) -> None:
|
|
32
|
-
"""Initialize the local
|
|
28
|
+
"""Initialize the local enricher.
|
|
33
29
|
|
|
34
30
|
Args:
|
|
35
31
|
model_name: The model name to use for enrichment.
|
|
@@ -49,13 +45,13 @@ class LocalEnrichmentProvider(EnrichmentProvider):
|
|
|
49
45
|
"""Enrich a list of requests using local model.
|
|
50
46
|
|
|
51
47
|
Args:
|
|
52
|
-
requests: List of enrichment requests.
|
|
48
|
+
requests: List of generic enrichment requests.
|
|
53
49
|
|
|
54
50
|
Yields:
|
|
55
|
-
|
|
51
|
+
Generic enrichment responses as they are processed.
|
|
56
52
|
|
|
57
53
|
"""
|
|
58
|
-
# Remove empty
|
|
54
|
+
# Remove empty requests
|
|
59
55
|
requests = [req for req in requests if req.text]
|
|
60
56
|
|
|
61
57
|
if not requests:
|
|
@@ -73,7 +69,7 @@ class LocalEnrichmentProvider(EnrichmentProvider):
|
|
|
73
69
|
self.model_name, padding_side="left"
|
|
74
70
|
)
|
|
75
71
|
if self.model is None:
|
|
76
|
-
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
|
72
|
+
os.environ["TOKENIZERS_PARALLELISM"] = "false"
|
|
77
73
|
self.model = AutoModelForCausalLM.from_pretrained(
|
|
78
74
|
self.model_name,
|
|
79
75
|
torch_dtype="auto",
|
|
@@ -83,13 +79,13 @@ class LocalEnrichmentProvider(EnrichmentProvider):
|
|
|
83
79
|
|
|
84
80
|
await asyncio.to_thread(_init_model)
|
|
85
81
|
|
|
86
|
-
# Prepare prompts
|
|
82
|
+
# Prepare prompts with custom system prompts
|
|
87
83
|
prompts = [
|
|
88
84
|
{
|
|
89
|
-
"id": req.
|
|
85
|
+
"id": req.id,
|
|
90
86
|
"text": self.tokenizer.apply_chat_template( # type: ignore[attr-defined]
|
|
91
87
|
[
|
|
92
|
-
{"role": "system", "content":
|
|
88
|
+
{"role": "system", "content": req.system_prompt},
|
|
93
89
|
{"role": "user", "content": req.text},
|
|
94
90
|
],
|
|
95
91
|
tokenize=False,
|
|
@@ -121,9 +117,8 @@ class LocalEnrichmentProvider(EnrichmentProvider):
|
|
|
121
117
|
)
|
|
122
118
|
|
|
123
119
|
content = await asyncio.to_thread(process_prompt, prompt)
|
|
124
|
-
# Remove thinking tags from the response
|
|
125
120
|
cleaned_content = clean_thinking_tags(content)
|
|
126
121
|
yield EnrichmentResponse(
|
|
127
|
-
|
|
122
|
+
id=prompt["id"],
|
|
128
123
|
text=cleaned_content,
|
|
129
124
|
)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Null enricher implementation."""
|
|
2
|
+
|
|
3
|
+
from collections.abc import AsyncGenerator
|
|
4
|
+
|
|
5
|
+
import structlog
|
|
6
|
+
|
|
7
|
+
from kodit.domain.enrichments.enricher import Enricher
|
|
8
|
+
from kodit.domain.enrichments.request import EnrichmentRequest
|
|
9
|
+
from kodit.domain.enrichments.response import EnrichmentResponse
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class NullEnricher(Enricher):
|
|
13
|
+
"""Null enricher that returns empty responses."""
|
|
14
|
+
|
|
15
|
+
def __init__(self) -> None:
|
|
16
|
+
"""Initialize the null enricher."""
|
|
17
|
+
self.log = structlog.get_logger(__name__)
|
|
18
|
+
|
|
19
|
+
async def enrich(
|
|
20
|
+
self, requests: list[EnrichmentRequest]
|
|
21
|
+
) -> AsyncGenerator[EnrichmentResponse, None]:
|
|
22
|
+
"""Return empty responses for all requests.
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
requests: List of generic enrichment requests.
|
|
26
|
+
|
|
27
|
+
Yields:
|
|
28
|
+
Empty generic enrichment responses.
|
|
29
|
+
|
|
30
|
+
"""
|
|
31
|
+
self.log.info("NullEnricher: returning empty responses", count=len(requests))
|
|
32
|
+
for request in requests:
|
|
33
|
+
yield EnrichmentResponse(
|
|
34
|
+
id=request.id,
|
|
35
|
+
text="",
|
|
36
|
+
)
|
|
@@ -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
|
+
)
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"""Mapping between domain Git entities and SQLAlchemy entities."""
|
|
2
2
|
|
|
3
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
|
|
4
6
|
from kodit.domain.value_objects import Enrichment, EnrichmentType
|
|
5
7
|
from kodit.infrastructure.sqlalchemy import entities as db_entities
|
|
6
8
|
|
|
@@ -12,19 +14,17 @@ class SnippetMapper:
|
|
|
12
14
|
self,
|
|
13
15
|
db_snippet: db_entities.SnippetV2,
|
|
14
16
|
db_files: list[db_entities.GitCommitFile],
|
|
15
|
-
db_enrichments: list[
|
|
17
|
+
db_enrichments: list[EnrichmentV2],
|
|
16
18
|
) -> domain_git_entities.SnippetV2:
|
|
17
19
|
"""Convert SQLAlchemy SnippetV2 to domain SnippetV2."""
|
|
18
|
-
# Convert enrichments
|
|
19
|
-
enrichments = [
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
enrichment = Enrichment(
|
|
24
|
-
type=enrichment_type,
|
|
25
|
-
content=db_enrichment.content,
|
|
20
|
+
# Convert enrichments from SnippetEnrichment to Enrichment value objects
|
|
21
|
+
enrichments: list[Enrichment] = [
|
|
22
|
+
Enrichment(
|
|
23
|
+
type=EnrichmentType.SUMMARIZATION,
|
|
24
|
+
content=enrichment.content,
|
|
26
25
|
)
|
|
27
|
-
|
|
26
|
+
for enrichment in db_enrichments
|
|
27
|
+
]
|
|
28
28
|
|
|
29
29
|
derives_from = [
|
|
30
30
|
domain_git_entities.GitFile(
|
|
@@ -59,20 +59,18 @@ class SnippetMapper:
|
|
|
59
59
|
)
|
|
60
60
|
|
|
61
61
|
def from_domain_enrichments(
|
|
62
|
-
self,
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
snippet_sha=snippet_sha,
|
|
71
|
-
type=db_enrichment_type,
|
|
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,
|
|
72
70
|
content=enrichment.content,
|
|
73
71
|
)
|
|
74
|
-
|
|
75
|
-
|
|
72
|
+
for enrichment in enrichments
|
|
73
|
+
]
|
|
76
74
|
|
|
77
75
|
def to_domain_commit_index(
|
|
78
76
|
self,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Physical architecture discovery infrastructure."""
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"""Component detectors for physical architecture discovery."""
|