coding-client 1.21.2__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.
- coding_client/__init__.py +1 -0
- coding_client/api/__init__.py +19 -0
- coding_client/api/exception_handlers.py +158 -0
- coding_client/api/logging_setup.py +44 -0
- coding_client/api/metrics.py +40 -0
- coding_client/api/openapi_config.py +124 -0
- coding_client/api/request_logging.py +60 -0
- coding_client/api/validation.py +150 -0
- coding_client/auth/__init__.py +78 -0
- coding_client/auth/_default_tenant.py +132 -0
- coding_client/auth/_header_trust.py +98 -0
- coding_client/auth/_onbehalf.py +315 -0
- coding_client/auth/_trusted_networks.py +94 -0
- coding_client/auth/dependencies.py +61 -0
- coding_client/auth/middleware.py +445 -0
- coding_client/auth/models.py +83 -0
- coding_client/auth/outbound.py +137 -0
- coding_client/auth/rbac.py +21 -0
- coding_client/auth/rbac_coding.py +5 -0
- coding_client/auth/tenant.py +650 -0
- coding_client/auth/websocket.py +148 -0
- coding_client/clients/__init__.py +24 -0
- coding_client/clients/base.py +131 -0
- coding_client/clients/coding_ai.py +33 -0
- coding_client/clients/coding_analysis.py +36 -0
- coding_client/clients/coding_containers.py +45 -0
- coding_client/clients/coding_github.py +127 -0
- coding_client/clients/coding_realtime.py +127 -0
- coding_client/clients/coding_security.py +51 -0
- coding_client/clients/coding_testing.py +31 -0
- coding_client/clients/coding_workspaces.py +265 -0
- coding_client/config/__init__.py +12 -0
- coding_client/config/base_settings.py +61 -0
- coding_client/config/yaml_config_loader.py +172 -0
- coding_client/db/__init__.py +42 -0
- coding_client/db/db_types.py +122 -0
- coding_client/db/exceptions.py +59 -0
- coding_client/db/postgres_connection.py +572 -0
- coding_client/db/tenant_query_helper.py +417 -0
- coding_client/db_init.py +49 -0
- coding_client/exceptions/__init__.py +67 -0
- coding_client/exceptions/api_exceptions.py +395 -0
- coding_client/exceptions/pydantic_ai_exceptions.py +533 -0
- coding_client/interfaces/__init__.py +22 -0
- coding_client/interfaces/cache_interface.py +179 -0
- coding_client/interfaces/container_interface.py +49 -0
- coding_client/interfaces/docker_interface.py +283 -0
- coding_client/interfaces/graph_interface.py +28 -0
- coding_client/interfaces/security_interface.py +72 -0
- coding_client/interfaces/webhook_interface.py +67 -0
- coding_client/llm/__init__.py +54 -0
- coding_client/llm/base_agent.py +195 -0
- coding_client/llm/context.py +121 -0
- coding_client/llm/responses.py +102 -0
- coding_client/llm/routing.py +82 -0
- coding_client/llm/settings.py +102 -0
- coding_client/models/__init__.py +62 -0
- coding_client/models/agent.py +38 -0
- coding_client/models/ai_test_failure.py +745 -0
- coding_client/models/analysis.py +330 -0
- coding_client/models/architecture.py +685 -0
- coding_client/models/bug.py +128 -0
- coding_client/models/code_graph.py +317 -0
- coding_client/models/container.py +241 -0
- coding_client/models/core.py +878 -0
- coding_client/models/docker_container.py +104 -0
- coding_client/models/github.py +293 -0
- coding_client/models/logging.py +29 -0
- coding_client/models/package_manager.py +257 -0
- coding_client/models/pr_validation.py +440 -0
- coding_client/models/pydantic_ai.py +395 -0
- coding_client/models/repo_scanner.py +249 -0
- coding_client/models/responses.py +431 -0
- coding_client/models/security.py +185 -0
- coding_client/models/static_analysis.py +508 -0
- coding_client/models/system.py +48 -0
- coding_client/models/test_executor.py +204 -0
- coding_client/models/testing.py +673 -0
- coding_client/models/testing_config.py +200 -0
- coding_client/models/validation.py +127 -0
- coding_client/models_init.py +272 -0
- coding_client/telemetry.py +195 -0
- coding_client/testing.py +180 -0
- coding_client/types/__init__.py +130 -0
- coding_client/types/constraint_types.py +276 -0
- coding_client/types/core_types.py +112 -0
- coding_client/types/state_machine.py +443 -0
- coding_client/utils/__init__.py +86 -0
- coding_client/utils/archive_utils.py +387 -0
- coding_client/utils/ast_debug.py +45 -0
- coding_client/utils/async_timeout.py +364 -0
- coding_client/utils/constants.py +518 -0
- coding_client/utils/content_processing.py +326 -0
- coding_client/utils/database.py +916 -0
- coding_client/utils/encoding_helper.py +222 -0
- coding_client/utils/enum_helpers.py +166 -0
- coding_client/utils/file_operations.py +177 -0
- coding_client/utils/filesystem_ops.py +528 -0
- coding_client/utils/http_client.py +562 -0
- coding_client/utils/path_utils.py +471 -0
- coding_client/utils/profiling.py +421 -0
- coding_client/utils/response_builder.py +240 -0
- coding_client/utils/retry_helper.py +712 -0
- coding_client/utils/security_validation.py +423 -0
- coding_client-1.21.2.dist-info/METADATA +234 -0
- coding_client-1.21.2.dist-info/RECORD +109 -0
- coding_client-1.21.2.dist-info/WHEEL +5 -0
- coding_client-1.21.2.dist-info/licenses/LICENSE +201 -0
- coding_client-1.21.2.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,878 @@
|
|
|
1
|
+
"""Core models for unified multi-language code analysis and entity representation.
|
|
2
|
+
|
|
3
|
+
This module provides the foundational data structures for code analysis, entities,
|
|
4
|
+
and relationships across all supported programming languages. It serves as the
|
|
5
|
+
central schema definition for the code graph helper system, supporting both
|
|
6
|
+
static analysis and dynamic runtime data.
|
|
7
|
+
|
|
8
|
+
The core models enable:
|
|
9
|
+
- Universal entity representation across programming languages
|
|
10
|
+
- Type-safe relationship modeling between code elements
|
|
11
|
+
- Comprehensive analysis result aggregation
|
|
12
|
+
- Multi-language code complexity measurement
|
|
13
|
+
- Security pattern detection and reporting
|
|
14
|
+
|
|
15
|
+
Key Model Categories:
|
|
16
|
+
Entity Models: CoreCodeEntity, EntityRelation for representing code structure
|
|
17
|
+
Analysis Models: CoreAnalysisResult, CoreFileAnalysisResult for analysis outcomes
|
|
18
|
+
Metrics Models: CoreComplexityMetrics, CodeSecurityPattern for code quality assessment
|
|
19
|
+
Request/Response Models: CodebaseAnalysisRequest, AnalysisResponse for API operations
|
|
20
|
+
|
|
21
|
+
Language Support:
|
|
22
|
+
- Python: Full AST analysis with type hints and decorators
|
|
23
|
+
- JavaScript/TypeScript: ES6+ features and type annotations
|
|
24
|
+
- Java: Classes, interfaces, and annotations
|
|
25
|
+
- C#: Properties, LINQ, and async/await patterns
|
|
26
|
+
- Go: Goroutines, channels, and interfaces
|
|
27
|
+
- Rust: Traits, lifetimes, and ownership patterns
|
|
28
|
+
- C++: Templates, namespaces, and STL containers
|
|
29
|
+
|
|
30
|
+
Example:
|
|
31
|
+
```python
|
|
32
|
+
from core_models import CoreCodeEntity, EntityType, RelationType, EntityRelation
|
|
33
|
+
|
|
34
|
+
# Create a function entity
|
|
35
|
+
function = CoreCodeEntity(
|
|
36
|
+
id="func_123",
|
|
37
|
+
name="process_data",
|
|
38
|
+
type=EntityType.FUNCTION,
|
|
39
|
+
language="python",
|
|
40
|
+
file_path="src/processor.py",
|
|
41
|
+
line_number=42,
|
|
42
|
+
signature="def process_data(data: List[Dict]) -> Dict:",
|
|
43
|
+
return_type=TypeInfo(name="Dict", module="typing"),
|
|
44
|
+
visibility="public"
|
|
45
|
+
)
|
|
46
|
+
|
|
47
|
+
# Create a relationship
|
|
48
|
+
relation = EntityRelation(
|
|
49
|
+
source_id="module_main",
|
|
50
|
+
target_id="func_123",
|
|
51
|
+
type=RelationType.CALLS,
|
|
52
|
+
weight=0.8
|
|
53
|
+
)
|
|
54
|
+
```
|
|
55
|
+
"""
|
|
56
|
+
|
|
57
|
+
from __future__ import annotations
|
|
58
|
+
|
|
59
|
+
import logging
|
|
60
|
+
from datetime import UTC, datetime
|
|
61
|
+
from enum import StrEnum
|
|
62
|
+
from typing import Any
|
|
63
|
+
|
|
64
|
+
from pydantic import BaseModel, ConfigDict, Field
|
|
65
|
+
from typing_extensions import TypedDict # PEP 728 support for extra_items
|
|
66
|
+
|
|
67
|
+
# Configure logging
|
|
68
|
+
logger = logging.getLogger(__name__)
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
# TypedDict classes for structured type safety
|
|
72
|
+
class CodeEntityProperties(TypedDict, total=False):
|
|
73
|
+
"""Type-safe structure for CoreCodeEntity properties with common language fields."""
|
|
74
|
+
|
|
75
|
+
# Core properties
|
|
76
|
+
decorators: list[str]
|
|
77
|
+
annotations: list[str]
|
|
78
|
+
access_modifiers: list[str]
|
|
79
|
+
language_specific: dict[str, Any]
|
|
80
|
+
is_constructor: bool
|
|
81
|
+
is_destructor: bool
|
|
82
|
+
is_property: bool
|
|
83
|
+
is_method: bool
|
|
84
|
+
is_field: bool
|
|
85
|
+
access_level: str
|
|
86
|
+
modifiers: list[str] | dict[str, Any] # Java uses dict, others use list
|
|
87
|
+
attributes: dict[str, Any]
|
|
88
|
+
|
|
89
|
+
# TypeScript/JavaScript specific
|
|
90
|
+
generic_parameters: list[str]
|
|
91
|
+
extends: str
|
|
92
|
+
implements: list[str]
|
|
93
|
+
is_exported: bool
|
|
94
|
+
type_kind: str
|
|
95
|
+
type_definition: str
|
|
96
|
+
is_union_type: bool
|
|
97
|
+
is_conditional_type: bool
|
|
98
|
+
is_mapped_type: bool
|
|
99
|
+
is_const_enum: bool
|
|
100
|
+
parameters: list[dict[str, Any]]
|
|
101
|
+
return_type: str
|
|
102
|
+
is_arrow_function: bool
|
|
103
|
+
module_path: str
|
|
104
|
+
import_path: str
|
|
105
|
+
type_safety_impact: dict[str, Any]
|
|
106
|
+
|
|
107
|
+
# Rust specific
|
|
108
|
+
is_public: bool
|
|
109
|
+
use_path: str
|
|
110
|
+
impl_type: str
|
|
111
|
+
trait_name: str
|
|
112
|
+
type_name: str
|
|
113
|
+
node_type: str
|
|
114
|
+
|
|
115
|
+
# Python specific
|
|
116
|
+
import_type: str
|
|
117
|
+
alias: str
|
|
118
|
+
module: str
|
|
119
|
+
name: str
|
|
120
|
+
bases: list[str]
|
|
121
|
+
arguments: list[str]
|
|
122
|
+
|
|
123
|
+
# Java specific
|
|
124
|
+
is_static: bool
|
|
125
|
+
is_wildcard: bool
|
|
126
|
+
package_name: str
|
|
127
|
+
file_path: str
|
|
128
|
+
is_constant: bool
|
|
129
|
+
|
|
130
|
+
# C# specific
|
|
131
|
+
namespace_name: str
|
|
132
|
+
using_directive: str
|
|
133
|
+
is_sealed: bool
|
|
134
|
+
interface_type: bool
|
|
135
|
+
is_readonly: bool
|
|
136
|
+
value_type: bool
|
|
137
|
+
enum_type: bool
|
|
138
|
+
is_virtual: bool
|
|
139
|
+
is_override: bool
|
|
140
|
+
property_type: str
|
|
141
|
+
field_type: str
|
|
142
|
+
is_const: bool
|
|
143
|
+
|
|
144
|
+
# Multi-language factory
|
|
145
|
+
file_size: int
|
|
146
|
+
file_extension: str
|
|
147
|
+
minimal_graph: bool
|
|
148
|
+
detected_version: str
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
class CodeEntityMetadata(TypedDict, total=False):
|
|
152
|
+
"""Type-safe structure for CoreCodeEntity metadata."""
|
|
153
|
+
|
|
154
|
+
source_hash: str
|
|
155
|
+
last_modified: str
|
|
156
|
+
analysis_version: str
|
|
157
|
+
confidence_score: float
|
|
158
|
+
tags: list[str]
|
|
159
|
+
category: str
|
|
160
|
+
complexity_score: float
|
|
161
|
+
maintainability_index: float
|
|
162
|
+
test_coverage: float
|
|
163
|
+
documentation_coverage: float
|
|
164
|
+
legacy_fields: dict[str, Any]
|
|
165
|
+
|
|
166
|
+
# Additional analyzer fields
|
|
167
|
+
language: str
|
|
168
|
+
var_type: str
|
|
169
|
+
|
|
170
|
+
|
|
171
|
+
class RelationProperties(TypedDict, total=False):
|
|
172
|
+
"""Type-safe structure for EntityRelation properties."""
|
|
173
|
+
|
|
174
|
+
weight: float
|
|
175
|
+
confidence: float
|
|
176
|
+
context: str
|
|
177
|
+
frequency: int
|
|
178
|
+
strength: float
|
|
179
|
+
call_count: int
|
|
180
|
+
import_style: str
|
|
181
|
+
access_pattern: str
|
|
182
|
+
dependency_type: str
|
|
183
|
+
metadata: dict[str, Any]
|
|
184
|
+
|
|
185
|
+
# TypeScript analyzer specific
|
|
186
|
+
coupling_strength: str
|
|
187
|
+
is_type_relationship: bool
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class RelationMetadata(TypedDict, total=False):
|
|
191
|
+
"""Type-safe structure for EntityRelation metadata."""
|
|
192
|
+
|
|
193
|
+
source_location: str
|
|
194
|
+
target_location: str
|
|
195
|
+
analysis_confidence: float
|
|
196
|
+
detected_by: str
|
|
197
|
+
verification_status: str
|
|
198
|
+
last_verified: str
|
|
199
|
+
flags: list[str]
|
|
200
|
+
tags: list[str]
|
|
201
|
+
legacy_fields: dict[str, Any]
|
|
202
|
+
|
|
203
|
+
|
|
204
|
+
class DependencyMetadata(TypedDict, total=False):
|
|
205
|
+
"""Type-safe structure for DependencyInfoModel metadata."""
|
|
206
|
+
|
|
207
|
+
version: str
|
|
208
|
+
resolved_path: str
|
|
209
|
+
package_manager: str
|
|
210
|
+
dependency_scope: str
|
|
211
|
+
is_dev_dependency: bool
|
|
212
|
+
is_optional: bool
|
|
213
|
+
resolution_method: str
|
|
214
|
+
confidence_score: float
|
|
215
|
+
flags: list[str]
|
|
216
|
+
|
|
217
|
+
# TypeScript analyzer specific
|
|
218
|
+
full_path: str
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
class SecurityMetadata(TypedDict, total=False):
|
|
222
|
+
"""Type-safe structure for CodeSecurityPattern metadata."""
|
|
223
|
+
|
|
224
|
+
rule_id: str
|
|
225
|
+
confidence: float
|
|
226
|
+
impact: str
|
|
227
|
+
remediation: str
|
|
228
|
+
references: list[str]
|
|
229
|
+
tags: list[str]
|
|
230
|
+
custom_fields: dict[str, Any]
|
|
231
|
+
|
|
232
|
+
# Analyzer specific
|
|
233
|
+
match_text: str
|
|
234
|
+
|
|
235
|
+
|
|
236
|
+
class AnalysisMetadata(TypedDict, total=False):
|
|
237
|
+
"""Type-safe structure for CoreAnalysisResult metadata."""
|
|
238
|
+
|
|
239
|
+
analyzer_version: str
|
|
240
|
+
analysis_mode: str
|
|
241
|
+
configuration: dict[str, Any]
|
|
242
|
+
performance_metrics: dict[str, Any]
|
|
243
|
+
quality_metrics: dict[str, Any]
|
|
244
|
+
tags: list[str]
|
|
245
|
+
flags: list[str]
|
|
246
|
+
custom_fields: dict[str, Any]
|
|
247
|
+
|
|
248
|
+
# Common analyzer fields
|
|
249
|
+
file_path: str
|
|
250
|
+
directory_path: str
|
|
251
|
+
directory: str
|
|
252
|
+
snippet: bool
|
|
253
|
+
error: str
|
|
254
|
+
error_type: str
|
|
255
|
+
error_timestamp: str
|
|
256
|
+
repo_path: str
|
|
257
|
+
total_files: int
|
|
258
|
+
successful_files: int
|
|
259
|
+
failed_files: list[str]
|
|
260
|
+
files_analyzed: int
|
|
261
|
+
error_count: int
|
|
262
|
+
languages: list[str]
|
|
263
|
+
language: str
|
|
264
|
+
detected_language: str
|
|
265
|
+
snippet_language: str
|
|
266
|
+
has_context: bool
|
|
267
|
+
|
|
268
|
+
# Symbolic analyzer fields
|
|
269
|
+
symbolic_analysis: dict[str, Any]
|
|
270
|
+
analyzer: str
|
|
271
|
+
documentation: dict[str, Any]
|
|
272
|
+
original_file: str
|
|
273
|
+
|
|
274
|
+
# TypeScript analyzer fields
|
|
275
|
+
parser_used: str
|
|
276
|
+
typescript_version: str
|
|
277
|
+
type_safety: dict[str, Any]
|
|
278
|
+
complexity: dict[str, Any]
|
|
279
|
+
typescript_specific: dict[str, Any]
|
|
280
|
+
analysis_timestamp: str
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
class RepositorySummary(TypedDict, total=False):
|
|
284
|
+
"""Type-safe structure for repository analysis summary."""
|
|
285
|
+
|
|
286
|
+
total_files: int
|
|
287
|
+
files_by_language: dict[str, int]
|
|
288
|
+
lines_of_code: int
|
|
289
|
+
complexity_distribution: dict[str, int]
|
|
290
|
+
security_findings: dict[str, int]
|
|
291
|
+
quality_score: float
|
|
292
|
+
maintainability_index: float
|
|
293
|
+
test_coverage: float
|
|
294
|
+
documentation_coverage: float
|
|
295
|
+
dependency_count: int
|
|
296
|
+
external_dependencies: int
|
|
297
|
+
analysis_duration_seconds: float
|
|
298
|
+
timestamp: str
|
|
299
|
+
|
|
300
|
+
# Code processor fields
|
|
301
|
+
message: str
|
|
302
|
+
|
|
303
|
+
|
|
304
|
+
class AnalysisPatterns(TypedDict, total=False):
|
|
305
|
+
"""Type-safe structure for analysis patterns."""
|
|
306
|
+
|
|
307
|
+
pattern_type: str
|
|
308
|
+
pattern_name: str
|
|
309
|
+
confidence: float
|
|
310
|
+
frequency: int
|
|
311
|
+
instances: list[dict[str, str | int | bool | float]]
|
|
312
|
+
locations: list[str]
|
|
313
|
+
description: str
|
|
314
|
+
category: str
|
|
315
|
+
impact: str
|
|
316
|
+
recommendations: list[str]
|
|
317
|
+
tags: list[str]
|
|
318
|
+
|
|
319
|
+
|
|
320
|
+
class CoreArchitectureAnalysis(TypedDict, total=False):
|
|
321
|
+
"""Type-safe structure for architecture analysis results."""
|
|
322
|
+
|
|
323
|
+
layers: list[dict[str, str | int | bool | float]]
|
|
324
|
+
components: list[dict[str, str | int | bool | float]]
|
|
325
|
+
dependencies: list[dict[str, str | int | bool | float]]
|
|
326
|
+
patterns: list[dict[str, str | int | bool | float]]
|
|
327
|
+
metrics: dict[str, str | int | float]
|
|
328
|
+
quality_indicators: dict[str, str | int | float]
|
|
329
|
+
recommendations: list[str]
|
|
330
|
+
analysis_timestamp: str
|
|
331
|
+
# Extended fields used by analysis_orchestrator
|
|
332
|
+
architectural_style: str
|
|
333
|
+
total_modules: int
|
|
334
|
+
total_components: int
|
|
335
|
+
coupling_score: float
|
|
336
|
+
cohesion_score: float
|
|
337
|
+
complexity_score: float
|
|
338
|
+
patterns_detected: list[str]
|
|
339
|
+
dependencies_count: int
|
|
340
|
+
layer_violations: int
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
class ImpactAnalysis(TypedDict, total=False):
|
|
344
|
+
"""Type-safe structure for impact analysis results."""
|
|
345
|
+
|
|
346
|
+
affected_components: list[str]
|
|
347
|
+
risk_level: str
|
|
348
|
+
change_propagation: dict[str, str | int | bool | float]
|
|
349
|
+
test_impact: dict[str, str | int | bool | float]
|
|
350
|
+
performance_impact: dict[str, str | int | bool | float]
|
|
351
|
+
recommendations: list[str]
|
|
352
|
+
confidence_score: float
|
|
353
|
+
analysis_timestamp: str
|
|
354
|
+
# Extended fields used by analysis_orchestrator
|
|
355
|
+
affected_files: int
|
|
356
|
+
breaking_changes: list[str]
|
|
357
|
+
change_complexity: float
|
|
358
|
+
dependencies_affected: list[str]
|
|
359
|
+
|
|
360
|
+
|
|
361
|
+
class StyleScore(TypedDict, total=False):
|
|
362
|
+
"""Type-safe structure for style evaluation scores."""
|
|
363
|
+
|
|
364
|
+
overall_score: float
|
|
365
|
+
naming_conventions: float
|
|
366
|
+
code_organization: float
|
|
367
|
+
documentation_quality: float
|
|
368
|
+
consistency_score: float
|
|
369
|
+
best_practices: float
|
|
370
|
+
maintainability: float
|
|
371
|
+
readability: float
|
|
372
|
+
detailed_metrics: dict[str, str | int | float]
|
|
373
|
+
|
|
374
|
+
|
|
375
|
+
class ProcessingTimeBreakdown(TypedDict, total=False):
|
|
376
|
+
"""Type-safe structure for processing time breakdown."""
|
|
377
|
+
|
|
378
|
+
total_time_seconds: float
|
|
379
|
+
parsing_time_seconds: float
|
|
380
|
+
analysis_time_seconds: float
|
|
381
|
+
relationship_extraction_seconds: float
|
|
382
|
+
metrics_calculation_seconds: float
|
|
383
|
+
post_processing_seconds: float
|
|
384
|
+
file_io_seconds: float
|
|
385
|
+
memory_usage_mb: float
|
|
386
|
+
cpu_usage_percent: float
|
|
387
|
+
concurrent_workers: int
|
|
388
|
+
files_per_second: float
|
|
389
|
+
|
|
390
|
+
|
|
391
|
+
# Enums
|
|
392
|
+
class EntityType(StrEnum):
|
|
393
|
+
"""Universal entity types across all programming languages."""
|
|
394
|
+
|
|
395
|
+
# Core entities (universal)
|
|
396
|
+
MODULE = "module"
|
|
397
|
+
FILE = "file"
|
|
398
|
+
FUNCTION = "function"
|
|
399
|
+
VARIABLE = "variable"
|
|
400
|
+
CONSTANT = "constant"
|
|
401
|
+
IMPORT = "import"
|
|
402
|
+
|
|
403
|
+
# Object-oriented entities
|
|
404
|
+
CLASS = "class"
|
|
405
|
+
INTERFACE = "interface"
|
|
406
|
+
TRAIT = "trait"
|
|
407
|
+
ENUM = "enum"
|
|
408
|
+
STRUCT = "struct"
|
|
409
|
+
UNION = "union"
|
|
410
|
+
|
|
411
|
+
# Functional entities
|
|
412
|
+
CLOSURE = "closure"
|
|
413
|
+
LAMBDA = "lambda"
|
|
414
|
+
GENERATOR = "generator"
|
|
415
|
+
|
|
416
|
+
# Language-specific entities
|
|
417
|
+
NAMESPACE = "namespace"
|
|
418
|
+
PACKAGE = "package"
|
|
419
|
+
ANNOTATION = "annotation"
|
|
420
|
+
DECORATOR = "decorator"
|
|
421
|
+
MACRO = "macro"
|
|
422
|
+
GENERIC = "generic"
|
|
423
|
+
TYPE_ALIAS = "type_alias"
|
|
424
|
+
|
|
425
|
+
# Documentation entities
|
|
426
|
+
COMMENT = "comment"
|
|
427
|
+
DOCSTRING = "docstring"
|
|
428
|
+
TODO = "todo"
|
|
429
|
+
|
|
430
|
+
|
|
431
|
+
class RelationType(StrEnum):
|
|
432
|
+
"""Universal relationship types between entities."""
|
|
433
|
+
|
|
434
|
+
# Structural relationships
|
|
435
|
+
CONTAINS = "contains" # Module contains class
|
|
436
|
+
DEFINES = "defines" # Class defines method
|
|
437
|
+
DECLARES = "declares" # Function declares variable
|
|
438
|
+
|
|
439
|
+
# Call relationships
|
|
440
|
+
CALLS = "calls" # Function calls another function
|
|
441
|
+
INVOKES = "invokes" # Class instantiation
|
|
442
|
+
REFERENCES = "references" # Variable reference
|
|
443
|
+
|
|
444
|
+
# Inheritance relationships
|
|
445
|
+
INHERITS = "inherits" # Class inheritance
|
|
446
|
+
IMPLEMENTS = "implements" # Interface implementation
|
|
447
|
+
EXTENDS = "extends" # Trait/mixin extension
|
|
448
|
+
|
|
449
|
+
# Import/dependency relationships
|
|
450
|
+
IMPORTS = "imports" # Module imports
|
|
451
|
+
DEPENDS_ON = "depends_on" # Dependency relationship
|
|
452
|
+
EXPORTS = "exports" # Module exports
|
|
453
|
+
|
|
454
|
+
# Type relationships
|
|
455
|
+
INSTANTIATES = "instantiates" # Variable instantiates type
|
|
456
|
+
CASTS_TO = "casts_to" # Type casting
|
|
457
|
+
GENERIC_OF = "generic_of" # Generic type parameter
|
|
458
|
+
|
|
459
|
+
# Documentation relationships
|
|
460
|
+
DOCUMENTS = "documents" # Comment/docstring relationship
|
|
461
|
+
ANNOTATES = "annotates" # Annotation relationship
|
|
462
|
+
|
|
463
|
+
# Legacy compatibility
|
|
464
|
+
INHERITANCE = "inherits" # Maps to INHERITS
|
|
465
|
+
COMPOSITION = "contains" # Maps to CONTAINS
|
|
466
|
+
DEPENDENCY = "depends_on" # Maps to DEPENDS_ON
|
|
467
|
+
CALL = "calls" # Maps to CALLS
|
|
468
|
+
IMPORT = "imports" # Maps to IMPORTS
|
|
469
|
+
USAGE = "references" # Maps to REFERENCES
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
# Core Entity Models
|
|
473
|
+
class SourceLocation(BaseModel):
|
|
474
|
+
"""Precise location information within source code."""
|
|
475
|
+
|
|
476
|
+
model_config = ConfigDict(frozen=True)
|
|
477
|
+
|
|
478
|
+
file_path: str
|
|
479
|
+
line_start: int = Field(..., ge=1)
|
|
480
|
+
line_end: int = Field(..., ge=1)
|
|
481
|
+
column_start: int = Field(..., ge=0)
|
|
482
|
+
column_end: int = Field(..., ge=0)
|
|
483
|
+
|
|
484
|
+
|
|
485
|
+
class TypeInfo(BaseModel):
|
|
486
|
+
"""Type information for entities."""
|
|
487
|
+
|
|
488
|
+
model_config = ConfigDict(frozen=True)
|
|
489
|
+
|
|
490
|
+
name: str
|
|
491
|
+
module: str | None = None
|
|
492
|
+
is_generic: bool = False
|
|
493
|
+
generic_params: list[str] = Field(default_factory=list)
|
|
494
|
+
is_nullable: bool = False
|
|
495
|
+
is_array: bool = False
|
|
496
|
+
array_dimensions: int = 0
|
|
497
|
+
|
|
498
|
+
|
|
499
|
+
class CoreCodeEntity(BaseModel):
|
|
500
|
+
"""
|
|
501
|
+
Universal code entity representation for multi-language support.
|
|
502
|
+
|
|
503
|
+
Combines the best features from both previous implementations with language-agnostic design.
|
|
504
|
+
"""
|
|
505
|
+
|
|
506
|
+
id: str = Field(..., description="Unique identifier for the entity")
|
|
507
|
+
name: str = Field(..., description="Entity name")
|
|
508
|
+
type: EntityType = Field(..., description="Type of code entity")
|
|
509
|
+
language: str = Field(..., description="Programming language")
|
|
510
|
+
|
|
511
|
+
# Location information (augmented for multi-language)
|
|
512
|
+
file_path: str = Field(..., description="File path where entity is defined")
|
|
513
|
+
line_number: int = Field(..., description="Starting line number")
|
|
514
|
+
end_line_number: int | None = Field(None, description="Ending line number")
|
|
515
|
+
column_start: int | None = Field(None, description="Starting column")
|
|
516
|
+
column_end: int | None = Field(None, description="Ending column")
|
|
517
|
+
|
|
518
|
+
# Type information
|
|
519
|
+
return_type: TypeInfo | None = None
|
|
520
|
+
parameter_types: list[TypeInfo] = Field(default_factory=list)
|
|
521
|
+
|
|
522
|
+
# Modifiers and attributes (language-agnostic)
|
|
523
|
+
visibility: str | None = Field(None, description="public, private, protected, internal")
|
|
524
|
+
is_static: bool = False
|
|
525
|
+
is_abstract: bool = False
|
|
526
|
+
is_final: bool = False
|
|
527
|
+
is_async: bool = False
|
|
528
|
+
is_generic: bool = False
|
|
529
|
+
|
|
530
|
+
# Content and documentation
|
|
531
|
+
code_snippet: str | None = Field(None, description="Code snippet")
|
|
532
|
+
docstring: str | None = Field(None, description="Documentation string")
|
|
533
|
+
signature: str | None = Field(None, description="Function/method signature")
|
|
534
|
+
source_code: str | None = Field(None, description="Full source code")
|
|
535
|
+
|
|
536
|
+
# Language-specific properties (Dict for Pydantic compatibility, matches CodeEntityProperties structure)
|
|
537
|
+
properties: dict[str, Any] = Field(
|
|
538
|
+
default_factory=dict, description="Language-specific metadata"
|
|
539
|
+
)
|
|
540
|
+
metadata: dict[str, Any] = Field(
|
|
541
|
+
default_factory=dict,
|
|
542
|
+
description="Additional metadata (legacy compatibility)",
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
# Timestamps
|
|
546
|
+
created_at: datetime | None = Field(None, description="Creation timestamp")
|
|
547
|
+
updated_at: datetime | None = Field(None, description="Last update timestamp")
|
|
548
|
+
|
|
549
|
+
model_config = ConfigDict(from_attributes=True)
|
|
550
|
+
|
|
551
|
+
def model_post_init(self, __context: Any) -> None:
|
|
552
|
+
"""Log entity creation for debugging purposes."""
|
|
553
|
+
logger.debug(
|
|
554
|
+
f"Created CoreCodeEntity: {self.name} ({self.type.value}) in {self.file_path}:{self.line_number}"
|
|
555
|
+
)
|
|
556
|
+
|
|
557
|
+
|
|
558
|
+
class EntityRelation(BaseModel):
|
|
559
|
+
"""
|
|
560
|
+
Universal relationship model between two code entities for multi-language support.
|
|
561
|
+
|
|
562
|
+
Combines features from both previous implementations with backward compatibility.
|
|
563
|
+
"""
|
|
564
|
+
|
|
565
|
+
# Core relationship
|
|
566
|
+
source_id: str = Field(..., description="ID of the source entity")
|
|
567
|
+
target_id: str = Field(..., description="ID of the target entity")
|
|
568
|
+
type: RelationType = Field(..., description="Type of relationship")
|
|
569
|
+
|
|
570
|
+
# Relationship metadata
|
|
571
|
+
weight: float = Field(default=1.0, ge=0.0, le=1.0, description="Relationship strength")
|
|
572
|
+
properties: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
573
|
+
|
|
574
|
+
# Context information
|
|
575
|
+
location: SourceLocation | None = None
|
|
576
|
+
context: str | None = None # Code snippet showing relationship
|
|
577
|
+
|
|
578
|
+
# Legacy compatibility fields
|
|
579
|
+
id: str | None = Field(None, description="Unique identifier for the relationship")
|
|
580
|
+
relationship_type: str | None = Field(None, description="Backward compatibility alias")
|
|
581
|
+
line_number: int | None = Field(None, description="Line number where relationship occurs")
|
|
582
|
+
detail: str | None = Field(None, description="Additional relationship details")
|
|
583
|
+
metadata: dict[str, Any] = Field(
|
|
584
|
+
default_factory=dict, description="Additional metadata (legacy)"
|
|
585
|
+
)
|
|
586
|
+
created_at: datetime | None = Field(None, description="Creation timestamp")
|
|
587
|
+
|
|
588
|
+
model_config = ConfigDict(from_attributes=True, populate_by_name=True)
|
|
589
|
+
|
|
590
|
+
def __init__(self, **data: Any) -> None:
|
|
591
|
+
# Handle backward compatibility for relationship_type field
|
|
592
|
+
if "relationship_type" in data and "type" not in data:
|
|
593
|
+
data["type"] = data["relationship_type"]
|
|
594
|
+
elif "type" in data and isinstance(data["type"], str):
|
|
595
|
+
# Convert string to enum if needed
|
|
596
|
+
try:
|
|
597
|
+
data["type"] = RelationType(data["type"])
|
|
598
|
+
except ValueError:
|
|
599
|
+
# If conversion fails, keep as string (will be validated by Pydantic)
|
|
600
|
+
pass
|
|
601
|
+
|
|
602
|
+
# Generate ID if not provided
|
|
603
|
+
if "id" not in data or data["id"] is None:
|
|
604
|
+
source_id = data.get("source_id", "")
|
|
605
|
+
target_id = data.get("target_id", "")
|
|
606
|
+
rel_type = data.get("type", "")
|
|
607
|
+
if hasattr(rel_type, "value"):
|
|
608
|
+
rel_type = rel_type.value
|
|
609
|
+
data["id"] = f"{source_id}-{rel_type}-{target_id}"
|
|
610
|
+
|
|
611
|
+
super().__init__(**data)
|
|
612
|
+
|
|
613
|
+
# Log relationship creation for debugging
|
|
614
|
+
logger.debug(
|
|
615
|
+
f"Created EntityRelation: {self.source_id} -> {self.target_id} ({self.type.value})"
|
|
616
|
+
)
|
|
617
|
+
|
|
618
|
+
|
|
619
|
+
# Analysis Support Models
|
|
620
|
+
class DependencyInfoModel(BaseModel):
|
|
621
|
+
"""Information about code dependencies."""
|
|
622
|
+
|
|
623
|
+
module_name: str = Field(..., description="Name of the dependency module")
|
|
624
|
+
import_type: str = Field(..., description="Type of import ('import' or 'from_import')")
|
|
625
|
+
alias: str | None = Field(None, description="Import alias if used")
|
|
626
|
+
line_number: int = Field(0, description="Line number of import")
|
|
627
|
+
is_external: bool = Field(False, description="Whether dependency is external")
|
|
628
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
629
|
+
|
|
630
|
+
def model_post_init(self, __context: Any) -> None:
|
|
631
|
+
"""Log dependency creation for debugging purposes."""
|
|
632
|
+
logger.debug(
|
|
633
|
+
f"Created DependencyInfoModel: {self.module_name} ({self.import_type}) - external: {self.is_external}"
|
|
634
|
+
)
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
class CoreComplexityMetrics(BaseModel):
|
|
638
|
+
"""Code complexity measurements for multi-language support."""
|
|
639
|
+
|
|
640
|
+
model_config = ConfigDict(frozen=True)
|
|
641
|
+
|
|
642
|
+
cyclomatic_complexity: float = 0.0
|
|
643
|
+
cognitive_complexity: float = 0.0
|
|
644
|
+
lines_of_code: int = 0
|
|
645
|
+
logical_lines: int = 0
|
|
646
|
+
parameters_count: int = 0
|
|
647
|
+
returns_count: int = 0
|
|
648
|
+
branches_count: int = 0
|
|
649
|
+
nested_depth: int = 0
|
|
650
|
+
|
|
651
|
+
# Extended metrics
|
|
652
|
+
maintainability_index: float = Field(0.0, description="Maintainability index score")
|
|
653
|
+
halstead_volume: float = Field(0.0, description="Halstead volume metric")
|
|
654
|
+
halstead_difficulty: float = Field(0.0, description="Halstead difficulty metric")
|
|
655
|
+
halstead_effort: float = Field(0.0, description="Halstead effort metric")
|
|
656
|
+
|
|
657
|
+
# Legacy compatibility
|
|
658
|
+
function_count: int = Field(0, description="Number of functions")
|
|
659
|
+
class_count: int = Field(0, description="Number of classes")
|
|
660
|
+
comment_lines: int = Field(0, description="Lines of comments")
|
|
661
|
+
blank_lines: int = Field(0, description="Blank lines")
|
|
662
|
+
docstring_coverage: float = Field(0.0, description="Docstring coverage percentage")
|
|
663
|
+
|
|
664
|
+
|
|
665
|
+
class CodeSecurityPattern(BaseModel):
|
|
666
|
+
"""Security pattern detection result from code analysis."""
|
|
667
|
+
|
|
668
|
+
type: str = Field(..., description="Type of security pattern")
|
|
669
|
+
severity: str = Field(..., description="Severity level (low, medium, high, critical)")
|
|
670
|
+
line_number: int = Field(..., description="Line number where pattern was found")
|
|
671
|
+
description: str = Field(..., description="Description of the pattern")
|
|
672
|
+
cwe_id: str | None = Field(None, description="Common Weakness Enumeration ID")
|
|
673
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
674
|
+
|
|
675
|
+
def model_post_init(self, __context: Any) -> None:
|
|
676
|
+
"""Log security pattern detection for debugging purposes."""
|
|
677
|
+
logger.warning(
|
|
678
|
+
f"SecurityPattern detected: {self.type} (severity: {self.severity}) at line {self.line_number}"
|
|
679
|
+
)
|
|
680
|
+
|
|
681
|
+
|
|
682
|
+
# Analysis Result Models
|
|
683
|
+
class CoreAnalysisResult(BaseModel):
|
|
684
|
+
"""Result of code analysis operation."""
|
|
685
|
+
|
|
686
|
+
success: bool = Field(..., description="Whether analysis was successful")
|
|
687
|
+
language: str = Field(..., description="Programming language")
|
|
688
|
+
file_path: str = Field(..., description="Path to analyzed file")
|
|
689
|
+
entities: list[CoreCodeEntity] = Field(default_factory=list, description="Discovered entities")
|
|
690
|
+
relationships: list[EntityRelation] = Field(
|
|
691
|
+
default_factory=list, description="Entity relationships"
|
|
692
|
+
)
|
|
693
|
+
dependencies: list[DependencyInfoModel] = Field(
|
|
694
|
+
default_factory=list, description="Dependencies found"
|
|
695
|
+
)
|
|
696
|
+
complexity_metrics: CoreComplexityMetrics | None = Field(None, description="Complexity metrics")
|
|
697
|
+
security_patterns: list[CodeSecurityPattern] = Field(
|
|
698
|
+
default_factory=list, description="Security patterns"
|
|
699
|
+
)
|
|
700
|
+
error: str | None = Field(None, description="Error message if analysis failed")
|
|
701
|
+
errors: list[str] = Field(default_factory=list, description="Error messages")
|
|
702
|
+
warnings: list[str] = Field(default_factory=list, description="Warning messages")
|
|
703
|
+
parse_time_ms: float = Field(0.0, description="Parse time in milliseconds")
|
|
704
|
+
total_lines: int = Field(0, description="Total lines of code")
|
|
705
|
+
timestamp: datetime | None = Field(None, description="Analysis timestamp")
|
|
706
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
707
|
+
|
|
708
|
+
def model_post_init(self, __context: Any) -> None:
|
|
709
|
+
"""Log analysis result creation for debugging purposes."""
|
|
710
|
+
status = "successful" if self.success else "failed"
|
|
711
|
+
logger.info(
|
|
712
|
+
f"CoreAnalysisResult created: {status} for {self.file_path} ({self.language}) - "
|
|
713
|
+
f"entities: {len(self.entities)}, relationships: {len(self.relationships)}"
|
|
714
|
+
)
|
|
715
|
+
|
|
716
|
+
|
|
717
|
+
class CoreFileAnalysisResult(BaseModel):
|
|
718
|
+
"""Analysis result for a single file."""
|
|
719
|
+
|
|
720
|
+
file_path: str = Field(..., description="Path to analyzed file")
|
|
721
|
+
language: str = Field(..., description="Programming language")
|
|
722
|
+
analysis_result: CoreAnalysisResult = Field(..., description="Analysis results")
|
|
723
|
+
timestamp: datetime = Field(
|
|
724
|
+
default_factory=lambda: datetime.now(UTC),
|
|
725
|
+
description="Analysis timestamp",
|
|
726
|
+
)
|
|
727
|
+
|
|
728
|
+
|
|
729
|
+
class RepositoryAnalysis(BaseModel):
|
|
730
|
+
"""Analysis results for an entire repository."""
|
|
731
|
+
|
|
732
|
+
success: bool = Field(..., description="Whether repository analysis was successful")
|
|
733
|
+
file_results: list[CoreAnalysisResult] = Field(
|
|
734
|
+
default_factory=list, description="File analysis results"
|
|
735
|
+
)
|
|
736
|
+
failed_files: list[dict[str, str]] = Field(
|
|
737
|
+
default_factory=list, description="Files that failed analysis"
|
|
738
|
+
)
|
|
739
|
+
summary: dict[str, Any] = Field(default_factory=dict, description="Analysis summary")
|
|
740
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
741
|
+
|
|
742
|
+
def model_post_init(self, __context: Any) -> None:
|
|
743
|
+
"""Log repository analysis completion for debugging purposes."""
|
|
744
|
+
status = "successful" if self.success else "failed"
|
|
745
|
+
total_files = len(self.file_results)
|
|
746
|
+
failed_count = len(self.failed_files)
|
|
747
|
+
logger.info(
|
|
748
|
+
f"RepositoryAnalysis completed: {status} - {total_files} files processed, {failed_count} failed"
|
|
749
|
+
)
|
|
750
|
+
|
|
751
|
+
|
|
752
|
+
class FullAnalysis(BaseModel):
|
|
753
|
+
"""Complete analysis results including architecture analysis."""
|
|
754
|
+
|
|
755
|
+
success: bool = Field(..., description="Whether full analysis was successful")
|
|
756
|
+
file_results: list[CoreFileAnalysisResult] = Field(
|
|
757
|
+
default_factory=list, description="File analysis results"
|
|
758
|
+
)
|
|
759
|
+
summary: dict[str, Any] = Field(default_factory=dict, description="Analysis summary")
|
|
760
|
+
patterns: list[dict[str, Any]] = Field(default_factory=list, description="Detected patterns")
|
|
761
|
+
architecture_analysis: dict[str, Any] = Field(
|
|
762
|
+
default_factory=dict, description="Architecture analysis"
|
|
763
|
+
)
|
|
764
|
+
error: str | None = Field(None, description="Error message if analysis failed")
|
|
765
|
+
|
|
766
|
+
def model_post_init(self, __context: Any) -> None:
|
|
767
|
+
"""Log full analysis completion for debugging purposes."""
|
|
768
|
+
status = "successful" if self.success else "failed"
|
|
769
|
+
pattern_count = len(self.patterns)
|
|
770
|
+
logger.info(
|
|
771
|
+
f"FullAnalysis completed: {status} - {len(self.file_results)} files, {pattern_count} patterns detected"
|
|
772
|
+
)
|
|
773
|
+
|
|
774
|
+
|
|
775
|
+
class IncrementalAnalysis(BaseModel):
|
|
776
|
+
"""Results of incremental code analysis."""
|
|
777
|
+
|
|
778
|
+
success: bool = Field(..., description="Whether incremental analysis was successful")
|
|
779
|
+
changed_files: list[CoreFileAnalysisResult] = Field(
|
|
780
|
+
default_factory=list, description="Changed file results"
|
|
781
|
+
)
|
|
782
|
+
impact_analysis: dict[str, Any] = Field(default_factory=dict, description="Impact analysis")
|
|
783
|
+
error: str | None = Field(None, description="Error message if analysis failed")
|
|
784
|
+
|
|
785
|
+
def model_post_init(self, __context: Any) -> None:
|
|
786
|
+
"""Log incremental analysis completion for debugging purposes."""
|
|
787
|
+
status = "successful" if self.success else "failed"
|
|
788
|
+
changed_count = len(self.changed_files)
|
|
789
|
+
logger.info(
|
|
790
|
+
f"IncrementalAnalysis completed: {status} - {changed_count} changed files analyzed"
|
|
791
|
+
)
|
|
792
|
+
|
|
793
|
+
|
|
794
|
+
class SnippetEvaluation(BaseModel):
|
|
795
|
+
"""Evaluation results for a code snippet."""
|
|
796
|
+
|
|
797
|
+
success: bool = Field(..., description="Whether snippet evaluation was successful")
|
|
798
|
+
analysis: CoreAnalysisResult | None = Field(None, description="Analysis results")
|
|
799
|
+
compatibility_score: float = Field(0.0, description="Compatibility score")
|
|
800
|
+
style_score: dict[str, Any] = Field(default_factory=dict, description="Style evaluation")
|
|
801
|
+
pattern_matches: list[dict[str, Any]] = Field(
|
|
802
|
+
default_factory=list, description="Pattern matches"
|
|
803
|
+
)
|
|
804
|
+
recommendations: list[str] = Field(default_factory=list, description="Recommendations")
|
|
805
|
+
error: str | None = Field(None, description="Error message if evaluation failed")
|
|
806
|
+
metadata: dict[str, Any] = Field(default_factory=dict, description="Additional metadata")
|
|
807
|
+
|
|
808
|
+
def model_post_init(self, __context: Any) -> None:
|
|
809
|
+
"""Log snippet evaluation completion for debugging purposes."""
|
|
810
|
+
status = "successful" if self.success else "failed"
|
|
811
|
+
logger.info(
|
|
812
|
+
f"SnippetEvaluation completed: {status} - compatibility: {self.compatibility_score:.2f}"
|
|
813
|
+
)
|
|
814
|
+
|
|
815
|
+
|
|
816
|
+
# Graph and Metrics Models
|
|
817
|
+
class GraphMetrics(BaseModel):
|
|
818
|
+
"""Metrics for an entity in the code graph."""
|
|
819
|
+
|
|
820
|
+
entity_id: str = Field(..., description="Entity identifier")
|
|
821
|
+
entity_name: str = Field(..., description="Entity name")
|
|
822
|
+
degree_centrality: float = Field(0.0, description="Degree centrality metric")
|
|
823
|
+
betweenness_centrality: float = Field(0.0, description="Betweenness centrality metric")
|
|
824
|
+
closeness_centrality: float = Field(0.0, description="Closeness centrality metric")
|
|
825
|
+
pagerank: float = Field(0.0, description="PageRank metric")
|
|
826
|
+
importance_score: float = Field(0.0, description="Combined importance score")
|
|
827
|
+
|
|
828
|
+
|
|
829
|
+
class OverallGraphMetrics(BaseModel):
|
|
830
|
+
"""Overall statistics for the entire code graph."""
|
|
831
|
+
|
|
832
|
+
node_count: int = Field(0, description="Total number of nodes")
|
|
833
|
+
edge_count: int = Field(0, description="Total number of edges")
|
|
834
|
+
density: float = Field(0.0, description="Graph density")
|
|
835
|
+
average_degree: float = Field(0.0, description="Average degree")
|
|
836
|
+
node_types: dict[str, int] = Field(default_factory=dict, description="Node count by type")
|
|
837
|
+
relationship_types: dict[str, int] = Field(
|
|
838
|
+
default_factory=dict, description="Edge count by type"
|
|
839
|
+
)
|
|
840
|
+
calculation_time_seconds: float = Field(0.0, description="Time taken for calculation")
|
|
841
|
+
|
|
842
|
+
|
|
843
|
+
# Request Models
|
|
844
|
+
class CodebaseAnalysisRequest(BaseModel):
|
|
845
|
+
"""Request model for codebase analysis operations."""
|
|
846
|
+
|
|
847
|
+
directory: str = Field(..., description="Directory to analyze")
|
|
848
|
+
languages: list[str] = Field(["python"], description="Programming languages to analyze")
|
|
849
|
+
max_workers: int | None = Field(None, description="Maximum number of worker processes")
|
|
850
|
+
include_tests: bool = Field(False, description="Whether to include test files")
|
|
851
|
+
ignore_patterns: list[str] = Field(default_factory=list, description="File patterns to ignore")
|
|
852
|
+
|
|
853
|
+
|
|
854
|
+
# Response Models
|
|
855
|
+
class AnalysisResponse(BaseModel):
|
|
856
|
+
"""Response model for codebase analysis."""
|
|
857
|
+
|
|
858
|
+
status: str = Field(..., description="Analysis status")
|
|
859
|
+
directory: str = Field(..., description="Analyzed directory")
|
|
860
|
+
files_processed: int = Field(..., description="Number of files processed")
|
|
861
|
+
files_failed: int = Field(..., description="Number of files that failed")
|
|
862
|
+
total_entities: int = Field(..., description="Total entities found")
|
|
863
|
+
total_relations: int = Field(..., description="Total relationships found")
|
|
864
|
+
processing_time: ProcessingTimeBreakdown = Field(..., description="Processing time breakdown")
|
|
865
|
+
languages: list[str] = Field(..., description="Languages analyzed")
|
|
866
|
+
|
|
867
|
+
def model_post_init(self, __context: Any) -> None:
|
|
868
|
+
"""Log analysis response creation for debugging purposes."""
|
|
869
|
+
success_rate = (
|
|
870
|
+
(self.files_processed - self.files_failed) / self.files_processed * 100
|
|
871
|
+
if self.files_processed > 0
|
|
872
|
+
else 0
|
|
873
|
+
)
|
|
874
|
+
logger.info(
|
|
875
|
+
f"AnalysisResponse created: {self.status} - {self.files_processed} files processed "
|
|
876
|
+
f"({success_rate:.1f}% success rate), {self.total_entities} entities, "
|
|
877
|
+
f"{self.total_relations} relationships"
|
|
878
|
+
)
|