codeboarding 0.15.1__tar.gz → 0.15.2__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 (196) hide show
  1. {codeboarding-0.15.1 → codeboarding-0.15.2}/PKG-INFO +1 -1
  2. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/llm_errors.py +66 -39
  3. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/tree_planner_agent.py +4 -2
  4. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/PKG-INFO +1 -1
  5. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/commands/full_analysis.py +3 -3
  6. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/commands/incremental_analysis.py +3 -3
  7. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/main.py +10 -15
  8. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/diagram_generator.py +6 -4
  9. {codeboarding-0.15.1 → codeboarding-0.15.2}/pyproject.toml +1 -1
  10. {codeboarding-0.15.1 → codeboarding-0.15.2}/LICENSE +0 -0
  11. {codeboarding-0.15.1 → codeboarding-0.15.2}/PYPI.md +0 -0
  12. {codeboarding-0.15.1 → codeboarding-0.15.2}/README.md +0 -0
  13. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/__init__.py +0 -0
  14. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/agent_responses.py +0 -0
  15. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/change_status.py +0 -0
  16. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/component_ownership.py +0 -0
  17. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/constants.py +0 -0
  18. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/content_hash.py +0 -0
  19. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/file_index_models.py +0 -0
  20. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/incremental_results.py +0 -0
  21. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/llm_config.py +0 -0
  22. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/llm_renderers/__init__.py +0 -0
  23. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/llm_renderers/call_graph.py +0 -0
  24. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/llm_renderers/scope.py +0 -0
  25. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/model_capabilities.py +0 -0
  26. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/planner_agent.py +0 -0
  27. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/prompts/__init__.py +0 -0
  28. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/prompts/profiles.py +0 -0
  29. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/prompts/shared.py +0 -0
  30. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/relation_edges.py +0 -0
  31. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/retry.py +0 -0
  32. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/scope_analysis_agent.py +0 -0
  33. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/scope_ids.py +0 -0
  34. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/tools/__init__.py +0 -0
  35. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/tools/base.py +0 -0
  36. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/tools/get_method_calls.py +0 -0
  37. {codeboarding-0.15.1 → codeboarding-0.15.2}/agents/tools/read_file.py +0 -0
  38. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/SOURCES.txt +0 -0
  39. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/dependency_links.txt +0 -0
  40. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/entry_points.txt +0 -0
  41. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/requires.txt +0 -0
  42. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding.egg-info/top_level.txt +0 -0
  43. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/__init__.py +0 -0
  44. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/bootstrap.py +0 -0
  45. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/commands/__init__.py +0 -0
  46. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/commands/partial_analysis.py +0 -0
  47. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/github_action.py +0 -0
  48. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/render.py +0 -0
  49. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_cli/view_instructions.py +0 -0
  50. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/__init__.py +0 -0
  51. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/analysis.py +0 -0
  52. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/fingerprint_diff.py +0 -0
  53. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/orchestration.py +0 -0
  54. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/sources/__init__.py +0 -0
  55. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/sources/local.py +0 -0
  56. {codeboarding-0.15.1 → codeboarding-0.15.2}/codeboarding_workflows/sources/remote.py +0 -0
  57. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/__init__.py +0 -0
  58. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/analysis_json.py +0 -0
  59. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/cluster_relations.py +0 -0
  60. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/exceptions.py +0 -0
  61. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/file_coverage.py +0 -0
  62. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/file_index.py +0 -0
  63. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/incremental_changes.py +0 -0
  64. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/incremental_update.py +0 -0
  65. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/io_utils.py +0 -0
  66. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/reference_resolver.py +0 -0
  67. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/run_context.py +0 -0
  68. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/run_mode.py +0 -0
  69. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/scope_assembly.py +0 -0
  70. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/scope_plan.py +0 -0
  71. {codeboarding-0.15.1 → codeboarding-0.15.2}/diagram_analysis/tree_shape.py +0 -0
  72. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/__init__.py +0 -0
  73. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/checks/__init__.py +0 -0
  74. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/checks/circular_deps.py +0 -0
  75. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/checks/function_size.py +0 -0
  76. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/checks/unused_code_diagnostics.py +0 -0
  77. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/config.py +0 -0
  78. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/main.py +0 -0
  79. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/models.py +0 -0
  80. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/plugins/__init__.py +0 -0
  81. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/plugins/plugin_loader.py +0 -0
  82. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/plugins/protocols.py +0 -0
  83. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/plugins/registry.py +0 -0
  84. {codeboarding-0.15.1 → codeboarding-0.15.2}/health/runner.py +0 -0
  85. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/__init__.py +0 -0
  86. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/clustering_ids.py +0 -0
  87. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/constants.py +0 -0
  88. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/install.py +0 -0
  89. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/logging_config.py +0 -0
  90. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/__init__.py +0 -0
  91. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/callbacks.py +0 -0
  92. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/context.py +0 -0
  93. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/mixin.py +0 -0
  94. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/paths.py +0 -0
  95. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/stats.py +0 -0
  96. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/telemetry/__init__.py +0 -0
  97. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/telemetry/device_id.py +0 -0
  98. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/telemetry/events.py +0 -0
  99. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/telemetry/schemas.py +0 -0
  100. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/telemetry/service.py +0 -0
  101. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/monitoring/writers.py +0 -0
  102. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/__init__.py +0 -0
  103. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/change_detector.py +0 -0
  104. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/errors.py +0 -0
  105. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/git_ops.py +0 -0
  106. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/ignore.py +0 -0
  107. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/repo_utils/path_utils.py +0 -0
  108. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/__init__.py +0 -0
  109. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/grammars.py +0 -0
  110. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/installers.py +0 -0
  111. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/java.py +0 -0
  112. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/manifest.py +0 -0
  113. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/paths.py +0 -0
  114. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/tool_registry/registry.py +0 -0
  115. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/user_config.py +0 -0
  116. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/utils.py +0 -0
  117. {codeboarding-0.15.1 → codeboarding-0.15.2}/infra/vscode_constants.py +0 -0
  118. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/__init__.py +0 -0
  119. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/html.py +0 -0
  120. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/html_template.py +0 -0
  121. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/markdown.py +0 -0
  122. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/mdx.py +0 -0
  123. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/rendering.py +0 -0
  124. {codeboarding-0.15.1 → codeboarding-0.15.2}/output_generators/sphinx.py +0 -0
  125. {codeboarding-0.15.1 → codeboarding-0.15.2}/setup.cfg +0 -0
  126. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/__init__.py +0 -0
  127. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/analysis_cache.py +0 -0
  128. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/analysis_result.py +0 -0
  129. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/cfg/__init__.py +0 -0
  130. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/cfg/call_graph.py +0 -0
  131. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/cfg/edge.py +0 -0
  132. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/cfg/location_key.py +0 -0
  133. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/__init__.py +0 -0
  134. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/exceptions.py +0 -0
  135. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/models.py +0 -0
  136. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/__init__.py +0 -0
  137. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/draft.py +0 -0
  138. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/frontier.py +0 -0
  139. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/inventory.py +0 -0
  140. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/replay.py +0 -0
  141. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/spec.py +0 -0
  142. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/names/tokens.py +0 -0
  143. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/clustering/service.py +0 -0
  144. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/config.py +0 -0
  145. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/csharp_config_scanner.py +0 -0
  146. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/dotnet_sdk.py +0 -0
  147. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/dotnet_solution.py +0 -0
  148. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/__init__.py +0 -0
  149. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/__init__.py +0 -0
  150. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/csharp_adapter.py +0 -0
  151. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/go_adapter.py +0 -0
  152. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/java_adapter.py +0 -0
  153. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/kotlin_adapter.py +0 -0
  154. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/php_adapter.py +0 -0
  155. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/python_adapter.py +0 -0
  156. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/rust_adapter.py +0 -0
  157. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/adapters/typescript_adapter.py +0 -0
  158. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/call_graph_builder.py +0 -0
  159. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/edge_build_context.py +0 -0
  160. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/edge_builder.py +0 -0
  161. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/hierarchy_builder.py +0 -0
  162. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/language_adapter.py +0 -0
  163. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/lsp_client.py +0 -0
  164. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/lsp_constants.py +0 -0
  165. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/lsp_recycler.py +0 -0
  166. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/models.py +0 -0
  167. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/process_memory.py +0 -0
  168. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/progress.py +0 -0
  169. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/protocols.py +0 -0
  170. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/result_converter.py +0 -0
  171. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/source_inspector.py +0 -0
  172. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/symbol_table.py +0 -0
  173. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/engine/utils.py +0 -0
  174. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/exceptions.py +0 -0
  175. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/external_calls.py +0 -0
  176. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/graph_definitions.py +0 -0
  177. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/incremental_orchestrator.py +0 -0
  178. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/internal_references.py +0 -0
  179. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/java_config_scanner.py +0 -0
  180. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/java_utils.py +0 -0
  181. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/language_results.py +0 -0
  182. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/lsp_client/__init__.py +0 -0
  183. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/lsp_client/diagnostics.py +0 -0
  184. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/node.py +0 -0
  185. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/programming_language.py +0 -0
  186. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/scanner.py +0 -0
  187. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/typescript_config_scanner.py +0 -0
  188. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/typescript_plugin/node_modules/codeboarding-workspace-sources/index.js +0 -0
  189. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/typescript_plugin/node_modules/codeboarding-workspace-sources/package.json +0 -0
  190. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/typescript_workspace.py +0 -0
  191. {codeboarding-0.15.1 → codeboarding-0.15.2}/static_analyzer/workspace_dependencies.py +0 -0
  192. {codeboarding-0.15.1 → codeboarding-0.15.2}/tests/test_persisted_analysis_artifacts.py +0 -0
  193. {codeboarding-0.15.1 → codeboarding-0.15.2}/tests/test_pyproject_packages.py +0 -0
  194. {codeboarding-0.15.1 → codeboarding-0.15.2}/tests/test_view_instructions.py +0 -0
  195. {codeboarding-0.15.1 → codeboarding-0.15.2}/tests/test_windows_compatibility.py +0 -0
  196. {codeboarding-0.15.1 → codeboarding-0.15.2}/tests/test_windows_encoding.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.15.1
3
+ Version: 0.15.2
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -1,17 +1,4 @@
1
- """Provider-agnostic detection and typing of LLM authentication failures.
2
-
3
- A rejected API key (HTTP 401, or a provider's equivalent auth/permission
4
- error) is *permanent* for the run: retrying it wastes minutes of backoff and
5
- floods telemetry with identical ``$exception`` events. The agent retry loop and
6
- the CLI both need to recognize one when they see it, regardless of which SDK
7
- raised it.
8
-
9
- ``detect_auth_error`` maps a raw provider exception to an :class:`LLMAuthError`
10
- (or ``None`` when it isn't an auth failure). The typed error carries the
11
- provider, a masked key tail, and the provider's own message, and forwards them
12
- as ``telemetry_properties`` so the PostHog ``$exception`` event — and the
13
- dashboard's structured ``error`` columns — populate instead of staying null.
14
- """
1
+ """Provider-agnostic LLM failure classification, exceptions, and retry helpers."""
15
2
 
16
3
  from __future__ import annotations
17
4
 
@@ -33,6 +20,11 @@ EXIT_AUTH_ERROR = 2
33
20
  # Process exit code for an exhausted token or credit quota: the key is fine, the account is not.
34
21
  EXIT_QUOTA_EXHAUSTED = 3
35
22
 
23
+ CODEBOARDING_QUOTA_CODE = "free_credits_exhausted"
24
+ # Response contract: licensing-aws/gha_proxy/handler.py.
25
+ PROXY_ERROR_TYPE = "gha_proxy"
26
+ PROXY_QUOTA_MESSAGE = "Resource exhausted: token limit reached"
27
+
36
28
  # Class names, across SDKs, that always mean "credentials were rejected".
37
29
  # openai/anthropic/cerebras raise ``AuthenticationError``; google raises
38
30
  # ``Unauthenticated``/``PermissionDenied``; Bedrock (botocore) surfaces
@@ -114,6 +106,65 @@ class LLMAuthError(RuntimeError):
114
106
  self.telemetry_properties = telemetry_properties
115
107
 
116
108
 
109
+ class LLMQuotaError(RuntimeError):
110
+ """An LLM quota is exhausted, with recovery guidance and failure telemetry."""
111
+
112
+ def __init__(self, error: BaseException):
113
+ self.telemetry_properties = llm_failure_properties(error)
114
+ self.is_codeboarding_quota = _is_codeboarding_quota(error)
115
+ _, key_tail = current_provider_key_context()
116
+ if self.is_codeboarding_quota:
117
+ message = (
118
+ "Your CodeBoarding quota is exhausted. "
119
+ "Buy a CodeBoarding license at https://codeboarding.org/pricing, "
120
+ "or wait for your weekly reset."
121
+ )
122
+ elif key_tail == CODEBOARDING_KEY_TAIL:
123
+ message = (
124
+ "The hosted LLM provider's quota is exhausted. "
125
+ "This is a CodeBoarding service issue. Please try again later or contact CodeBoarding support."
126
+ )
127
+ else:
128
+ message = (
129
+ "The LLM provider's token or credit quota is exhausted. "
130
+ "Add credits or raise the quota for this provider, then re-run."
131
+ )
132
+ super().__init__(message)
133
+
134
+
135
+ def llm_failure_properties(exc: BaseException) -> dict:
136
+ """Classify a failed LLM call for exception telemetry."""
137
+ quota = is_quota_exhausted(exc)
138
+ context = isinstance(exc, ScopeContextTooLargeError) or any(p.search(str(exc)) for p in _CONTEXT_OVERFLOW_PATTERNS)
139
+ provider, _key_tail = current_provider_key_context()
140
+ properties = {
141
+ "error_type": "quota" if quota else "context" if context else "llm",
142
+ "error_provider": provider,
143
+ "error_status_code": _status_code(exc),
144
+ "error_message": str(exc)[:500],
145
+ }
146
+ if _is_codeboarding_quota(exc):
147
+ properties["error_code"] = CODEBOARDING_QUOTA_CODE
148
+ return properties
149
+
150
+
151
+ def is_quota_exhausted(exc: BaseException) -> bool:
152
+ status = _status_code(exc)
153
+ quota_code = getattr(exc, "code", None) == "insufficient_quota" or "insufficient_quota" in str(exc)
154
+ return status == 402 or (status == 429 and quota_code)
155
+
156
+
157
+ def _is_codeboarding_quota(exc: BaseException) -> bool:
158
+ body = getattr(exc, "body", {})
159
+ error = body.get("error", body) if isinstance(body, dict) else {}
160
+ return (
161
+ _status_code(exc) == 402
162
+ and isinstance(error, dict)
163
+ and error.get("type") == PROXY_ERROR_TYPE
164
+ and error.get("message") == PROXY_QUOTA_MESSAGE
165
+ )
166
+
167
+
117
168
  def _status_code(exc: BaseException) -> int | None:
118
169
  code = getattr(exc, "status_code", None)
119
170
  if code is None:
@@ -183,30 +234,6 @@ def detect_auth_error(exc: BaseException, *, provider: str, key_tail: str) -> LL
183
234
  )
184
235
 
185
236
 
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
-
192
- def llm_failure_properties(exc: BaseException) -> dict:
193
- """``$exception`` properties for a failed LLM call, telling an exhausted quota or an oversized prompt
194
- apart from other failures.
195
-
196
- Why: the hosted proxy's paywall is a 402, and OpenAI reports an empty balance as a 429 ``insufficient_quota``.
197
- An oversized prompt is ours to fix, not the provider's, so it gets its own type on the dashboard.
198
- """
199
- quota = _is_quota_exhausted(exc)
200
- context = isinstance(exc, ScopeContextTooLargeError) or any(p.search(str(exc)) for p in _CONTEXT_OVERFLOW_PATTERNS)
201
- provider, _key_tail = current_provider_key_context()
202
- return {
203
- "error_type": "quota" if quota else "context" if context else "llm",
204
- "error_provider": provider,
205
- "error_status_code": _status_code(exc),
206
- "error_message": str(exc)[:500],
207
- }
208
-
209
-
210
237
  def is_transient_llm_error(exc: BaseException) -> bool:
211
238
  """Whether the same request may succeed if sent again: throttled, a server error, or no answer at all.
212
239
 
@@ -216,7 +243,7 @@ def is_transient_llm_error(exc: BaseException) -> bool:
216
243
  """
217
244
  status = _status_code(exc)
218
245
  if status is not None:
219
- return status in (408, 429) and not _is_quota_exhausted(exc) or status >= 500
246
+ return status in (408, 429) and not is_quota_exhausted(exc) or status >= 500
220
247
  return any(cls.__name__ in _TRANSIENT_TYPE_NAMES for cls in type(exc).__mro__)
221
248
 
222
249
 
@@ -16,7 +16,7 @@ from langchain_core.prompts import PromptTemplate
16
16
  from agents.agent_responses import PlannedGroup, TreePlanInsights
17
17
  from agents.llm_config import get_current_prompt_profile, supports_json_mode
18
18
  from infra.monitoring.callbacks import MONITORING_CALLBACK
19
- from agents.llm_errors import LLMAuthError, raise_if_auth_error
19
+ from agents.llm_errors import LLMAuthError, LLMQuotaError, is_quota_exhausted, raise_if_auth_error
20
20
  from agents.prompts import get_tree_plan_prompts
21
21
  from agents.retry import LLM_MAX_ATTEMPTS, RetryAction, RetryDecision, classify_llm_error, with_retries
22
22
  from infra.monitoring import trace
@@ -103,7 +103,7 @@ class TreePlannerAgent(MonitoringMixin):
103
103
  return folded
104
104
 
105
105
  def _draw(self, prompt: str, labelled: dict[str, CandidateGroup]) -> list[TreePlanInsights]:
106
- """``draws`` answers to one prompt, drawn concurrently; a draw that fails is dropped."""
106
+ """Draw concurrently, dropping failed draws unless credentials or quota prevent further work."""
107
107
  # Not ``with``: its ``__exit__`` waits for a stalled draw; a copied context carries the
108
108
  # monitoring step into each worker.
109
109
  pool = ThreadPoolExecutor(max_workers=self.draws)
@@ -117,6 +117,8 @@ class TreePlannerAgent(MonitoringMixin):
117
117
  except LLMAuthError:
118
118
  raise
119
119
  except Exception as exc:
120
+ if is_quota_exhausted(exc):
121
+ raise LLMQuotaError(exc) from exc
120
122
  failures.append(exc)
121
123
  logger.warning("[Planner] draw failed: %s", exc)
122
124
  finally:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codeboarding
3
- Version: 0.15.1
3
+ Version: 0.15.2
4
4
  Summary: Interactive Diagrams for Code
5
5
  Author: CodeBoarding Team
6
6
  License-Expression: MIT
@@ -5,7 +5,8 @@ from pathlib import Path
5
5
  from tqdm import tqdm
6
6
 
7
7
  from agents.llm_config import LLMConfigError
8
- from agents.llm_errors import LLMAuthError
8
+ from agents.llm_errors import LLMAuthError, LLMQuotaError
9
+ from diagram_analysis.exceptions import ScopeSemanticsError
9
10
  from codeboarding_cli.bootstrap import bootstrap_environment, resolve_local_run_paths
10
11
  from codeboarding_cli.view_instructions import print_view_instructions
11
12
  from codeboarding_workflows.analysis import run_full
@@ -13,7 +14,6 @@ from codeboarding_workflows.orchestration import run_analysis_pipeline
13
14
  from codeboarding_workflows.sources import SourceContext, local_source, remote_source
14
15
  from infra.constants import CLI_ROOT_DOCUMENT_NAME
15
16
  from diagram_analysis import DEFAULT_DEPTH_CAP, RunContext, RunPaths
16
- from diagram_analysis.exceptions import ScopeSemanticsError
17
17
  from infra.monitoring import monitor_execution
18
18
  from infra.monitoring.paths import get_monitoring_run_dir
19
19
  from output_generators.rendering import render_docs
@@ -161,7 +161,7 @@ def _run_remote(args: argparse.Namespace) -> None:
161
161
  upload=args.upload,
162
162
  should_monitor=should_monitor,
163
163
  )
164
- except (LLMAuthError, ScopeSemanticsError):
164
+ except (LLMAuthError, LLMQuotaError, ScopeSemanticsError):
165
165
  # The next repository would fail the same way, so stop the run.
166
166
  raise
167
167
  except Exception:
@@ -5,12 +5,12 @@ import sys
5
5
  from typing import Any
6
6
 
7
7
  from agents.llm_config import LLMConfigError
8
- from agents.llm_errors import LLMAuthError
8
+ from agents.llm_errors import LLMAuthError, LLMQuotaError
9
+ from diagram_analysis.exceptions import ScopeSemanticsError
9
10
  from codeboarding_cli.bootstrap import bootstrap_environment, resolve_local_run_paths
10
11
  from codeboarding_cli.view_instructions import print_view_instructions
11
12
  from codeboarding_workflows.analysis import BaselineUnavailableError, run_incremental
12
13
  from diagram_analysis import RunContext
13
- from diagram_analysis.exceptions import ScopeSemanticsError
14
14
  from diagram_analysis.run_mode import RunMode
15
15
  from infra.utils import monitoring_enabled
16
16
 
@@ -61,7 +61,7 @@ def run_from_args(args: argparse.Namespace, parser: argparse.ArgumentParser) ->
61
61
  # to prompt for a full run; no stack trace needed.
62
62
  logger.info("Incremental unavailable: %s", exc)
63
63
  _emit_error(str(exc))
64
- except (LLMAuthError, ScopeSemanticsError):
64
+ except (LLMAuthError, LLMQuotaError, ScopeSemanticsError):
65
65
  # A full run would fail the same way, so don't ask for one.
66
66
  raise
67
67
  except Exception as exc:
@@ -1,18 +1,20 @@
1
1
  import argparse
2
+ import logging
2
3
  import os
3
4
  import sys
4
- import traceback
5
5
  from pathlib import Path
6
6
 
7
7
  from agents.llm_config import CODEBOARDING_KEY_TAIL
8
- from agents.llm_errors import EXIT_AUTH_ERROR, EXIT_QUOTA_EXHAUSTED, LLMAuthError
8
+ from agents.llm_errors import EXIT_AUTH_ERROR, EXIT_QUOTA_EXHAUSTED, LLMAuthError, LLMQuotaError
9
9
  from codeboarding_cli.bootstrap import resolve_local_run_paths
10
10
  from codeboarding_cli.commands import full_analysis, incremental_analysis, partial_analysis
11
- from diagram_analysis.exceptions import ScopeSemanticsError
12
11
  from output_generators import SUPPORTED_FORMATS, render as render_output
13
12
  from infra.utils import ANALYSIS_FILENAME
14
13
 
15
14
  _SUBCOMMANDS = {"full", "incremental", "partial"}
15
+ # CodeBoarding-action/scripts/analyze_repository.py parses this prefix; keep it stable.
16
+ _ERROR_PREFIX = "CodeBoarding: "
17
+ logger = logging.getLogger(__name__)
16
18
 
17
19
 
18
20
  def _build_shared_parser() -> argparse.ArgumentParser:
@@ -108,22 +110,15 @@ def _dispatch(args: argparse.Namespace, parser: argparse.ArgumentParser) -> None
108
110
  output_dir=run_paths.output_dir,
109
111
  )
110
112
  except LLMAuthError as exc:
111
- # A rejected API key is the user's to fix, not a crash: print one
112
- # actionable line (no traceback) and exit with a distinct code.
113
- print(f"\nCodeBoarding: {exc}", file=sys.stderr)
113
+ logger.error("%s%s", _ERROR_PREFIX, exc)
114
114
  if exc.key_tail != CODEBOARDING_KEY_TAIL:
115
- print(
115
+ logger.error(
116
116
  "Check your LLM provider API key (shell env or ~/.codeboarding/config.toml) and re-run.",
117
- file=sys.stderr,
118
117
  )
119
118
  raise SystemExit(EXIT_AUTH_ERROR) from exc
120
- except ScopeSemanticsError as exc:
121
- if exc.telemetry_properties.get("error_type") != "quota":
122
- raise
123
- # Same exit as any failure, but with a code callers (the GitHub Action) can name.
124
- traceback.print_exception(exc)
125
- print("\nCodeBoarding: the LLM provider's token or credit quota is exhausted.", file=sys.stderr)
126
- print("Add credits or raise the quota for this provider, then re-run.", file=sys.stderr)
119
+ except LLMQuotaError as exc:
120
+ logger.exception("LLM quota failure")
121
+ logger.error("%s%s", _ERROR_PREFIX, exc)
127
122
  raise SystemExit(EXIT_QUOTA_EXHAUSTED) from exc
128
123
 
129
124
 
@@ -30,7 +30,7 @@ from diagram_analysis.incremental_update import (
30
30
  from agents.incremental_results import RecursiveScopeUpdateResult
31
31
  from agents.file_index_models import FileEntry, FileMethodGroup, MethodEntry
32
32
  from agents.llm_config import initialize_agent_llm
33
- from agents.llm_errors import LLMAuthError, llm_failure_properties
33
+ from agents.llm_errors import LLMAuthError, LLMQuotaError, is_quota_exhausted, llm_failure_properties
34
34
  from agents.relation_edges import (
35
35
  drop_misattributed_edges,
36
36
  index_relation_endpoints,
@@ -818,9 +818,11 @@ class DiagramGenerator:
818
818
  incremental,
819
819
  enclosing_names=enclosing_names,
820
820
  )
821
- except LLMAuthError:
821
+ except (LLMAuthError, LLMQuotaError, ScopeSemanticsError):
822
822
  raise
823
823
  except Exception as error:
824
+ if is_quota_exhausted(error):
825
+ raise LLMQuotaError(error) from error
824
826
  raise ScopeSemanticsError(scope.scope_id, telemetry_properties=llm_failure_properties(error)) from error
825
827
  if semantics is None:
826
828
  with self._naming_counts_lock:
@@ -1120,7 +1122,7 @@ class DiagramGenerator:
1120
1122
  new_components = [child for child in analysis.components if child.component_id in preclustered_scopes]
1121
1123
 
1122
1124
  return component.component_id, analysis, new_components
1123
- except (LLMAuthError, ScopeSemanticsError):
1125
+ except (LLMAuthError, LLMQuotaError, ScopeSemanticsError):
1124
1126
  # An LLM failure aborts the whole run rather than shipping this component with deterministic names.
1125
1127
  raise
1126
1128
  except Exception:
@@ -1335,7 +1337,7 @@ class DiagramGenerator:
1335
1337
  stats["completed"] += 1
1336
1338
  try:
1337
1339
  outcomes.append((component, level, future.result()))
1338
- except (LLMAuthError, ScopeSemanticsError):
1340
+ except (LLMAuthError, LLMQuotaError, ScopeSemanticsError):
1339
1341
  for pending in future_to_task:
1340
1342
  pending.cancel()
1341
1343
  raise
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codeboarding"
7
- version = "0.15.1"
7
+ version = "0.15.2"
8
8
  description = "Interactive Diagrams for Code"
9
9
  readme = "PYPI.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes