graph-dependency-analyzer 0.2.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.
Files changed (86) hide show
  1. graph_dependency_analyzer-0.2.0.dist-info/METADATA +158 -0
  2. graph_dependency_analyzer-0.2.0.dist-info/RECORD +86 -0
  3. graph_dependency_analyzer-0.2.0.dist-info/WHEEL +5 -0
  4. graph_dependency_analyzer-0.2.0.dist-info/entry_points.txt +2 -0
  5. graph_dependency_analyzer-0.2.0.dist-info/top_level.txt +1 -0
  6. src/__init__.py +0 -0
  7. src/application/__init__.py +0 -0
  8. src/application/dtos/__init__.py +0 -0
  9. src/application/dtos/affected_component.py +59 -0
  10. src/application/dtos/batch_processing_result.py +17 -0
  11. src/application/dtos/impact_analysis_response.py +56 -0
  12. src/application/dtos/impact_query_request.py +38 -0
  13. src/application/dtos/index_batch_request.py +53 -0
  14. src/application/dtos/index_batch_response.py +72 -0
  15. src/application/dtos/index_result.py +20 -0
  16. src/application/dtos/repository_index_result.py +79 -0
  17. src/application/exceptions.py +41 -0
  18. src/application/services/__init__.py +0 -0
  19. src/application/services/file_scanner_service.py +258 -0
  20. src/application/services/progress_tracker.py +132 -0
  21. src/application/use_cases/__init__.py +0 -0
  22. src/application/use_cases/clear_all_data_use_case.py +180 -0
  23. src/application/use_cases/index_batch_use_case.py +153 -0
  24. src/application/use_cases/index_repository_use_case.py +683 -0
  25. src/application/use_cases/indexing_orchestrator.py +181 -0
  26. src/application/use_cases/list_repositories_use_case.py +84 -0
  27. src/cli.py +512 -0
  28. src/config/__init__.py +5 -0
  29. src/config/container.py +211 -0
  30. src/config/logging_config.py +123 -0
  31. src/config/settings.py +165 -0
  32. src/domain/__init__.py +0 -0
  33. src/domain/entities/__init__.py +20 -0
  34. src/domain/entities/ast_node.py +32 -0
  35. src/domain/entities/code_chunk.py +45 -0
  36. src/domain/entities/code_file.py +44 -0
  37. src/domain/entities/dependency_graph.py +110 -0
  38. src/domain/entities/repository.py +46 -0
  39. src/domain/exceptions.py +36 -0
  40. src/domain/repositories/__init__.py +22 -0
  41. src/domain/repositories/i_code_parser.py +50 -0
  42. src/domain/repositories/i_dependency_extractor.py +35 -0
  43. src/domain/repositories/i_embedding_provider.py +31 -0
  44. src/domain/repositories/i_graph_repository.py +78 -0
  45. src/domain/repositories/i_vector_repository.py +55 -0
  46. src/domain/services/__init__.py +8 -0
  47. src/domain/services/dependency_extractor.py +962 -0
  48. src/domain/services/semantic_chunk_builder.py +719 -0
  49. src/domain/value_objects/__init__.py +12 -0
  50. src/domain/value_objects/chunk_type.py +24 -0
  51. src/domain/value_objects/dependency_type.py +22 -0
  52. src/domain/value_objects/node_type.py +22 -0
  53. src/domain/value_objects/qualified_name.py +78 -0
  54. src/infrastructure/__init__.py +0 -0
  55. src/infrastructure/exceptions.py +41 -0
  56. src/infrastructure/external_apis/__init__.py +0 -0
  57. src/infrastructure/external_apis/ollama_embedding_provider.py +134 -0
  58. src/infrastructure/external_apis/openai_embedding_provider.py +231 -0
  59. src/infrastructure/parsing/__init__.py +20 -0
  60. src/infrastructure/parsing/config_file_parser.py +347 -0
  61. src/infrastructure/parsing/gradle_dependency_parser.py +159 -0
  62. src/infrastructure/parsing/groovy_parser.py +198 -0
  63. src/infrastructure/parsing/maven_dependency_parser.py +147 -0
  64. src/infrastructure/parsing/microfrontend_config_parser.py +242 -0
  65. src/infrastructure/parsing/npm_package_dependency_parser.py +255 -0
  66. src/infrastructure/parsing/python_parser.py +211 -0
  67. src/infrastructure/parsing/sql_schema_parser.py +658 -0
  68. src/infrastructure/parsing/tree_sitter_java_parser.py +434 -0
  69. src/infrastructure/parsing/tree_sitter_typescript_parser.py +600 -0
  70. src/infrastructure/persistence/__init__.py +0 -0
  71. src/infrastructure/persistence/graph_export_repository.py +443 -0
  72. src/infrastructure/persistence/neo4j_dependency_repository.py +657 -0
  73. src/infrastructure/persistence/qdrant_vector_repository.py +357 -0
  74. src/infrastructure/persistence/repository_relationship_repository.py +1312 -0
  75. src/presentation/__init__.py +0 -0
  76. src/presentation/api/__init__.py +0 -0
  77. src/presentation/api/rest/__init__.py +0 -0
  78. src/presentation/api/rest/exception_handlers.py +174 -0
  79. src/presentation/api/rest/main.py +80 -0
  80. src/presentation/api/rest/routers/__init__.py +5 -0
  81. src/presentation/api/rest/routers/admin.py +103 -0
  82. src/presentation/api/rest/routers/analysis.py +980 -0
  83. src/presentation/api/rest/routers/export.py +442 -0
  84. src/presentation/api/rest/routers/health.py +117 -0
  85. src/presentation/api/rest/routers/indexing.py +148 -0
  86. src/presentation/api/rest/routers/relationships.py +1089 -0
@@ -0,0 +1,12 @@
1
+ """Domain value objects module."""
2
+ from src.domain.value_objects.qualified_name import QualifiedName
3
+ from src.domain.value_objects.dependency_type import DependencyType
4
+ from src.domain.value_objects.chunk_type import ChunkType
5
+ from src.domain.value_objects.node_type import NodeType
6
+
7
+ __all__ = [
8
+ "QualifiedName",
9
+ "DependencyType",
10
+ "ChunkType",
11
+ "NodeType",
12
+ ]
@@ -0,0 +1,24 @@
1
+ """ChunkType enum - types of code chunks for embeddings."""
2
+ from enum import Enum
3
+
4
+
5
+ class ChunkType(Enum):
6
+ """
7
+ ChunkType enum representing types of semantic code chunks.
8
+
9
+ Values:
10
+ METHOD: Complete method with body
11
+ CLASS: Class declaration with imports (when no methods)
12
+ IMPORT_BLOCK: Import statements block
13
+ CONSTRUCTOR: Constructor method
14
+ FUNCTION: TypeScript/JavaScript function (Task 15.1)
15
+ HOOK: React hook function (Task 15.1)
16
+ COMPONENT: React/Angular/Vue component (Task 15.2)
17
+ """
18
+ METHOD = "method"
19
+ CLASS = "class"
20
+ IMPORT_BLOCK = "import_block"
21
+ CONSTRUCTOR = "constructor"
22
+ FUNCTION = "function"
23
+ HOOK = "hook"
24
+ COMPONENT = "component"
@@ -0,0 +1,22 @@
1
+ """DependencyType enum - types of dependencies detected in code."""
2
+ from enum import Enum
3
+
4
+
5
+ class DependencyType(Enum):
6
+ """
7
+ DependencyType enum representing types of dependencies.
8
+
9
+ Values:
10
+ LIBRARY: Maven/Gradle library dependency (e.g., org.springframework.boot:spring-boot-starter-web)
11
+ API: External HTTP/HTTPS API endpoint
12
+ DATABASE: Database connection (JDBC, JPA)
13
+ MICROSERVICE: Another internal microservice/repository
14
+ INTERNAL_CLASS: Class in the same repository
15
+ INTERNAL_METHOD: Method in the same repository
16
+ """
17
+ LIBRARY = "library"
18
+ API = "api"
19
+ DATABASE = "database"
20
+ MICROSERVICE = "microservice"
21
+ INTERNAL_CLASS = "internal_class"
22
+ INTERNAL_METHOD = "internal_method"
@@ -0,0 +1,22 @@
1
+ """NodeType enum - types of AST nodes."""
2
+ from enum import Enum
3
+
4
+
5
+ class NodeType(Enum):
6
+ """
7
+ NodeType enum representing types of Abstract Syntax Tree nodes.
8
+
9
+ Values:
10
+ CLASS: Class declaration
11
+ INTERFACE: Interface declaration
12
+ METHOD: Method declaration
13
+ CONSTRUCTOR: Constructor declaration
14
+ IMPORT: Import statement
15
+ METHOD_CALL: Method invocation/call
16
+ """
17
+ CLASS = "class"
18
+ INTERFACE = "interface"
19
+ METHOD = "method"
20
+ CONSTRUCTOR = "constructor"
21
+ IMPORT = "import"
22
+ METHOD_CALL = "method_call"
@@ -0,0 +1,78 @@
1
+ """QualifiedName value object - represents a fully qualified name."""
2
+ from dataclasses import dataclass
3
+
4
+
5
+ @dataclass(frozen=True)
6
+ class QualifiedName:
7
+ """
8
+ QualifiedName value object representing a fully qualified name.
9
+
10
+ A qualified name follows the format: package.Class or package.Class.method
11
+ Examples:
12
+ - com.example.orders.OrderService
13
+ - com.example.orders.OrderService.createOrder
14
+
15
+ Attributes:
16
+ value: The fully qualified name string
17
+
18
+ Business Rules:
19
+ - Must contain at least one dot (package separator)
20
+ - Cannot be None or empty
21
+ - Immutable (frozen dataclass)
22
+ """
23
+ value: str
24
+
25
+ def __post_init__(self):
26
+ """Validate business rules after initialization."""
27
+ if self.value is None:
28
+ raise ValueError("Qualified name cannot be None or empty")
29
+
30
+ if not self.value or "." not in self.value:
31
+ raise ValueError("Qualified name must contain package")
32
+
33
+ def __str__(self) -> str:
34
+ """Return string representation."""
35
+ return self.value
36
+
37
+ def get_package(self) -> str:
38
+ """
39
+ Extract package from qualified name.
40
+
41
+ Returns:
42
+ Package name (everything before the last class/method part)
43
+
44
+ Example:
45
+ com.example.orders.OrderService -> com.example.orders
46
+ com.example.orders.OrderService.createOrder -> com.example.orders
47
+ """
48
+ parts = self.value.split(".")
49
+
50
+ # If it's package.Class.method, package is everything except last 2 parts
51
+ # If it's package.Class, package is everything except last part
52
+ # Heuristic: if last part starts with lowercase, it's a method
53
+ if len(parts) >= 3 and parts[-1][0].islower():
54
+ # package.Class.method -> package
55
+ return ".".join(parts[:-2])
56
+ else:
57
+ # package.Class -> package
58
+ return ".".join(parts[:-1])
59
+
60
+ def get_class_name(self) -> str:
61
+ """
62
+ Extract class name from qualified name.
63
+
64
+ Returns:
65
+ Class name (simple name without package)
66
+
67
+ Example:
68
+ com.example.orders.OrderService -> OrderService
69
+ com.example.orders.OrderService.createOrder -> OrderService
70
+ """
71
+ parts = self.value.split(".")
72
+
73
+ # If last part starts with lowercase, it's a method, so class is second-to-last
74
+ if len(parts) >= 2 and parts[-1][0].islower():
75
+ return parts[-2]
76
+ else:
77
+ # Last part is the class
78
+ return parts[-1]
File without changes
@@ -0,0 +1,41 @@
1
+ """
2
+ Infrastructure Layer Exceptions (Task 9.3)
3
+
4
+ Exception hierarchy for infrastructure layer errors.
5
+ """
6
+
7
+
8
+ class InfrastructureException(Exception):
9
+ """Base exception for infrastructure layer errors."""
10
+
11
+ def __init__(self, message: str, details: dict | None = None):
12
+ """
13
+ Initialize infrastructure exception.
14
+
15
+ Args:
16
+ message: Human-readable error message
17
+ details: Optional dict with additional context
18
+ """
19
+ super().__init__(message)
20
+ self.message = message
21
+ self.details = details or {}
22
+
23
+
24
+ class OpenAIAPIError(InfrastructureException):
25
+ """Error communicating with OpenAI API."""
26
+ pass
27
+
28
+
29
+ class QdrantConnectionError(InfrastructureException):
30
+ """Error connecting to or communicating with Qdrant."""
31
+ pass
32
+
33
+
34
+ class Neo4jConnectionError(InfrastructureException):
35
+ """Error connecting to or communicating with Neo4j."""
36
+ pass
37
+
38
+
39
+ class ParseError(InfrastructureException):
40
+ """Error parsing source code."""
41
+ pass
File without changes
@@ -0,0 +1,134 @@
1
+ """
2
+ Ollama Embedding Provider — generates embeddings using a local Ollama instance.
3
+
4
+ No API keys, no rate limits, fully local.
5
+
6
+ Supported models (install with `ollama pull <model>`):
7
+ nomic-embed-text — 768-dim, fast, good quality (recommended)
8
+ mxbai-embed-large — 1024-dim, best quality, slower
9
+ all-minilm — 384-dim, very fast, lower quality
10
+
11
+ Set in .env:
12
+ EMBEDDING_PROVIDER=ollama
13
+ OLLAMA_BASE_URL=http://localhost:11434
14
+ OLLAMA_EMBEDDING_MODEL=nomic-embed-text
15
+ OLLAMA_EMBEDDING_DIM=768
16
+ QDRANT_VECTOR_SIZE=768 ← must match the model dimension
17
+
18
+ Install Ollama: https://ollama.com/download
19
+ Pull a model: ollama pull nomic-embed-text
20
+ """
21
+ from __future__ import annotations
22
+
23
+ import structlog
24
+ import httpx
25
+
26
+ logger = structlog.get_logger(__name__)
27
+
28
+
29
+ class OllamaEmbeddingProvider:
30
+ """
31
+ Local embedding provider using Ollama.
32
+
33
+ Supports batch processing (sequentially — Ollama processes one at a time).
34
+ No rate limits, no API key required.
35
+ """
36
+
37
+ def __init__(self, config=None):
38
+ base_url = "http://localhost:11434"
39
+ model = "nomic-embed-text"
40
+
41
+ if config is not None:
42
+ base_url = getattr(config, "ollama_base_url", base_url)
43
+ model = getattr(config, "ollama_embedding_model", model)
44
+
45
+ self.base_url = base_url.rstrip("/")
46
+ self.model = model
47
+ self._client: httpx.AsyncClient | None = None
48
+
49
+ @property
50
+ def client(self) -> httpx.AsyncClient:
51
+ if self._client is None:
52
+ self._client = httpx.AsyncClient(
53
+ timeout=120.0,
54
+ limits=httpx.Limits(max_connections=4)
55
+ )
56
+ return self._client
57
+
58
+ async def embed_batch(
59
+ self,
60
+ texts: list[str],
61
+ batch_size: int = 10,
62
+ ) -> list[list[float]]:
63
+ """
64
+ Generate embeddings for a list of texts using Ollama.
65
+
66
+ Ollama's /api/embed endpoint supports multiple inputs in one call.
67
+ We process in batches to avoid memory issues with large lists.
68
+
69
+ Args:
70
+ texts: List of text strings to embed
71
+ batch_size: Number of texts per Ollama API call (default 10)
72
+
73
+ Returns:
74
+ List of embedding vectors
75
+ """
76
+ if not texts:
77
+ return []
78
+
79
+ all_embeddings: list[list[float]] = []
80
+
81
+ for i in range(0, len(texts), batch_size):
82
+ batch = texts[i:i + batch_size]
83
+ embeddings = await self._embed_batch_ollama(batch)
84
+ all_embeddings.extend(embeddings)
85
+
86
+ logger.info(
87
+ "embeddings_generated",
88
+ model=self.model,
89
+ total_texts=len(texts),
90
+ total_embeddings=len(all_embeddings),
91
+ provider="ollama",
92
+ )
93
+ return all_embeddings
94
+
95
+ async def _embed_batch_ollama(self, texts: list[str]) -> list[list[float]]:
96
+ """Call Ollama /api/embed for a batch of texts."""
97
+ url = f"{self.base_url}/api/embed"
98
+
99
+ payload = {
100
+ "model": self.model,
101
+ "input": texts,
102
+ }
103
+
104
+ try:
105
+ response = await self.client.post(url, json=payload)
106
+ response.raise_for_status()
107
+ data = response.json()
108
+
109
+ # Ollama /api/embed returns {"embeddings": [[...], [...]]}
110
+ embeddings = data.get("embeddings", [])
111
+
112
+ if len(embeddings) != len(texts):
113
+ raise ValueError(
114
+ f"Ollama returned {len(embeddings)} embeddings for {len(texts)} texts"
115
+ )
116
+
117
+ return embeddings
118
+
119
+ except httpx.ConnectError:
120
+ raise ConnectionError(
121
+ f"Cannot connect to Ollama at {self.base_url}. "
122
+ "Make sure Ollama is running: `ollama serve`"
123
+ )
124
+ except httpx.HTTPStatusError as e:
125
+ if e.response.status_code == 404:
126
+ raise ValueError(
127
+ f"Model '{self.model}' not found in Ollama. "
128
+ f"Pull it first: `ollama pull {self.model}`"
129
+ )
130
+ raise
131
+
132
+ async def close(self):
133
+ if self._client is not None:
134
+ await self._client.aclose()
@@ -0,0 +1,231 @@
1
+ """
2
+ OpenAI Embedding Provider Implementation (Task 6.1)
3
+
4
+ Generates embeddings via OpenAI API with support for Flow AI proxy.
5
+ Implements retry logic with exponential backoff for resilience.
6
+ """
7
+ from dataclasses import dataclass
8
+ from typing import Any
9
+ import structlog
10
+ import httpx
11
+ from tenacity import (
12
+ retry,
13
+ stop_after_attempt,
14
+ wait_exponential,
15
+ retry_if_exception_type
16
+ )
17
+
18
+ from src.config.settings import EmbeddingConfig, get_settings
19
+
20
+ logger = structlog.get_logger(__name__)
21
+
22
+
23
+ class EmbeddingProviderError(Exception):
24
+ """Error raised when embedding generation fails"""
25
+ pass
26
+
27
+
28
+ class OpenAIEmbeddingProvider:
29
+ """
30
+ OpenAI API client for generating embeddings.
31
+
32
+ Supports:
33
+ - OpenAI standard endpoint
34
+ - Flow AI (CI&T proxy) with custom headers
35
+ - Local embedding servers
36
+ - Batch processing (10 texts per API call)
37
+ - Automatic retry with exponential backoff (10 attempts, 2-30s)
38
+ - 1536-dimensional embeddings (text-embedding-3-small)
39
+
40
+ Configuration via .env:
41
+ - OPENAI_API_KEY: API key (required)
42
+ - OPENAI_BASE_URL: Base URL (default: https://api.openai.com/v1)
43
+ - OPENAI_EMBEDDING_MODEL: Model name (default: text-embedding-3-small)
44
+
45
+ Requirements: 8.1-8.7
46
+ """
47
+
48
+ def __init__(
49
+ self,
50
+ config: EmbeddingConfig | None = None,
51
+ client: httpx.AsyncClient | None = None
52
+ ):
53
+ """
54
+ Initialize embedding provider.
55
+
56
+ Args:
57
+ config: Embedding configuration (default: loaded from .env)
58
+ client: Optional httpx client (for testing)
59
+ """
60
+ if config is None:
61
+ config = get_settings().embedding
62
+
63
+ self.api_key = config.openai_api_key
64
+ self.base_url = config.openai_base_url.rstrip("/")
65
+ self.model = config.openai_embedding_model
66
+ self._client = client
67
+ self._is_flow_ai = "flow.ciandt.com" in self.base_url
68
+
69
+ @property
70
+ def client(self) -> httpx.AsyncClient:
71
+ """Get or create httpx client"""
72
+ if self._client is None:
73
+ # Desabilitar verificação SSL para ambientes corporativos
74
+ self._client = httpx.AsyncClient(
75
+ timeout=180.0,
76
+ verify=False, # Desabilita verificação SSL
77
+ limits=httpx.Limits(max_connections=10)
78
+ )
79
+ logger.debug("httpx_client_created", verify_ssl=False)
80
+ return self._client
81
+
82
+ async def embed_batch(
83
+ self,
84
+ texts: list[str],
85
+ batch_size: int = 10
86
+ ) -> list[list[float]]:
87
+ """
88
+ Generate embeddings for batch of texts.
89
+
90
+ Processes texts in batches for optimal API usage.
91
+ Automatically retries on failures with exponential backoff.
92
+
93
+ Args:
94
+ texts: List of text chunks to embed
95
+ batch_size: Number of texts per API call (default 10)
96
+
97
+ Returns:
98
+ List of embedding vectors (1536 floats each)
99
+
100
+ Raises:
101
+ EmbeddingProviderError: If API fails after retries
102
+ """
103
+ all_embeddings = []
104
+
105
+ # Process in batches
106
+ for i in range(0, len(texts), batch_size):
107
+ batch_texts = texts[i:i + batch_size]
108
+
109
+ try:
110
+ # Call API for this batch with retry
111
+ batch_embeddings = await self._generate_embeddings_with_retry(batch_texts)
112
+ all_embeddings.extend(batch_embeddings)
113
+
114
+ except Exception as e:
115
+ logger.error(
116
+ "embedding_generation_failed",
117
+ error=str(e),
118
+ error_type=type(e).__name__
119
+ )
120
+ raise EmbeddingProviderError(f"Failed to generate embeddings: {e}")
121
+
122
+ logger.info(
123
+ "embeddings_generated",
124
+ total_texts=len(texts),
125
+ total_embeddings=len(all_embeddings),
126
+ model=self.model
127
+ )
128
+
129
+ return all_embeddings
130
+
131
+ @retry(
132
+ stop=stop_after_attempt(10),
133
+ wait=wait_exponential(min=2, max=30),
134
+ retry=retry_if_exception_type(httpx.HTTPError)
135
+ )
136
+ async def _generate_embeddings_with_retry(self, texts: list[str]) -> list[list[float]]:
137
+ """
138
+ Generate embeddings with retry logic.
139
+
140
+ Args:
141
+ texts: List of texts to embed
142
+
143
+ Returns:
144
+ List of embedding vectors
145
+
146
+ Raises:
147
+ httpx.HTTPError: On API failures (for retry)
148
+ """
149
+ return await self._generate_embeddings(texts)
150
+
151
+ async def _generate_embeddings(self, texts: list[str]) -> list[list[float]]:
152
+ """
153
+ Generate embeddings for a single batch via API call.
154
+
155
+ Args:
156
+ texts: List of texts (max 10)
157
+
158
+ Returns:
159
+ List of embedding vectors
160
+
161
+ Raises:
162
+ httpx.HTTPError: On API failures
163
+ EmbeddingProviderError: On validation failures
164
+ """
165
+ # Build headers
166
+ headers = {
167
+ "Authorization": f"Bearer {self.api_key}",
168
+ "Content-Type": "application/json"
169
+ }
170
+
171
+ # Add Flow AI custom header if needed
172
+ if self._is_flow_ai:
173
+ headers["flowAgent"] = "knowledge-graph-indexing"
174
+
175
+ # Build payload
176
+ payload = {
177
+ "model": self.model,
178
+ "input": texts,
179
+ "encoding_format": "float"
180
+ }
181
+
182
+ # POST to API - endpoint depends on API type
183
+ if self._is_flow_ai:
184
+ # Flow AI requires /v1/openai/embeddings path
185
+ url = f"{self.base_url}/v1/openai/embeddings"
186
+ else:
187
+ # OpenAI standard endpoint
188
+ url = f"{self.base_url}/embeddings"
189
+
190
+ logger.info(
191
+ "embedding_request_starting",
192
+ url=url,
193
+ is_flow_ai=self._is_flow_ai,
194
+ texts_count=len(texts),
195
+ model=self.model
196
+ )
197
+
198
+ response = await self.client.post(
199
+ url=url,
200
+ headers=headers,
201
+ json=payload
202
+ )
203
+
204
+ # Validate response
205
+ response.raise_for_status() # Let httpx.HTTPError propagate for retry
206
+
207
+ # Parse response
208
+ data = response.json()
209
+
210
+ # Extract embeddings
211
+ if "data" not in data:
212
+ raise EmbeddingProviderError("API response missing 'data' field")
213
+
214
+ embeddings_data = data["data"]
215
+
216
+ # Validate count
217
+ if len(embeddings_data) != len(texts):
218
+ raise EmbeddingProviderError(
219
+ f"Embedding count mismatch: expected {len(texts)}, "
220
+ f"got {len(embeddings_data)}"
221
+ )
222
+
223
+ # Extract embedding vectors
224
+ embeddings = [item["embedding"] for item in embeddings_data]
225
+
226
+ return embeddings
227
+
228
+ async def close(self):
229
+ """Close the HTTP client"""
230
+ if self._client is not None:
231
+ await self._client.aclose()
@@ -0,0 +1,20 @@
1
+ """Infrastructure parsing module."""
2
+ from src.infrastructure.parsing.tree_sitter_java_parser import TreeSitterJavaParser, ParseError
3
+ from src.infrastructure.parsing.tree_sitter_typescript_parser import TreeSitterTypeScriptParser
4
+ from src.infrastructure.parsing.maven_dependency_parser import MavenDependencyParser
5
+ from src.infrastructure.parsing.gradle_dependency_parser import GradleDependencyParser
6
+ from src.infrastructure.parsing.config_file_parser import ConfigFileParser, ParsedConfig
7
+ from src.infrastructure.parsing.npm_package_dependency_parser import NpmPackageDependencyParser
8
+ from src.infrastructure.parsing.microfrontend_config_parser import MicrofrontendConfigParser
9
+
10
+ __all__ = [
11
+ "TreeSitterJavaParser",
12
+ "TreeSitterTypeScriptParser",
13
+ "ParseError",
14
+ "MavenDependencyParser",
15
+ "GradleDependencyParser",
16
+ "ConfigFileParser",
17
+ "ParsedConfig",
18
+ "NpmPackageDependencyParser",
19
+ "MicrofrontendConfigParser",
20
+ ]