codeboarding 0.10.1__tar.gz → 0.10.2__tar.gz
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.
- {codeboarding-0.10.1/codeboarding.egg-info → codeboarding-0.10.2}/PKG-INFO +1 -1
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/cluster_methods_mixin.py +26 -6
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/meta_agent.py +0 -1
- {codeboarding-0.10.1 → codeboarding-0.10.2/codeboarding.egg-info}/PKG-INFO +1 -1
- {codeboarding-0.10.1 → codeboarding-0.10.2}/install.py +64 -9
- {codeboarding-0.10.1 → codeboarding-0.10.2}/main.py +2 -2
- {codeboarding-0.10.1 → codeboarding-0.10.2}/pyproject.toml +1 -1
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/cluster_helpers.py +46 -23
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tool_registry.py +83 -25
- {codeboarding-0.10.1 → codeboarding-0.10.2}/LICENSE +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/PYPI.md +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/README.md +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/abstraction_agent.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/agent.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/agent_responses.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/change_status.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/dependency_discovery.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/details_agent.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/llm_config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/planner_agent.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/abstract_prompt_factory.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/claude_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/deepseek_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/gemini_flash_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/glm_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/gpt_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/kimi_prompts.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/prompts/prompt_factory.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/base.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/get_external_deps.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/get_method_invocations.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_cfg.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_docs.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_file.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_file_structure.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_git_diff.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_packages.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_source.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/read_structure.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/tools/toolkit.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/agents/validation.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/caching/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/caching/cache.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/caching/details_cache.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/caching/meta_cache.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/codeboarding.egg-info/SOURCES.txt +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/codeboarding.egg-info/dependency_links.txt +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/codeboarding.egg-info/entry_points.txt +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/codeboarding.egg-info/requires.txt +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/codeboarding.egg-info/top_level.txt +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/core/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/core/plugin_loader.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/core/protocols.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/core/registry.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/analysis_json.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/diagram_generator.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/file_coverage.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/incremental_types.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/incremental_updater.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/io_utils.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/manifest.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/run_context.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/diagram_analysis/version.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/duckdb_crud.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/github_action.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/circular_deps.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/cohesion.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/coupling.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/function_size.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/god_class.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/inheritance.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/instability.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/checks/unused_code_diagnostics.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/models.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health/runner.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/health_main.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/logging_config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/callbacks.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/context.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/mixin.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/paths.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/stats.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/monitoring/writers.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/html.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/html_template.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/markdown.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/mdx.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/output_generators/sphinx.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/change_detector.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/errors.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/git_diff.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/ignore.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/repo_utils/method_diff.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/setup.cfg +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/analysis_cache.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/analysis_result.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/cluster_change_analyzer.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/cluster_relations.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/go_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/java_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/php_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/python_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/call_graph_builder.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/edge_build_context.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/edge_builder.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/hierarchy_builder.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/language_adapter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/lsp_client.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/lsp_constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/models.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/progress.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/protocols.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/result_converter.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/source_inspector.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/symbol_table.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/utils.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/git_diff_analyzer.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/graph.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/incremental_orchestrator.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/java_config_scanner.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/java_utils.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/lsp_client/__init__.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/lsp_client/diagnostics.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/node.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/programming_language.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/reference_resolve_mixin.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/scanner.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/typescript_config_scanner.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_github_action.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_install.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_logging_config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_main.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_pyproject_packages.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_tool_registry.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_user_config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_vscode_constants.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_windows_compatibility.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/tests/test_windows_encoding.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/user_config.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/utils.py +0 -0
- {codeboarding-0.10.1 → codeboarding-0.10.2}/vscode_constants.py +0 -0
|
@@ -16,8 +16,11 @@ from agents.agent_responses import (
|
|
|
16
16
|
from constants import MIN_CLUSTERS_THRESHOLD
|
|
17
17
|
from static_analyzer.analysis_result import StaticAnalysisResults
|
|
18
18
|
from static_analyzer.cluster_helpers import (
|
|
19
|
+
MAX_LLM_CLUSTERS,
|
|
20
|
+
enforce_cross_language_budget,
|
|
19
21
|
get_all_cluster_ids,
|
|
20
22
|
get_files_for_cluster_ids,
|
|
23
|
+
merge_clusters,
|
|
21
24
|
)
|
|
22
25
|
from static_analyzer.cluster_relations import (
|
|
23
26
|
build_component_relations,
|
|
@@ -250,7 +253,6 @@ class ClusterMethodsMixin:
|
|
|
250
253
|
abs_path = os.path.join(self.repo_dir, f) if not os.path.isabs(f) else f
|
|
251
254
|
assigned_file_set.add(abs_path)
|
|
252
255
|
|
|
253
|
-
result_parts = []
|
|
254
256
|
cluster_results: dict[str, ClusterResult] = {}
|
|
255
257
|
subgraph_cfgs: dict[str, CallGraph] = {}
|
|
256
258
|
|
|
@@ -266,15 +268,33 @@ class ClusterMethodsMixin:
|
|
|
266
268
|
# Calculate clusters for the subgraph
|
|
267
269
|
sub_cluster_result = sub_cfg.cluster()
|
|
268
270
|
|
|
271
|
+
# Merge into super-clusters if too many (same limit as AbstractionAgent)
|
|
272
|
+
if len(sub_cluster_result.clusters) > MAX_LLM_CLUSTERS:
|
|
273
|
+
n_before = len(sub_cluster_result.clusters)
|
|
274
|
+
sub_cluster_result = merge_clusters(sub_cluster_result, sub_cfg.to_networkx(), MAX_LLM_CLUSTERS)
|
|
275
|
+
logger.info(
|
|
276
|
+
f"[DetailsAgent] Subgraph for '{component.name}': "
|
|
277
|
+
f"merged {n_before} -> {len(sub_cluster_result.clusters)} super-clusters"
|
|
278
|
+
)
|
|
279
|
+
|
|
269
280
|
# Expand to method-level if insufficient clusters
|
|
270
281
|
sub_cluster_result = self._expand_to_method_level_clusters(sub_cfg, sub_cluster_result)
|
|
271
282
|
cluster_results[lang] = sub_cluster_result
|
|
272
283
|
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
284
|
+
# Cross-language: enforce combined budget and unique IDs
|
|
285
|
+
if len(cluster_results) > 1:
|
|
286
|
+
cfg_nx = {lang: subgraph_cfgs[lang].to_networkx() for lang in cluster_results}
|
|
287
|
+
enforce_cross_language_budget(cluster_results, cfg_nx)
|
|
288
|
+
|
|
289
|
+
result_parts = []
|
|
290
|
+
for lang in self.static_analysis.get_languages():
|
|
291
|
+
if lang not in cluster_results:
|
|
292
|
+
continue
|
|
293
|
+
cluster_str = subgraph_cfgs[lang].to_cluster_string(cluster_result=cluster_results[lang])
|
|
294
|
+
if cluster_str.strip() and cluster_str not in ("empty", "none", "No clusters found."):
|
|
295
|
+
result_parts.append(f"\n## {lang.capitalize()} - Component CFG\n")
|
|
296
|
+
result_parts.append(cluster_str)
|
|
297
|
+
result_parts.append("\n")
|
|
278
298
|
|
|
279
299
|
result = "".join(result_parts)
|
|
280
300
|
|
|
@@ -46,7 +46,6 @@ class MetaAgent(CodeBoardingAgent):
|
|
|
46
46
|
)
|
|
47
47
|
|
|
48
48
|
self._meta_cache = MetaCache(repo_dir=repo_dir, ignore_manager=self.ignore_manager)
|
|
49
|
-
self._cache = self._meta_cache # Backward-compatible alias for tests/callers.
|
|
50
49
|
|
|
51
50
|
@trace
|
|
52
51
|
def analyze_project_metadata(self, skip_cache: bool = False) -> MetaAnalysisInsights:
|
|
@@ -14,12 +14,15 @@ import requests
|
|
|
14
14
|
|
|
15
15
|
from tool_registry import (
|
|
16
16
|
TOOL_REGISTRY,
|
|
17
|
+
ProgressCallback,
|
|
17
18
|
ToolKind,
|
|
19
|
+
_acquire_lock,
|
|
18
20
|
_write_manifest,
|
|
19
21
|
get_servers_dir,
|
|
20
22
|
install_archive_tool,
|
|
21
23
|
install_native_tools,
|
|
22
24
|
install_node_tools,
|
|
25
|
+
needs_install,
|
|
23
26
|
npm_subprocess_env,
|
|
24
27
|
platform_bin_dir,
|
|
25
28
|
preferred_node_path,
|
|
@@ -207,13 +210,13 @@ def get_platform_bin_dir(servers_dir: Path) -> Path:
|
|
|
207
210
|
return platform_bin_dir(servers_dir)
|
|
208
211
|
|
|
209
212
|
|
|
210
|
-
def install_node_servers(target_dir: Path):
|
|
213
|
+
def install_node_servers(target_dir: Path, on_progress: ProgressCallback | None = None):
|
|
211
214
|
"""Install Node.js based servers (TypeScript, Pyright) using npm in target_dir."""
|
|
212
215
|
print("Step: Node.js servers installation started")
|
|
213
216
|
target_dir.mkdir(parents=True, exist_ok=True)
|
|
214
217
|
|
|
215
218
|
node_deps = [d for d in TOOL_REGISTRY if d.kind is ToolKind.NODE]
|
|
216
|
-
install_node_tools(target_dir, node_deps)
|
|
219
|
+
install_node_tools(target_dir, node_deps, on_progress=on_progress)
|
|
217
220
|
|
|
218
221
|
# Verify the installation
|
|
219
222
|
ts_lsp_path = target_dir / "node_modules" / ".bin" / "typescript-language-server"
|
|
@@ -369,11 +372,11 @@ def resolve_missing_vcpp(auto_install_vcpp: bool = False) -> bool:
|
|
|
369
372
|
return False
|
|
370
373
|
|
|
371
374
|
|
|
372
|
-
def download_binaries(target_dir: Path, auto_install_vcpp: bool = False):
|
|
375
|
+
def download_binaries(target_dir: Path, auto_install_vcpp: bool = False, on_progress: ProgressCallback | None = None):
|
|
373
376
|
"""Download tokei and gopls binaries from the latest GitHub release."""
|
|
374
377
|
print("Step: Binary download started")
|
|
375
378
|
native_deps = [d for d in TOOL_REGISTRY if d.kind is ToolKind.NATIVE]
|
|
376
|
-
install_native_tools(target_dir, native_deps)
|
|
379
|
+
install_native_tools(target_dir, native_deps, on_progress=on_progress)
|
|
377
380
|
|
|
378
381
|
# Verify downloaded binaries actually work (catch missing DLL issues on Windows)
|
|
379
382
|
if platform.system() == "Windows":
|
|
@@ -411,12 +414,12 @@ def download_binaries(target_dir: Path, auto_install_vcpp: bool = False):
|
|
|
411
414
|
print("Step: Binary download finished")
|
|
412
415
|
|
|
413
416
|
|
|
414
|
-
def download_jdtls(target_dir: Path):
|
|
417
|
+
def download_jdtls(target_dir: Path, on_progress: ProgressCallback | None = None):
|
|
415
418
|
"""Download and extract JDTLS from the latest GitHub release."""
|
|
416
419
|
print("Step: JDTLS download started")
|
|
417
420
|
archive_deps = [d for d in TOOL_REGISTRY if d.kind is ToolKind.ARCHIVE]
|
|
418
421
|
for dep in archive_deps:
|
|
419
|
-
install_archive_tool(target_dir, dep)
|
|
422
|
+
install_archive_tool(target_dir, dep, on_progress=on_progress)
|
|
420
423
|
|
|
421
424
|
print("Step: JDTLS download finished")
|
|
422
425
|
return True
|
|
@@ -530,27 +533,79 @@ def print_language_support_summary(npm_available: bool, target_dir: Path):
|
|
|
530
533
|
print(f" reason: {reason}")
|
|
531
534
|
|
|
532
535
|
|
|
536
|
+
def ensure_tools(
|
|
537
|
+
auto_install_npm: bool = False,
|
|
538
|
+
auto_install_vcpp: bool = False,
|
|
539
|
+
on_progress: ProgressCallback | None = None,
|
|
540
|
+
) -> None:
|
|
541
|
+
"""Install tools to ~/.codeboarding/servers/ if needed. No-op if already current.
|
|
542
|
+
|
|
543
|
+
Uses a file lock so that concurrent instances (multiple VSCode windows)
|
|
544
|
+
don't corrupt binaries by downloading simultaneously.
|
|
545
|
+
|
|
546
|
+
Args:
|
|
547
|
+
on_progress: Optional callback invoked as (tool_name, step, total) during downloads.
|
|
548
|
+
"""
|
|
549
|
+
servers_dir = get_servers_dir()
|
|
550
|
+
servers_dir.mkdir(parents=True, exist_ok=True)
|
|
551
|
+
lock_path = servers_dir / ".download.lock"
|
|
552
|
+
|
|
553
|
+
with open(lock_path, "w") as lock_fd:
|
|
554
|
+
_acquire_lock(lock_fd)
|
|
555
|
+
|
|
556
|
+
if not needs_install():
|
|
557
|
+
return
|
|
558
|
+
|
|
559
|
+
run_install(
|
|
560
|
+
target_dir=servers_dir,
|
|
561
|
+
auto_install_npm=auto_install_npm,
|
|
562
|
+
auto_install_vcpp=auto_install_vcpp,
|
|
563
|
+
on_progress=on_progress,
|
|
564
|
+
)
|
|
565
|
+
_write_manifest()
|
|
566
|
+
|
|
567
|
+
|
|
533
568
|
def run_install(
|
|
534
569
|
target_dir: Path | None = None,
|
|
535
570
|
auto_install_npm: bool = False,
|
|
536
571
|
auto_install_vcpp: bool = False,
|
|
572
|
+
on_progress: ProgressCallback | None = None,
|
|
537
573
|
) -> None:
|
|
538
574
|
"""Core installation logic — callable programmatically or via CLI.
|
|
539
575
|
|
|
540
576
|
Downloads language server binaries to target_dir (defaults to ~/.codeboarding/servers/).
|
|
541
577
|
Safe to call multiple times; already-installed tools are skipped.
|
|
578
|
+
|
|
579
|
+
The ``on_progress`` callback receives ``(tool_name, step, total)`` where
|
|
580
|
+
step/total count across *all* tool categories (native, node, archive).
|
|
542
581
|
"""
|
|
543
582
|
target = (target_dir or get_servers_dir()).resolve()
|
|
544
583
|
target.mkdir(parents=True, exist_ok=True)
|
|
545
584
|
|
|
546
585
|
ensure_config_template()
|
|
547
586
|
|
|
587
|
+
# Compute a unified total so the caller sees a single progress stream.
|
|
588
|
+
native_count = sum(1 for d in TOOL_REGISTRY if d.kind is ToolKind.NATIVE and d.github_asset_template)
|
|
589
|
+
node_deps = [d for d in TOOL_REGISTRY if d.kind is ToolKind.NODE]
|
|
590
|
+
archive_count = sum(1 for d in TOOL_REGISTRY if d.kind is ToolKind.ARCHIVE)
|
|
548
591
|
npm_available = resolve_npm_availability(auto_install_npm=auto_install_npm, target_dir=target)
|
|
592
|
+
total_steps = native_count + (1 if npm_available and node_deps else 0) + archive_count
|
|
593
|
+
|
|
594
|
+
step = 0
|
|
595
|
+
|
|
596
|
+
def unified_progress(name: str, _i: int, _t: int) -> None:
|
|
597
|
+
nonlocal step
|
|
598
|
+
step += 1
|
|
599
|
+
if on_progress:
|
|
600
|
+
on_progress(name, step, total_steps)
|
|
601
|
+
|
|
602
|
+
tracker = unified_progress if on_progress else None
|
|
603
|
+
|
|
549
604
|
if npm_available:
|
|
550
|
-
install_node_servers(target)
|
|
605
|
+
install_node_servers(target, on_progress=tracker)
|
|
551
606
|
|
|
552
|
-
download_binaries(target, auto_install_vcpp=auto_install_vcpp)
|
|
553
|
-
download_jdtls(target)
|
|
607
|
+
download_binaries(target, auto_install_vcpp=auto_install_vcpp, on_progress=tracker)
|
|
608
|
+
download_jdtls(target, on_progress=tracker)
|
|
554
609
|
install_pre_commit_hooks()
|
|
555
610
|
print_language_support_summary(npm_available, target)
|
|
556
611
|
|
|
@@ -17,6 +17,8 @@ from diagram_analysis.io_utils import load_full_analysis, save_sub_analysis
|
|
|
17
17
|
from logging_config import setup_logging
|
|
18
18
|
from monitoring import monitor_execution
|
|
19
19
|
from monitoring.paths import get_monitoring_run_dir
|
|
20
|
+
from install import ensure_tools
|
|
21
|
+
from tool_registry import needs_install
|
|
20
22
|
from output_generators.markdown import generate_markdown_file
|
|
21
23
|
from repo_utils import (
|
|
22
24
|
clone_repository,
|
|
@@ -473,8 +475,6 @@ Examples:
|
|
|
473
475
|
if args.binary_location:
|
|
474
476
|
update_config(args.binary_location)
|
|
475
477
|
else:
|
|
476
|
-
from tool_registry import ensure_tools, needs_install
|
|
477
|
-
|
|
478
478
|
if needs_install():
|
|
479
479
|
logger.info("First run: downloading language server binaries to ~/.codeboarding/servers/ ...")
|
|
480
480
|
ensure_tools(auto_install_npm=True, auto_install_vcpp=True)
|
|
@@ -88,32 +88,55 @@ def build_all_cluster_results(static_analysis: StaticAnalysisResults) -> dict[st
|
|
|
88
88
|
# within MAX_LLM_CLUSTERS by proportionally reducing per-language counts,
|
|
89
89
|
# then re-index IDs so they don't overlap across languages.
|
|
90
90
|
if len(cluster_results) > 1:
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
# Proportionally allocate budget, minimum 2 per language
|
|
94
|
-
for lang in list(cluster_results.keys()):
|
|
95
|
-
cr = cluster_results[lang]
|
|
96
|
-
lang_count = len(cr.clusters)
|
|
97
|
-
lang_target = max(2, round(MAX_LLM_CLUSTERS * lang_count / total_clusters))
|
|
98
|
-
if lang_count > lang_target:
|
|
99
|
-
cfg = static_analysis.get_cfg(lang)
|
|
100
|
-
logger.info(
|
|
101
|
-
f"[SuperCluster] {lang}: reducing {lang_count} -> {lang_target} (cross-language budget)"
|
|
102
|
-
)
|
|
103
|
-
cluster_results[lang] = merge_clusters(cr, cfg.to_networkx(), lang_target)
|
|
104
|
-
|
|
105
|
-
# Re-index so IDs don't overlap across languages
|
|
106
|
-
offset = 0
|
|
107
|
-
for lang in sorted(cluster_results.keys()):
|
|
108
|
-
cr = cluster_results[lang]
|
|
109
|
-
if offset > 0:
|
|
110
|
-
cluster_results[lang] = _reindex_cluster_result(cr, offset)
|
|
111
|
-
logger.info(f"[ReIndex] {lang}: offset IDs by +{offset} (now {offset + 1}-{offset + len(cr.clusters)})")
|
|
112
|
-
offset += len(cr.clusters)
|
|
91
|
+
cfg_graphs = {lang: static_analysis.get_cfg(lang).to_networkx() for lang in cluster_results}
|
|
92
|
+
enforce_cross_language_budget(cluster_results, cfg_graphs)
|
|
113
93
|
|
|
114
94
|
return cluster_results
|
|
115
95
|
|
|
116
96
|
|
|
97
|
+
def enforce_cross_language_budget(
|
|
98
|
+
cluster_results: dict[str, ClusterResult],
|
|
99
|
+
cfg_graphs: dict[str, nx.DiGraph],
|
|
100
|
+
target: int = MAX_LLM_CLUSTERS,
|
|
101
|
+
) -> None:
|
|
102
|
+
"""Enforce a combined cluster budget across languages and re-index IDs.
|
|
103
|
+
|
|
104
|
+
Mutates *cluster_results* in place:
|
|
105
|
+
1. If the combined cluster count exceeds *target*, proportionally reduce
|
|
106
|
+
each language's count (minimum 2 per language) via ``merge_clusters``.
|
|
107
|
+
2. Re-index cluster IDs with per-language offsets so they form a unique,
|
|
108
|
+
non-overlapping namespace (required by downstream code that maps
|
|
109
|
+
cluster_id -> component in a single dict).
|
|
110
|
+
|
|
111
|
+
Args:
|
|
112
|
+
cluster_results: Language -> ClusterResult mapping (mutated in place).
|
|
113
|
+
cfg_graphs: Language -> networkx DiGraph for each language (needed by
|
|
114
|
+
``merge_clusters`` when reducing).
|
|
115
|
+
target: Maximum total clusters across all languages.
|
|
116
|
+
"""
|
|
117
|
+
if len(cluster_results) <= 1:
|
|
118
|
+
return
|
|
119
|
+
|
|
120
|
+
total_clusters = sum(len(cr.clusters) for cr in cluster_results.values())
|
|
121
|
+
if total_clusters > target:
|
|
122
|
+
for lang in list(cluster_results.keys()):
|
|
123
|
+
cr = cluster_results[lang]
|
|
124
|
+
lang_count = len(cr.clusters)
|
|
125
|
+
lang_target = max(2, round(target * lang_count / total_clusters))
|
|
126
|
+
if lang_count > lang_target:
|
|
127
|
+
logger.info(f"[SuperCluster] {lang}: reducing {lang_count} -> {lang_target} (cross-language budget)")
|
|
128
|
+
cluster_results[lang] = merge_clusters(cr, cfg_graphs[lang], lang_target)
|
|
129
|
+
|
|
130
|
+
# Re-index so IDs don't overlap across languages
|
|
131
|
+
offset = 0
|
|
132
|
+
for lang in sorted(cluster_results.keys()):
|
|
133
|
+
cr = cluster_results[lang]
|
|
134
|
+
if offset > 0:
|
|
135
|
+
cluster_results[lang] = reindex_cluster_result(cr, offset)
|
|
136
|
+
logger.info(f"[ReIndex] {lang}: offset IDs by +{offset} (now {offset + 1}-{offset + len(cr.clusters)})")
|
|
137
|
+
offset += len(cr.clusters)
|
|
138
|
+
|
|
139
|
+
|
|
117
140
|
# ---------------------------------------------------------------------------
|
|
118
141
|
# Meta-graph construction
|
|
119
142
|
# ---------------------------------------------------------------------------
|
|
@@ -267,7 +290,7 @@ def _find_nearest_by_file_overlap(
|
|
|
267
290
|
return best_idx
|
|
268
291
|
|
|
269
292
|
|
|
270
|
-
def
|
|
293
|
+
def reindex_cluster_result(cluster_result: ClusterResult, offset: int) -> ClusterResult:
|
|
271
294
|
"""Re-index all cluster IDs in a ClusterResult by adding an offset.
|
|
272
295
|
|
|
273
296
|
Args:
|
|
@@ -18,19 +18,30 @@ import os
|
|
|
18
18
|
import platform
|
|
19
19
|
import shutil
|
|
20
20
|
import subprocess
|
|
21
|
+
import sys
|
|
21
22
|
import tarfile
|
|
23
|
+
import time
|
|
24
|
+
from collections.abc import Callable
|
|
22
25
|
from copy import deepcopy
|
|
23
26
|
from dataclasses import dataclass, field
|
|
24
27
|
from enum import StrEnum
|
|
25
28
|
from pathlib import Path
|
|
26
29
|
from typing import Any, cast
|
|
27
30
|
|
|
31
|
+
if sys.platform == "win32":
|
|
32
|
+
import msvcrt
|
|
33
|
+
else:
|
|
34
|
+
import fcntl
|
|
35
|
+
|
|
28
36
|
import requests
|
|
29
37
|
|
|
30
38
|
from vscode_constants import VSCODE_CONFIG, find_runnable
|
|
31
39
|
|
|
32
40
|
logger = logging.getLogger(__name__)
|
|
33
41
|
|
|
42
|
+
# Callback type for reporting download progress: (tool_name, current_step, total_steps)
|
|
43
|
+
ProgressCallback = Callable[[str, int, int], None]
|
|
44
|
+
|
|
34
45
|
GITHUB_REPO = "CodeBoarding/CodeBoarding"
|
|
35
46
|
|
|
36
47
|
_PLATFORM_SUFFIX = {
|
|
@@ -292,18 +303,31 @@ def needs_install() -> bool:
|
|
|
292
303
|
return not has_required_tools(get_servers_dir())
|
|
293
304
|
|
|
294
305
|
|
|
295
|
-
def
|
|
296
|
-
"""
|
|
297
|
-
if
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
306
|
+
def _acquire_lock(lock_fd: Any) -> None:
|
|
307
|
+
"""Acquire an exclusive file lock, logging if we have to wait."""
|
|
308
|
+
if sys.platform == "win32":
|
|
309
|
+
# msvcrt.LK_LOCK only retries for ~10 s which is too short for tool
|
|
310
|
+
# downloads. Poll with LK_NBLCK every 2 s instead — no hard timeout.
|
|
311
|
+
try:
|
|
312
|
+
msvcrt.locking(lock_fd.fileno(), msvcrt.LK_NBLCK, 1)
|
|
313
|
+
except OSError:
|
|
314
|
+
logger.info("Another instance is downloading tools, waiting...")
|
|
315
|
+
print("Waiting for another instance to finish downloading tools...", flush=True, file=sys.stderr)
|
|
316
|
+
while True:
|
|
317
|
+
time.sleep(2)
|
|
318
|
+
try:
|
|
319
|
+
msvcrt.locking(lock_fd.fileno(), msvcrt.LK_NBLCK, 1)
|
|
320
|
+
break
|
|
321
|
+
except OSError:
|
|
322
|
+
continue
|
|
323
|
+
else:
|
|
324
|
+
# fcntl.LOCK_EX blocks indefinitely — exactly what we want.
|
|
325
|
+
try:
|
|
326
|
+
fcntl.flock(lock_fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
327
|
+
except BlockingIOError:
|
|
328
|
+
logger.info("Another instance is downloading tools, waiting...")
|
|
329
|
+
print("Waiting for another instance to finish downloading tools...", flush=True, file=sys.stderr)
|
|
330
|
+
fcntl.flock(lock_fd, fcntl.LOCK_EX)
|
|
307
331
|
|
|
308
332
|
|
|
309
333
|
def build_config() -> dict[str, Any]:
|
|
@@ -461,19 +485,36 @@ def get_latest_release_tag() -> str:
|
|
|
461
485
|
|
|
462
486
|
|
|
463
487
|
def download_asset(tag: str, asset_name: str, destination: Path) -> bool:
|
|
464
|
-
"""Download a GitHub release asset to destination. Returns True on success.
|
|
488
|
+
"""Download a GitHub release asset to destination. Returns True on success.
|
|
489
|
+
|
|
490
|
+
Writes to a temp file first, then atomically renames to prevent
|
|
491
|
+
corrupt binaries if the download is interrupted.
|
|
492
|
+
"""
|
|
465
493
|
destination.parent.mkdir(parents=True, exist_ok=True)
|
|
494
|
+
temp_dest = destination.with_suffix(destination.suffix + ".download")
|
|
466
495
|
url = f"https://github.com/{GITHUB_REPO}/releases/download/{tag}/{asset_name}"
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
496
|
+
try:
|
|
497
|
+
response = requests.get(url, stream=True, timeout=300, allow_redirects=True)
|
|
498
|
+
response.raise_for_status()
|
|
499
|
+
with open(temp_dest, "wb") as f:
|
|
500
|
+
for chunk in response.iter_content(chunk_size=32768):
|
|
501
|
+
if chunk:
|
|
502
|
+
f.write(chunk)
|
|
503
|
+
if temp_dest.stat().st_size > 0:
|
|
504
|
+
os.replace(temp_dest, destination)
|
|
505
|
+
return True
|
|
506
|
+
temp_dest.unlink(missing_ok=True)
|
|
507
|
+
return False
|
|
508
|
+
except Exception:
|
|
509
|
+
temp_dest.unlink(missing_ok=True)
|
|
510
|
+
raise
|
|
474
511
|
|
|
475
512
|
|
|
476
|
-
def install_native_tools(
|
|
513
|
+
def install_native_tools(
|
|
514
|
+
target_dir: Path,
|
|
515
|
+
deps: list[ToolDependency],
|
|
516
|
+
on_progress: ProgressCallback | None = None,
|
|
517
|
+
) -> None:
|
|
477
518
|
"""Download native binaries from GitHub releases."""
|
|
478
519
|
system = platform.system()
|
|
479
520
|
suffix = _PLATFORM_SUFFIX.get(system)
|
|
@@ -491,8 +532,10 @@ def install_native_tools(target_dir: Path, deps: list[ToolDependency]) -> None:
|
|
|
491
532
|
logger.exception("Could not determine latest release")
|
|
492
533
|
return
|
|
493
534
|
|
|
494
|
-
for
|
|
495
|
-
|
|
535
|
+
downloadable = [d for d in deps if d.github_asset_template]
|
|
536
|
+
for i, dep in enumerate(downloadable, 1):
|
|
537
|
+
if on_progress:
|
|
538
|
+
on_progress(dep.binary_name, i, len(downloadable))
|
|
496
539
|
binary_path = bin_dir / f"{dep.binary_name}{exe_suffix()}"
|
|
497
540
|
if binary_path.exists():
|
|
498
541
|
logger.info(" %s: already installed, skipping", dep.binary_name)
|
|
@@ -511,7 +554,11 @@ def install_native_tools(target_dir: Path, deps: list[ToolDependency]) -> None:
|
|
|
511
554
|
binary_path.unlink(missing_ok=True)
|
|
512
555
|
|
|
513
556
|
|
|
514
|
-
def install_node_tools(
|
|
557
|
+
def install_node_tools(
|
|
558
|
+
target_dir: Path,
|
|
559
|
+
deps: list[ToolDependency],
|
|
560
|
+
on_progress: ProgressCallback | None = None,
|
|
561
|
+
) -> None:
|
|
515
562
|
"""Install Node.js tools via npm."""
|
|
516
563
|
npm_command = preferred_npm_command(target_dir)
|
|
517
564
|
if not npm_command:
|
|
@@ -527,6 +574,8 @@ def install_node_tools(target_dir: Path, deps: list[ToolDependency]) -> None:
|
|
|
527
574
|
return
|
|
528
575
|
|
|
529
576
|
env = npm_subprocess_env(target_dir)
|
|
577
|
+
if on_progress:
|
|
578
|
+
on_progress("npm packages", 1, 1)
|
|
530
579
|
logger.info("Installing Node.js packages: %s", all_packages)
|
|
531
580
|
try:
|
|
532
581
|
if not (target_dir / "package.json").exists():
|
|
@@ -548,11 +597,18 @@ def install_node_tools(target_dir: Path, deps: list[ToolDependency]) -> None:
|
|
|
548
597
|
logger.exception("Node.js package installation failed")
|
|
549
598
|
|
|
550
599
|
|
|
551
|
-
def install_archive_tool(
|
|
600
|
+
def install_archive_tool(
|
|
601
|
+
target_dir: Path,
|
|
602
|
+
dep: ToolDependency,
|
|
603
|
+
on_progress: ProgressCallback | None = None,
|
|
604
|
+
) -> None:
|
|
552
605
|
"""Download and extract an archive tool."""
|
|
553
606
|
assert dep.archive_asset, f"{dep.key}: archive_asset required for archive tools"
|
|
554
607
|
assert dep.archive_subdir, f"{dep.key}: archive_subdir required for archive tools"
|
|
555
608
|
|
|
609
|
+
if on_progress:
|
|
610
|
+
on_progress(dep.key, 1, 1)
|
|
611
|
+
|
|
556
612
|
extract_dir = target_dir / "bin" / dep.archive_subdir
|
|
557
613
|
if extract_dir.exists() and (extract_dir / "plugins").is_dir():
|
|
558
614
|
logger.info("%s already installed", dep.key)
|
|
@@ -575,3 +631,5 @@ def install_archive_tool(target_dir: Path, dep: ToolDependency) -> None:
|
|
|
575
631
|
except Exception:
|
|
576
632
|
logger.exception("%s installation failed", dep.key)
|
|
577
633
|
archive_path.unlink(missing_ok=True)
|
|
634
|
+
logger.exception("%s installation failed", dep.key)
|
|
635
|
+
archive_path.unlink(missing_ok=True)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/python_adapter.py
RENAMED
|
File without changes
|
{codeboarding-0.10.1 → codeboarding-0.10.2}/static_analyzer/engine/adapters/typescript_adapter.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|