codeboarding 0.14.5__tar.gz → 0.15.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.
Files changed (207) hide show
  1. {codeboarding-0.14.5/codeboarding.egg-info → codeboarding-0.15.0}/PKG-INFO +4 -2
  2. {codeboarding-0.14.5 → codeboarding-0.15.0}/PYPI.md +2 -1
  3. {codeboarding-0.14.5 → codeboarding-0.15.0}/README.md +16 -12
  4. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/agent_responses.py +1 -1
  5. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/content_hash.py +1 -1
  6. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/llm_config.py +1 -6
  7. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/llm_errors.py +59 -4
  8. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/llm_renderers/scope.py +1 -1
  9. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/model_capabilities.py +2 -2
  10. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/relation_edges.py +2 -2
  11. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/retry.py +26 -0
  12. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/scope_analysis_agent.py +23 -2
  13. codeboarding-0.15.0/agents/scope_ids.py +3 -0
  14. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/tools/read_file.py +1 -1
  15. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/tree_planner_agent.py +18 -10
  16. {codeboarding-0.14.5 → codeboarding-0.15.0/codeboarding.egg-info}/PKG-INFO +4 -2
  17. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding.egg-info/SOURCES.txt +46 -51
  18. codeboarding-0.15.0/codeboarding.egg-info/entry_points.txt +4 -0
  19. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding.egg-info/requires.txt +1 -0
  20. codeboarding-0.15.0/codeboarding.egg-info/top_level.txt +8 -0
  21. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/bootstrap.py +6 -6
  22. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/commands/full_analysis.py +7 -7
  23. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/commands/incremental_analysis.py +1 -1
  24. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/commands/partial_analysis.py +2 -2
  25. {codeboarding-0.14.5 → codeboarding-0.15.0/codeboarding_cli}/github_action.py +2 -2
  26. {codeboarding-0.14.5 → codeboarding-0.15.0/codeboarding_cli}/main.py +1 -1
  27. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/render.py +1 -1
  28. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/analysis.py +3 -3
  29. {codeboarding-0.14.5/repo_utils → codeboarding-0.15.0/codeboarding_workflows}/fingerprint_diff.py +1 -1
  30. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/sources/remote.py +2 -2
  31. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/analysis_json.py +1 -1
  32. {codeboarding-0.14.5/static_analyzer → codeboarding-0.15.0/diagram_analysis}/cluster_relations.py +2 -2
  33. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/diagram_generator.py +13 -13
  34. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/file_coverage.py +3 -3
  35. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/file_index.py +2 -2
  36. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/incremental_changes.py +2 -2
  37. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/incremental_update.py +3 -3
  38. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/io_utils.py +1 -1
  39. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/run_context.py +2 -2
  40. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/scope_assembly.py +4 -4
  41. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/scope_plan.py +1 -1
  42. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/checks/function_size.py +1 -1
  43. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/config.py +2 -2
  44. codeboarding-0.15.0/health/main.py +152 -0
  45. {codeboarding-0.14.5/core → codeboarding-0.15.0/health/plugins}/__init__.py +7 -7
  46. {codeboarding-0.14.5/core → codeboarding-0.15.0/health/plugins}/plugin_loader.py +1 -1
  47. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/runner.py +2 -2
  48. codeboarding-0.15.0/infra/__init__.py +1 -0
  49. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/install.py +28 -11
  50. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/__init__.py +2 -2
  51. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/callbacks.py +6 -2
  52. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/context.py +1 -1
  53. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/mixin.py +2 -2
  54. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/paths.py +1 -1
  55. {codeboarding-0.14.5 → codeboarding-0.15.0/infra/monitoring}/telemetry/__init__.py +1 -1
  56. {codeboarding-0.14.5 → codeboarding-0.15.0/infra/monitoring}/telemetry/events.py +3 -3
  57. {codeboarding-0.14.5 → codeboarding-0.15.0/infra/monitoring}/telemetry/service.py +1 -1
  58. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/writers.py +1 -1
  59. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/__init__.py +4 -4
  60. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/change_detector.py +1 -1
  61. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/ignore.py +1 -3
  62. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/tool_registry/__init__.py +6 -0
  63. codeboarding-0.15.0/infra/tool_registry/grammars.py +47 -0
  64. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/tool_registry/installers.py +97 -11
  65. codeboarding-0.14.5/static_analyzer/java_utils.py → codeboarding-0.15.0/infra/tool_registry/java.py +6 -109
  66. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/tool_registry/manifest.py +24 -10
  67. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/tool_registry/paths.py +1 -1
  68. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/tool_registry/registry.py +48 -7
  69. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/user_config.py +1 -1
  70. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/utils.py +4 -4
  71. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/vscode_constants.py +12 -0
  72. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/html.py +1 -1
  73. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/markdown.py +1 -1
  74. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/mdx.py +1 -1
  75. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/rendering.py +2 -2
  76. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/sphinx.py +1 -1
  77. {codeboarding-0.14.5 → codeboarding-0.15.0}/pyproject.toml +10 -19
  78. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/__init__.py +221 -162
  79. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/analysis_cache.py +5 -3
  80. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/cfg/call_graph.py +10 -10
  81. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/models.py +1 -1
  82. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/draft.py +1 -1
  83. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/inventory.py +1 -1
  84. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/spec.py +1 -1
  85. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/service.py +2 -2
  86. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/config.py +5 -0
  87. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/csharp_config_scanner.py +1 -1
  88. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/dotnet_sdk.py +1 -1
  89. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/__init__.py +2 -0
  90. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/csharp_adapter.py +4 -3
  91. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/go_adapter.py +2 -2
  92. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/java_adapter.py +1 -1
  93. codeboarding-0.15.0/static_analyzer/engine/adapters/kotlin_adapter.py +348 -0
  94. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/php_adapter.py +1 -1
  95. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/python_adapter.py +1 -1
  96. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/rust_adapter.py +1 -1
  97. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/adapters/typescript_adapter.py +5 -1
  98. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/call_graph_builder.py +20 -4
  99. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/edge_builder.py +69 -11
  100. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/hierarchy_builder.py +83 -3
  101. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/language_adapter.py +85 -5
  102. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/lsp_client.py +118 -9
  103. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/lsp_constants.py +6 -3
  104. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/lsp_recycler.py +12 -5
  105. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/process_memory.py +0 -8
  106. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/protocols.py +11 -0
  107. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/result_converter.py +31 -22
  108. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/source_inspector.py +279 -27
  109. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/exceptions.py +4 -0
  110. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/external_calls.py +38 -5
  111. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/graph_definitions.py +14 -3
  112. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/incremental_orchestrator.py +3 -1
  113. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/java_config_scanner.py +1 -1
  114. codeboarding-0.15.0/static_analyzer/java_utils.py +112 -0
  115. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/language_results.py +19 -3
  116. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/scanner.py +3 -3
  117. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/typescript_config_scanner.py +75 -25
  118. codeboarding-0.15.0/static_analyzer/workspace_dependencies.py +93 -0
  119. {codeboarding-0.14.5 → codeboarding-0.15.0}/tests/test_persisted_analysis_artifacts.py +3 -3
  120. {codeboarding-0.14.5 → codeboarding-0.15.0}/tests/test_pyproject_packages.py +2 -9
  121. {codeboarding-0.14.5 → codeboarding-0.15.0}/tests/test_windows_compatibility.py +13 -13
  122. codeboarding-0.14.5/agents/scope_ids.py +0 -3
  123. codeboarding-0.14.5/codeboarding.egg-info/entry_points.txt +0 -4
  124. codeboarding-0.14.5/codeboarding.egg-info/top_level.txt +0 -21
  125. codeboarding-0.14.5/tests/test_cli_parser.py +0 -265
  126. codeboarding-0.14.5/tests/test_github_action.py +0 -477
  127. codeboarding-0.14.5/tests/test_install.py +0 -303
  128. codeboarding-0.14.5/tests/test_logging_config.py +0 -267
  129. codeboarding-0.14.5/tests/test_main.py +0 -725
  130. codeboarding-0.14.5/tests/test_registry_coverage.py +0 -396
  131. codeboarding-0.14.5/tests/test_telemetry_events.py +0 -199
  132. codeboarding-0.14.5/tests/test_telemetry_service.py +0 -216
  133. codeboarding-0.14.5/tests/test_tool_registry.py +0 -1740
  134. codeboarding-0.14.5/tests/test_user_config.py +0 -313
  135. codeboarding-0.14.5/tests/test_vscode_constants.py +0 -239
  136. {codeboarding-0.14.5 → codeboarding-0.15.0}/LICENSE +0 -0
  137. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/__init__.py +0 -0
  138. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/change_status.py +0 -0
  139. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/component_ownership.py +0 -0
  140. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/constants.py +0 -0
  141. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/file_index_models.py +0 -0
  142. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/incremental_results.py +0 -0
  143. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/llm_renderers/__init__.py +0 -0
  144. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/llm_renderers/call_graph.py +0 -0
  145. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/planner_agent.py +0 -0
  146. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/prompts/__init__.py +0 -0
  147. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/prompts/profiles.py +0 -0
  148. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/prompts/shared.py +0 -0
  149. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/tools/__init__.py +0 -0
  150. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/tools/base.py +0 -0
  151. {codeboarding-0.14.5 → codeboarding-0.15.0}/agents/tools/get_method_calls.py +0 -0
  152. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding.egg-info/dependency_links.txt +0 -0
  153. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/__init__.py +0 -0
  154. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/commands/__init__.py +0 -0
  155. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_cli/view_instructions.py +0 -0
  156. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/__init__.py +0 -0
  157. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/orchestration.py +0 -0
  158. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/sources/__init__.py +0 -0
  159. {codeboarding-0.14.5 → codeboarding-0.15.0}/codeboarding_workflows/sources/local.py +0 -0
  160. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/__init__.py +0 -0
  161. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/exceptions.py +0 -0
  162. {codeboarding-0.14.5/static_analyzer → codeboarding-0.15.0/diagram_analysis}/reference_resolver.py +0 -0
  163. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/run_mode.py +0 -0
  164. {codeboarding-0.14.5 → codeboarding-0.15.0}/diagram_analysis/tree_shape.py +0 -0
  165. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/__init__.py +0 -0
  166. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/checks/__init__.py +0 -0
  167. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/checks/circular_deps.py +0 -0
  168. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/checks/unused_code_diagnostics.py +0 -0
  169. {codeboarding-0.14.5 → codeboarding-0.15.0}/health/models.py +0 -0
  170. {codeboarding-0.14.5/core → codeboarding-0.15.0/health/plugins}/protocols.py +0 -0
  171. {codeboarding-0.14.5/core → codeboarding-0.15.0/health/plugins}/registry.py +0 -0
  172. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/clustering_ids.py +0 -0
  173. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/constants.py +0 -0
  174. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/logging_config.py +0 -0
  175. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/monitoring/stats.py +0 -0
  176. {codeboarding-0.14.5 → codeboarding-0.15.0/infra/monitoring}/telemetry/device_id.py +0 -0
  177. {codeboarding-0.14.5 → codeboarding-0.15.0/infra/monitoring}/telemetry/schemas.py +0 -0
  178. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/errors.py +0 -0
  179. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/git_ops.py +0 -0
  180. {codeboarding-0.14.5 → codeboarding-0.15.0/infra}/repo_utils/path_utils.py +0 -0
  181. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/__init__.py +0 -0
  182. {codeboarding-0.14.5 → codeboarding-0.15.0}/output_generators/html_template.py +0 -0
  183. {codeboarding-0.14.5 → codeboarding-0.15.0}/setup.cfg +0 -0
  184. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/analysis_result.py +0 -0
  185. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/cfg/__init__.py +0 -0
  186. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/cfg/edge.py +0 -0
  187. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/cfg/location_key.py +0 -0
  188. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/__init__.py +0 -0
  189. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/exceptions.py +0 -0
  190. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/__init__.py +0 -0
  191. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/frontier.py +0 -0
  192. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/replay.py +0 -0
  193. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/clustering/names/tokens.py +0 -0
  194. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/dotnet_solution.py +0 -0
  195. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/__init__.py +0 -0
  196. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/edge_build_context.py +0 -0
  197. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/models.py +0 -0
  198. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/progress.py +0 -0
  199. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/symbol_table.py +0 -0
  200. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/engine/utils.py +0 -0
  201. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/internal_references.py +0 -0
  202. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/lsp_client/__init__.py +0 -0
  203. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/lsp_client/diagnostics.py +0 -0
  204. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/node.py +0 -0
  205. {codeboarding-0.14.5 → codeboarding-0.15.0}/static_analyzer/programming_language.py +0 -0
  206. {codeboarding-0.14.5 → codeboarding-0.15.0}/tests/test_view_instructions.py +0 -0
  207. {codeboarding-0.14.5 → codeboarding-0.15.0}/tests/test_windows_encoding.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.14.5
3
+ Version: 0.15.0
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -52,6 +52,7 @@ Requires-Dist: tree-sitter-c-sharp==0.23.5
52
52
  Requires-Dist: tree-sitter-go==0.25.0
53
53
  Requires-Dist: tree-sitter-java==0.23.5
54
54
  Requires-Dist: tree-sitter-javascript==0.25.0
55
+ Requires-Dist: tree-sitter-language-pack==1.21.0
55
56
  Requires-Dist: tree-sitter-php==0.24.1
56
57
  Requires-Dist: tree-sitter-python==0.25.0
57
58
  Requires-Dist: tree-sitter-rust==0.24.2
@@ -84,13 +85,14 @@ Dynamic: license-file
84
85
  - Builds layered abstractions with an LLM agent (OpenAI, Anthropic, Google Gemini, Ollama, and more)
85
86
  - Outputs Mermaid.js diagrams ready for docs, IDEs, and CI/CD pipelines
86
87
 
87
- **Supported languages:** Python · TypeScript · JavaScript · Java · Go · PHP
88
+ **Supported languages:** Python · TypeScript · JavaScript · Java · Kotlin · Go · PHP
88
89
 
89
90
  ---
90
91
 
91
92
  ## Requirements
92
93
 
93
94
  - **Python 3.12 or 3.13** — other versions are currently not supported.
95
+ - **Linux:** glibc 2.34 or newer (Ubuntu 22.04, Debian 12, RHEL 9 or later), for the Kotlin parser.
94
96
 
95
97
  ## Installation
96
98
 
@@ -11,13 +11,14 @@
11
11
  - Builds layered abstractions with an LLM agent (OpenAI, Anthropic, Google Gemini, Ollama, and more)
12
12
  - Outputs Mermaid.js diagrams ready for docs, IDEs, and CI/CD pipelines
13
13
 
14
- **Supported languages:** Python · TypeScript · JavaScript · Java · Go · PHP
14
+ **Supported languages:** Python · TypeScript · JavaScript · Java · Kotlin · Go · PHP
15
15
 
16
16
  ---
17
17
 
18
18
  ## Requirements
19
19
 
20
20
  - **Python 3.12 or 3.13** — other versions are currently not supported.
21
+ - **Linux:** glibc 2.34 or newer (Ubuntu 22.04, Debian 12, RHEL 9 or later), for the Kotlin parser.
21
22
 
22
23
  ## Installation
23
24
 
@@ -17,6 +17,7 @@ The example starts with a large pull-request diff, then shows the six components
17
17
  [![JavaScript](https://img.shields.io/badge/JavaScript-222222?style=flat-square&logo=javascript&logoColor=F7DF1E)](https://developer.mozilla.org/en-US/docs/Web/JavaScript)
18
18
  [![TypeScript](https://img.shields.io/badge/TypeScript-3178C6?style=flat-square&logo=typescript&logoColor=white)](https://www.typescriptlang.org/)
19
19
  [![Java](https://img.shields.io/badge/Java-E76F00?style=flat-square&logo=openjdk&logoColor=white)](https://www.java.com/)
20
+ [![Kotlin](https://img.shields.io/badge/Kotlin-7F52FF?style=flat-square&logo=kotlin&logoColor=white)](https://kotlinlang.org/)
20
21
  [![Python](https://img.shields.io/badge/Python-3776AB?style=flat-square&logo=python&logoColor=white)](https://www.python.org/)
21
22
  [![Go](https://img.shields.io/badge/Go-00ADD8?style=flat-square&logo=go&logoColor=white)](https://go.dev/)
22
23
  [![PHP](https://img.shields.io/badge/PHP-777BB4?style=flat-square&logo=php&logoColor=white)](https://www.php.net/)
@@ -103,8 +104,8 @@ git clone https://github.com/CodeBoarding/CodeBoarding.git
103
104
  cd CodeBoarding
104
105
  uv sync --frozen
105
106
  source .venv/bin/activate # On Windows: .venv\Scripts\activate
106
- python install.py
107
- python main.py full --local /path/to/repo
107
+ python -m infra.install
108
+ python -m codeboarding_cli.main full --local /path/to/repo
108
109
  ```
109
110
 
110
111
  ### Use the packaged CLI
@@ -152,7 +153,7 @@ codeboarding-render /path/to/analysis.json --format mdx --output-dir /path/to/do
152
153
  python codeboarding_cli/render.py ../../demo/markitdown/.codeboarding/analysis.json --format md
153
154
  ```
154
155
 
155
- `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.
156
+ `python -m infra.install` 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.
156
157
 
157
158
  ## Configuration
158
159
 
@@ -184,32 +185,33 @@ On first run, CodeBoarding creates `~/.codeboarding/config.toml`. Set one provid
184
185
 
185
186
  Shell environment variables such as `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `GOOGLE_API_KEY`, and `OLLAMA_BASE_URL` take precedence over the config file. For private repositories, set `GITHUB_TOKEN` in your environment.
186
187
 
187
- Two environment variables tune the static analysis itself:
188
+ Three environment variables tune the static analysis itself:
188
189
 
189
190
  | Variable | Effect |
190
191
  | --- | --- |
191
- | `CODEBOARDING_LSP_REQUEST_TIMEOUT` | Seconds a language-server request may block *when it uses the per-language default* (120s for C#, 60s elsewhere). Not a hard cap on every request: the indexing and didOpen-drain probes pass their own scaled budget (60s plus 2s per file, capped at 1800s) and are unaffected. Applies to every language in the run. Unset or empty leaves the defaults alone; any other unusable value fails the run rather than falling back. |
192
- | `CODEBOARDING_MAX_CONCURRENT_ENGINES` | How many language servers may be resident at once. `0` (the default) leaves the bound off. |
192
+ | `CODEBOARDING_LSP_REQUEST_TIMEOUT` | Seconds a language-server request may block *when it uses the per-language default* (120s for C# and Kotlin, 60s elsewhere). Not a hard cap on every request: `initialize` has its own startup budget (the request default), Kotlin's build import is awaited separately (up to 1800s), and the indexing and didOpen-drain probes pass their own scaled budget (60s plus 2s per file, capped at 1800s); neither is affected. Applies to every language in the run. Unset or empty leaves the defaults alone; any other unusable value fails the run rather than falling back. |
193
+ | `CODEBOARDING_MAX_CONCURRENT_ENGINES` | How many language servers an analysis runs at once. Unset or `0`, the CLI and the GitHub Action run one at a time, each stopped when its language is done, and the editor keeps one per project running. Set, the editor's servers also start only for an analysis, so its file queries are unavailable. |
194
+ | `CODEBOARDING_LSP_MEMORY_BUDGET_MB` | Megabytes the language servers running at once share; tsserver's heap is its share less 512. Unset, it is three quarters of the machine's memory (or of a cgroup v2 container's limit, when lower), at most 12 GB. |
193
195
 
194
196
  ## Common commands
195
197
 
196
198
  ```bash
197
199
  # Analyze a local repository
198
- python main.py full --local ./my-project
200
+ python -m codeboarding_cli.main full --local ./my-project
199
201
 
200
202
  # Raise the depth ceiling to auto-expand deeper (rarely needed — a component that
201
203
  # outgrows the leaf ceiling is flagged expandable at whatever depth the run stops
202
204
  # and can be expanded on demand; --depth-cap is a safety-valve cap, default 3)
203
- python main.py full --local ./my-project --depth-cap 5
205
+ python -m codeboarding_cli.main full --local ./my-project --depth-cap 5
204
206
 
205
207
  # Re-analyze only changed parts when possible
206
- python main.py incremental --local ./my-project
208
+ python -m codeboarding_cli.main incremental --local ./my-project
207
209
 
208
210
  # Update a single component by ID
209
- python main.py partial --local ./my-project --component-id "1.2"
211
+ python -m codeboarding_cli.main partial --local ./my-project --component-id "1.2"
210
212
 
211
213
  # Analyze a remote GitHub repository
212
- python main.py full https://github.com/pytorch/pytorch
214
+ python -m codeboarding_cli.main full https://github.com/pytorch/pytorch
213
215
  ```
214
216
 
215
217
  `--depth-cap` configures `metadata.depth_cap`; `metadata.depth_level` records the
@@ -244,7 +246,9 @@ for the actual depth. Existing baseline loading behavior is unchanged: prefer
244
246
 
245
247
  ## Supported stack
246
248
 
247
- - Languages: Python, TypeScript, JavaScript, Java, Go, PHP, Rust, C#.
249
+ - Languages: Python, TypeScript, JavaScript, Java, Kotlin, Go, PHP, Rust, C#.
250
+ - Java needs a JDK (21 recommended).
251
+ - Kotlin is analysed with JetBrains' [kotlin-lsp](https://github.com/Kotlin/kotlin-lsp) (about 360 MB with its own Java runtime, under the [JetBrains Free Plugin License](https://github.com/Kotlin/kotlin-lsp/blob/main/kotlin-vscode/LICENSE.txt)) and needs glibc 2.34 or newer on Linux. Kotlin calls into Java are not drawn yet.
248
252
  - LLM providers: OpenAI, Anthropic, Google, Vercel AI Gateway, AWS Bedrock, Ollama, OpenRouter, OrcaRouter, Requesty, LiteLLM proxy, and more.
249
253
 
250
254
  ## Examples
@@ -8,7 +8,7 @@ from enum import StrEnum
8
8
 
9
9
  from pydantic import BaseModel, Field
10
10
 
11
- from clustering_ids import ComponentId
11
+ from infra.clustering_ids import ComponentId
12
12
  from agents.file_index_models import FileEntry, FileMethodGroup, MethodIndexEntry
13
13
  from agents.scope_ids import ROOT_SCOPE_ID
14
14
 
@@ -10,7 +10,7 @@ import os
10
10
  from pathlib import Path
11
11
  from typing import NamedTuple
12
12
 
13
- from repo_utils.ignore import RepoIgnoreManager
13
+ from infra.repo_utils.ignore import RepoIgnoreManager
14
14
 
15
15
  SOURCE_ENCODING = "utf-8"
16
16
  SOURCE_DECODE_ERRORS = "surrogateescape"
@@ -15,12 +15,7 @@ from langchain_openai import ChatOpenAI
15
15
  from agents.constants import LLMDefaults, ModelCapabilities
16
16
  from agents.model_capabilities import ContextWindow, get_context_window
17
17
  from agents.prompts import PromptProfile, resolve_prompt_profile
18
- from monitoring.callbacks import MonitoringCallback
19
-
20
- # Initialize global monitoring callback with its own stats container to avoid ContextVar dependency
21
- from monitoring.stats import RunStats
22
-
23
- MONITORING_CALLBACK = MonitoringCallback(stats_container=RunStats())
18
+ from infra.monitoring.callbacks import MONITORING_CALLBACK
24
19
 
25
20
  logger = logging.getLogger(__name__)
26
21
 
@@ -15,8 +15,10 @@ dashboard's structured ``error`` columns — populate instead of staying null.
15
15
 
16
16
  from __future__ import annotations
17
17
 
18
+ import email.utils
18
19
  import logging
19
20
  import re
21
+ import time
20
22
 
21
23
  from agents.llm_config import CODEBOARDING_KEY_TAIL, current_provider_key_context
22
24
 
@@ -62,6 +64,11 @@ _AUTH_MESSAGE_PATTERNS = (
62
64
  )
63
65
 
64
66
 
67
+ # Class names, across SDKs, for a request that never got an answer: openai/anthropic/cerebras raise
68
+ # ``APIConnectionError`` (``APITimeoutError`` subclasses it), ollama lets httpx's ``TransportError`` through.
69
+ _TRANSIENT_TYPE_NAMES = {"APIConnectionError", "TransportError", "TimeoutError", "ConnectionError"}
70
+
71
+
65
72
  # What each provider says when the prompt is over the model's context window: Google, OpenAI, Anthropic.
66
73
  _CONTEXT_OVERFLOW_PATTERNS = (
67
74
  re.compile(r"exceeds the maximum number of tokens", re.IGNORECASE),
@@ -111,6 +118,10 @@ def _status_code(exc: BaseException) -> int | None:
111
118
  code = getattr(exc, "status_code", None)
112
119
  if code is None:
113
120
  code = getattr(exc, "code", None) # google GoogleAPICallError.code
121
+ if code is None:
122
+ response = getattr(exc, "response", None) # botocore ClientError (Bedrock) keeps it in a dict
123
+ if isinstance(response, dict):
124
+ code = response.get("ResponseMetadata", {}).get("HTTPStatusCode")
114
125
  if code is None:
115
126
  return None
116
127
  try:
@@ -144,7 +155,11 @@ def detect_auth_error(exc: BaseException, *, provider: str, key_tail: str) -> LL
144
155
  status = _status_code(exc)
145
156
  provider_message = str(exc)
146
157
  status_note = f" (HTTP {status})" if status is not None else ""
147
- if key_tail == CODEBOARDING_KEY_TAIL:
158
+ if status == 403:
159
+ # A 403 can refuse one request (a router's moderation, a model the key may not use) while the same key
160
+ # serves the rest, so the provider's own reason says more than a hint about the key.
161
+ friendly = f"{provider} refused the request (HTTP 403): {provider_message[:500]}"
162
+ elif key_tail == CODEBOARDING_KEY_TAIL:
148
163
  friendly = (
149
164
  f"CodeBoarding's hosted {provider} credentials were rejected{status_note}. This run used no key of "
150
165
  "yours: check that the workflow grants `id-token: write`, then re-run."
@@ -168,6 +183,12 @@ def detect_auth_error(exc: BaseException, *, provider: str, key_tail: str) -> LL
168
183
  )
169
184
 
170
185
 
186
+ def _is_quota_exhausted(exc: BaseException) -> bool:
187
+ status = _status_code(exc)
188
+ quota_code = getattr(exc, "code", None) == "insufficient_quota" or "insufficient_quota" in str(exc)
189
+ return status == 402 or (status == 429 and quota_code)
190
+
191
+
171
192
  def llm_failure_properties(exc: BaseException) -> dict:
172
193
  """``$exception`` properties for a failed LLM call, telling an exhausted quota or an oversized prompt
173
194
  apart from other failures.
@@ -175,18 +196,52 @@ def llm_failure_properties(exc: BaseException) -> dict:
175
196
  Why: the hosted proxy's paywall is a 402, and OpenAI reports an empty balance as a 429 ``insufficient_quota``.
176
197
  An oversized prompt is ours to fix, not the provider's, so it gets its own type on the dashboard.
177
198
  """
178
- status = _status_code(exc)
179
- quota = status == 402 or (status == 429 and "insufficient_quota" in str(exc))
199
+ quota = _is_quota_exhausted(exc)
180
200
  context = isinstance(exc, ScopeContextTooLargeError) or any(p.search(str(exc)) for p in _CONTEXT_OVERFLOW_PATTERNS)
181
201
  provider, _key_tail = current_provider_key_context()
182
202
  return {
183
203
  "error_type": "quota" if quota else "context" if context else "llm",
184
204
  "error_provider": provider,
185
- "error_status_code": status,
205
+ "error_status_code": _status_code(exc),
186
206
  "error_message": str(exc)[:500],
187
207
  }
188
208
 
189
209
 
210
+ def is_transient_llm_error(exc: BaseException) -> bool:
211
+ """Whether the same request may succeed if sent again: throttled, a server error, or no answer at all.
212
+
213
+ Why: the hosted proxy answers a burst over its concurrency cap with a 429 and a failed upstream call with a
214
+ 502, and one of either used to fail the whole run. A rejected key, a spent quota or a malformed request fails
215
+ the same way every time.
216
+ """
217
+ status = _status_code(exc)
218
+ if status is not None:
219
+ return status in (408, 429) and not _is_quota_exhausted(exc) or status >= 500
220
+ return any(cls.__name__ in _TRANSIENT_TYPE_NAMES for cls in type(exc).__mro__)
221
+
222
+
223
+ def retry_after_seconds(exc: BaseException) -> float | None:
224
+ """The wait a provider asked for, when the exception carries the response: ``retry-after-ms``, or
225
+ ``Retry-After`` as seconds or an HTTP date. None when absent, unreadable or already past."""
226
+ headers = getattr(getattr(exc, "response", None), "headers", None)
227
+ if headers is None:
228
+ return None
229
+ try:
230
+ return max(0.0, float(headers.get("retry-after-ms", "")) / 1000)
231
+ except (TypeError, ValueError):
232
+ pass
233
+ value = headers.get("retry-after", "")
234
+ try:
235
+ return max(0.0, float(value))
236
+ except (TypeError, ValueError):
237
+ pass
238
+ try:
239
+ wait = email.utils.parsedate_to_datetime(value).timestamp() - time.time()
240
+ except (TypeError, ValueError):
241
+ return None
242
+ return wait if wait > 0 else None
243
+
244
+
190
245
  def raise_if_auth_error(exc: Exception) -> None:
191
246
  """Raise a typed terminal error when a provider rejected its credentials."""
192
247
  provider, key_tail = current_provider_key_context()
@@ -12,7 +12,7 @@ from typing import Any
12
12
  from agents.agent_responses import AnalysisInsights
13
13
  from agents.constants import ModelCapabilities
14
14
  from agents.llm_errors import ScopeContextTooLargeError
15
- from repo_utils.path_utils import normalize_repo_path
15
+ from infra.repo_utils.path_utils import normalize_repo_path
16
16
  from static_analyzer.cfg.edge import EdgeKind
17
17
  from static_analyzer.clustering import ClusterConnectionEdge, ClusterGroup, ClusterScopeResult
18
18
  from static_analyzer.node import Node
@@ -9,7 +9,7 @@ from functools import lru_cache
9
9
  from pathlib import Path
10
10
 
11
11
  from agents.constants import ModelCapabilities
12
- from utils import get_cache_dir
12
+ from infra.utils import get_cache_dir
13
13
 
14
14
  logger = logging.getLogger(__name__)
15
15
 
@@ -74,7 +74,7 @@ def _resolve_user_config(provider: str, model_name: str) -> tuple[int, int] | No
74
74
  def _user_context_window_override() -> int | None:
75
75
  # Why: delayed import avoids a module-load cycle; lru_cache avoids re-parsing
76
76
  # config.toml on every get_context_window call.
77
- from user_config import load_user_config
77
+ from infra.user_config import load_user_config
78
78
 
79
79
  return load_user_config().llm.context_window
80
80
 
@@ -4,8 +4,8 @@ from collections.abc import Callable, Collection
4
4
  from pathlib import Path
5
5
 
6
6
  from agents.agent_responses import AnalysisInsights, Relation, RelationEdge, SourceCodeReference
7
- from clustering_ids import is_self_or_descendant
8
- from repo_utils.path_utils import normalize_repo_path
7
+ from infra.clustering_ids import is_self_or_descendant
8
+ from infra.repo_utils.path_utils import normalize_repo_path
9
9
 
10
10
 
11
11
  def append_or_merge_relation(
@@ -3,12 +3,15 @@
3
3
  from __future__ import annotations
4
4
 
5
5
  import logging
6
+ import random
6
7
  import time
7
8
  from collections.abc import Callable
8
9
  from dataclasses import dataclass
9
10
  from enum import Enum, auto
10
11
  from typing import TypeVar
11
12
 
13
+ from agents.llm_errors import is_transient_llm_error, retry_after_seconds
14
+
12
15
  logger = logging.getLogger(__name__)
13
16
 
14
17
  T = TypeVar("T")
@@ -37,6 +40,29 @@ def default_backoff(attempt: int, *, initial_s: float, multiplier: float, max_s:
37
40
  return min(delay, max_s) if max_s is not None else delay
38
41
 
39
42
 
43
+ #: Attempts per model request. Why these numbers: the full-jitter ceilings run 4, 8, 16 and 32 s, so the
44
+ #: four retries span up to a minute — long enough for a slot to free up behind the hosted proxy's concurrency cap
45
+ #: (one held slot is one model call in flight, often tens of seconds) without doubling a run that is failing anyway.
46
+ LLM_MAX_ATTEMPTS = 5
47
+ LLM_BACKOFF_INITIAL_S = 4.0
48
+ LLM_BACKOFF_MAX_S = 60.0
49
+
50
+
51
+ def classify_llm_error(exc: Exception, attempt: int) -> RetryDecision:
52
+ """Retry a transient provider failure after the wait its ``Retry-After`` asks for, else a full-jitter backoff.
53
+
54
+ Why full jitter: the parallel calls one burst throttles would otherwise all retry in the same second and
55
+ collide again.
56
+ """
57
+ if not is_transient_llm_error(exc):
58
+ return RetryDecision(action=RetryAction.GIVE_UP)
59
+ delay = retry_after_seconds(exc)
60
+ if delay is None:
61
+ ceiling = default_backoff(attempt, initial_s=LLM_BACKOFF_INITIAL_S, multiplier=2.0, max_s=LLM_BACKOFF_MAX_S)
62
+ delay = random.uniform(0.0, ceiling)
63
+ return RetryDecision(action=RetryAction.RETRY, backoff_s=min(delay, LLM_BACKOFF_MAX_S))
64
+
65
+
40
66
  def _default_classify(_exc: Exception, _attempt: int) -> RetryDecision:
41
67
  return RetryDecision(action=RetryAction.RETRY)
42
68
 
@@ -25,13 +25,15 @@ from pydantic import Field
25
25
 
26
26
  from agents.agent_responses import AnalysisInsights, LLMBaseModel, RelationEdge, SourceCodeReference
27
27
  from agents.constants import ModelCapabilities
28
- from agents.llm_config import MONITORING_CALLBACK, get_current_agent_context_window, get_current_prompt_profile
28
+ from agents.llm_config import get_current_agent_context_window, get_current_prompt_profile
29
+ from infra.monitoring.callbacks import MONITORING_CALLBACK
29
30
  from agents.llm_errors import ScopeContextTooLargeError, raise_if_auth_error
30
31
  from agents.llm_renderers import render_scope_context, scope_file_paths, scope_method_names
31
32
  from agents.prompts import get_scope_analysis_prompts
33
+ from agents.retry import LLM_MAX_ATTEMPTS, classify_llm_error, with_retries
32
34
  from agents.tools import MethodCallsTool, ReadFileTool
33
35
  from agents.tools.base import RepoContext
34
- from monitoring.mixin import MonitoringMixin
36
+ from infra.monitoring.mixin import MonitoringMixin
35
37
  from static_analyzer.analysis_result import StaticAnalysisResults
36
38
  from static_analyzer.clustering import ClusterScopeResult
37
39
 
@@ -159,6 +161,24 @@ class ScopeInputBudget(AgentMiddleware):
159
161
  logger.warning("Scope %s: truncating tool result %s to fit context", self.scope_id, message.tool_call_id)
160
162
 
161
163
 
164
+ class TransientErrorRetry(AgentMiddleware):
165
+ """Send a model request again when the provider failed it transiently (throttled, 5xx, connection lost).
166
+
167
+ Why here: one model request is retried, not the agent run, so the tool calls already made are kept.
168
+ """
169
+
170
+ def __init__(self, scope_id: str):
171
+ self.scope_id = scope_id
172
+
173
+ def wrap_model_call(self, request: ModelRequest, handler: Callable[[ModelRequest], ModelResponse]) -> ModelResponse:
174
+ return with_retries(
175
+ lambda: handler(request),
176
+ max_attempts=LLM_MAX_ATTEMPTS,
177
+ classify=classify_llm_error,
178
+ log_prefix=f"Scope {self.scope_id} model call",
179
+ )
180
+
181
+
162
182
  class ScopeAnalysisAgent(MonitoringMixin):
163
183
  """Analyze any deterministic scope with two scope-restricted tools."""
164
184
 
@@ -209,6 +229,7 @@ class ScopeAnalysisAgent(MonitoringMixin):
209
229
  RepositoryToolBudget(run_limit=MAX_SCOPE_TOOL_CALLS, exit_behavior="continue"),
210
230
  ModelCallLimitMiddleware(run_limit=MAX_SCOPE_MODEL_CALLS, exit_behavior="error"),
211
231
  input_budget,
232
+ TransientErrorRetry(scope.scope_id),
212
233
  ]
213
234
  agent: CompiledStateGraph = create_agent(
214
235
  model=self.agent_llm,
@@ -0,0 +1,3 @@
1
+ from infra.clustering_ids import ROOT_SCOPE_ID
2
+
3
+ __all__ = ["ROOT_SCOPE_ID"]
@@ -4,7 +4,7 @@ from langchain_core.tools import ArgsSchema
4
4
  from pydantic import BaseModel, Field
5
5
 
6
6
  from agents.tools.base import BaseRepoTool
7
- from repo_utils.path_utils import normalize_repo_path
7
+ from infra.repo_utils.path_utils import normalize_repo_path
8
8
 
9
9
  logger = logging.getLogger(__name__)
10
10
 
@@ -3,6 +3,7 @@
3
3
  import json
4
4
  import logging
5
5
  import re
6
+ import time
6
7
  from collections import Counter
7
8
  from collections.abc import Sequence
8
9
  from concurrent.futures import ThreadPoolExecutor
@@ -13,12 +14,13 @@ from langchain_core.messages import HumanMessage, SystemMessage
13
14
  from langchain_core.prompts import PromptTemplate
14
15
 
15
16
  from agents.agent_responses import PlannedGroup, TreePlanInsights
16
- from agents.llm_config import MONITORING_CALLBACK, get_current_prompt_profile, supports_json_mode
17
+ from agents.llm_config import get_current_prompt_profile, supports_json_mode
18
+ from infra.monitoring.callbacks import MONITORING_CALLBACK
17
19
  from agents.llm_errors import LLMAuthError, raise_if_auth_error
18
20
  from agents.prompts import get_tree_plan_prompts
19
- from agents.retry import RetryAction, RetryDecision, default_backoff, with_retries
20
- from monitoring import trace
21
- from monitoring.mixin import MonitoringMixin
21
+ from agents.retry import LLM_MAX_ATTEMPTS, RetryAction, RetryDecision, classify_llm_error, with_retries
22
+ from infra.monitoring import trace
23
+ from infra.monitoring.mixin import MonitoringMixin
22
24
  from static_analyzer.clustering.names import CandidateGroup, GroupingContext, KinshipGrouper, stem, tokenize
23
25
  from static_analyzer.clustering.names.draft import GUARD_SHARE, MIN_UNITS
24
26
  from static_analyzer.clustering.names.frontier import Candidate
@@ -135,15 +137,21 @@ class TreePlannerAgent(MonitoringMixin):
135
137
  raise ValueError("planner returned malformed JSON")
136
138
  return insights
137
139
 
140
+ # Why: ``_draw`` stops waiting after DRAW_TIMEOUT_SECONDS but cannot stop this worker, so no new
141
+ # attempt starts once the draw has been abandoned.
142
+ deadline = time.monotonic() + DRAW_TIMEOUT_SECONDS
143
+
138
144
  def classify(exc: Exception, attempt: int) -> RetryDecision:
139
145
  raise_if_auth_error(exc)
140
146
  if isinstance(exc, ValueError):
141
- return RetryDecision(action=RetryAction.RETRY_NOW)
142
- return RetryDecision(
143
- action=RetryAction.RETRY, backoff_s=default_backoff(attempt, initial_s=10.0, multiplier=2.0, max_s=60.0)
144
- )
145
-
146
- return with_retries(once, max_attempts=3, classify=classify, log_prefix="Planner draw")
147
+ decision = RetryDecision(action=RetryAction.RETRY_NOW)
148
+ else:
149
+ decision = classify_llm_error(exc, attempt)
150
+ if time.monotonic() + decision.backoff_s >= deadline:
151
+ return RetryDecision(action=RetryAction.GIVE_UP)
152
+ return decision
153
+
154
+ return with_retries(once, max_attempts=LLM_MAX_ATTEMPTS, classify=classify, log_prefix="Planner draw")
147
155
 
148
156
  @staticmethod
149
157
  def _read(text: str, labelled: dict[str, CandidateGroup]) -> TreePlanInsights | None:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.14.5
3
+ Version: 0.15.0
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -52,6 +52,7 @@ Requires-Dist: tree-sitter-c-sharp==0.23.5
52
52
  Requires-Dist: tree-sitter-go==0.25.0
53
53
  Requires-Dist: tree-sitter-java==0.23.5
54
54
  Requires-Dist: tree-sitter-javascript==0.25.0
55
+ Requires-Dist: tree-sitter-language-pack==1.21.0
55
56
  Requires-Dist: tree-sitter-php==0.24.1
56
57
  Requires-Dist: tree-sitter-python==0.25.0
57
58
  Requires-Dist: tree-sitter-rust==0.24.2
@@ -84,13 +85,14 @@ Dynamic: license-file
84
85
  - Builds layered abstractions with an LLM agent (OpenAI, Anthropic, Google Gemini, Ollama, and more)
85
86
  - Outputs Mermaid.js diagrams ready for docs, IDEs, and CI/CD pipelines
86
87
 
87
- **Supported languages:** Python · TypeScript · JavaScript · Java · Go · PHP
88
+ **Supported languages:** Python · TypeScript · JavaScript · Java · Kotlin · Go · PHP
88
89
 
89
90
  ---
90
91
 
91
92
  ## Requirements
92
93
 
93
94
  - **Python 3.12 or 3.13** — other versions are currently not supported.
95
+ - **Linux:** glibc 2.34 or newer (Ubuntu 22.04, Debian 12, RHEL 9 or later), for the Kotlin parser.
94
96
 
95
97
  ## Installation
96
98