codeboarding 0.13.11__tar.gz → 0.14.1__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 (237) hide show
  1. {codeboarding-0.13.11/codeboarding.egg-info → codeboarding-0.14.1}/PKG-INFO +9 -11
  2. {codeboarding-0.13.11 → codeboarding-0.14.1}/PYPI.md +8 -6
  3. {codeboarding-0.13.11 → codeboarding-0.14.1}/README.md +19 -6
  4. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/agent_responses.py +18 -239
  5. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/component_ownership.py +1 -13
  6. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/constants.py +3 -7
  7. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/llm_config.py +57 -99
  8. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/llm_errors.py +14 -0
  9. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/llm_renderers/__init__.py +4 -10
  10. codeboarding-0.14.1/agents/llm_renderers/scope.py +217 -0
  11. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/planner_agent.py +1 -1
  12. codeboarding-0.14.1/agents/prompts/__init__.py +41 -0
  13. codeboarding-0.14.1/agents/prompts/profiles.py +27 -0
  14. codeboarding-0.14.1/agents/prompts/shared.py +107 -0
  15. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/retry.py +1 -25
  16. codeboarding-0.14.1/agents/scope_analysis_agent.py +164 -0
  17. codeboarding-0.14.1/agents/tools/__init__.py +4 -0
  18. codeboarding-0.14.1/agents/tools/base.py +36 -0
  19. codeboarding-0.14.1/agents/tools/get_method_calls.py +55 -0
  20. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/tools/read_file.py +16 -31
  21. codeboarding-0.14.1/agents/tree_planner_agent.py +288 -0
  22. {codeboarding-0.13.11 → codeboarding-0.14.1/codeboarding.egg-info}/PKG-INFO +9 -11
  23. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding.egg-info/SOURCES.txt +15 -39
  24. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding.egg-info/requires.txt +0 -4
  25. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding.egg-info/top_level.txt +0 -1
  26. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/bootstrap.py +1 -1
  27. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/commands/full_analysis.py +15 -11
  28. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/analysis.py +17 -19
  29. {codeboarding-0.13.11 → codeboarding-0.14.1}/constants.py +4 -2
  30. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/__init__.py +4 -4
  31. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/analysis_json.py +10 -3
  32. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/diagram_generator.py +463 -311
  33. codeboarding-0.13.11/agents/incremental_agent.py → codeboarding-0.14.1/diagram_analysis/incremental_update.py +45 -317
  34. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/io_utils.py +20 -8
  35. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/run_context.py +2 -2
  36. codeboarding-0.14.1/diagram_analysis/scope_assembly.py +408 -0
  37. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/scope_plan.py +29 -24
  38. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/tree_shape.py +1 -9
  39. {codeboarding-0.13.11 → codeboarding-0.14.1}/github_action.py +8 -6
  40. {codeboarding-0.13.11 → codeboarding-0.14.1}/main.py +1 -1
  41. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/rendering.py +3 -2
  42. {codeboarding-0.13.11 → codeboarding-0.14.1}/pyproject.toml +2 -6
  43. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/__init__.py +11 -12
  44. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/analysis_cache.py +8 -1
  45. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/analysis_result.py +0 -14
  46. codeboarding-0.14.1/static_analyzer/clustering/__init__.py +21 -0
  47. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/clustering/exceptions.py +14 -0
  48. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/clustering/models.py +18 -68
  49. codeboarding-0.14.1/static_analyzer/clustering/names/__init__.py +56 -0
  50. codeboarding-0.14.1/static_analyzer/clustering/names/draft.py +667 -0
  51. codeboarding-0.14.1/static_analyzer/clustering/names/frontier.py +263 -0
  52. codeboarding-0.14.1/static_analyzer/clustering/names/inventory.py +116 -0
  53. codeboarding-0.14.1/static_analyzer/clustering/names/replay.py +139 -0
  54. codeboarding-0.14.1/static_analyzer/clustering/names/spec.py +222 -0
  55. codeboarding-0.14.1/static_analyzer/clustering/names/tokens.py +131 -0
  56. codeboarding-0.14.1/static_analyzer/clustering/service.py +464 -0
  57. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/config.py +1 -38
  58. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/csharp_adapter.py +41 -27
  59. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/java_adapter.py +31 -54
  60. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/call_graph_builder.py +31 -9
  61. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/language_adapter.py +16 -0
  62. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/models.py +3 -0
  63. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/source_inspector.py +35 -0
  64. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/symbol_table.py +9 -9
  65. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/language_results.py +0 -3
  66. {codeboarding-0.13.11 → codeboarding-0.14.1}/telemetry/events.py +3 -3
  67. {codeboarding-0.13.11 → codeboarding-0.14.1}/telemetry/schemas.py +2 -2
  68. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_cli_parser.py +85 -0
  69. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_github_action.py +21 -17
  70. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_main.py +28 -25
  71. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_telemetry_events.py +9 -6
  72. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_user_config.py +31 -0
  73. {codeboarding-0.13.11 → codeboarding-0.14.1}/user_config.py +27 -4
  74. codeboarding-0.13.11/agents/abstraction_agent.py +0 -218
  75. codeboarding-0.13.11/agents/agent.py +0 -492
  76. codeboarding-0.13.11/agents/dependency_discovery.py +0 -159
  77. codeboarding-0.13.11/agents/details_agent.py +0 -244
  78. codeboarding-0.13.11/agents/llm_renderers/clustering.py +0 -129
  79. codeboarding-0.13.11/agents/meta_agent.py +0 -64
  80. codeboarding-0.13.11/agents/prompts/__init__.py +0 -85
  81. codeboarding-0.13.11/agents/prompts/abstract_prompt_factory.py +0 -63
  82. codeboarding-0.13.11/agents/prompts/claude_prompts.py +0 -309
  83. codeboarding-0.13.11/agents/prompts/deepseek_prompts.py +0 -355
  84. codeboarding-0.13.11/agents/prompts/gemini_flash_prompts.py +0 -291
  85. codeboarding-0.13.11/agents/prompts/glm_prompts.py +0 -335
  86. codeboarding-0.13.11/agents/prompts/gpt_prompts.py +0 -353
  87. codeboarding-0.13.11/agents/prompts/kimi_prompts.py +0 -335
  88. codeboarding-0.13.11/agents/prompts/prompt_factory.py +0 -183
  89. codeboarding-0.13.11/agents/repair.py +0 -124
  90. codeboarding-0.13.11/agents/static_analysis_enricher_mixin.py +0 -225
  91. codeboarding-0.13.11/agents/tools/__init__.py +0 -9
  92. codeboarding-0.13.11/agents/tools/base.py +0 -104
  93. codeboarding-0.13.11/agents/tools/component_bridge_edges.py +0 -68
  94. codeboarding-0.13.11/agents/tools/get_external_deps.py +0 -47
  95. codeboarding-0.13.11/agents/tools/get_method_invocations.py +0 -47
  96. codeboarding-0.13.11/agents/tools/list_git_changes.py +0 -27
  97. codeboarding-0.13.11/agents/tools/read_cfg.py +0 -62
  98. codeboarding-0.13.11/agents/tools/read_docs.py +0 -132
  99. codeboarding-0.13.11/agents/tools/read_file_structure.py +0 -155
  100. codeboarding-0.13.11/agents/tools/read_packages.py +0 -60
  101. codeboarding-0.13.11/agents/tools/read_source.py +0 -85
  102. codeboarding-0.13.11/agents/tools/read_structure.py +0 -49
  103. codeboarding-0.13.11/agents/tools/toolkit.py +0 -128
  104. codeboarding-0.13.11/agents/validation.py +0 -481
  105. codeboarding-0.13.11/caching/__init__.py +0 -8
  106. codeboarding-0.13.11/caching/cache.py +0 -255
  107. codeboarding-0.13.11/caching/meta_cache.py +0 -108
  108. codeboarding-0.13.11/static_analyzer/clustering/__init__.py +0 -27
  109. codeboarding-0.13.11/static_analyzer/clustering/cache.py +0 -104
  110. codeboarding-0.13.11/static_analyzer/clustering/delta.py +0 -473
  111. codeboarding-0.13.11/static_analyzer/clustering/engine.py +0 -223
  112. codeboarding-0.13.11/static_analyzer/clustering/expansion.py +0 -30
  113. codeboarding-0.13.11/static_analyzer/clustering/grouping.py +0 -436
  114. codeboarding-0.13.11/static_analyzer/clustering/service.py +0 -780
  115. codeboarding-0.13.11/static_analyzer/clustering/snapshot.py +0 -111
  116. codeboarding-0.13.11/static_analyzer/leiden_utils.py +0 -101
  117. {codeboarding-0.13.11 → codeboarding-0.14.1}/LICENSE +0 -0
  118. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/__init__.py +0 -0
  119. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/change_status.py +0 -0
  120. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/content_hash.py +0 -0
  121. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/file_index_models.py +0 -0
  122. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/incremental_results.py +0 -0
  123. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/llm_renderers/call_graph.py +0 -0
  124. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/model_capabilities.py +0 -0
  125. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/relation_edges.py +0 -0
  126. {codeboarding-0.13.11 → codeboarding-0.14.1}/agents/scope_ids.py +0 -0
  127. {codeboarding-0.13.11 → codeboarding-0.14.1}/clustering_ids.py +0 -0
  128. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding.egg-info/dependency_links.txt +0 -0
  129. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding.egg-info/entry_points.txt +0 -0
  130. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/__init__.py +0 -0
  131. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/commands/__init__.py +0 -0
  132. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/commands/incremental_analysis.py +0 -0
  133. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/commands/partial_analysis.py +0 -0
  134. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/render.py +0 -0
  135. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_cli/view_instructions.py +0 -0
  136. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/__init__.py +0 -0
  137. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/orchestration.py +0 -0
  138. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/sources/__init__.py +0 -0
  139. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/sources/local.py +0 -0
  140. {codeboarding-0.13.11 → codeboarding-0.14.1}/codeboarding_workflows/sources/remote.py +0 -0
  141. {codeboarding-0.13.11 → codeboarding-0.14.1}/core/__init__.py +0 -0
  142. {codeboarding-0.13.11 → codeboarding-0.14.1}/core/plugin_loader.py +0 -0
  143. {codeboarding-0.13.11 → codeboarding-0.14.1}/core/protocols.py +0 -0
  144. {codeboarding-0.13.11 → codeboarding-0.14.1}/core/registry.py +0 -0
  145. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/exceptions.py +0 -0
  146. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/file_coverage.py +0 -0
  147. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/file_index.py +0 -0
  148. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/incremental_changes.py +0 -0
  149. {codeboarding-0.13.11 → codeboarding-0.14.1}/diagram_analysis/run_mode.py +0 -0
  150. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/__init__.py +0 -0
  151. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/checks/__init__.py +0 -0
  152. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/checks/circular_deps.py +0 -0
  153. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/checks/function_size.py +0 -0
  154. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/checks/unused_code_diagnostics.py +0 -0
  155. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/config.py +0 -0
  156. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/models.py +0 -0
  157. {codeboarding-0.13.11 → codeboarding-0.14.1}/health/runner.py +0 -0
  158. {codeboarding-0.13.11 → codeboarding-0.14.1}/install.py +0 -0
  159. {codeboarding-0.13.11 → codeboarding-0.14.1}/logging_config.py +0 -0
  160. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/__init__.py +0 -0
  161. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/callbacks.py +0 -0
  162. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/context.py +0 -0
  163. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/mixin.py +0 -0
  164. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/paths.py +0 -0
  165. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/stats.py +0 -0
  166. {codeboarding-0.13.11 → codeboarding-0.14.1}/monitoring/writers.py +0 -0
  167. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/__init__.py +0 -0
  168. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/html.py +0 -0
  169. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/html_template.py +0 -0
  170. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/markdown.py +0 -0
  171. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/mdx.py +0 -0
  172. {codeboarding-0.13.11 → codeboarding-0.14.1}/output_generators/sphinx.py +0 -0
  173. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/__init__.py +0 -0
  174. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/change_detector.py +0 -0
  175. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/errors.py +0 -0
  176. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/fingerprint_diff.py +0 -0
  177. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/git_ops.py +0 -0
  178. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/ignore.py +0 -0
  179. {codeboarding-0.13.11 → codeboarding-0.14.1}/repo_utils/path_utils.py +0 -0
  180. {codeboarding-0.13.11 → codeboarding-0.14.1}/setup.cfg +0 -0
  181. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/cfg/__init__.py +0 -0
  182. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/cfg/call_graph.py +0 -0
  183. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/cfg/edge.py +0 -0
  184. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/cfg/location_key.py +0 -0
  185. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/cluster_relations.py +0 -0
  186. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/csharp_config_scanner.py +0 -0
  187. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/dotnet_sdk.py +0 -0
  188. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/__init__.py +0 -0
  189. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/__init__.py +0 -0
  190. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/go_adapter.py +0 -0
  191. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/php_adapter.py +0 -0
  192. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/python_adapter.py +0 -0
  193. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/rust_adapter.py +0 -0
  194. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
  195. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/edge_build_context.py +0 -0
  196. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/edge_builder.py +0 -0
  197. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/hierarchy_builder.py +0 -0
  198. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/lsp_client.py +0 -0
  199. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/lsp_constants.py +0 -0
  200. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/lsp_recycler.py +0 -0
  201. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/process_memory.py +0 -0
  202. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/progress.py +0 -0
  203. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/protocols.py +0 -0
  204. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/result_converter.py +0 -0
  205. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/engine/utils.py +0 -0
  206. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/incremental_orchestrator.py +0 -0
  207. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/internal_references.py +0 -0
  208. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/java_config_scanner.py +0 -0
  209. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/java_utils.py +0 -0
  210. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/lsp_client/__init__.py +0 -0
  211. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/lsp_client/diagnostics.py +0 -0
  212. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/node.py +0 -0
  213. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/programming_language.py +0 -0
  214. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/reference_resolver.py +0 -0
  215. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/scanner.py +0 -0
  216. {codeboarding-0.13.11 → codeboarding-0.14.1}/static_analyzer/typescript_config_scanner.py +0 -0
  217. {codeboarding-0.13.11 → codeboarding-0.14.1}/telemetry/__init__.py +0 -0
  218. {codeboarding-0.13.11 → codeboarding-0.14.1}/telemetry/device_id.py +0 -0
  219. {codeboarding-0.13.11 → codeboarding-0.14.1}/telemetry/service.py +0 -0
  220. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_install.py +0 -0
  221. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_logging_config.py +0 -0
  222. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_persisted_analysis_artifacts.py +0 -0
  223. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_pyproject_packages.py +0 -0
  224. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_registry_coverage.py +0 -0
  225. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_telemetry_service.py +0 -0
  226. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_tool_registry.py +0 -0
  227. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_view_instructions.py +0 -0
  228. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_vscode_constants.py +0 -0
  229. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_windows_compatibility.py +0 -0
  230. {codeboarding-0.13.11 → codeboarding-0.14.1}/tests/test_windows_encoding.py +0 -0
  231. {codeboarding-0.13.11 → codeboarding-0.14.1}/tool_registry/__init__.py +0 -0
  232. {codeboarding-0.13.11 → codeboarding-0.14.1}/tool_registry/installers.py +0 -0
  233. {codeboarding-0.13.11 → codeboarding-0.14.1}/tool_registry/manifest.py +0 -0
  234. {codeboarding-0.13.11 → codeboarding-0.14.1}/tool_registry/paths.py +0 -0
  235. {codeboarding-0.13.11 → codeboarding-0.14.1}/tool_registry/registry.py +0 -0
  236. {codeboarding-0.13.11 → codeboarding-0.14.1}/utils.py +0 -0
  237. {codeboarding-0.13.11 → codeboarding-0.14.1}/vscode_constants.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.13.11
3
+ Version: 0.14.1
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -22,7 +22,6 @@ Requires-Dist: fastapi>=0.115
22
22
  Requires-Dist: filelock>=3.12
23
23
  Requires-Dist: gitpython>=3.1
24
24
  Requires-Dist: google-api-core>=2.10
25
- Requires-Dist: igraph>=1.0
26
25
  Requires-Dist: jsonpatch>=1.33
27
26
  Requires-Dist: jsonschema>=4.25
28
27
  Requires-Dist: langchain>=1.2
@@ -35,7 +34,6 @@ Requires-Dist: langchain-google-genai>=3.1
35
34
  Requires-Dist: langchain-ollama>=1.0
36
35
  Requires-Dist: langchain-openai>=1.1
37
36
  Requires-Dist: langgraph>=1.0
38
- Requires-Dist: leidenalg>=0.10
39
37
  Requires-Dist: markdown>=3.8
40
38
  Requires-Dist: markdown-it-py>=3.0
41
39
  Requires-Dist: markitdown>=0.1
@@ -48,7 +46,6 @@ Requires-Dist: pyyaml>=6.0
48
46
  Requires-Dist: regex>=2024.11
49
47
  Requires-Dist: requests>=2.32
50
48
  Requires-Dist: rich>=12.6
51
- Requires-Dist: sqlalchemy>=2.0
52
49
  Requires-Dist: tqdm>=4.67
53
50
  Requires-Dist: tree-sitter==0.25.2
54
51
  Requires-Dist: tree-sitter-c-sharp==0.23.5
@@ -59,7 +56,6 @@ Requires-Dist: tree-sitter-php==0.24.1
59
56
  Requires-Dist: tree-sitter-python==0.25.0
60
57
  Requires-Dist: tree-sitter-rust==0.24.2
61
58
  Requires-Dist: tree-sitter-typescript==0.23.2
62
- Requires-Dist: trustcall>=0.0.39
63
59
  Requires-Dist: uvicorn>=0.23
64
60
  Provides-Extra: dev
65
61
  Requires-Dist: pytest>=8.3; extra == "dev"
@@ -144,7 +140,7 @@ generated `.codeboarding/analysis.json` — it is parsed in your browser, nothin
144
140
  ```python
145
141
  import json
146
142
  from pathlib import Path
147
- from diagram_analysis import DiagramGenerator, configure_models
143
+ from diagram_analysis import DiagramGenerator, RunContext, configure_models
148
144
  from diagram_analysis.analysis_json import parse_unified_analysis
149
145
 
150
146
  # Pass the key programmatically — shell env vars always take precedence if already set.
@@ -157,14 +153,17 @@ output_dir = repo_path / ".codeboarding"
157
153
  output_dir.mkdir(parents=True, exist_ok=True)
158
154
 
159
155
  # Generate the architectural diagram
156
+ context = RunContext.resolve("my-project")
160
157
  generator = DiagramGenerator(
161
158
  repo_location=repo_path,
162
159
  temp_folder=output_dir,
163
160
  repo_name="my-project",
164
161
  output_dir=output_dir,
165
- depth_level=3, # safety-valve cap; a component that outgrows the leaf ceiling is flagged expandable and can be expanded on demand
162
+ depth_cap=3, # Maximum hierarchy depth for automatic expansion, not a target.
163
+ run_id=context.run_id,
164
+ log_path=context.log_path,
166
165
  )
167
- [analysis_path] = generator.generate_analysis()
166
+ analysis_path = generator.generate_analysis()
168
167
 
169
168
  # Read and inspect the results
170
169
  with open(analysis_path) as f:
@@ -201,8 +200,7 @@ LLM provider keys and model overrides are stored in `~/.codeboarding/config.toml
201
200
 
202
201
  [llm]
203
202
  # Optional: override the default model for your active provider
204
- # agent_model = "gemini-3.7-flash"
205
- # parsing_model = "gemini-3.1-flash-lite"
203
+ # agent_model = "gemini-3.8-flash"
206
204
  ```
207
205
 
208
206
  Shell environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.) always take precedence over the config file, so CI/CD pipelines need no changes. For private repositories, set `GITHUB_TOKEN` in your environment.
@@ -226,7 +224,7 @@ codeboarding-render PATH/analysis.json --format FORMAT # render an existing anal
226
224
  |---|---|
227
225
  | `--local PATH` | Analyze a local repository (output: `PATH/.codeboarding/`) |
228
226
  | `--render {md,html,mdx,rst}` | Render overview and component files from the local `analysis.json` for full, incremental, or partial commands |
229
- | `--depth-level INT` | Safety-valve depth cap (default: 3) on how deep auto-expansion goes; a component that outgrows the leaf ceiling is flagged expandable regardless, and can be expanded on demand |
227
+ | `--depth-cap INT` | Maximum allowed hierarchy depth for automatic expansion (default: 3), not a target. Components can still be expanded on demand. Configures `metadata.depth_cap`, not `metadata.depth_level` (the depth actually reached). No input alias is accepted. |
230
228
  | `--force` | (full only) Force full reanalysis, skip cached static analysis |
231
229
  | `--base-ref REF` / `--target-ref REF` | (incremental only) Git refs to diff |
232
230
  | `--component-id ID` | (partial only) ID of the component to update |
@@ -67,7 +67,7 @@ generated `.codeboarding/analysis.json` — it is parsed in your browser, nothin
67
67
  ```python
68
68
  import json
69
69
  from pathlib import Path
70
- from diagram_analysis import DiagramGenerator, configure_models
70
+ from diagram_analysis import DiagramGenerator, RunContext, configure_models
71
71
  from diagram_analysis.analysis_json import parse_unified_analysis
72
72
 
73
73
  # Pass the key programmatically — shell env vars always take precedence if already set.
@@ -80,14 +80,17 @@ output_dir = repo_path / ".codeboarding"
80
80
  output_dir.mkdir(parents=True, exist_ok=True)
81
81
 
82
82
  # Generate the architectural diagram
83
+ context = RunContext.resolve("my-project")
83
84
  generator = DiagramGenerator(
84
85
  repo_location=repo_path,
85
86
  temp_folder=output_dir,
86
87
  repo_name="my-project",
87
88
  output_dir=output_dir,
88
- depth_level=3, # safety-valve cap; a component that outgrows the leaf ceiling is flagged expandable and can be expanded on demand
89
+ depth_cap=3, # Maximum hierarchy depth for automatic expansion, not a target.
90
+ run_id=context.run_id,
91
+ log_path=context.log_path,
89
92
  )
90
- [analysis_path] = generator.generate_analysis()
93
+ analysis_path = generator.generate_analysis()
91
94
 
92
95
  # Read and inspect the results
93
96
  with open(analysis_path) as f:
@@ -124,8 +127,7 @@ LLM provider keys and model overrides are stored in `~/.codeboarding/config.toml
124
127
 
125
128
  [llm]
126
129
  # Optional: override the default model for your active provider
127
- # agent_model = "gemini-3.7-flash"
128
- # parsing_model = "gemini-3.1-flash-lite"
130
+ # agent_model = "gemini-3.8-flash"
129
131
  ```
130
132
 
131
133
  Shell environment variables (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, etc.) always take precedence over the config file, so CI/CD pipelines need no changes. For private repositories, set `GITHUB_TOKEN` in your environment.
@@ -149,7 +151,7 @@ codeboarding-render PATH/analysis.json --format FORMAT # render an existing anal
149
151
  |---|---|
150
152
  | `--local PATH` | Analyze a local repository (output: `PATH/.codeboarding/`) |
151
153
  | `--render {md,html,mdx,rst}` | Render overview and component files from the local `analysis.json` for full, incremental, or partial commands |
152
- | `--depth-level INT` | Safety-valve depth cap (default: 3) on how deep auto-expansion goes; a component that outgrows the leaf ceiling is flagged expandable regardless, and can be expanded on demand |
154
+ | `--depth-cap INT` | Maximum allowed hierarchy depth for automatic expansion (default: 3), not a target. Components can still be expanded on demand. Configures `metadata.depth_cap`, not `metadata.depth_level` (the depth actually reached). No input alias is accepted. |
153
155
  | `--force` | (full only) Force full reanalysis, skip cached static analysis |
154
156
  | `--base-ref REF` / `--target-ref REF` | (incremental only) Git refs to diff |
155
157
  | `--component-id ID` | (partial only) ID of the component to update |
@@ -138,13 +138,12 @@ On first run, CodeBoarding creates `~/.codeboarding/config.toml`. Set one provid
138
138
  # litellm_api_key = "sk-..." # LiteLLM proxy server key (optional)
139
139
 
140
140
  [llm]
141
- # agent_model = "gemini-3.7-flash"
142
- # parsing_model = "gemini-3.1-flash-lite"
141
+ # agent_model = "gemini-3.8-flash"
143
142
  ```
144
143
 
145
- `openai_base_url` points CodeBoarding at any OpenAI-compatible gateway. Set the gateway API key as `openai_api_key`, then choose its model IDs with `agent_model` and `parsing_model`. The equivalent shell variables are `OPENAI_BASE_URL`, `OPENAI_API_KEY`, `AGENT_MODEL`, and `PARSING_MODEL`.
144
+ `openai_base_url` points CodeBoarding at any OpenAI-compatible gateway, including LM Studio. Set its model ID with `agent_model`; CodeBoarding adapts its prompts for the model families already represented by its provider defaults, including Qwen. The equivalent shell variables are `OPENAI_BASE_URL`, `OPENAI_API_KEY`, and `AGENT_MODEL`.
146
145
 
147
- `anthropic_base_url` points the Anthropic client at a compatible Messages API, including Azure Foundry Claude deployments. Set the deployment key as `anthropic_api_key` and use canonical Anthropic model IDs such as `claude-sonnet-5` for `agent_model` and `parsing_model` so CodeBoarding selects the correct model capabilities and prompts.
146
+ `anthropic_base_url` points the Anthropic client at a compatible Messages API, including Azure Foundry Claude deployments. Set the deployment key as `anthropic_api_key` and use canonical Anthropic model IDs such as `claude-sonnet-5` for `agent_model` so CodeBoarding selects the correct model capabilities and prompts.
148
147
 
149
148
  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.
150
149
 
@@ -156,8 +155,8 @@ python main.py full --local ./my-project
156
155
 
157
156
  # Raise the depth ceiling to auto-expand deeper (rarely needed — a component that
158
157
  # outgrows the leaf ceiling is flagged expandable at whatever depth the run stops
159
- # and can be expanded on demand; --depth-level is a safety-valve cap, default 3)
160
- python main.py full --local ./my-project --depth-level 5
158
+ # and can be expanded on demand; --depth-cap is a safety-valve cap, default 3)
159
+ python main.py full --local ./my-project --depth-cap 5
161
160
 
162
161
  # Re-analyze only changed parts when possible
163
162
  python main.py incremental --local ./my-project
@@ -169,6 +168,20 @@ python main.py partial --local ./my-project --component-id "1.2"
169
168
  python main.py full https://github.com/pytorch/pytorch
170
169
  ```
171
170
 
171
+ `--depth-cap` configures `metadata.depth_cap`; `metadata.depth_level` records the
172
+ depth actually reached. The cap is a maximum, not a target depth. `--depth-level`
173
+ is rejected; there is no compatibility alias.
174
+
175
+ Python callers must use `run_full(..., depth_cap=...)`,
176
+ `build_generator(..., depth_cap=...)`, and `DiagramGenerator(..., depth_cap=...)`.
177
+ The generator attribute is `depth_cap` and the exported default is
178
+ `diagram_analysis.DEFAULT_DEPTH_CAP` (3). The GitHub helper uses `DIAGRAM_DEPTH_CAP`
179
+ and rejects `DIAGRAM_DEPTH_LEVEL`. Telemetry reports configured `depth_cap`, not
180
+ `depth_level`. Readers of analysis results must keep reading `metadata.depth_level`
181
+ for the actual depth. Existing baseline loading behavior is unchanged: prefer
182
+ `metadata.depth_cap`, fall back to legacy `metadata.depth_level`, then use
183
+ `DEFAULT_DEPTH_CAP` if neither exists. This metadata fallback is not a CLI alias.
184
+
172
185
  > **Incremental needs a baseline.** `incremental` diffs the working tree against the previous
173
186
  > analysis in `.codeboarding/` (`analysis.json` + `fingerprint.json`). That baseline can live
174
187
  > purely locally — a prior `full`/`incremental` run in the same output dir is enough. Commit
@@ -5,10 +5,8 @@ import logging
5
5
  from abc import abstractmethod
6
6
  from collections.abc import Hashable
7
7
  from enum import StrEnum
8
- from typing import get_origin
9
8
 
10
9
  from pydantic import BaseModel, Field
11
- from pydantic.fields import FieldInfo
12
10
 
13
11
  from clustering_ids import ComponentId
14
12
  from agents.file_index_models import FileEntry, FileMethodGroup, MethodIndexEntry
@@ -18,112 +16,12 @@ logger = logging.getLogger(__name__)
18
16
 
19
17
 
20
18
  class LLMBaseModel(BaseModel, abc.ABC):
21
- """Base model for LLM-parseable response types."""
19
+ """Base model for semantic response types with prompt rendering."""
22
20
 
23
21
  @abstractmethod
24
22
  def llm_str(self) -> str:
25
23
  raise NotImplementedError("LLM String has to be implemented.")
26
24
 
27
- @classmethod
28
- def _is_field_hidden(cls, fvalue: FieldInfo) -> bool:
29
- if fvalue.exclude:
30
- return True
31
- extra = fvalue.json_schema_extra
32
- if isinstance(extra, dict):
33
- return bool(extra.get("hidden"))
34
- return False
35
-
36
- @classmethod
37
- def _excluded_fields(cls, include_hidden: bool = False) -> set[str]:
38
- if include_hidden:
39
- return set()
40
- names: set[str] = set()
41
- for klass in cls.__mro__:
42
- if hasattr(klass, "model_fields"):
43
- for fname, finfo in klass.model_fields.items():
44
- if cls._is_field_hidden(finfo):
45
- names.add(fname)
46
- return names
47
-
48
- @classmethod
49
- def _resolve_excluded_by_title(cls, include_hidden: bool = False) -> dict[str, set[str]]:
50
- seen: set[type] = set()
51
- result: dict[str, set[str]] = {}
52
-
53
- def walk(model: type) -> None:
54
- if model in seen or not hasattr(model, "model_fields"):
55
- return
56
- seen.add(model)
57
- title = getattr(model, "__name__", "")
58
- excluded = model._excluded_fields(include_hidden) # type: ignore[attr-defined]
59
- if excluded:
60
- result[title] = excluded
61
- for finfo in getattr(model, "model_fields", {}).values():
62
- ann = finfo.annotation
63
- for candidate in getattr(ann, "__args__", [ann]):
64
- if isinstance(candidate, type) and issubclass(candidate, LLMBaseModel):
65
- walk(candidate) # type: ignore[arg-type]
66
-
67
- walk(cls)
68
- return result
69
-
70
- @classmethod
71
- def _extractor_fields(cls, indent: str = " ", include_hidden: bool = False) -> str:
72
- parts: list[str] = []
73
- for fname, fvalue in cls.model_fields.items():
74
- if cls._is_field_hidden(fvalue) and not include_hidden:
75
- continue
76
- ftype = fvalue.annotation
77
- if get_origin(ftype) is list:
78
- if ftype is not None and hasattr(ftype, "__args__"):
79
- inner = ftype.__args__[0]
80
- if isinstance(inner, type) and issubclass(inner, LLMBaseModel):
81
- parts.append(
82
- f"{indent}- {fname}: a list, where each item has:\n{inner._extractor_fields(indent + ' ', include_hidden)}"
83
- )
84
- continue
85
- parts.append(f"{indent}- {fname}: {fvalue.description}")
86
- elif isinstance(ftype, type) and issubclass(ftype, LLMBaseModel):
87
- parts.append(ftype._extractor_fields(indent, include_hidden))
88
- else:
89
- parts.append(f"{indent}- {fname}: {fvalue.description}")
90
- return "\n".join(parts)
91
-
92
- @classmethod
93
- def extractor_str(cls, include_hidden: bool = False) -> str:
94
- title = cls.__name__
95
- fields = cls._extractor_fields(include_hidden=include_hidden)
96
- return (
97
- f"You are a JSON extraction expert. "
98
- f"Extract a valid JSON object of type `{title}` from the text below.\n"
99
- f"The JSON must have these fields:\n{fields}\n\n"
100
- )
101
-
102
- @classmethod
103
- def model_json_schema(
104
- cls,
105
- by_alias: bool = True,
106
- ref_template: str = "#/$defs/{model}",
107
- schema_generator: type | None = None,
108
- mode: str = "validation",
109
- include_hidden: bool = False,
110
- **kwargs,
111
- ) -> dict:
112
- call_kwargs: dict = {"by_alias": by_alias, "ref_template": ref_template, "mode": mode}
113
- if schema_generator is not None:
114
- call_kwargs["schema_generator"] = schema_generator
115
- call_kwargs.update(kwargs)
116
- schema = super().model_json_schema(**call_kwargs)
117
- excluded_by_title = cls._resolve_excluded_by_title(include_hidden)
118
- for title, excluded in excluded_by_title.items():
119
- defn = schema.get("$defs", {}).get(title)
120
- if isinstance(defn, dict) and "properties" in defn:
121
- defn["properties"] = {k: v for k, v in defn["properties"].items() if k not in excluded}
122
- own_excluded = cls._excluded_fields(include_hidden)
123
- if "properties" in schema:
124
- schema["properties"] = {k: v for k, v in schema["properties"].items() if k not in own_excluded}
125
- return schema
126
-
127
25
 
128
26
  class SourceCodeReference(LLMBaseModel):
129
27
  """Reference to source code including qualified name and file location."""
@@ -189,7 +87,6 @@ class RelationEdge(LLMBaseModel):
189
87
  default_factory=list,
190
88
  description="Call-site line and column pairs for this edge.",
191
89
  exclude=True,
192
- json_schema_extra={"hidden": True},
193
90
  )
194
91
 
195
92
  @classmethod
@@ -290,7 +187,6 @@ class Relation(LLMBaseModel):
290
187
  default_factory=list,
291
188
  description="All known source-to-target edges for this relation, populated deterministically when available.",
292
189
  exclude=True,
293
- json_schema_extra={"hidden": True},
294
190
  )
295
191
 
296
192
  @classmethod
@@ -385,30 +281,22 @@ class Component(LLMBaseModel):
385
281
  description="The most important/critical classes and methods that represent this component's core functionality. Pick 2-5 key entities."
386
282
  )
387
283
 
388
- source_group_names: list[str] = Field(
389
- description="Names of the cluster groups from the grouping analysis that this component encompasses.",
390
- default_factory=list,
391
- )
392
-
393
284
  source_cluster_ids: list[ComponentId] = Field(
394
- description="List of cluster IDs from CFG analysis that this component encompasses (populated deterministically from source_group_names).",
285
+ description="List of cluster IDs from CFG analysis that this component encompasses.",
395
286
  default_factory=list,
396
287
  exclude=True,
397
- json_schema_extra={"hidden": True},
398
288
  )
399
289
 
400
290
  file_methods: list[FileMethodGroup] = Field(
401
291
  description="All methods/functions belonging to this component, grouped by file (populated deterministically from cluster results).",
402
292
  default_factory=list,
403
293
  exclude=True,
404
- json_schema_extra={"hidden": True},
405
294
  )
406
295
 
407
296
  component_id: str = Field(
408
297
  default="",
409
298
  description="Deterministic unique identifier for this component.",
410
299
  exclude=True,
411
- json_schema_extra={"hidden": True},
412
300
  )
413
301
 
414
302
  def file_paths(self) -> list[str]:
@@ -418,14 +306,11 @@ class Component(LLMBaseModel):
418
306
  def llm_str(self):
419
307
  n = f"**Component:** `{self.name}`"
420
308
  d = f" - *Description*: {self.description}"
421
- sg = ""
422
- if self.source_group_names:
423
- sg = f" - *Source Group Names*: {', '.join(self.source_group_names)}"
424
309
  qn = ""
425
310
  if self.key_entities:
426
311
  qn += " - *Key Entities*: "
427
312
  qn += ", ".join(f"`{q.llm_str()}`" for q in self.key_entities)
428
- return "\n".join([n, d, sg, qn]).strip()
313
+ return "\n".join([n, d, qn]).strip()
429
314
 
430
315
 
431
316
  class AnalysisInsights(LLMBaseModel):
@@ -438,7 +323,6 @@ class AnalysisInsights(LLMBaseModel):
438
323
  default_factory=dict,
439
324
  description="Top-level file index keyed by relative file path. Contains all methods and statuses.",
440
325
  exclude=True,
441
- json_schema_extra={"hidden": True},
442
326
  )
443
327
  components: list[Component] = Field(description="List of the components identified in the project.")
444
328
  components_relations: list[Relation] = Field(description="List of relations among the components.")
@@ -469,81 +353,6 @@ class AnalysisInsights(LLMBaseModel):
469
353
  return title + body + relations
470
354
 
471
355
 
472
- class ComponentArchitecture(LLMBaseModel):
473
- """Component-only architecture before relation discovery."""
474
-
475
- description: str = Field(
476
- description="One paragraph explaining the functionality represented by this graph, its main flow, and purpose."
477
- )
478
- components: list[Component] = Field(description="List of the components identified in the project.")
479
-
480
- def llm_str(self):
481
- if not self.components:
482
- return "No abstract components found."
483
- title = "# Abstract Components Overview\n"
484
- body = "\n".join(ac.llm_str() for ac in self.components)
485
- return title + body
486
-
487
-
488
- class ComponentApiSurface(LLMBaseModel):
489
- """The provided and consumed APIs for one component."""
490
-
491
- component_name: str = Field(description="Exact component name this API surface describes.")
492
- provided_interfaces: list[SourceCodeReference] = Field(
493
- default_factory=list,
494
- description="Methods/classes/config symbols this component exposes or uses as entrypoints.",
495
- )
496
- consumed_interfaces: list[SourceCodeReference] = Field(
497
- default_factory=list,
498
- description="Methods/classes/config symbols this component calls, configures, imports, or expects from others.",
499
- )
500
- incoming_api_paths: list[str] = Field(
501
- default_factory=list,
502
- description="How other components enter this component's API, such as direct calls, registry dispatch, REST, queues, plugins, files, or config.",
503
- )
504
- outgoing_api_paths: list[str] = Field(
505
- default_factory=list,
506
- description="How this component reaches other components' APIs, such as direct calls, registry dispatch, REST, queues, plugins, files, or config.",
507
- )
508
- notes: str = Field(default="", description="Short notes about the component's API role.")
509
-
510
- def llm_str(self):
511
- provided = ", ".join(ref.llm_str() for ref in self.provided_interfaces) or "none"
512
- consumed = ", ".join(ref.llm_str() for ref in self.consumed_interfaces) or "none"
513
- incoming = ", ".join(self.incoming_api_paths) or "none"
514
- outgoing = ", ".join(self.outgoing_api_paths) or "none"
515
- return (
516
- f"**{self.component_name}**\n"
517
- f" Provided: {provided}\n"
518
- f" Consumed: {consumed}\n"
519
- f" Incoming API paths: {incoming}\n"
520
- f" Outgoing API paths: {outgoing}\n"
521
- f" Notes: {self.notes}"
522
- )
523
-
524
-
525
- class ComponentApiSurfaces(LLMBaseModel):
526
- """API surfaces for all components in a scope."""
527
-
528
- api_surfaces: list[ComponentApiSurface] = Field(description="API surface for each component in this scope.")
529
-
530
- def llm_str(self):
531
- if not self.api_surfaces:
532
- return "No component API surfaces found."
533
- return "\n".join(surface.llm_str() for surface in self.api_surfaces)
534
-
535
-
536
- class ComponentRelations(LLMBaseModel):
537
- """Relations discovered from component API surfaces."""
538
-
539
- components_relations: list[Relation] = Field(description="List of relations among the components.")
540
-
541
- def llm_str(self):
542
- if not self.components_relations:
543
- return "No component relations found."
544
- return "\n".join(relation.llm_str() for relation in self.components_relations)
545
-
546
-
547
356
  def assign_component_ids(analysis: AnalysisInsights, parent_id: str = "", only_new: bool = False) -> None:
548
357
  """Assign hierarchical component IDs based on sibling index.
549
358
 
@@ -632,58 +441,27 @@ def index_components_by_id(
632
441
  return {c.component_id: c for c in iter_components(root_analysis, sub_analyses) if c.component_id}
633
442
 
634
443
 
635
- class MetaAnalysisInsights(LLMBaseModel):
636
- """Insights from analyzing project metadata including type, domain, and architecture."""
444
+ class PlannedGroup(LLMBaseModel):
445
+ """One component the planner proposes, as the candidate groups it gathers."""
637
446
 
638
- project_type: str = Field(
639
- description="Type/category of the project (e.g., web framework, data processing, ML library, etc.)"
447
+ name: str = Field(description="One responsibility; never two joined by 'and' or '&'")
448
+ members: list[str] = Field(description="Labels of the candidate groups this component gathers, e.g. ['G1', 'G4']")
449
+ owns: list[str] = Field(
450
+ default_factory=list, description="Domain words this component owns, as they appear in identifiers"
640
451
  )
641
- domain: str = Field(
642
- description="Domain or field the project belongs to (e.g., web development, data science, DevOps, etc.)"
643
- )
644
- architectural_patterns: list[str] = Field(description="Main architectural patterns typically used in such projects")
645
- expected_components: list[str] = Field(description="Expected high-level components/modules based on project type")
646
- technology_stack: list[str] = Field(description="Main technologies, frameworks, and libraries used")
647
- architectural_bias: str = Field(
648
- description="Guidance on how to interpret and organize components for this project type"
649
- )
650
-
651
- def llm_str(self):
652
- title = "# Project Metadata Analysis\n"
653
- content = f"""
654
- **Project Type:** {self.project_type}
655
- **Domain:** {self.domain}
656
- **Technology Stack:** {", ".join(self.technology_stack)}
657
- **Architectural Patterns:** {", ".join(self.architectural_patterns)}
658
- **Expected Components:** {", ".join(self.expected_components)}
659
- **Architectural Bias:** {self.architectural_bias}
660
- """
661
- return title + content
662
-
663
-
664
- class FileClassification(LLMBaseModel):
665
- """Classification of a file to a component."""
666
-
667
- component_name: str = Field(description="Name of the component or module")
668
- file_path: str = Field(description="Path to the file")
669
452
 
670
453
  def llm_str(self):
671
- return f"`{self.file_path}` -> Component: `{self.component_name}`"
454
+ return f"{self.name}: {', '.join(self.members)}"
672
455
 
673
456
 
674
- class ComponentFiles(LLMBaseModel):
675
- """Collection of file classifications for components."""
457
+ class TreePlanInsights(LLMBaseModel):
458
+ """How the candidate groups of one scope fold into components."""
676
459
 
677
- file_paths: list[FileClassification] = Field(
678
- description="All files with their classifications for each of the files assigned to a component."
679
- )
460
+ groups: list[PlannedGroup] = Field(description="The components, each gathering one or more candidate groups")
461
+ notes: str = Field(default="", description="What the names say about this scope's shape")
680
462
 
681
463
  def llm_str(self):
682
- if not self.file_paths:
683
- return "No files classified."
684
- title = "# Component File Classifications\n"
685
- body = "\n".join(f"- `{fc.file_path}` -> Component: `{fc.component_name}`" for fc in self.file_paths)
686
- return title + body
464
+ return "# Tree plan\n" + "\n".join(f"- {group.llm_str()}" for group in self.groups)
687
465
 
688
466
 
689
467
  class ScopeOperationAction(StrEnum):
@@ -712,7 +490,8 @@ class ScopeOperation(LLMBaseModel):
712
490
  cluster_refs: list[ScopedClusterRef] = Field(description="New-side clusters this operation accounts for.")
713
491
  component_id: str | None = Field(
714
492
  default=None,
715
- description="Existing component id for update/delete/noop; null when creating a component.",
493
+ description="Existing component id for update/delete/noop; the id the tree specification "
494
+ "allocated when creating a component, or null to allocate the next sibling index.",
716
495
  )
717
496
  name: str | None = Field(default=None, description="Component name for create/update operations.")
718
497
  description: str | None = Field(default=None, description="Component description for create/update operations.")
@@ -739,7 +518,7 @@ class ScopeOperation(LLMBaseModel):
739
518
 
740
519
 
741
520
  class ScopeUpdateDecision(LLMBaseModel):
742
- """LLM-selected operations for one incremental scope update."""
521
+ """Deterministic operations for one incremental scope update."""
743
522
 
744
523
  operations: list[ScopeOperation] = Field(description="Operations to apply to the current scope.")
745
524
 
@@ -2,21 +2,9 @@
2
2
 
3
3
  from __future__ import annotations
4
4
 
5
- from collections.abc import Collection
6
5
  from dataclasses import dataclass
7
6
 
8
- from agents.agent_responses import AnalysisInsights, Component, SourceCodeReference
9
-
10
-
11
- def group_ids_by_name(components: list[Component], valid_group_ids: Collection[str]) -> dict[str, str]:
12
- """Map component source-group names to their authoritative live group IDs."""
13
- valid_ids = set(valid_group_ids)
14
- return {
15
- name: component.component_id
16
- for component in components
17
- if component.component_id in valid_ids
18
- for name in component.source_group_names
19
- }
7
+ from agents.agent_responses import AnalysisInsights, SourceCodeReference
20
8
 
21
9
 
22
10
  @dataclass(frozen=True)
@@ -3,14 +3,10 @@
3
3
 
4
4
  class LLMDefaults:
5
5
  DEFAULT_AGENT_TEMPERATURE = 0
6
- DEFAULT_PARSING_TEMPERATURE = 0
7
6
  AWS_MAX_TOKENS = 4096
8
-
9
-
10
- class FileStructureConfig:
11
- MAX_LINES = 500
12
- DEFAULT_MAX_DEPTH = 10
13
- FALLBACK_MAX_LINES = 50000
7
+ # Why: the provider configs below pass this straight to the client. ``None`` there disables the
8
+ # SDK's own default, so a stalled socket hangs the whole analysis with nothing to interrupt it.
9
+ REQUEST_TIMEOUT_SECONDS = 300.0
14
10
 
15
11
 
16
12
  class ModelCapabilities: