codeboarding 0.13.10__tar.gz → 0.14.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 (238) hide show
  1. {codeboarding-0.13.10/codeboarding.egg-info → codeboarding-0.14.0}/PKG-INFO +2 -7
  2. {codeboarding-0.13.10 → codeboarding-0.14.0}/PYPI.md +1 -2
  3. {codeboarding-0.13.10 → codeboarding-0.14.0}/README.md +3 -4
  4. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/agent_responses.py +18 -239
  5. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/component_ownership.py +1 -13
  6. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/constants.py +3 -7
  7. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/llm_config.py +89 -110
  8. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/llm_errors.py +14 -0
  9. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/llm_renderers/__init__.py +4 -10
  10. codeboarding-0.14.0/agents/llm_renderers/scope.py +217 -0
  11. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/planner_agent.py +1 -1
  12. codeboarding-0.14.0/agents/prompts/__init__.py +41 -0
  13. codeboarding-0.14.0/agents/prompts/profiles.py +27 -0
  14. codeboarding-0.14.0/agents/prompts/shared.py +107 -0
  15. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/retry.py +1 -25
  16. codeboarding-0.14.0/agents/scope_analysis_agent.py +164 -0
  17. codeboarding-0.14.0/agents/tools/__init__.py +4 -0
  18. codeboarding-0.14.0/agents/tools/base.py +36 -0
  19. codeboarding-0.14.0/agents/tools/get_method_calls.py +55 -0
  20. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/tools/read_file.py +16 -31
  21. codeboarding-0.14.0/agents/tree_planner_agent.py +288 -0
  22. {codeboarding-0.13.10 → codeboarding-0.14.0/codeboarding.egg-info}/PKG-INFO +2 -7
  23. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding.egg-info/SOURCES.txt +15 -40
  24. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding.egg-info/requires.txt +0 -4
  25. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding.egg-info/top_level.txt +0 -1
  26. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/bootstrap.py +1 -1
  27. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/commands/full_analysis.py +2 -1
  28. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/analysis.py +6 -1
  29. {codeboarding-0.13.10 → codeboarding-0.14.0}/constants.py +4 -2
  30. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/analysis_json.py +9 -2
  31. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/diagram_generator.py +457 -305
  32. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/file_index.py +2 -2
  33. codeboarding-0.13.10/agents/incremental_agent.py → codeboarding-0.14.0/diagram_analysis/incremental_update.py +45 -317
  34. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/io_utils.py +17 -1
  35. codeboarding-0.14.0/diagram_analysis/scope_assembly.py +408 -0
  36. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/scope_plan.py +29 -24
  37. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/tree_shape.py +1 -9
  38. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/rendering.py +3 -2
  39. {codeboarding-0.13.10 → codeboarding-0.14.0}/pyproject.toml +2 -6
  40. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/__init__.py +11 -12
  41. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/analysis_cache.py +8 -1
  42. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/analysis_result.py +0 -14
  43. codeboarding-0.14.0/static_analyzer/clustering/__init__.py +21 -0
  44. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/clustering/exceptions.py +14 -0
  45. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/clustering/models.py +18 -68
  46. codeboarding-0.14.0/static_analyzer/clustering/names/__init__.py +56 -0
  47. codeboarding-0.14.0/static_analyzer/clustering/names/draft.py +667 -0
  48. codeboarding-0.14.0/static_analyzer/clustering/names/frontier.py +263 -0
  49. codeboarding-0.14.0/static_analyzer/clustering/names/inventory.py +116 -0
  50. codeboarding-0.14.0/static_analyzer/clustering/names/replay.py +139 -0
  51. codeboarding-0.14.0/static_analyzer/clustering/names/spec.py +222 -0
  52. codeboarding-0.14.0/static_analyzer/clustering/names/tokens.py +131 -0
  53. codeboarding-0.14.0/static_analyzer/clustering/service.py +464 -0
  54. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/config.py +1 -38
  55. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/csharp_adapter.py +41 -27
  56. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/java_adapter.py +31 -54
  57. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/call_graph_builder.py +31 -9
  58. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/language_adapter.py +16 -0
  59. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/models.py +3 -0
  60. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/source_inspector.py +35 -0
  61. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/symbol_table.py +9 -9
  62. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/language_results.py +0 -3
  63. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_main.py +7 -8
  64. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_user_config.py +31 -0
  65. {codeboarding-0.13.10 → codeboarding-0.14.0}/user_config.py +27 -4
  66. codeboarding-0.13.10/agents/abstraction_agent.py +0 -218
  67. codeboarding-0.13.10/agents/agent.py +0 -492
  68. codeboarding-0.13.10/agents/dependency_discovery.py +0 -159
  69. codeboarding-0.13.10/agents/details_agent.py +0 -244
  70. codeboarding-0.13.10/agents/llm_renderers/clustering.py +0 -129
  71. codeboarding-0.13.10/agents/meta_agent.py +0 -64
  72. codeboarding-0.13.10/agents/prompts/__init__.py +0 -85
  73. codeboarding-0.13.10/agents/prompts/abstract_prompt_factory.py +0 -63
  74. codeboarding-0.13.10/agents/prompts/claude_prompts.py +0 -309
  75. codeboarding-0.13.10/agents/prompts/deepseek_prompts.py +0 -355
  76. codeboarding-0.13.10/agents/prompts/gemini_flash_prompts.py +0 -291
  77. codeboarding-0.13.10/agents/prompts/glm_prompts.py +0 -335
  78. codeboarding-0.13.10/agents/prompts/gpt_prompts.py +0 -353
  79. codeboarding-0.13.10/agents/prompts/kimi_prompts.py +0 -335
  80. codeboarding-0.13.10/agents/prompts/prompt_factory.py +0 -183
  81. codeboarding-0.13.10/agents/repair.py +0 -124
  82. codeboarding-0.13.10/agents/static_analysis_enricher_mixin.py +0 -225
  83. codeboarding-0.13.10/agents/tools/__init__.py +0 -9
  84. codeboarding-0.13.10/agents/tools/base.py +0 -104
  85. codeboarding-0.13.10/agents/tools/component_bridge_edges.py +0 -68
  86. codeboarding-0.13.10/agents/tools/get_external_deps.py +0 -47
  87. codeboarding-0.13.10/agents/tools/get_method_invocations.py +0 -47
  88. codeboarding-0.13.10/agents/tools/list_git_changes.py +0 -27
  89. codeboarding-0.13.10/agents/tools/read_cfg.py +0 -62
  90. codeboarding-0.13.10/agents/tools/read_docs.py +0 -132
  91. codeboarding-0.13.10/agents/tools/read_file_structure.py +0 -155
  92. codeboarding-0.13.10/agents/tools/read_packages.py +0 -60
  93. codeboarding-0.13.10/agents/tools/read_source.py +0 -85
  94. codeboarding-0.13.10/agents/tools/read_structure.py +0 -49
  95. codeboarding-0.13.10/agents/tools/toolkit.py +0 -128
  96. codeboarding-0.13.10/agents/validation.py +0 -481
  97. codeboarding-0.13.10/caching/__init__.py +0 -8
  98. codeboarding-0.13.10/caching/cache.py +0 -255
  99. codeboarding-0.13.10/caching/meta_cache.py +0 -108
  100. codeboarding-0.13.10/health_main.py +0 -152
  101. codeboarding-0.13.10/static_analyzer/clustering/__init__.py +0 -27
  102. codeboarding-0.13.10/static_analyzer/clustering/cache.py +0 -104
  103. codeboarding-0.13.10/static_analyzer/clustering/delta.py +0 -473
  104. codeboarding-0.13.10/static_analyzer/clustering/engine.py +0 -223
  105. codeboarding-0.13.10/static_analyzer/clustering/expansion.py +0 -30
  106. codeboarding-0.13.10/static_analyzer/clustering/grouping.py +0 -436
  107. codeboarding-0.13.10/static_analyzer/clustering/service.py +0 -780
  108. codeboarding-0.13.10/static_analyzer/clustering/snapshot.py +0 -111
  109. codeboarding-0.13.10/static_analyzer/leiden_utils.py +0 -101
  110. {codeboarding-0.13.10 → codeboarding-0.14.0}/LICENSE +0 -0
  111. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/__init__.py +0 -0
  112. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/change_status.py +0 -0
  113. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/content_hash.py +0 -0
  114. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/file_index_models.py +0 -0
  115. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/incremental_results.py +0 -0
  116. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/llm_renderers/call_graph.py +0 -0
  117. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/model_capabilities.py +0 -0
  118. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/relation_edges.py +0 -0
  119. {codeboarding-0.13.10 → codeboarding-0.14.0}/agents/scope_ids.py +0 -0
  120. {codeboarding-0.13.10 → codeboarding-0.14.0}/clustering_ids.py +0 -0
  121. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding.egg-info/dependency_links.txt +0 -0
  122. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding.egg-info/entry_points.txt +0 -0
  123. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/__init__.py +0 -0
  124. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/commands/__init__.py +0 -0
  125. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/commands/incremental_analysis.py +0 -0
  126. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/commands/partial_analysis.py +0 -0
  127. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/render.py +0 -0
  128. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_cli/view_instructions.py +0 -0
  129. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/__init__.py +0 -0
  130. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/orchestration.py +0 -0
  131. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/sources/__init__.py +0 -0
  132. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/sources/local.py +0 -0
  133. {codeboarding-0.13.10 → codeboarding-0.14.0}/codeboarding_workflows/sources/remote.py +0 -0
  134. {codeboarding-0.13.10 → codeboarding-0.14.0}/core/__init__.py +0 -0
  135. {codeboarding-0.13.10 → codeboarding-0.14.0}/core/plugin_loader.py +0 -0
  136. {codeboarding-0.13.10 → codeboarding-0.14.0}/core/protocols.py +0 -0
  137. {codeboarding-0.13.10 → codeboarding-0.14.0}/core/registry.py +0 -0
  138. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/__init__.py +0 -0
  139. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/exceptions.py +0 -0
  140. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/file_coverage.py +0 -0
  141. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/incremental_changes.py +0 -0
  142. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/run_context.py +0 -0
  143. {codeboarding-0.13.10 → codeboarding-0.14.0}/diagram_analysis/run_mode.py +0 -0
  144. {codeboarding-0.13.10 → codeboarding-0.14.0}/github_action.py +0 -0
  145. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/__init__.py +0 -0
  146. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/checks/__init__.py +0 -0
  147. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/checks/circular_deps.py +0 -0
  148. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/checks/function_size.py +0 -0
  149. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/checks/unused_code_diagnostics.py +0 -0
  150. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/config.py +0 -0
  151. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/models.py +0 -0
  152. {codeboarding-0.13.10 → codeboarding-0.14.0}/health/runner.py +0 -0
  153. {codeboarding-0.13.10 → codeboarding-0.14.0}/install.py +0 -0
  154. {codeboarding-0.13.10 → codeboarding-0.14.0}/logging_config.py +0 -0
  155. {codeboarding-0.13.10 → codeboarding-0.14.0}/main.py +0 -0
  156. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/__init__.py +0 -0
  157. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/callbacks.py +0 -0
  158. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/context.py +0 -0
  159. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/mixin.py +0 -0
  160. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/paths.py +0 -0
  161. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/stats.py +0 -0
  162. {codeboarding-0.13.10 → codeboarding-0.14.0}/monitoring/writers.py +0 -0
  163. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/__init__.py +0 -0
  164. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/html.py +0 -0
  165. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/html_template.py +0 -0
  166. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/markdown.py +0 -0
  167. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/mdx.py +0 -0
  168. {codeboarding-0.13.10 → codeboarding-0.14.0}/output_generators/sphinx.py +0 -0
  169. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/__init__.py +0 -0
  170. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/change_detector.py +0 -0
  171. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/errors.py +0 -0
  172. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/fingerprint_diff.py +0 -0
  173. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/git_ops.py +0 -0
  174. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/ignore.py +0 -0
  175. {codeboarding-0.13.10 → codeboarding-0.14.0}/repo_utils/path_utils.py +0 -0
  176. {codeboarding-0.13.10 → codeboarding-0.14.0}/setup.cfg +0 -0
  177. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/cfg/__init__.py +0 -0
  178. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/cfg/call_graph.py +0 -0
  179. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/cfg/edge.py +0 -0
  180. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/cfg/location_key.py +0 -0
  181. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/cluster_relations.py +0 -0
  182. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/csharp_config_scanner.py +0 -0
  183. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/dotnet_sdk.py +0 -0
  184. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/__init__.py +0 -0
  185. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/__init__.py +0 -0
  186. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/go_adapter.py +0 -0
  187. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/php_adapter.py +0 -0
  188. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/python_adapter.py +0 -0
  189. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/rust_adapter.py +0 -0
  190. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
  191. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/edge_build_context.py +0 -0
  192. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/edge_builder.py +0 -0
  193. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/hierarchy_builder.py +0 -0
  194. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/lsp_client.py +0 -0
  195. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/lsp_constants.py +0 -0
  196. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/lsp_recycler.py +0 -0
  197. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/process_memory.py +0 -0
  198. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/progress.py +0 -0
  199. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/protocols.py +0 -0
  200. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/result_converter.py +0 -0
  201. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/engine/utils.py +0 -0
  202. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/incremental_orchestrator.py +0 -0
  203. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/internal_references.py +0 -0
  204. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/java_config_scanner.py +0 -0
  205. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/java_utils.py +0 -0
  206. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/lsp_client/__init__.py +0 -0
  207. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/lsp_client/diagnostics.py +0 -0
  208. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/node.py +0 -0
  209. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/programming_language.py +0 -0
  210. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/reference_resolver.py +0 -0
  211. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/scanner.py +0 -0
  212. {codeboarding-0.13.10 → codeboarding-0.14.0}/static_analyzer/typescript_config_scanner.py +0 -0
  213. {codeboarding-0.13.10 → codeboarding-0.14.0}/telemetry/__init__.py +0 -0
  214. {codeboarding-0.13.10 → codeboarding-0.14.0}/telemetry/device_id.py +0 -0
  215. {codeboarding-0.13.10 → codeboarding-0.14.0}/telemetry/events.py +0 -0
  216. {codeboarding-0.13.10 → codeboarding-0.14.0}/telemetry/schemas.py +0 -0
  217. {codeboarding-0.13.10 → codeboarding-0.14.0}/telemetry/service.py +0 -0
  218. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_cli_parser.py +0 -0
  219. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_github_action.py +0 -0
  220. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_install.py +0 -0
  221. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_logging_config.py +0 -0
  222. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_persisted_analysis_artifacts.py +0 -0
  223. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_pyproject_packages.py +0 -0
  224. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_registry_coverage.py +0 -0
  225. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_telemetry_events.py +0 -0
  226. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_telemetry_service.py +0 -0
  227. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_tool_registry.py +0 -0
  228. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_view_instructions.py +0 -0
  229. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_vscode_constants.py +0 -0
  230. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_windows_compatibility.py +0 -0
  231. {codeboarding-0.13.10 → codeboarding-0.14.0}/tests/test_windows_encoding.py +0 -0
  232. {codeboarding-0.13.10 → codeboarding-0.14.0}/tool_registry/__init__.py +0 -0
  233. {codeboarding-0.13.10 → codeboarding-0.14.0}/tool_registry/installers.py +0 -0
  234. {codeboarding-0.13.10 → codeboarding-0.14.0}/tool_registry/manifest.py +0 -0
  235. {codeboarding-0.13.10 → codeboarding-0.14.0}/tool_registry/paths.py +0 -0
  236. {codeboarding-0.13.10 → codeboarding-0.14.0}/tool_registry/registry.py +0 -0
  237. {codeboarding-0.13.10 → codeboarding-0.14.0}/utils.py +0 -0
  238. {codeboarding-0.13.10 → codeboarding-0.14.0}/vscode_constants.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.13.10
3
+ Version: 0.14.0
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"
@@ -201,8 +197,7 @@ LLM provider keys and model overrides are stored in `~/.codeboarding/config.toml
201
197
 
202
198
  [llm]
203
199
  # Optional: override the default model for your active provider
204
- # agent_model = "gemini-3.7-flash"
205
- # parsing_model = "gemini-3.1-flash-lite"
200
+ # agent_model = "gemini-3.8-flash"
206
201
  ```
207
202
 
208
203
  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.
@@ -124,8 +124,7 @@ LLM provider keys and model overrides are stored in `~/.codeboarding/config.toml
124
124
 
125
125
  [llm]
126
126
  # Optional: override the default model for your active provider
127
- # agent_model = "gemini-3.7-flash"
128
- # parsing_model = "gemini-3.1-flash-lite"
127
+ # agent_model = "gemini-3.8-flash"
129
128
  ```
130
129
 
131
130
  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.
@@ -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
 
@@ -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: