codeboarding 0.10.3__tar.gz → 0.11.0__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.3/codeboarding.egg-info → codeboarding-0.11.0}/PKG-INFO +21 -9
- {codeboarding-0.10.3 → codeboarding-0.11.0}/PYPI.md +10 -8
- {codeboarding-0.10.3 → codeboarding-0.11.0}/README.md +8 -8
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/abstraction_agent.py +14 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/agent.py +108 -118
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/agent_responses.py +13 -16
- codeboarding-0.11.0/agents/analysis_patcher.py +206 -0
- codeboarding-0.11.0/agents/cluster_budget.py +21 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/cluster_methods_mixin.py +170 -17
- codeboarding-0.11.0/agents/constants.py +38 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/details_agent.py +12 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/llm_config.py +83 -43
- codeboarding-0.11.0/agents/model_capabilities.py +217 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/abstract_prompt_factory.py +8 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/claude_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/deepseek_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/gemini_flash_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/glm_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/gpt_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/kimi_prompts.py +37 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/prompt_factory.py +8 -0
- codeboarding-0.11.0/agents/retry.py +118 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/toolkit.py +0 -8
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/validation.py +12 -29
- {codeboarding-0.10.3 → codeboarding-0.11.0/codeboarding.egg-info}/PKG-INFO +21 -9
- {codeboarding-0.10.3 → codeboarding-0.11.0}/codeboarding.egg-info/SOURCES.txt +32 -6
- {codeboarding-0.10.3 → codeboarding-0.11.0}/codeboarding.egg-info/requires.txt +10 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/codeboarding.egg-info/top_level.txt +2 -0
- codeboarding-0.11.0/codeboarding_cli/__init__.py +1 -0
- codeboarding-0.11.0/codeboarding_cli/bootstrap.py +53 -0
- codeboarding-0.11.0/codeboarding_cli/commands/__init__.py +1 -0
- codeboarding-0.11.0/codeboarding_cli/commands/full_analysis.py +197 -0
- codeboarding-0.11.0/codeboarding_cli/commands/incremental_analysis.py +137 -0
- codeboarding-0.11.0/codeboarding_cli/commands/partial_analysis.py +69 -0
- codeboarding-0.11.0/codeboarding_workflows/__init__.py +14 -0
- codeboarding-0.11.0/codeboarding_workflows/analysis.py +144 -0
- codeboarding-0.11.0/codeboarding_workflows/orchestration.py +48 -0
- codeboarding-0.11.0/codeboarding_workflows/rendering.py +92 -0
- codeboarding-0.11.0/codeboarding_workflows/sources/__init__.py +12 -0
- codeboarding-0.11.0/codeboarding_workflows/sources/local.py +23 -0
- codeboarding-0.11.0/codeboarding_workflows/sources/remote.py +71 -0
- codeboarding-0.11.0/diagram_analysis/__init__.py +22 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/analysis_json.py +146 -115
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/diagram_generator.py +293 -69
- codeboarding-0.11.0/diagram_analysis/ease.py +68 -0
- codeboarding-0.10.3/diagram_analysis/incremental_types.py → codeboarding-0.11.0/diagram_analysis/incremental/delta.py +23 -9
- codeboarding-0.11.0/diagram_analysis/incremental/models.py +220 -0
- codeboarding-0.11.0/diagram_analysis/incremental/payload.py +129 -0
- codeboarding-0.11.0/diagram_analysis/incremental/pipeline.py +264 -0
- codeboarding-0.11.0/diagram_analysis/incremental/semantic_diff.py +557 -0
- codeboarding-0.11.0/diagram_analysis/incremental/trace_planner.py +435 -0
- codeboarding-0.11.0/diagram_analysis/incremental/tracer.py +458 -0
- codeboarding-0.10.3/diagram_analysis/incremental_updater.py → codeboarding-0.11.0/diagram_analysis/incremental/updater.py +174 -125
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/io_utils.py +3 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/run_context.py +3 -0
- codeboarding-0.11.0/diagram_analysis/run_metadata.py +146 -0
- codeboarding-0.11.0/github_action.py +129 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/install.py +1 -1
- {codeboarding-0.10.3 → codeboarding-0.11.0}/logging_config.py +1 -1
- codeboarding-0.11.0/main.py +99 -0
- codeboarding-0.11.0/output_generators/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/pyproject.toml +45 -3
- {codeboarding-0.10.3 → codeboarding-0.11.0}/repo_utils/__init__.py +2 -5
- codeboarding-0.11.0/repo_utils/change_detector.py +311 -0
- codeboarding-0.11.0/repo_utils/diff_parser.py +277 -0
- codeboarding-0.11.0/repo_utils/git_ops.py +283 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/__init__.py +2 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/analysis_result.py +38 -0
- codeboarding-0.11.0/static_analyzer/cfg_skip_planner.py +207 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/constants.py +31 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/csharp_adapter.py +3 -3
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/go_adapter.py +3 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/java_adapter.py +3 -3
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/php_adapter.py +3 -3
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/python_adapter.py +3 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/rust_adapter.py +5 -4
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/typescript_adapter.py +5 -4
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/language_adapter.py +15 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/graph.py +85 -27
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/incremental_orchestrator.py +11 -11
- codeboarding-0.11.0/tests/test_cli_parser.py +70 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_github_action.py +11 -11
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_main.py +212 -218
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_tool_registry.py +10 -2
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_user_config.py +34 -1
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tool_registry/registry.py +4 -3
- {codeboarding-0.10.3 → codeboarding-0.11.0}/user_config.py +23 -6
- {codeboarding-0.10.3 → codeboarding-0.11.0}/utils.py +14 -1
- {codeboarding-0.10.3 → codeboarding-0.11.0}/vscode_constants.py +2 -2
- codeboarding-0.10.3/agents/constants.py +0 -13
- codeboarding-0.10.3/agents/tools/read_git_diff.py +0 -131
- codeboarding-0.10.3/diagram_analysis/__init__.py +0 -3
- codeboarding-0.10.3/github_action.py +0 -173
- codeboarding-0.10.3/main.py +0 -567
- codeboarding-0.10.3/repo_utils/change_detector.py +0 -294
- codeboarding-0.10.3/repo_utils/git_diff.py +0 -74
- codeboarding-0.10.3/repo_utils/method_diff.py +0 -177
- codeboarding-0.10.3/static_analyzer/git_diff_analyzer.py +0 -224
- {codeboarding-0.10.3 → codeboarding-0.11.0}/LICENSE +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/change_status.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/dependency_discovery.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/meta_agent.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/planner_agent.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/prompts/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/base.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/get_external_deps.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/get_method_invocations.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_cfg.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_docs.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_file.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_file_structure.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_packages.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_source.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/agents/tools/read_structure.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/caching/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/caching/cache.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/caching/details_cache.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/caching/meta_cache.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/codeboarding.egg-info/dependency_links.txt +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/codeboarding.egg-info/entry_points.txt +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/constants.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/core/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/core/plugin_loader.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/core/protocols.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/core/registry.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/file_coverage.py +1 -1
- {codeboarding-0.10.3/output_generators → codeboarding-0.11.0/diagram_analysis/incremental}/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/diagram_analysis/version.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/duckdb_crud.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/circular_deps.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/cohesion.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/coupling.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/function_size.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/god_class.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/inheritance.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/instability.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/checks/unused_code_diagnostics.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/config.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/constants.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/models.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health/runner.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/health_main.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/callbacks.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/context.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/mixin.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/paths.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/stats.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/monitoring/writers.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/output_generators/html.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/output_generators/html_template.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/output_generators/markdown.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/output_generators/mdx.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/output_generators/sphinx.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/repo_utils/errors.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/repo_utils/ignore.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/setup.cfg +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/analysis_cache.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/cluster_change_analyzer.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/cluster_helpers.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/cluster_relations.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/csharp_config_scanner.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/adapters/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/call_graph_builder.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/edge_build_context.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/edge_builder.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/hierarchy_builder.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/lsp_client.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/lsp_constants.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/models.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/progress.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/protocols.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/result_converter.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/source_inspector.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/symbol_table.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/engine/utils.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/java_config_scanner.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/java_utils.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/lsp_client/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/lsp_client/diagnostics.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/node.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/programming_language.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/reference_resolve_mixin.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/scanner.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/static_analyzer/typescript_config_scanner.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_install.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_logging_config.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_pyproject_packages.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_registry_coverage.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_vscode_constants.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_windows_compatibility.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tests/test_windows_encoding.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tool_registry/__init__.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tool_registry/installers.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tool_registry/manifest.py +0 -0
- {codeboarding-0.10.3 → codeboarding-0.11.0}/tool_registry/paths.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codeboarding
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.11.0
|
|
4
4
|
Summary: Interactive Diagrams for Code
|
|
5
5
|
Author: CodeBoarding Team
|
|
6
6
|
License-Expression: MIT
|
|
@@ -24,6 +24,7 @@ Requires-Dist: fastapi>=0.115
|
|
|
24
24
|
Requires-Dist: filelock>=3.12
|
|
25
25
|
Requires-Dist: gitpython>=3.1
|
|
26
26
|
Requires-Dist: google-api-core>=2.10
|
|
27
|
+
Requires-Dist: jsonpatch>=1.33
|
|
27
28
|
Requires-Dist: jsonschema>=4.25
|
|
28
29
|
Requires-Dist: langchain>=1.2
|
|
29
30
|
Requires-Dist: langchain-anthropic>=1.3
|
|
@@ -42,6 +43,15 @@ Requires-Dist: pathspec>=0.12
|
|
|
42
43
|
Requires-Dist: pyyaml>=6.0
|
|
43
44
|
Requires-Dist: regex>=2024.11
|
|
44
45
|
Requires-Dist: rich>=12.6
|
|
46
|
+
Requires-Dist: tree-sitter>=0.23
|
|
47
|
+
Requires-Dist: tree-sitter-c-sharp>=0.23
|
|
48
|
+
Requires-Dist: tree-sitter-go>=0.23
|
|
49
|
+
Requires-Dist: tree-sitter-java>=0.23
|
|
50
|
+
Requires-Dist: tree-sitter-javascript>=0.23
|
|
51
|
+
Requires-Dist: tree-sitter-php>=0.23
|
|
52
|
+
Requires-Dist: tree-sitter-python>=0.23
|
|
53
|
+
Requires-Dist: tree-sitter-rust>=0.23
|
|
54
|
+
Requires-Dist: tree-sitter-typescript>=0.23
|
|
45
55
|
Requires-Dist: trustcall>=0.0.39
|
|
46
56
|
Requires-Dist: uvicorn>=0.23
|
|
47
57
|
Provides-Extra: dev
|
|
@@ -110,10 +120,10 @@ codeboarding-setup
|
|
|
110
120
|
|
|
111
121
|
```bash
|
|
112
122
|
# Analyze a local repository (output goes to /path/to/repo/.codeboarding/)
|
|
113
|
-
codeboarding --local /path/to/repo
|
|
123
|
+
codeboarding full --local /path/to/repo
|
|
114
124
|
|
|
115
125
|
# Analyze a remote GitHub repository (cloned to cwd/repo_name/, output to cwd/repo_name/.codeboarding/)
|
|
116
|
-
codeboarding https://github.com/user/repo
|
|
126
|
+
codeboarding full https://github.com/user/repo
|
|
117
127
|
```
|
|
118
128
|
|
|
119
129
|
### Python API
|
|
@@ -188,19 +198,21 @@ Shell environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.) always
|
|
|
188
198
|
## CLI Reference
|
|
189
199
|
|
|
190
200
|
```
|
|
191
|
-
codeboarding [REPO_URL ...] # remote: clone + analyze
|
|
192
|
-
codeboarding --local PATH # local: analyze in-place
|
|
201
|
+
codeboarding full [REPO_URL ...] # remote: clone + analyze
|
|
202
|
+
codeboarding full --local PATH # local: analyze in-place
|
|
203
|
+
codeboarding incremental --local PATH # re-analyze only changed parts
|
|
204
|
+
codeboarding partial --local PATH --component-id ID # update one component
|
|
193
205
|
```
|
|
194
206
|
|
|
195
207
|
| Option | Description |
|
|
196
208
|
|---|---|
|
|
197
209
|
| `--local PATH` | Analyze a local repository (output: `PATH/.codeboarding/`) |
|
|
198
210
|
| `--depth-level INT` | Diagram depth (default: 1) |
|
|
199
|
-
| `--
|
|
200
|
-
| `--
|
|
201
|
-
| `--
|
|
211
|
+
| `--force` | (full only) Force full reanalysis, skip cached static analysis |
|
|
212
|
+
| `--base-ref REF` / `--target-ref REF` | (incremental only) Git refs to diff |
|
|
213
|
+
| `--component-id ID` | (partial only) ID of the component to update |
|
|
202
214
|
| `--binary-location PATH` | Custom path to language server binaries (overrides `~/.codeboarding/servers/`) |
|
|
203
|
-
| `--upload` | Upload results to GeneratedOnBoardings repo
|
|
215
|
+
| `--upload` | (full, remote only) Upload results to GeneratedOnBoardings repo |
|
|
204
216
|
| `--enable-monitoring` | Enable run monitoring |
|
|
205
217
|
|
|
206
218
|
---
|
|
@@ -50,10 +50,10 @@ codeboarding-setup
|
|
|
50
50
|
|
|
51
51
|
```bash
|
|
52
52
|
# Analyze a local repository (output goes to /path/to/repo/.codeboarding/)
|
|
53
|
-
codeboarding --local /path/to/repo
|
|
53
|
+
codeboarding full --local /path/to/repo
|
|
54
54
|
|
|
55
55
|
# Analyze a remote GitHub repository (cloned to cwd/repo_name/, output to cwd/repo_name/.codeboarding/)
|
|
56
|
-
codeboarding https://github.com/user/repo
|
|
56
|
+
codeboarding full https://github.com/user/repo
|
|
57
57
|
```
|
|
58
58
|
|
|
59
59
|
### Python API
|
|
@@ -128,19 +128,21 @@ Shell environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.) always
|
|
|
128
128
|
## CLI Reference
|
|
129
129
|
|
|
130
130
|
```
|
|
131
|
-
codeboarding [REPO_URL ...] # remote: clone + analyze
|
|
132
|
-
codeboarding --local PATH # local: analyze in-place
|
|
131
|
+
codeboarding full [REPO_URL ...] # remote: clone + analyze
|
|
132
|
+
codeboarding full --local PATH # local: analyze in-place
|
|
133
|
+
codeboarding incremental --local PATH # re-analyze only changed parts
|
|
134
|
+
codeboarding partial --local PATH --component-id ID # update one component
|
|
133
135
|
```
|
|
134
136
|
|
|
135
137
|
| Option | Description |
|
|
136
138
|
|---|---|
|
|
137
139
|
| `--local PATH` | Analyze a local repository (output: `PATH/.codeboarding/`) |
|
|
138
140
|
| `--depth-level INT` | Diagram depth (default: 1) |
|
|
139
|
-
| `--
|
|
140
|
-
| `--
|
|
141
|
-
| `--
|
|
141
|
+
| `--force` | (full only) Force full reanalysis, skip cached static analysis |
|
|
142
|
+
| `--base-ref REF` / `--target-ref REF` | (incremental only) Git refs to diff |
|
|
143
|
+
| `--component-id ID` | (partial only) ID of the component to update |
|
|
142
144
|
| `--binary-location PATH` | Custom path to language server binaries (overrides `~/.codeboarding/servers/`) |
|
|
143
|
-
| `--upload` | Upload results to GeneratedOnBoardings repo
|
|
145
|
+
| `--upload` | (full, remote only) Upload results to GeneratedOnBoardings repo |
|
|
144
146
|
| `--enable-monitoring` | Enable run monitoring |
|
|
145
147
|
|
|
146
148
|
---
|
|
@@ -70,7 +70,7 @@ For a deeper architecture walkthrough, see [`.codeboarding/overview.md`](.codebo
|
|
|
70
70
|
uv sync --frozen
|
|
71
71
|
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
72
72
|
python install.py
|
|
73
|
-
python main.py --local /path/to/repo
|
|
73
|
+
python main.py full --local /path/to/repo
|
|
74
74
|
```
|
|
75
75
|
|
|
76
76
|
### Use the packaged CLI
|
|
@@ -80,7 +80,7 @@ Requires **Python 3.12 or 3.13**. The recommended install method is [pipx](https
|
|
|
80
80
|
```bash
|
|
81
81
|
pipx install codeboarding --python python3.12
|
|
82
82
|
codeboarding-setup
|
|
83
|
-
codeboarding --local /path/to/repo
|
|
83
|
+
codeboarding full --local /path/to/repo
|
|
84
84
|
```
|
|
85
85
|
|
|
86
86
|
Or, if you prefer pip, install into a virtual environment (not the global Python):
|
|
@@ -88,7 +88,7 @@ Or, if you prefer pip, install into a virtual environment (not the global Python
|
|
|
88
88
|
```bash
|
|
89
89
|
pip install codeboarding
|
|
90
90
|
codeboarding-setup
|
|
91
|
-
codeboarding --local /path/to/repo
|
|
91
|
+
codeboarding full --local /path/to/repo
|
|
92
92
|
```
|
|
93
93
|
|
|
94
94
|
Output is written to `/path/to/repo/.codeboarding/`.
|
|
@@ -120,19 +120,19 @@ Shell environment variables such as `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOG
|
|
|
120
120
|
|
|
121
121
|
```bash
|
|
122
122
|
# Analyze a local repository
|
|
123
|
-
python main.py --local ./my-project
|
|
123
|
+
python main.py full --local ./my-project
|
|
124
124
|
|
|
125
125
|
# Increase diagram depth
|
|
126
|
-
python main.py --local ./my-project --depth-level 2
|
|
126
|
+
python main.py full --local ./my-project --depth-level 2
|
|
127
127
|
|
|
128
128
|
# Re-analyze only changed parts when possible
|
|
129
|
-
python main.py --local ./my-project
|
|
129
|
+
python main.py incremental --local ./my-project
|
|
130
130
|
|
|
131
131
|
# Update a single component by ID
|
|
132
|
-
python main.py --local ./my-project --
|
|
132
|
+
python main.py partial --local ./my-project --component-id "1.2"
|
|
133
133
|
|
|
134
134
|
# Analyze a remote GitHub repository
|
|
135
|
-
python main.py https://github.com/pytorch/pytorch
|
|
135
|
+
python main.py full https://github.com/pytorch/pytorch
|
|
136
136
|
```
|
|
137
137
|
|
|
138
138
|
## Where to use it
|
|
@@ -70,8 +70,20 @@ class AbstractionAgent(ClusterMethodsMixin, CodeBoardingAgent):
|
|
|
70
70
|
|
|
71
71
|
programming_langs = self.static_analysis.get_languages()
|
|
72
72
|
|
|
73
|
-
#
|
|
74
|
-
|
|
73
|
+
# Measure everything that wraps cfg_clusters (system message + rendered
|
|
74
|
+
# template with an empty slot) so the skip planner can back it out of
|
|
75
|
+
# the input window before budgeting the cluster string.
|
|
76
|
+
overhead_chars = len(str(self.system_message.content)) + len(
|
|
77
|
+
self.prompts["group_clusters"].format(
|
|
78
|
+
project_name=self.project_name,
|
|
79
|
+
cfg_clusters="",
|
|
80
|
+
meta_context=meta_context_str,
|
|
81
|
+
project_type=project_type,
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
cluster_str = self._build_cluster_string(
|
|
85
|
+
programming_langs, cluster_results, prompt_overhead_chars=overhead_chars
|
|
86
|
+
)
|
|
75
87
|
|
|
76
88
|
prompt = self.prompts["group_clusters"].format(
|
|
77
89
|
project_name=self.project_name,
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import json
|
|
2
2
|
import logging
|
|
3
|
-
import time
|
|
4
3
|
from pathlib import Path
|
|
5
4
|
|
|
6
5
|
from google.api_core.exceptions import ResourceExhausted
|
|
@@ -15,6 +14,7 @@ from pydantic import ValidationError
|
|
|
15
14
|
from trustcall import create_extractor
|
|
16
15
|
|
|
17
16
|
from agents.prompts import get_validation_feedback_message
|
|
17
|
+
from agents.retry import RetryAction, RetryDecision, default_backoff, with_retries
|
|
18
18
|
from agents.tools.base import RepoContext
|
|
19
19
|
from agents.tools.toolkit import CodeBoardingToolkit
|
|
20
20
|
from agents.validation import ValidationResult, score_validation_results, VALIDATOR_WEIGHTS, DEFAULT_VALIDATOR_WEIGHT
|
|
@@ -96,86 +96,69 @@ class CodeBoardingAgent(ReferenceResolverMixin, MonitoringMixin):
|
|
|
96
96
|
def _invoke(self, prompt, callbacks: list | None = None) -> str:
|
|
97
97
|
"""Unified agent invocation method with timeout and exponential backoff.
|
|
98
98
|
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
99
|
+
Classification applied per exception:
|
|
100
|
+
- ``TimeoutError``: backoff ``min(10·2^n, 120)``, raise on exhaustion.
|
|
101
|
+
- ``ResourceExhausted``: backoff ``min(30·2^n, 300)``, raise on exhaustion.
|
|
102
|
+
- ``status_code == 404``: raise immediately (retired model ID, etc.).
|
|
103
|
+
- Other exceptions: backoff ``min(10·2^n, 120)``, return fallback string
|
|
104
|
+
on exhaustion (non-raising — callers treat the fallback as a failed run).
|
|
102
105
|
"""
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
+
max_attempts = 5
|
|
107
|
+
# Counter captured by the closure so we can vary the per-attempt timeout
|
|
108
|
+
# without reaching into the retry helper.
|
|
109
|
+
attempt_counter = [0]
|
|
110
|
+
|
|
111
|
+
def call_once() -> str:
|
|
112
|
+
attempt = attempt_counter[0]
|
|
113
|
+
attempt_counter[0] += 1
|
|
106
114
|
timeout_seconds = 300 if attempt == 0 else 600
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
115
|
+
callback_list = (callbacks or []) + [MONITORING_CALLBACK, self.agent_monitoring_callback]
|
|
116
|
+
logger.info(
|
|
117
|
+
f"Starting agent.invoke() [attempt {attempt + 1}/{max_attempts}] with prompt length: {len(prompt)}, timeout: {timeout_seconds}s"
|
|
118
|
+
)
|
|
119
|
+
response = self._invoke_with_timeout(
|
|
120
|
+
timeout_seconds=timeout_seconds, callback_list=callback_list, prompt=prompt
|
|
121
|
+
)
|
|
122
|
+
logger.info(
|
|
123
|
+
f"Completed agent.invoke() - message count: {len(response['messages'])}, last message type: {type(response['messages'][-1])}"
|
|
124
|
+
)
|
|
125
|
+
agent_response = response["messages"][-1]
|
|
126
|
+
assert isinstance(agent_response, AIMessage), f"Expected AIMessage, but got {type(agent_response)}"
|
|
127
|
+
if isinstance(agent_response.content, str):
|
|
128
|
+
return agent_response.content
|
|
129
|
+
if isinstance(agent_response.content, list):
|
|
130
|
+
return "".join(str(m) if not isinstance(m, str) else m for m in agent_response.content)
|
|
131
|
+
return "" # unreachable for AIMessage but satisfies typing
|
|
132
|
+
|
|
133
|
+
def classify(exc: Exception, attempt: int) -> RetryDecision:
|
|
134
|
+
if getattr(exc, "status_code", None) == 404:
|
|
135
|
+
logger.error(f"Permanent HTTP 404 — not retrying: {type(exc).__name__}: {exc}")
|
|
136
|
+
return RetryDecision(action=RetryAction.GIVE_UP)
|
|
137
|
+
if isinstance(exc, ResourceExhausted):
|
|
138
|
+
return RetryDecision(
|
|
139
|
+
action=RetryAction.RETRY,
|
|
140
|
+
backoff_s=default_backoff(attempt, initial_s=30.0, multiplier=2.0, max_s=300.0),
|
|
123
141
|
)
|
|
142
|
+
# TimeoutError + generic Exception share the same backoff.
|
|
143
|
+
return RetryDecision(
|
|
144
|
+
action=RetryAction.RETRY,
|
|
145
|
+
backoff_s=default_backoff(attempt, initial_s=10.0, multiplier=2.0, max_s=120.0),
|
|
146
|
+
)
|
|
124
147
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# Exponential backoff: 10s * 2^attempt (10s, 20s, 40s, 80s)
|
|
140
|
-
delay = min(10 * (2**attempt), 120)
|
|
141
|
-
logger.warning(
|
|
142
|
-
f"Agent invocation timed out after {timeout_seconds}s, retrying in {delay}s... (attempt {attempt + 1}/{max_retries})"
|
|
143
|
-
)
|
|
144
|
-
time.sleep(delay)
|
|
145
|
-
else:
|
|
146
|
-
logger.error(f"Agent invocation timed out after {timeout_seconds}s on final attempt")
|
|
147
|
-
raise
|
|
148
|
-
|
|
149
|
-
except ResourceExhausted as e:
|
|
150
|
-
if attempt < max_retries - 1:
|
|
151
|
-
# Longer backoff for rate limits: 30s * 2^attempt (30s, 60s, 120s, 240s)
|
|
152
|
-
delay = min(30 * (2**attempt), 300)
|
|
153
|
-
logger.warning(
|
|
154
|
-
f"ResourceExhausted (rate limit): {e}\n"
|
|
155
|
-
f"Retrying in {delay}s... (attempt {attempt + 1}/{max_retries})"
|
|
156
|
-
)
|
|
157
|
-
time.sleep(delay)
|
|
158
|
-
else:
|
|
159
|
-
logger.error(f"Max retries ({max_retries}) reached. ResourceExhausted: {e}")
|
|
160
|
-
raise
|
|
161
|
-
|
|
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
|
-
|
|
168
|
-
# Other errors (network, parsing, etc.) get standard exponential backoff
|
|
169
|
-
if attempt < max_retries - 1:
|
|
170
|
-
delay = min(10 * (2**attempt), 120)
|
|
171
|
-
logger.warning(
|
|
172
|
-
f"Agent error: {type(e).__name__}: {e}, retrying in {delay}s... (attempt {attempt + 1}/{max_retries})"
|
|
173
|
-
)
|
|
174
|
-
time.sleep(delay)
|
|
175
|
-
# On final attempt, fall through to return error message below
|
|
176
|
-
|
|
177
|
-
logger.error("Max retries reached. Failed to get response from the agent.")
|
|
178
|
-
return "Could not get response from the agent."
|
|
148
|
+
def on_exhausted(exc: Exception) -> str:
|
|
149
|
+
# Typed exceptions surface the original error; only generic falls through
|
|
150
|
+
# to the historic fallback string that callers have long relied on.
|
|
151
|
+
if isinstance(exc, (TimeoutError, ResourceExhausted)):
|
|
152
|
+
raise exc
|
|
153
|
+
return "Could not get response from the agent."
|
|
154
|
+
|
|
155
|
+
return with_retries(
|
|
156
|
+
call_once,
|
|
157
|
+
max_attempts=max_attempts,
|
|
158
|
+
classify=classify,
|
|
159
|
+
on_exhausted=on_exhausted,
|
|
160
|
+
log_prefix="Agent invocation",
|
|
161
|
+
)
|
|
179
162
|
|
|
180
163
|
def _invoke_with_timeout(self, timeout_seconds: int, callback_list: list, prompt: str):
|
|
181
164
|
"""Invoke agent with a timeout using threading."""
|
|
@@ -336,18 +319,27 @@ class CodeBoardingAgent(ReferenceResolverMixin, MonitoringMixin):
|
|
|
336
319
|
return best_result
|
|
337
320
|
|
|
338
321
|
def _parse_response(self, prompt, response, return_type, max_retries=5, attempt=0):
|
|
339
|
-
if attempt >= max_retries:
|
|
340
|
-
logger.error(f"Max retries ({max_retries}) reached for parsing response: {response}")
|
|
341
|
-
raise Exception(f"Max retries reached for parsing response: {response}")
|
|
342
|
-
|
|
343
|
-
extractor = create_extractor(self.parsing_llm, tools=[return_type], tool_choice=return_type.__name__)
|
|
344
322
|
if response is None or response.strip() == "":
|
|
345
323
|
logger.error(f"Empty response for prompt: {prompt}")
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
)
|
|
324
|
+
|
|
325
|
+
def call_once():
|
|
326
|
+
# Extractor is rebuilt on every attempt — previous trustcall state
|
|
327
|
+
# may have corrupted attributes (see the tool_call_id bug below).
|
|
328
|
+
extractor = create_extractor(self.parsing_llm, tools=[return_type], tool_choice=return_type.__name__)
|
|
329
|
+
try:
|
|
330
|
+
result = extractor.invoke(
|
|
331
|
+
return_type.extractor_str() + response,
|
|
332
|
+
config={"callbacks": [MONITORING_CALLBACK, self.agent_monitoring_callback]},
|
|
333
|
+
)
|
|
334
|
+
except AttributeError as e:
|
|
335
|
+
# Trustcall bug: https://github.com/hinthornw/trustcall/issues/47
|
|
336
|
+
# 'ExtractionState' object has no attribute 'tool_call_id' during validation retry.
|
|
337
|
+
# Treat as a non-retriable fallback to the Pydantic parser.
|
|
338
|
+
if "tool_call_id" in str(e):
|
|
339
|
+
logger.warning(f"Trustcall bug encountered, falling back to Pydantic parser: {e}")
|
|
340
|
+
parser = PydanticOutputParser(pydantic_object=return_type)
|
|
341
|
+
return self._try_parse(response, parser)
|
|
342
|
+
raise
|
|
351
343
|
if "responses" in result and len(result["responses"]) != 0:
|
|
352
344
|
return return_type.model_validate(result["responses"][0])
|
|
353
345
|
if "messages" in result and len(result["messages"]) != 0:
|
|
@@ -358,38 +350,36 @@ class CodeBoardingAgent(ReferenceResolverMixin, MonitoringMixin):
|
|
|
358
350
|
return self._try_parse(message, parser)
|
|
359
351
|
parser = PydanticOutputParser(pydantic_object=return_type)
|
|
360
352
|
return self._try_parse(response, parser)
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
if "tool_call_id" in str(e):
|
|
368
|
-
logger.warning(f"Trustcall bug encountered, falling back to Pydantic parser: {e}")
|
|
369
|
-
parser = PydanticOutputParser(pydantic_object=return_type)
|
|
370
|
-
return self._try_parse(response, parser)
|
|
371
|
-
raise
|
|
372
|
-
except IndexError as e:
|
|
373
|
-
# try to parse with the json parser if possible
|
|
374
|
-
logger.warning(f"IndexError while parsing response (attempt {attempt + 1}/{max_retries}): {e}")
|
|
375
|
-
return self._parse_response(prompt, response, return_type, max_retries, attempt + 1)
|
|
376
|
-
except (json.JSONDecodeError, ValueError) as e:
|
|
377
|
-
logger.warning(f"Parse error (attempt {attempt + 1}/{max_retries}): {e}")
|
|
378
|
-
return self._parse_response(prompt, response, return_type, max_retries, attempt + 1)
|
|
379
|
-
except ResourceExhausted as e:
|
|
380
|
-
# Parsing uses exponential backoff for rate limits
|
|
381
|
-
if attempt < max_retries - 1:
|
|
382
|
-
# Exponential backoff: 30s * 2^attempt, capped at 300s
|
|
383
|
-
delay = min(30 * (2**attempt), 300)
|
|
384
|
-
logger.warning(
|
|
385
|
-
f"ResourceExhausted during parsing (rate limit): {e}\n"
|
|
386
|
-
f"Retrying in {delay}s... (attempt {attempt + 1}/{max_retries})"
|
|
353
|
+
|
|
354
|
+
def classify(exc: Exception, attempt: int) -> RetryDecision:
|
|
355
|
+
if isinstance(exc, ResourceExhausted):
|
|
356
|
+
return RetryDecision(
|
|
357
|
+
action=RetryAction.RETRY,
|
|
358
|
+
backoff_s=default_backoff(attempt, initial_s=30.0, multiplier=2.0, max_s=300.0),
|
|
387
359
|
)
|
|
388
|
-
|
|
389
|
-
return
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
360
|
+
if isinstance(exc, (EmptyExtractorMessageError, IndexError, json.JSONDecodeError, ValueError)):
|
|
361
|
+
return RetryDecision(action=RetryAction.RETRY_NOW)
|
|
362
|
+
# AttributeError (non-tool_call_id) and any other exception: give up.
|
|
363
|
+
return RetryDecision(action=RetryAction.GIVE_UP)
|
|
364
|
+
|
|
365
|
+
def on_exhausted(exc: Exception):
|
|
366
|
+
# Preserve historic shape: ResourceExhausted surfaces the original exception;
|
|
367
|
+
# parse-error exhaustion wraps with a descriptive message naming the response.
|
|
368
|
+
if isinstance(exc, ResourceExhausted):
|
|
369
|
+
logger.error(f"Resource exhausted on final parsing attempt: {exc}")
|
|
370
|
+
raise exc
|
|
371
|
+
logger.error(f"Max retries ({max_retries}) reached for parsing response: {response}")
|
|
372
|
+
raise Exception(f"Max retries reached for parsing response: {response}")
|
|
373
|
+
|
|
374
|
+
# ``attempt`` kwarg kept for backwards-compat with callers that passed it;
|
|
375
|
+
# the effective attempt count is ``max_retries - attempt``.
|
|
376
|
+
return with_retries(
|
|
377
|
+
call_once,
|
|
378
|
+
max_attempts=max(1, max_retries - attempt),
|
|
379
|
+
classify=classify,
|
|
380
|
+
on_exhausted=on_exhausted,
|
|
381
|
+
log_prefix="Parse response",
|
|
382
|
+
)
|
|
393
383
|
|
|
394
384
|
def _try_parse(self, message_content, parser):
|
|
395
385
|
try:
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
import abc
|
|
2
4
|
import logging
|
|
3
5
|
from abc import abstractmethod
|
|
@@ -6,8 +8,6 @@ from typing import get_origin, Optional
|
|
|
6
8
|
|
|
7
9
|
from pydantic import BaseModel, Field
|
|
8
10
|
|
|
9
|
-
from agents.change_status import ChangeStatus
|
|
10
|
-
|
|
11
11
|
logger = logging.getLogger(__name__)
|
|
12
12
|
|
|
13
13
|
|
|
@@ -142,10 +142,6 @@ class MethodEntry(BaseModel):
|
|
|
142
142
|
start_line: int = Field(description="Starting line number in the file.")
|
|
143
143
|
end_line: int = Field(description="Ending line number in the file.")
|
|
144
144
|
node_type: str = Field(description="Node type name matching NodeType enum (e.g. METHOD, FUNCTION, CLASS).")
|
|
145
|
-
status: ChangeStatus = Field(
|
|
146
|
-
default=ChangeStatus.UNCHANGED,
|
|
147
|
-
description="Diff status of this method: added, modified, deleted, or unchanged.",
|
|
148
|
-
)
|
|
149
145
|
|
|
150
146
|
def __hash__(self) -> int:
|
|
151
147
|
return hash(self.qualified_name)
|
|
@@ -156,13 +152,22 @@ class MethodEntry(BaseModel):
|
|
|
156
152
|
return self.qualified_name == other.qualified_name
|
|
157
153
|
|
|
158
154
|
@classmethod
|
|
159
|
-
def from_method_change(cls, method_change
|
|
155
|
+
def from_method_change(cls, method_change) -> MethodEntry:
|
|
160
156
|
return cls(
|
|
161
157
|
qualified_name=method_change.qualified_name,
|
|
162
158
|
start_line=method_change.start_line,
|
|
163
159
|
end_line=method_change.end_line,
|
|
164
160
|
node_type=method_change.node_type,
|
|
165
|
-
|
|
161
|
+
)
|
|
162
|
+
|
|
163
|
+
@classmethod
|
|
164
|
+
def from_node(cls, node) -> MethodEntry:
|
|
165
|
+
"""Build from a ``static_analyzer.Node``. Accepts ``Any`` to avoid a hard dep."""
|
|
166
|
+
return cls(
|
|
167
|
+
qualified_name=node.fully_qualified_name,
|
|
168
|
+
start_line=node.line_start,
|
|
169
|
+
end_line=node.line_end,
|
|
170
|
+
node_type=node.type.name,
|
|
166
171
|
)
|
|
167
172
|
|
|
168
173
|
|
|
@@ -170,10 +175,6 @@ class FileMethodGroup(BaseModel):
|
|
|
170
175
|
"""All methods/functions belonging to a component within a single file."""
|
|
171
176
|
|
|
172
177
|
file_path: str = Field(description="Relative path to the source file.")
|
|
173
|
-
file_status: ChangeStatus = Field(
|
|
174
|
-
default=ChangeStatus.UNCHANGED,
|
|
175
|
-
description="Diff status of this file: added, modified, deleted, renamed, or unchanged.",
|
|
176
|
-
)
|
|
177
178
|
methods: list[MethodEntry] = Field(
|
|
178
179
|
default_factory=list,
|
|
179
180
|
description="Methods and functions in this file that belong to the component, sorted by start_line.",
|
|
@@ -183,10 +184,6 @@ class FileMethodGroup(BaseModel):
|
|
|
183
184
|
class FileEntry(BaseModel):
|
|
184
185
|
"""Single source of truth for methods in one file."""
|
|
185
186
|
|
|
186
|
-
file_status: ChangeStatus = Field(
|
|
187
|
-
default=ChangeStatus.UNCHANGED,
|
|
188
|
-
description="Diff status of this file: added, modified, deleted, renamed, or unchanged.",
|
|
189
|
-
)
|
|
190
187
|
methods: list[MethodEntry] = Field(
|
|
191
188
|
default_factory=list,
|
|
192
189
|
description="Methods and functions in this file, sorted by start line.",
|