codeboarding 0.10.2__tar.gz → 0.10.3__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.
Files changed (171) hide show
  1. {codeboarding-0.10.2/codeboarding.egg-info → codeboarding-0.10.3}/PKG-INFO +2 -1
  2. {codeboarding-0.10.2 → codeboarding-0.10.3}/README.md +4 -2
  3. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/agent.py +5 -0
  4. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/agent_responses.py +5 -0
  5. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/llm_config.py +2 -2
  6. {codeboarding-0.10.2 → codeboarding-0.10.3/codeboarding.egg-info}/PKG-INFO +2 -1
  7. {codeboarding-0.10.2 → codeboarding-0.10.3}/codeboarding.egg-info/SOURCES.txt +10 -3
  8. {codeboarding-0.10.2 → codeboarding-0.10.3}/codeboarding.egg-info/requires.txt +1 -0
  9. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/__init__.py +0 -1
  10. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/diagram_generator.py +0 -27
  11. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/incremental_updater.py +80 -19
  12. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/unused_code_diagnostics.py +13 -0
  13. {codeboarding-0.10.2 → codeboarding-0.10.3}/install.py +206 -68
  14. {codeboarding-0.10.2 → codeboarding-0.10.3}/pyproject.toml +6 -3
  15. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/ignore.py +9 -2
  16. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/__init__.py +134 -11
  17. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/analysis_cache.py +2 -0
  18. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/constants.py +8 -10
  19. codeboarding-0.10.3/static_analyzer/csharp_config_scanner.py +96 -0
  20. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/__init__.py +4 -0
  21. codeboarding-0.10.3/static_analyzer/engine/adapters/csharp_adapter.py +222 -0
  22. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/go_adapter.py +15 -0
  23. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/java_adapter.py +14 -9
  24. codeboarding-0.10.3/static_analyzer/engine/adapters/rust_adapter.py +189 -0
  25. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/call_graph_builder.py +50 -40
  26. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/language_adapter.py +79 -0
  27. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/lsp_client.py +125 -18
  28. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/result_converter.py +2 -1
  29. codeboarding-0.10.3/static_analyzer/engine/utils.py +68 -0
  30. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/graph.py +68 -8
  31. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/incremental_orchestrator.py +1 -1
  32. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/java_utils.py +18 -1
  33. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/node.py +2 -0
  34. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_install.py +67 -0
  35. codeboarding-0.10.3/tests/test_registry_coverage.py +396 -0
  36. codeboarding-0.10.3/tests/test_tool_registry.py +1647 -0
  37. codeboarding-0.10.3/tests/test_windows_compatibility.py +61 -0
  38. codeboarding-0.10.3/tool_registry/__init__.py +72 -0
  39. codeboarding-0.10.3/tool_registry/installers.py +628 -0
  40. codeboarding-0.10.3/tool_registry/manifest.py +347 -0
  41. codeboarding-0.10.3/tool_registry/paths.py +264 -0
  42. codeboarding-0.10.3/tool_registry/registry.py +274 -0
  43. {codeboarding-0.10.2 → codeboarding-0.10.3}/vscode_constants.py +19 -0
  44. codeboarding-0.10.2/diagram_analysis/manifest.py +0 -153
  45. codeboarding-0.10.2/static_analyzer/engine/utils.py +0 -22
  46. codeboarding-0.10.2/tests/test_tool_registry.py +0 -94
  47. codeboarding-0.10.2/tests/test_windows_compatibility.py +0 -53
  48. codeboarding-0.10.2/tool_registry.py +0 -635
  49. {codeboarding-0.10.2 → codeboarding-0.10.3}/LICENSE +0 -0
  50. {codeboarding-0.10.2 → codeboarding-0.10.3}/PYPI.md +0 -0
  51. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/__init__.py +0 -0
  52. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/abstraction_agent.py +0 -0
  53. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/change_status.py +0 -0
  54. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/cluster_methods_mixin.py +0 -0
  55. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/constants.py +0 -0
  56. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/dependency_discovery.py +0 -0
  57. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/details_agent.py +0 -0
  58. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/meta_agent.py +0 -0
  59. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/planner_agent.py +0 -0
  60. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/__init__.py +0 -0
  61. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/abstract_prompt_factory.py +0 -0
  62. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/claude_prompts.py +0 -0
  63. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/deepseek_prompts.py +0 -0
  64. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/gemini_flash_prompts.py +0 -0
  65. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/glm_prompts.py +0 -0
  66. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/gpt_prompts.py +0 -0
  67. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/kimi_prompts.py +0 -0
  68. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/prompts/prompt_factory.py +0 -0
  69. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/__init__.py +0 -0
  70. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/base.py +0 -0
  71. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/get_external_deps.py +0 -0
  72. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/get_method_invocations.py +0 -0
  73. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_cfg.py +0 -0
  74. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_docs.py +0 -0
  75. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_file.py +0 -0
  76. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_file_structure.py +0 -0
  77. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_git_diff.py +0 -0
  78. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_packages.py +0 -0
  79. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_source.py +0 -0
  80. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/read_structure.py +0 -0
  81. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/tools/toolkit.py +0 -0
  82. {codeboarding-0.10.2 → codeboarding-0.10.3}/agents/validation.py +0 -0
  83. {codeboarding-0.10.2 → codeboarding-0.10.3}/caching/__init__.py +0 -0
  84. {codeboarding-0.10.2 → codeboarding-0.10.3}/caching/cache.py +0 -0
  85. {codeboarding-0.10.2 → codeboarding-0.10.3}/caching/details_cache.py +0 -0
  86. {codeboarding-0.10.2 → codeboarding-0.10.3}/caching/meta_cache.py +0 -0
  87. {codeboarding-0.10.2 → codeboarding-0.10.3}/codeboarding.egg-info/dependency_links.txt +0 -0
  88. {codeboarding-0.10.2 → codeboarding-0.10.3}/codeboarding.egg-info/entry_points.txt +0 -0
  89. {codeboarding-0.10.2 → codeboarding-0.10.3}/codeboarding.egg-info/top_level.txt +0 -0
  90. {codeboarding-0.10.2 → codeboarding-0.10.3}/constants.py +0 -0
  91. {codeboarding-0.10.2 → codeboarding-0.10.3}/core/__init__.py +0 -0
  92. {codeboarding-0.10.2 → codeboarding-0.10.3}/core/plugin_loader.py +0 -0
  93. {codeboarding-0.10.2 → codeboarding-0.10.3}/core/protocols.py +0 -0
  94. {codeboarding-0.10.2 → codeboarding-0.10.3}/core/registry.py +0 -0
  95. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/analysis_json.py +0 -0
  96. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/file_coverage.py +0 -0
  97. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/incremental_types.py +0 -0
  98. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/io_utils.py +0 -0
  99. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/run_context.py +0 -0
  100. {codeboarding-0.10.2 → codeboarding-0.10.3}/diagram_analysis/version.py +0 -0
  101. {codeboarding-0.10.2 → codeboarding-0.10.3}/duckdb_crud.py +0 -0
  102. {codeboarding-0.10.2 → codeboarding-0.10.3}/github_action.py +0 -0
  103. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/__init__.py +0 -0
  104. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/__init__.py +0 -0
  105. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/circular_deps.py +0 -0
  106. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/cohesion.py +0 -0
  107. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/coupling.py +0 -0
  108. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/function_size.py +0 -0
  109. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/god_class.py +0 -0
  110. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/inheritance.py +0 -0
  111. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/checks/instability.py +0 -0
  112. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/config.py +0 -0
  113. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/constants.py +0 -0
  114. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/models.py +0 -0
  115. {codeboarding-0.10.2 → codeboarding-0.10.3}/health/runner.py +0 -0
  116. {codeboarding-0.10.2 → codeboarding-0.10.3}/health_main.py +0 -0
  117. {codeboarding-0.10.2 → codeboarding-0.10.3}/logging_config.py +0 -0
  118. {codeboarding-0.10.2 → codeboarding-0.10.3}/main.py +0 -0
  119. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/__init__.py +0 -0
  120. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/callbacks.py +0 -0
  121. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/context.py +0 -0
  122. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/mixin.py +0 -0
  123. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/paths.py +0 -0
  124. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/stats.py +0 -0
  125. {codeboarding-0.10.2 → codeboarding-0.10.3}/monitoring/writers.py +0 -0
  126. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/__init__.py +0 -0
  127. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/html.py +0 -0
  128. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/html_template.py +0 -0
  129. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/markdown.py +0 -0
  130. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/mdx.py +0 -0
  131. {codeboarding-0.10.2 → codeboarding-0.10.3}/output_generators/sphinx.py +0 -0
  132. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/__init__.py +0 -0
  133. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/change_detector.py +0 -0
  134. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/errors.py +0 -0
  135. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/git_diff.py +0 -0
  136. {codeboarding-0.10.2 → codeboarding-0.10.3}/repo_utils/method_diff.py +0 -0
  137. {codeboarding-0.10.2 → codeboarding-0.10.3}/setup.cfg +0 -0
  138. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/analysis_result.py +0 -0
  139. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/cluster_change_analyzer.py +0 -0
  140. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/cluster_helpers.py +0 -0
  141. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/cluster_relations.py +0 -0
  142. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/__init__.py +0 -0
  143. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/php_adapter.py +0 -0
  144. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/python_adapter.py +0 -0
  145. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
  146. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/edge_build_context.py +0 -0
  147. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/edge_builder.py +0 -0
  148. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/hierarchy_builder.py +0 -0
  149. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/lsp_constants.py +0 -0
  150. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/models.py +0 -0
  151. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/progress.py +0 -0
  152. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/protocols.py +0 -0
  153. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/source_inspector.py +0 -0
  154. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/engine/symbol_table.py +0 -0
  155. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/git_diff_analyzer.py +0 -0
  156. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/java_config_scanner.py +0 -0
  157. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/lsp_client/__init__.py +0 -0
  158. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/lsp_client/diagnostics.py +0 -0
  159. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/programming_language.py +0 -0
  160. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/reference_resolve_mixin.py +0 -0
  161. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/scanner.py +0 -0
  162. {codeboarding-0.10.2 → codeboarding-0.10.3}/static_analyzer/typescript_config_scanner.py +0 -0
  163. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_github_action.py +0 -0
  164. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_logging_config.py +0 -0
  165. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_main.py +0 -0
  166. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_pyproject_packages.py +0 -0
  167. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_user_config.py +0 -0
  168. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_vscode_constants.py +0 -0
  169. {codeboarding-0.10.2 → codeboarding-0.10.3}/tests/test_windows_encoding.py +0 -0
  170. {codeboarding-0.10.2 → codeboarding-0.10.3}/user_config.py +0 -0
  171. {codeboarding-0.10.2 → codeboarding-0.10.3}/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -37,6 +37,7 @@ Requires-Dist: markdown>=3.8
37
37
  Requires-Dist: markdown-it-py>=3.0
38
38
  Requires-Dist: markitdown>=0.1
39
39
  Requires-Dist: networkx>=3.4
40
+ Requires-Dist: nodeenv>=1.10.0
40
41
  Requires-Dist: pathspec>=0.12
41
42
  Requires-Dist: pyyaml>=6.0
42
43
  Requires-Dist: regex>=2024.11
@@ -16,6 +16,8 @@ Install the extension from Open VSX.
16
16
  [![Python](https://img.shields.io/badge/Python-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
17
17
  [![Go](https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white)](https://go.dev/)
18
18
  [![PHP](https://img.shields.io/badge/PHP-777BB4?style=flat-square&logo=php&logoColor=white)](https://www.php.net/)
19
+ [![Rust](https://img.shields.io/badge/Rust-000000?style=flat-square&logo=rust&logoColor=white)](https://www.rust-lang.org/)
20
+ [![C#](https://custom-icon-badges.demolab.com/badge/C%23-512BD4.svg?style=flat-square&logo=cshrp&logoColor=white)](https://learn.microsoft.com/en-us/dotnet/csharp/)
19
21
 
20
22
  ## Few use cases:
21
23
 
@@ -91,7 +93,7 @@ codeboarding --local /path/to/repo
91
93
 
92
94
  Output is written to `/path/to/repo/.codeboarding/`.
93
95
 
94
- `python install.py` and `codeboarding-setup` download language server binaries to `~/.codeboarding/servers/`, shared across projects. `npm` is required for Python, TypeScript, JavaScript, and PHP language servers; if it is missing, setup can install it via `nodeenv`.
96
+ `python install.py` and `codeboarding-setup` download language server binaries to `~/.codeboarding/servers/`, shared across projects. Node.js (and its bundled `npm`) is required for the Python, TypeScript, JavaScript, and PHP language servers; if neither `node` nor `CODEBOARDING_NODE_PATH` is set, setup downloads a pinned Node.js runtime into `~/.codeboarding/servers/nodeenv/` automatically.
95
97
 
96
98
  ## Configuration
97
99
 
@@ -141,7 +143,7 @@ python main.py https://github.com/pytorch/pytorch
141
143
 
142
144
  ## Supported stack
143
145
 
144
- - Languages: Python, TypeScript, JavaScript, Java, Go, PHP.
146
+ - Languages: Python, TypeScript, JavaScript, Java, Go, PHP, Rust.
145
147
  - LLM providers: OpenAI, Anthropic, Google, Vercel AI Gateway, AWS Bedrock, Ollama, OpenRouter, and more.
146
148
 
147
149
  ## Examples
@@ -160,6 +160,11 @@ class CodeBoardingAgent(ReferenceResolverMixin, MonitoringMixin):
160
160
  raise
161
161
 
162
162
  except Exception as e:
163
+ # HTTP 404 (e.g. retired model ID) is permanent — retrying won't help.
164
+ if getattr(e, "status_code", None) == 404:
165
+ logger.error(f"Permanent HTTP 404 — not retrying: {type(e).__name__}: {e}")
166
+ raise
167
+
163
168
  # Other errors (network, parsing, etc.) get standard exponential backoff
164
169
  if attempt < max_retries - 1:
165
170
  delay = min(10 * (2**attempt), 120)
@@ -1,6 +1,7 @@
1
1
  import abc
2
2
  import logging
3
3
  from abc import abstractmethod
4
+ from pathlib import PurePosixPath
4
5
  from typing import get_origin, Optional
5
6
 
6
7
  from pydantic import BaseModel, Field
@@ -261,6 +262,10 @@ class AnalysisInsights(LLMBaseModel):
261
262
  relations = "\n".join(cr.llm_str() for cr in self.components_relations)
262
263
  return title + body + relations
263
264
 
265
+ def file_to_component(self) -> dict[str, str]:
266
+ """Build file path -> component_id mapping from root components."""
267
+ return {str(PurePosixPath(fg.file_path)): c.component_id for c in self.components for fg in c.file_methods}
268
+
264
269
 
265
270
  def assign_component_ids(analysis: AnalysisInsights, parent_id: str = "") -> None:
266
271
  """Assign hierarchical component IDs based on sibling index.
@@ -136,7 +136,7 @@ LLM_PROVIDERS = {
136
136
  "anthropic": LLMConfig(
137
137
  chat_class=ChatAnthropic,
138
138
  api_key_env="ANTHROPIC_API_KEY",
139
- agent_model="claude-3-7-sonnet-20250219",
139
+ agent_model="claude-sonnet-4-5-20250929",
140
140
  parsing_model="claude-3-haiku-20240307",
141
141
  llm_type=LLMType.CLAUDE,
142
142
  extra_args={
@@ -160,7 +160,7 @@ LLM_PROVIDERS = {
160
160
  "aws": LLMConfig(
161
161
  chat_class=ChatBedrockConverse,
162
162
  api_key_env="AWS_BEARER_TOKEN_BEDROCK", # Used for existence check
163
- agent_model="us.anthropic.claude-3-7-sonnet-20250219-v1:0",
163
+ agent_model="us.anthropic.claude-sonnet-4-5-20250929-v1:0",
164
164
  parsing_model="us.anthropic.claude-3-haiku-20240307-v1:0",
165
165
  llm_type=LLMType.CLAUDE,
166
166
  extra_args={
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.10.2
3
+ Version: 0.10.3
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -37,6 +37,7 @@ Requires-Dist: markdown>=3.8
37
37
  Requires-Dist: markdown-it-py>=3.0
38
38
  Requires-Dist: markitdown>=0.1
39
39
  Requires-Dist: networkx>=3.4
40
+ Requires-Dist: nodeenv>=1.10.0
40
41
  Requires-Dist: pathspec>=0.12
41
42
  Requires-Dist: pyyaml>=6.0
42
43
  Requires-Dist: regex>=2024.11
@@ -9,7 +9,6 @@ install.py
9
9
  logging_config.py
10
10
  main.py
11
11
  pyproject.toml
12
- tool_registry.py
13
12
  user_config.py
14
13
  utils.py
15
14
  vscode_constants.py
@@ -69,7 +68,6 @@ diagram_analysis/file_coverage.py
69
68
  diagram_analysis/incremental_types.py
70
69
  diagram_analysis/incremental_updater.py
71
70
  diagram_analysis/io_utils.py
72
- diagram_analysis/manifest.py
73
71
  diagram_analysis/run_context.py
74
72
  diagram_analysis/version.py
75
73
  health/__init__.py
@@ -112,6 +110,7 @@ static_analyzer/cluster_change_analyzer.py
112
110
  static_analyzer/cluster_helpers.py
113
111
  static_analyzer/cluster_relations.py
114
112
  static_analyzer/constants.py
113
+ static_analyzer/csharp_config_scanner.py
115
114
  static_analyzer/git_diff_analyzer.py
116
115
  static_analyzer/graph.py
117
116
  static_analyzer/incremental_orchestrator.py
@@ -138,10 +137,12 @@ static_analyzer/engine/source_inspector.py
138
137
  static_analyzer/engine/symbol_table.py
139
138
  static_analyzer/engine/utils.py
140
139
  static_analyzer/engine/adapters/__init__.py
140
+ static_analyzer/engine/adapters/csharp_adapter.py
141
141
  static_analyzer/engine/adapters/go_adapter.py
142
142
  static_analyzer/engine/adapters/java_adapter.py
143
143
  static_analyzer/engine/adapters/php_adapter.py
144
144
  static_analyzer/engine/adapters/python_adapter.py
145
+ static_analyzer/engine/adapters/rust_adapter.py
145
146
  static_analyzer/engine/adapters/typescript_adapter.py
146
147
  static_analyzer/lsp_client/__init__.py
147
148
  static_analyzer/lsp_client/diagnostics.py
@@ -150,8 +151,14 @@ tests/test_install.py
150
151
  tests/test_logging_config.py
151
152
  tests/test_main.py
152
153
  tests/test_pyproject_packages.py
154
+ tests/test_registry_coverage.py
153
155
  tests/test_tool_registry.py
154
156
  tests/test_user_config.py
155
157
  tests/test_vscode_constants.py
156
158
  tests/test_windows_compatibility.py
157
- tests/test_windows_encoding.py
159
+ tests/test_windows_encoding.py
160
+ tool_registry/__init__.py
161
+ tool_registry/installers.py
162
+ tool_registry/manifest.py
163
+ tool_registry/paths.py
164
+ tool_registry/registry.py
@@ -19,6 +19,7 @@ markdown>=3.8
19
19
  markdown-it-py>=3.0
20
20
  markitdown>=0.1
21
21
  networkx>=3.4
22
+ nodeenv>=1.10.0
22
23
  pathspec>=0.12
23
24
  pyyaml>=6.0
24
25
  regex>=2024.11
@@ -1,4 +1,3 @@
1
1
  from .diagram_generator import DiagramGenerator
2
- from .manifest import AnalysisManifest, load_manifest, save_manifest
3
2
  from .run_context import RunContext
4
3
  from agents.llm_config import configure_models
@@ -21,10 +21,6 @@ from diagram_analysis.analysis_json import (
21
21
  )
22
22
  from diagram_analysis.file_coverage import FileCoverage
23
23
  from diagram_analysis.io_utils import save_analysis
24
- from diagram_analysis.manifest import (
25
- build_manifest_from_analysis,
26
- save_manifest,
27
- )
28
24
  from diagram_analysis.version import Version
29
25
  from health.config import initialize_health_dir, load_health_config
30
26
  from health.runner import run_health_checks
@@ -452,31 +448,8 @@ class DiagramGenerator:
452
448
  # Write file_coverage.json
453
449
  self._write_file_coverage()
454
450
 
455
- # Save manifest for incremental updates
456
- self._save_manifest(analysis, expanded_components)
457
-
458
451
  return analysis_path
459
452
 
460
- def _save_manifest(self, analysis: AnalysisInsights, expanded_components: list) -> None:
461
- """Save the analysis manifest for incremental updates."""
462
- try:
463
- repo_state_hash = get_repo_state_hash(self.repo_location)
464
- base_commit = get_git_commit_hash(self.repo_location)
465
-
466
- expanded_names = [c.component_id for c in expanded_components]
467
-
468
- manifest = build_manifest_from_analysis(
469
- analysis=analysis,
470
- repo_state_hash=repo_state_hash,
471
- base_commit=base_commit,
472
- expanded_components=expanded_names,
473
- )
474
-
475
- save_manifest(manifest, self.output_dir)
476
- logger.info(f"Saved manifest with {len(manifest.file_to_component)} file mappings")
477
- except Exception as e:
478
- logger.warning(f"Failed to save manifest: {e}")
479
-
480
453
  def generate_analysis_smart(self) -> Path:
481
454
  """Run full analysis."""
482
455
  return self.generate_analysis()
@@ -18,7 +18,6 @@ from typing import Callable
18
18
  from agents.agent_responses import AnalysisInsights, Component, FileEntry, FileMethodGroup, MethodEntry
19
19
  from agents.change_status import ChangeStatus
20
20
  from diagram_analysis.incremental_types import FileDelta, IncrementalDelta, MethodChange
21
- from diagram_analysis.manifest import AnalysisManifest
22
21
  from repo_utils.change_detector import ChangeSet
23
22
  from repo_utils.method_diff import get_method_statuses_for_file
24
23
 
@@ -35,17 +34,22 @@ class IncrementalUpdater:
35
34
  to ensure consistent behavior with the main analysis pipeline.
36
35
  """
37
36
 
37
+ # Callable that resolves a new file path to a component_id using
38
+ # the current file_to_component mapping.
39
+ ComponentResolver = Callable[[str, dict[str, str]], str]
40
+
38
41
  def __init__(
39
42
  self,
40
43
  analysis: AnalysisInsights,
41
- manifest: AnalysisManifest,
42
44
  symbol_resolver: SymbolResolver,
43
45
  repo_dir: Path,
46
+ component_resolver: ComponentResolver | None = None,
44
47
  ):
45
48
  self.analysis = analysis
46
- self.manifest = manifest
47
49
  self._symbol_resolver = symbol_resolver
48
50
  self._repo_dir = repo_dir
51
+ self._component_resolver = component_resolver
52
+ self._file_to_component = analysis.file_to_component()
49
53
 
50
54
  def _get_current_methods(self, file_path: str) -> list[MethodEntry]:
51
55
  return self._symbol_resolver(file_path)
@@ -59,14 +63,6 @@ class IncrementalUpdater:
59
63
  def _get_previous_active_methods(self, file_path: str) -> dict[str, MethodEntry]:
60
64
  return {qn: m for qn, m in self._get_previous_methods(file_path).items() if m.status != ChangeStatus.DELETED}
61
65
 
62
- def _resolve_component(self, file_path: str, *, register_file: bool = False) -> tuple[str | None, bool]:
63
- component_id = self.manifest.get_component_for_file(file_path)
64
- if component_id is None:
65
- return None, True
66
- if register_file:
67
- self.manifest.add_file(file_path, component_id)
68
- return component_id, False
69
-
70
66
  def _apply_method_diff_statuses(
71
67
  self, file_path: str, current_methods: list[MethodEntry], changes: ChangeSet
72
68
  ) -> None:
@@ -95,7 +91,12 @@ class IncrementalUpdater:
95
91
  register_file: bool,
96
92
  changes: ChangeSet,
97
93
  ) -> tuple[FileDelta, bool]:
98
- component_id, missing = self._resolve_component(file_path, register_file=register_file)
94
+ component_id = self._file_to_component.get(file_path)
95
+ if component_id is None and register_file and self._component_resolver is not None:
96
+ component_id = self._component_resolver(file_path, self._file_to_component)
97
+ if component_id is not None and register_file:
98
+ self._file_to_component[file_path] = component_id
99
+ missing = component_id is None
99
100
 
100
101
  if file_status == ChangeStatus.ADDED:
101
102
  current = self._get_current_methods(file_path)
@@ -105,7 +106,9 @@ class IncrementalUpdater:
105
106
  file_path=file_path,
106
107
  file_status=ChangeStatus.ADDED,
107
108
  component_id=component_id,
108
- added_methods=[self._to_method_change(file_path, m) for m in current],
109
+ added_methods=[
110
+ self._to_method_change(file_path, m, change_type=ChangeStatus.ADDED) for m in current
111
+ ],
109
112
  ),
110
113
  missing,
111
114
  )
@@ -186,7 +189,8 @@ class IncrementalUpdater:
186
189
  Replaces the stored file state with the current unchanged snapshot,
187
190
  removing stale added/deleted/modified statuses from prior incremental updates.
188
191
  """
189
- component_id, missing = self._resolve_component(file_path)
192
+ component_id = self._file_to_component.get(file_path)
193
+ missing = component_id is None
190
194
  current = self._get_current_methods(file_path)
191
195
  for m in current:
192
196
  m.status = ChangeStatus.UNCHANGED
@@ -304,12 +308,66 @@ def _apply_file_delta_to_index(files: dict[str, FileEntry], file_delta: FileDelt
304
308
  existing.methods = _sorted_methods(methods_by_name)
305
309
 
306
310
 
307
- def _sync_component_methods(component: Component, files: dict[str, FileEntry]) -> None:
311
+ def _sync_component_methods(
312
+ component: Component,
313
+ files: dict[str, FileEntry],
314
+ deltas_by_path: dict[str, FileDelta],
315
+ parent_ids: set[str],
316
+ ) -> None:
317
+ """Rebuild component's file_methods, preserving method boundaries.
318
+
319
+ Strategy:
320
+ 1. Collect the qualified names this component originally owned.
321
+ 2. Remove deleted methods from ownership.
322
+ 3. Absorb newly added methods when the component is the primary owner
323
+ (``delta.component_id``) OR is an intermediate ancestor of the
324
+ primary (its ID is a descendant of the primary AND it has its own
325
+ children in ``parent_ids``). Leaf components and siblings that
326
+ don't own the file are unaffected.
327
+ 4. Filter the global files index to only include owned methods.
328
+ """
329
+ owned_qnames: set[str] = set()
330
+
331
+ for group in component.file_methods:
332
+ for method in group.methods:
333
+ owned_qnames.add(method.qualified_name)
334
+
335
+ for file_path, delta in deltas_by_path.items():
336
+ if not component.file_methods:
337
+ continue
338
+ if not any(group.file_path == file_path for group in component.file_methods):
339
+ continue
340
+
341
+ for method in delta.deleted_methods:
342
+ owned_qnames.discard(method.qualified_name)
343
+
344
+ primary_id = delta.component_id or ""
345
+ should_absorb = primary_id == component.component_id or (
346
+ component.component_id.startswith(primary_id + ".") and component.component_id in parent_ids
347
+ )
348
+
349
+ # A component that owned every pre-existing method in the file is a
350
+ # superset owner (e.g. a root component whose children partition its
351
+ # methods). It must absorb new methods so it stays a superset.
352
+ if not should_absorb and delta.added_methods:
353
+ file_entry = files.get(file_path)
354
+ if file_entry is not None:
355
+ added_qnames = {m.qualified_name for m in delta.added_methods}
356
+ pre_existing = {m.qualified_name for m in file_entry.methods} - added_qnames
357
+ if pre_existing and pre_existing <= owned_qnames:
358
+ should_absorb = True
359
+
360
+ if should_absorb:
361
+ for method in delta.added_methods:
362
+ owned_qnames.add(method.qualified_name)
363
+
308
364
  component.file_methods = [
309
365
  FileMethodGroup(
310
366
  file_path=fp,
311
- file_status=entry.file_status,
312
- methods=[m.model_copy(deep=True) for m in entry.methods],
367
+ file_status=entry.file_status if entry else ChangeStatus.UNCHANGED,
368
+ methods=[
369
+ m.model_copy(deep=True) for m in (entry.methods if entry else []) if m.qualified_name in owned_qnames
370
+ ],
313
371
  )
314
372
  for fp in sorted({g.file_path for g in component.file_methods})
315
373
  if (entry := files.get(fp)) is not None
@@ -327,8 +385,11 @@ def apply_delta(
327
385
 
328
386
  files = dict(root.files)
329
387
  component_lookup = _component_lookup(root, sub_analyses)
388
+ parent_ids = set(sub_analyses.keys())
330
389
 
390
+ deltas_by_path: dict[str, FileDelta] = {}
331
391
  for file_delta in delta.file_deltas:
392
+ deltas_by_path[file_delta.file_path] = file_delta
332
393
  _apply_file_delta_to_index(files, file_delta)
333
394
 
334
395
  component = component_lookup.get(file_delta.component_id or "")
@@ -342,9 +403,9 @@ def apply_delta(
342
403
 
343
404
  root.files = files
344
405
  for component in root.components:
345
- _sync_component_methods(component, files)
406
+ _sync_component_methods(component, files, deltas_by_path, parent_ids)
346
407
 
347
408
  for sub in sub_analyses.values():
348
409
  sub.files = files
349
410
  for component in sub.components:
350
- _sync_component_methods(component, files)
411
+ _sync_component_methods(component, files, deltas_by_path, parent_ids)
@@ -95,6 +95,19 @@ DIAGNOSTIC_CODE_MAPPINGS: dict[str, DeadCodeCategory] = {
95
95
  "no-unused-vars": DeadCodeCategory.UNUSED_VARIABLE,
96
96
  "unused-imports/no-unused-imports": DeadCodeCategory.UNUSED_IMPORT,
97
97
  "@typescript-eslint/no-unused-vars": DeadCodeCategory.UNUSED_VARIABLE,
98
+ # csharp-ls / Roslyn (C#)
99
+ "CS8019": DeadCodeCategory.UNUSED_IMPORT, # Unnecessary using directive
100
+ "CS0168": DeadCodeCategory.UNUSED_VARIABLE, # Variable declared but never used
101
+ "CS0219": DeadCodeCategory.UNUSED_VARIABLE, # Variable assigned but its value is never used
102
+ "CS0169": DeadCodeCategory.DEAD_CODE, # Field is never used
103
+ "CS0414": DeadCodeCategory.DEAD_CODE, # Field is assigned but its value is never used
104
+ "CS0649": DeadCodeCategory.DEAD_CODE, # Field is never assigned and will always have its default value
105
+ "CS0162": DeadCodeCategory.UNREACHABLE_CODE, # Unreachable code detected
106
+ "CS8321": DeadCodeCategory.UNUSED_FUNCTION, # Local function is declared but never used
107
+ "IDE0051": DeadCodeCategory.UNUSED_FUNCTION, # Private member is unused
108
+ "IDE0052": DeadCodeCategory.DEAD_CODE, # Private member can be removed
109
+ "IDE0059": DeadCodeCategory.UNUSED_VARIABLE, # Unnecessary value assignment
110
+ "IDE0060": DeadCodeCategory.UNUSED_PARAMETER, # Remove unused parameter
98
111
  }
99
112
 
100
113
  # Keywords that indicate unused/dead code in diagnostic messages