thothctl 0.16.3__tar.gz → 0.16.4__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 (504) hide show
  1. {thothctl-0.16.3 → thothctl-0.16.4}/PKG-INFO +1 -1
  2. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/ai_agent.py +30 -2
  3. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +7 -1
  4. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/context_builder.py +77 -27
  5. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/ai_settings.py +1 -1
  6. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/ollama_provider.py +63 -4
  7. thothctl-0.16.4/src/thothctl/services/ai_review/strands_agent.py +119 -0
  8. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/prompts.py +31 -10
  9. thothctl-0.16.4/src/thothctl/version.py +2 -0
  10. thothctl-0.16.3/src/thothctl/version.py +0 -2
  11. {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/Dockerfile +0 -0
  12. {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/README.md +0 -0
  13. {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/devcontainer.json +0 -0
  14. {thothctl-0.16.3 → thothctl-0.16.4}/.github/workflows/docs.yml +0 -0
  15. {thothctl-0.16.3 → thothctl-0.16.4}/.github/workflows/python-publish.yml +0 -0
  16. {thothctl-0.16.3 → thothctl-0.16.4}/.gitignore +0 -0
  17. {thothctl-0.16.3 → thothctl-0.16.4}/.pre-commit-config.yaml +0 -0
  18. {thothctl-0.16.3 → thothctl-0.16.4}/.readthedocs.yaml +0 -0
  19. {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_API_FINAL_REPORT.md +0 -0
  20. {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_API_IMPLEMENTATION_PLAN.md +0 -0
  21. {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_REFACTOR_REPORT.md +0 -0
  22. {thothctl-0.16.3 → thothctl-0.16.4}/Dockerfile +0 -0
  23. {thothctl-0.16.3 → thothctl-0.16.4}/LICENSE +0 -0
  24. {thothctl-0.16.3 → thothctl-0.16.4}/README.md +0 -0
  25. {thothctl-0.16.3 → thothctl-0.16.4}/TECHNICAL_DEBT_METRICS.md +0 -0
  26. {thothctl-0.16.3 → thothctl-0.16.4}/__init__.py +0 -0
  27. {thothctl-0.16.3 → thothctl-0.16.4}/docs/catalog/catalog-info.yaml +0 -0
  28. {thothctl-0.16.3 → thothctl-0.16.4}/docs/dashboard/README.md +0 -0
  29. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/README.md +0 -0
  30. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/agent_specifications.md +0 -0
  31. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/agentcore.md +0 -0
  32. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/blast-radius.md +0 -0
  33. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_environment.md +0 -0
  34. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_iac.md +0 -0
  35. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_overview.md +0 -0
  36. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_project_iac.md +0 -0
  37. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_space.md +0 -0
  38. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
  39. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/cost-analysis.md +0 -0
  40. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/customizing_rules.md +0 -0
  41. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/deps-advanced.md +0 -0
  42. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/deps.md +0 -0
  43. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/drift-detection.md +0 -0
  44. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/plan.md +0 -0
  45. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/customizing_docs.md +0 -0
  46. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/document_iac.md +0 -0
  47. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/document_overview.md +0 -0
  48. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/iac.md +0 -0
  49. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/use_cases.md +0 -0
  50. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/generate/generate_components.md +0 -0
  51. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/generate/generate_stacks.md +0 -0
  52. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/init/init.md +0 -0
  53. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/init/init_space.md +0 -0
  54. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/CHANGELOG.md +0 -0
  55. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
  56. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
  57. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/iac.md +0 -0
  58. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/inventory_iac.md +0 -0
  59. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/inventory_overview.md +0 -0
  60. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_overview.md +0 -0
  61. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_projects.md +0 -0
  62. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_spaces.md +0 -0
  63. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/mcp/mcp.md +0 -0
  64. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/iac.md +0 -0
  65. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_cleanup.md +0 -0
  66. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_convert.md +0 -0
  67. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_overview.md +0 -0
  68. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_upgrade.md +0 -0
  69. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/use_cases.md +0 -0
  70. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_overview.md +0 -0
  71. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_project.md +0 -0
  72. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_space.md +0 -0
  73. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/iac.md +0 -0
  74. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/scan_iac.md +0 -0
  75. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/scan_overview.md +0 -0
  76. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/use_cases.md +0 -0
  77. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
  78. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/concepts.md +0 -0
  79. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/cross_platform_support.md +0 -0
  80. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/framework_architecture.md +0 -0
  81. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/infrasctructure_composition.md +0 -0
  82. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/policy_as_code.md +0 -0
  83. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/roadmap_fdi.md +0 -0
  84. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/software_architecture.md +0 -0
  85. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/space_configuration.md +0 -0
  86. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/README.md +0 -0
  87. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/ai_dlc.md +0 -0
  88. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/check_command.md +0 -0
  89. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
  90. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
  91. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/inventory_command.md +0 -0
  92. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
  93. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/space_management.md +0 -0
  94. {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/tasks/create_template.md +0 -0
  95. {thothctl-0.16.3 → thothctl-0.16.4}/docs/iac_devsecops_use_case.md +0 -0
  96. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/automate_tasks_command.png +0 -0
  97. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/commnad_init.png +0 -0
  98. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/create_component.gif +0 -0
  99. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/create_inventory.gif +0 -0
  100. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/doc_command.png +0 -0
  101. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/document_project_code.gif +0 -0
  102. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/framework/thothforge-framework.svg +0 -0
  103. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/framework/thothfr.png +0 -0
  104. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/iacpeerbot_summary.png +0 -0
  105. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/icon-light.png +0 -0
  106. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/icon.png +0 -0
  107. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/init_project.gif +0 -0
  108. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/inventory_command.png +0 -0
  109. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/notification_img.png +0 -0
  110. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/report_dependencies.png +0 -0
  111. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/report_dependencies_summary.png +0 -0
  112. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/restore_inventory_version.gif +0 -0
  113. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/reuse_project_pattern.gif +0 -0
  114. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/scan_code.gif +0 -0
  115. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/scan_command.png +0 -0
  116. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/sync_wk_command.png +0 -0
  117. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/transform_command.png +0 -0
  118. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/update_inventory_version.gif +0 -0
  119. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_command.png +0 -0
  120. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_environment.gif +0 -0
  121. {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_project.gif +0 -0
  122. {thothctl-0.16.3 → thothctl-0.16.4}/docs/includes/abbreviations.md +0 -0
  123. {thothctl-0.16.3 → thothctl-0.16.4}/docs/index.md +0 -0
  124. {thothctl-0.16.3 → thothctl-0.16.4}/docs/installation/linux_installation.md +0 -0
  125. {thothctl-0.16.3 → thothctl-0.16.4}/docs/installation/windows_installation.md +0 -0
  126. {thothctl-0.16.3 → thothctl-0.16.4}/docs/javascripts/tablesort.js +0 -0
  127. {thothctl-0.16.3 → thothctl-0.16.4}/docs/mcp.md +0 -0
  128. {thothctl-0.16.3 → thothctl-0.16.4}/docs/navigation.md +0 -0
  129. {thothctl-0.16.3 → thothctl-0.16.4}/docs/quick_start.md +0 -0
  130. {thothctl-0.16.3 → thothctl-0.16.4}/docs/requirements.txt +0 -0
  131. {thothctl-0.16.3 → thothctl-0.16.4}/docs/stylesheets/extra-enhanced.css +0 -0
  132. {thothctl-0.16.3 → thothctl-0.16.4}/docs/stylesheets/extra.css +0 -0
  133. {thothctl-0.16.3 → thothctl-0.16.4}/docs/telemetry.md +0 -0
  134. {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/cli_commands_audit.md +0 -0
  135. {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/for_developers.md +0 -0
  136. {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/for_platform_engineers.md +0 -0
  137. {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/github_templates.md +0 -0
  138. {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/template_engine.md +0 -0
  139. {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/linux_troubleshooting.md +0 -0
  140. {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/macos_troubleshooting.md +0 -0
  141. {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/troubleshooting.md +0 -0
  142. {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/windows_troubleshooting.md +0 -0
  143. {thothctl-0.16.3 → thothctl-0.16.4}/mkdocs.yaml +0 -0
  144. {thothctl-0.16.3 → thothctl-0.16.4}/pyproject.toml +0 -0
  145. {thothctl-0.16.3 → thothctl-0.16.4}/scripts/run_mcp_server.sh +0 -0
  146. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/__init__.py +0 -0
  147. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/application/__init__.py +0 -0
  148. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/autocomplete.py +0 -0
  149. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/cli.py +0 -0
  150. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/__init__.py +0 -0
  151. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/__init__.py +0 -0
  152. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/cli.py +0 -0
  153. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
  154. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
  155. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
  156. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
  157. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
  158. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
  159. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/history.py +0 -0
  160. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
  161. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
  162. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/override.py +0 -0
  163. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/report.py +0 -0
  164. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
  165. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/__init__.py +0 -0
  166. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/cli.py +0 -0
  167. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/__init__.py +0 -0
  168. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/environment.py +0 -0
  169. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/iac.py +0 -0
  170. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
  171. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project/iac.py +0 -0
  172. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project.py +0 -0
  173. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/__init__.py +0 -0
  174. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/cli.py +0 -0
  175. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
  176. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
  177. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/__init__.py +0 -0
  178. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/cli.py +0 -0
  179. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/commands/__init__.py +0 -0
  180. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/commands/iac.py +0 -0
  181. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/__init__.py +0 -0
  182. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/cli.py +0 -0
  183. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/__init__.py +0 -0
  184. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/component.py +0 -0
  185. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/stacks.py +0 -0
  186. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/__init__.py +0 -0
  187. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/cli.py +0 -0
  188. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/__init__.py +0 -0
  189. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/env.py +0 -0
  190. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/project.py +0 -0
  191. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/space.py +0 -0
  192. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/template.py +0 -0
  193. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/__init__.py +0 -0
  194. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/cli.py +0 -0
  195. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
  196. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/check.py +0 -0
  197. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/iac.py +0 -0
  198. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/__init__.py +0 -0
  199. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/cli.py +0 -0
  200. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/__init__.py +0 -0
  201. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/projects.py +0 -0
  202. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/spaces.py +0 -0
  203. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/__init__.py +0 -0
  204. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/cli.py +0 -0
  205. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
  206. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/register.py +0 -0
  207. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/server.py +0 -0
  208. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/status.py +0 -0
  209. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/stop.py +0 -0
  210. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/__init__.py +0 -0
  211. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/cli.py +0 -0
  212. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/__init__.py +0 -0
  213. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
  214. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/cleanup.py +0 -0
  215. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/convert.py +0 -0
  216. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/upgrade.py +0 -0
  217. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/__init__.py +0 -0
  218. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/cli.py +0 -0
  219. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/project.py +0 -0
  220. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/space.py +0 -0
  221. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/__init__.py +0 -0
  222. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/cli.py +0 -0
  223. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/commands/__init__.py +0 -0
  224. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/commands/iac.py +0 -0
  225. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/__init__.py +0 -0
  226. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/cli.py +0 -0
  227. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/__init__.py +0 -0
  228. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/activate.py +0 -0
  229. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/update.py +0 -0
  230. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/upgrade/cli.py +0 -0
  231. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf.setup.toml +0 -0
  232. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_home.toml +0 -0
  233. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_module.toml +0 -0
  234. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_project.toml +0 -0
  235. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
  236. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/__init__.py +0 -0
  237. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/common.py +0 -0
  238. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
  239. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/__init__.py +0 -0
  240. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/constants.py +0 -0
  241. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/default_values.py +0 -0
  242. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/defaults.py +0 -0
  243. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/models.py +0 -0
  244. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/settings.py +0 -0
  245. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/template_config.py +0 -0
  246. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/template_configs.py +0 -0
  247. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/templates.py +0 -0
  248. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/validation.py +0 -0
  249. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/__init__.py +0 -0
  250. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/cli_ui.py +0 -0
  251. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/commands.py +0 -0
  252. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/config.py +0 -0
  253. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/__init__.py +0 -0
  254. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
  255. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
  256. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
  257. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/github/get_github.py +0 -0
  258. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
  259. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
  260. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
  261. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
  262. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pattern_names.py +0 -0
  263. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
  264. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
  265. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/logger.py +0 -0
  266. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/telemetry.py +0 -0
  267. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/version_tools.py +0 -0
  268. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/__init__.py +0 -0
  269. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/interfaces/__init__.py +0 -0
  270. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/models/__init__.py +0 -0
  271. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/README.md +0 -0
  272. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/__init__.py +0 -0
  273. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/server.py +0 -0
  274. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/__init__.py +0 -0
  275. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/__init__.py +0 -0
  276. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
  277. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
  278. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
  279. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
  280. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
  281. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/__init__.py +0 -0
  282. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
  283. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/decision_engine.py +0 -0
  284. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/main.py +0 -0
  285. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/memory.py +0 -0
  286. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/orchestrator.py +0 -0
  287. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
  288. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
  289. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/azure_provider.py +0 -0
  290. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +0 -0
  291. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -0
  292. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/openai_provider.py +0 -0
  293. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
  294. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
  295. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/tracing.py +0 -0
  296. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
  297. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
  298. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
  299. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
  300. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
  301. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/__init__.py +0 -0
  302. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/environment/__init__.py +0 -0
  303. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/environment/check_environment.py +0 -0
  304. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/org_policy_loader.py +0 -0
  305. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/__init__.py +0 -0
  306. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
  307. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/check_origin_version.py +0 -0
  308. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/check_project_structure.py +0 -0
  309. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/__init__.py +0 -0
  310. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
  311. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
  312. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
  313. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
  314. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
  315. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
  316. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
  317. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
  318. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
  319. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
  320. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
  321. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
  322. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
  323. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
  324. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
  325. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
  326. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
  327. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
  328. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
  329. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
  330. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
  331. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
  332. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
  333. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
  334. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
  335. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
  336. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
  337. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/__init__.py +0 -0
  338. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
  339. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
  340. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
  341. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
  342. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
  343. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/models.py +0 -0
  344. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/risk_assessment.py +0 -0
  345. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
  346. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/rule_merger.py +0 -0
  347. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/__init__.py +0 -0
  348. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
  349. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/data_loader.py +0 -0
  350. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/__init__.py +0 -0
  351. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/create_documentation.py +0 -0
  352. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/files_content.py +0 -0
  353. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/files_scan.py +0 -0
  354. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_documentation.py +0 -0
  355. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
  356. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_grunt_info.py +0 -0
  357. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/__init__.py +0 -0
  358. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
  359. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
  360. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
  361. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
  362. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
  363. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/__init__.py +0 -0
  364. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/config.yaml +0 -0
  365. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_code.py +0 -0
  366. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_component.py +0 -0
  367. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
  368. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
  369. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_template.py +0 -0
  370. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/files_content.py +0 -0
  371. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
  372. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
  373. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/__init__.py +0 -0
  374. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/environment/__init__.py +0 -0
  375. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/environment/install_tools.py +0 -0
  376. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/project/__init__.py +0 -0
  377. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/project/project.py +0 -0
  378. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/__init__.py +0 -0
  379. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/example_space.toml +0 -0
  380. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/local_registry.py +0 -0
  381. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/space.py +0 -0
  382. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/__init__.py +0 -0
  383. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/changelog_parser.py +0 -0
  384. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/inventory_service.py +0 -0
  385. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/models.py +0 -0
  386. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
  387. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/report_service.py +0 -0
  388. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
  389. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
  390. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/update_versions.py +0 -0
  391. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/version_service.py +0 -0
  392. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/README.md +0 -0
  393. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/__init__.py +0 -0
  394. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/amazon_q_server.py +0 -0
  395. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/example.py +0 -0
  396. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/service.py +0 -0
  397. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/simple_http_server.py +0 -0
  398. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/__init__.py +0 -0
  399. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
  400. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
  401. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/__init__.py +0 -0
  402. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
  403. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
  404. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/__init__.py +0 -0
  405. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/conversion_service.py +0 -0
  406. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/get_project_data.py +0 -0
  407. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/post_init.py +0 -0
  408. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/project_converter.py +0 -0
  409. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/project_defaults.py +0 -0
  410. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
  411. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
  412. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
  413. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
  414. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
  415. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/upgrade/__init__.py +0 -0
  416. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
  417. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/__init__.py +0 -0
  418. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/compliance_review.py +0 -0
  419. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/import_reports.py +0 -0
  420. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/models.py +0 -0
  421. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/report_parser.py +0 -0
  422. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/sarif_output.py +0 -0
  423. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scan_history.py +0 -0
  424. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scan_service.py +0 -0
  425. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/__init__.py +0 -0
  426. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/checkov.py +0 -0
  427. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/kics.py +0 -0
  428. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/opa.py +0 -0
  429. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
  430. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/scanners.py +0 -0
  431. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
  432. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
  433. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/trivy.py +0 -0
  434. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/reports/inventory_report.html +0 -0
  435. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/reports/inventory_report.js +0 -0
  436. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/unified_report_styles.css +0 -0
  437. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/__init__.py +0 -0
  438. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/banner.py +0 -0
  439. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/__init__.py +0 -0
  440. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
  441. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/create_html_reports.py +0 -0
  442. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/delete_directory.py +0 -0
  443. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/fix_report_styling.py +0 -0
  444. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/render_scan_report.py +0 -0
  445. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/report_html_utils.py +0 -0
  446. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/dashboard.html +0 -0
  447. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/index_report.html +0 -0
  448. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/individual_report.html +0 -0
  449. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/simple_report.html +0 -0
  450. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
  451. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_scan_report.html +0 -0
  452. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
  453. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
  454. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/crypto.py +0 -0
  455. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
  456. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
  457. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/__init__.py +0 -0
  458. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
  459. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
  460. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/platform_utils.py +0 -0
  461. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/__init__.py +0 -0
  462. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
  463. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
  464. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
  465. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
  466. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
  467. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
  468. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
  469. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
  470. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/template_loader.py +0 -0
  471. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/thoth_colors.py +0 -0
  472. {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/wellcome_banner.py +0 -0
  473. {thothctl-0.16.3 → thothctl-0.16.4}/tests/conftest.py +0 -0
  474. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_agentcore_entrypoint.py +0 -0
  475. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_aws_pricing_client.py +0 -0
  476. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_azure_devops_pr_comments.py +0 -0
  477. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_bedrock_pricing.py +0 -0
  478. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cdk_language_selection.py +0 -0
  479. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_context_steering.py +0 -0
  480. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_analyzer.py +0 -0
  481. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_models.py +0 -0
  482. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_pr_comments.py +0 -0
  483. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_dashboard_loading_fix.py +0 -0
  484. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_dashboard_service.py +0 -0
  485. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_drift.py +0 -0
  486. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_drift_detection.py +0 -0
  487. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_ec2_pricing.py +0 -0
  488. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_github_pr_comments.py +0 -0
  489. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_iac_cost_integration.py +0 -0
  490. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_inventory_pr_comments.py +0 -0
  491. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_kics_scanner.py +0 -0
  492. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_mermaid_edge_labels.py +0 -0
  493. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_new_cost_providers.py +0 -0
  494. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_parallel_scan.py +0 -0
  495. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_platform_utils.py +0 -0
  496. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_pr_comment_publisher.py +0 -0
  497. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_provider_source_url_fix.py +0 -0
  498. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_provider_versions.py +0 -0
  499. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_scan_pr_comments.py +0 -0
  500. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_space_command.py +0 -0
  501. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_space_management.py +0 -0
  502. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_template_url_fix.py +0 -0
  503. {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_terragrunt_parser.py +0 -0
  504. {thothctl-0.16.3 → thothctl-0.16.4}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thothctl
3
- Version: 0.16.3
3
+ Version: 0.16.4
4
4
  Summary: A CLI for Developer Control Plane. Accelerate your cloud IaC deployments.
5
5
  Project-URL: SourceCode, https://github.com/thothforge/thothctl
6
6
  Project-URL: HomePage, https://github.com/thothforge/thothctl
@@ -18,6 +18,7 @@ from .utils.prompts import (
18
18
  SYSTEM_SECURITY_ANALYST,
19
19
  SYSTEM_CODE_REVIEWER,
20
20
  SYSTEM_FULL_ANALYSIS,
21
+ SYSTEM_COMPACT,
21
22
  )
22
23
  from .utils.fix_prompts import SYSTEM_FIX_GENERATOR
23
24
  from .tracing import span
@@ -85,10 +86,12 @@ class AIReviewAgent:
85
86
  """
86
87
  with span("ai_agent.analyze_directory", {"directory": directory}) as s:
87
88
  logger.info(f"Building rich context for {directory}")
89
+ self._emit_status("📦 Collecting project context (inventory, scan reports, plans)...")
88
90
  ctx = self.context_builder.build_context(directory)
89
91
 
90
92
  basic_risk = None
91
93
  if ctx.scan_results.get("total_findings", 0) > 0:
94
+ self._emit_status(f"⚠️ Found {ctx.scan_results['total_findings']} scan findings, assessing risk...")
92
95
  basic_risk = self.risk_assessor.assess_risk(ctx.scan_results)
93
96
 
94
97
  if not self.cost_tracker.check_budget():
@@ -98,9 +101,28 @@ class AIReviewAgent:
98
101
  return self._basic_analysis(ctx.scan_results, basic_risk)
99
102
  return self._empty_result()
100
103
 
104
+ self._emit_status("🤖 Sending context to LLM for security analysis...")
101
105
  formatted = self.context_builder.format_for_ai(ctx)
102
- fallback = (lambda: self._basic_analysis(ctx.scan_results, basic_risk)) if basic_risk else self._empty_result
103
- result = self._call_ai(SYSTEM_FULL_ANALYSIS, formatted, "analyze_directory", fallback=fallback)
106
+
107
+ # Use compact prompt for local models (Ollama) to fit VRAM constraints
108
+ if self._provider.name == "ollama":
109
+ # Hybrid: scan data for structured findings + LLM for recommendations
110
+ base_result = self._basic_analysis(ctx.scan_results, basic_risk) if basic_risk else self._empty_result()
111
+ try:
112
+ ai_response = self._provider.analyze(SYSTEM_COMPACT, formatted)
113
+ # AI might return JSON or text — either way, use it as recommendations
114
+ if isinstance(ai_response, dict) and ai_response.get("recommendations"):
115
+ base_result["recommendations"] = ai_response["recommendations"]
116
+ base_result["architecture_assessment"] = ai_response.get("architecture_assessment", "")
117
+ elif isinstance(ai_response, dict) and ai_response.get("_raw_text"):
118
+ base_result["recommendations"] = [ai_response["_raw_text"][:2000]]
119
+ except Exception as e:
120
+ logger.debug(f"LLM recommendations failed: {e}")
121
+ result = base_result
122
+ else:
123
+ system_prompt = SYSTEM_FULL_ANALYSIS
124
+ fallback = (lambda: self._basic_analysis(ctx.scan_results, basic_risk)) if basic_risk else self._empty_result
125
+ result = self._call_ai(system_prompt, formatted, "analyze_directory", fallback=fallback)
104
126
 
105
127
  result["_context"] = {
106
128
  "project_type": ctx.project_type,
@@ -265,6 +287,12 @@ class AIReviewAgent:
265
287
  return fallback()
266
288
  return self._empty_result()
267
289
 
290
+ @staticmethod
291
+ def _emit_status(msg: str) -> None:
292
+ """Print a status message visible during the spinner."""
293
+ from rich.console import Console
294
+ Console(stderr=True).print(f"[dim]{msg}[/dim]")
295
+
268
296
  @staticmethod
269
297
  def _empty_result() -> Dict[str, Any]:
270
298
  return {
@@ -6,7 +6,7 @@ from typing import Dict, Any, List
6
6
  logger = logging.getLogger(__name__)
7
7
 
8
8
  # File extensions to analyze
9
- IAC_EXTENSIONS = {".tf", ".hcl", ".tfvars", ".yaml", ".yml", ".json"}
9
+ IAC_EXTENSIONS = {".tf", ".hcl", ".tfvars"}
10
10
 
11
11
 
12
12
  class CodeReviewer:
@@ -24,6 +24,12 @@ class CodeReviewer:
24
24
 
25
25
  for f in dir_path.rglob("*"):
26
26
  if f.suffix in exts and not any(p.startswith(".") for p in f.parts):
27
+ # Skip non-IaC directories
28
+ if any(skip in f.parts for skip in (
29
+ "Reports", ".terraform", "node_modules", ".terragrunt-cache",
30
+ "cdk.out", "__pycache__", ".git", "html_reports", "tfplan",
31
+ )):
32
+ continue
27
33
  try:
28
34
  content = f.read_text(errors="ignore")
29
35
  rel_path = str(f.relative_to(dir_path))
@@ -38,6 +38,7 @@ class ContextBuilder:
38
38
  # Run each collector independently — failures don't block others
39
39
  self._collect_inventory(ctx)
40
40
  self._collect_scan_results(ctx)
41
+ self._collect_plan_files(ctx)
41
42
  self._collect_blast_radius(ctx)
42
43
  self._collect_code(ctx)
43
44
 
@@ -97,12 +98,30 @@ class ContextBuilder:
97
98
  )
98
99
  sections.append("")
99
100
 
100
- # Code section (only key files, truncated)
101
+ # Code section only include files referenced in findings + plan summaries
101
102
  if ctx.code_files:
102
103
  sections.append("## Key IaC Files")
103
- char_budget = 30000
104
+ char_budget = 12000 # ~3K tokens for code context
105
+
106
+ # Prioritize: plans first, then files mentioned in scan findings
107
+ referenced_files = set()
108
+ for tool_data in ctx.scan_results.get("tools", {}).values():
109
+ for f in tool_data.get("findings", []):
110
+ ref = f.get("file", "")
111
+ if ref:
112
+ referenced_files.add(ref)
113
+
114
+ # Sort: plans first, then referenced files, then others
115
+ def priority(item):
116
+ path, _ = item
117
+ if "[PLAN]" in path:
118
+ return 0
119
+ if any(ref in path for ref in referenced_files):
120
+ return 1
121
+ return 2
122
+
104
123
  used = 0
105
- for path, content in sorted(ctx.code_files.items()):
124
+ for path, content in sorted(ctx.code_files.items(), key=priority):
106
125
  header = f"\n--- {path} ---\n"
107
126
  if used + len(header) + len(content) > char_budget:
108
127
  remaining = len(ctx.code_files) - len([s for s in sections if s.startswith("--- ")])
@@ -165,43 +184,74 @@ class ContextBuilder:
165
184
  ctx.errors.append(f"Inventory unavailable: {e}")
166
185
 
167
186
  def _collect_scan_results(self, ctx: IaCContext) -> None:
168
- """Check for existing scan reports or run a quick scan."""
187
+ """Check for existing scan reports at project root."""
169
188
  try:
170
- from ..report_analyzer import ReportAnalyzer
189
+ from .report_analyzer import ReportAnalyzer
171
190
 
172
191
  analyzer = ReportAnalyzer()
173
- reports_dir = Path(ctx.directory) / "Reports"
174
192
 
175
- # First check if reports already exist
176
- if reports_dir.exists():
193
+ # Look for Reports/ at target dir and up to project root
194
+ target = Path(ctx.directory)
195
+ reports_dir = None
196
+ for parent in [target] + list(target.parents):
197
+ candidate = parent / "Reports"
198
+ if candidate.exists():
199
+ reports_dir = candidate
200
+ break
201
+ if (parent / ".thothcf.toml").exists() or (parent / ".git").exists():
202
+ break
203
+
204
+ if reports_dir and reports_dir.exists():
177
205
  ctx.scan_results = analyzer.parse_scan_results(str(reports_dir))
178
206
  if ctx.scan_results.get("total_findings", 0) > 0:
179
207
  logger.info(f"Found existing scan results: {ctx.scan_results['total_findings']} findings")
180
208
  return
181
209
 
182
- # Try running a quick checkov scan
183
- try:
184
- from ...scan.scan_service import ScanService
185
-
186
- scan_svc = ScanService()
187
- tmp_reports = str(Path(ctx.directory) / "Reports")
188
- scan_svc.execute_scans(
189
- directory=ctx.directory,
190
- reports_dir=tmp_reports,
191
- selected_tools=["checkov"],
192
- options={},
193
- html_reports_format="simple",
194
- )
195
- ctx.scan_results = analyzer.parse_scan_results(tmp_reports)
196
- logger.info(f"Quick scan: {ctx.scan_results.get('total_findings', 0)} findings")
197
- except Exception as scan_err:
198
- logger.debug(f"Quick scan failed: {scan_err}")
199
- ctx.errors.append(f"Live scan unavailable: {scan_err}")
210
+ ctx.errors.append("No scan reports found. Run 'thothctl scan iac' first for richer AI analysis.")
200
211
 
201
212
  except Exception as e:
202
213
  logger.debug(f"Scan results collection failed: {e}")
203
214
  ctx.errors.append(f"Scan results unavailable: {e}")
204
215
 
216
+ def _collect_plan_files(self, ctx: IaCContext) -> None:
217
+ """Collect tfplan.json summaries for change analysis."""
218
+ try:
219
+ import json as _json
220
+ target = Path(ctx.directory)
221
+
222
+ # Find tfplan.json in target and project-level stacks/tfplan/
223
+ plan_files = list(target.rglob("tfplan.json"))
224
+ for parent in [target] + list(target.parents):
225
+ if (parent / ".thothcf.toml").exists() or (parent / ".git").exists():
226
+ tfplan_dir = parent / "stacks" / "tfplan"
227
+ if tfplan_dir.exists():
228
+ plan_files.extend(tfplan_dir.rglob("tfplan.json"))
229
+ break
230
+
231
+ for pf in plan_files[:5]:
232
+ try:
233
+ with open(pf) as f:
234
+ plan = _json.load(f)
235
+ changes = plan.get("resource_changes", [])
236
+ creates = sum(1 for c in changes if "create" in c.get("change", {}).get("actions", []))
237
+ updates = sum(1 for c in changes if "update" in c.get("change", {}).get("actions", []))
238
+ deletes = sum(1 for c in changes if "delete" in c.get("change", {}).get("actions", []))
239
+ ctx.code_files[f"[PLAN] {pf.name} ({pf.parent.name})"] = (
240
+ f"# Terraform Plan: {pf.parent.name}\n"
241
+ f"# Creates: {creates}, Updates: {updates}, Deletes: {deletes}\n"
242
+ f"# Total resource changes: {len(changes)}\n"
243
+ + "\n".join(
244
+ f"# {c['type']}.{c['name']} → {c['change']['actions']}"
245
+ for c in changes[:20]
246
+ )
247
+ )
248
+ except Exception:
249
+ pass
250
+ if plan_files:
251
+ logger.info(f"Found {len(plan_files)} tfplan.json files")
252
+ except Exception as e:
253
+ logger.debug(f"Plan file collection failed: {e}")
254
+
205
255
  def _collect_blast_radius(self, ctx: IaCContext) -> None:
206
256
  """Run BlastRadiusService for dependency analysis."""
207
257
  try:
@@ -235,7 +285,7 @@ class ContextBuilder:
235
285
  def _collect_code(self, ctx: IaCContext) -> None:
236
286
  """Collect raw IaC files as supplementary context."""
237
287
  try:
238
- from ..code_reviewer import CodeReviewer
288
+ from .code_reviewer import CodeReviewer
239
289
 
240
290
  reviewer = CodeReviewer()
241
291
  ctx.code_files = reviewer.collect_code_for_review(ctx.directory)
@@ -18,7 +18,7 @@ DEFAULT_CONFIG_FILE = "ai_config.yaml"
18
18
  class ProviderConfig:
19
19
  """Configuration for a single AI provider."""
20
20
  model: str = ""
21
- max_tokens: int = 4000
21
+ max_tokens: int = 8000
22
22
  temperature: float = 0.1
23
23
  api_key: str = ""
24
24
  region: str = "us-east-1"
@@ -1,6 +1,8 @@
1
1
  """Ollama provider for AI review — uses local models via OpenAI-compatible API."""
2
2
  import json
3
3
  import logging
4
+ import os
5
+ import uuid
4
6
  from typing import Dict, Any
5
7
 
6
8
  from ..config.ai_settings import ProviderConfig
@@ -11,6 +13,23 @@ logger = logging.getLogger(__name__)
11
13
  DEFAULT_OLLAMA_BASE_URL = "http://localhost:11434/v1"
12
14
  DEFAULT_OLLAMA_MODEL = "llama3"
13
15
 
16
+ # Session ID for grouping related traces in Langfuse
17
+ _session_id = None
18
+
19
+
20
+ def get_session_id() -> str:
21
+ """Get or create a session ID for this thothctl run."""
22
+ global _session_id
23
+ if _session_id is None:
24
+ _session_id = f"thothctl-{uuid.uuid4().hex[:8]}"
25
+ return _session_id
26
+
27
+
28
+ def reset_session():
29
+ """Reset session for a new workflow run."""
30
+ global _session_id
31
+ _session_id = None
32
+
14
33
 
15
34
  class OllamaProvider:
16
35
  """Ollama local model integration via its OpenAI-compatible API."""
@@ -26,10 +45,20 @@ class OllamaProvider:
26
45
  def client(self):
27
46
  if self._client is None:
28
47
  try:
29
- from openai import OpenAI
48
+ # Use Langfuse-wrapped OpenAI client if configured
49
+ import os
50
+ if os.environ.get("LANGFUSE_PUBLIC_KEY"):
51
+ try:
52
+ from langfuse.openai import OpenAI
53
+ logger.info("Using Langfuse-instrumented OpenAI client")
54
+ except Exception:
55
+ from openai import OpenAI
56
+ else:
57
+ from openai import OpenAI
30
58
  self._client = OpenAI(
31
59
  base_url=self.base_url,
32
60
  api_key="ollama", # Ollama doesn't need a real key
61
+ timeout=1800.0, # 30 min — large models on limited VRAM are very slow
33
62
  )
34
63
  except ImportError:
35
64
  raise ImportError("openai package required. Install with: pip install openai")
@@ -51,20 +80,50 @@ class OllamaProvider:
51
80
  "temperature": self.temperature,
52
81
  }
53
82
 
83
+ # Add Langfuse metadata if available
84
+ if os.environ.get("LANGFUSE_PUBLIC_KEY"):
85
+ kwargs["metadata"] = {
86
+ "session_id": get_session_id(),
87
+ "tags": ["thothctl", "ai-review"],
88
+ }
89
+
54
90
  try:
55
- kwargs["response_format"] = {"type": "json_object"}
56
91
  response = self.client.chat.completions.create(**kwargs)
92
+ if not response.choices[0].message.content:
93
+ raise ValueError("Empty response")
57
94
  except Exception:
58
- kwargs.pop("response_format", None)
95
+ kwargs.pop("metadata", None)
59
96
  response = self.client.chat.completions.create(**kwargs)
60
97
 
61
- text = response.choices[0].message.content
98
+ text = response.choices[0].message.content or ""
62
99
  usage = response.usage
63
100
 
101
+ if not text:
102
+ raise ValueError("Empty response from model")
103
+
104
+ # Try to extract JSON from response
64
105
  if "```json" in text:
65
106
  text = text.split("```json")[1].split("```")[0].strip()
66
107
  elif "```" in text:
67
108
  text = text.split("```")[1].split("```")[0].strip()
109
+ elif text.strip().startswith("{"):
110
+ text = text.strip()
111
+ else:
112
+ # Model didn't return JSON — find any JSON block in the response
113
+ import re
114
+ json_match = re.search(r'\{[^{}]*(?:\{[^{}]*\}[^{}]*)*\}', text, re.DOTALL)
115
+ if json_match:
116
+ text = json_match.group(0)
117
+ else:
118
+ # No JSON at all — wrap the text response as a result
119
+ text = json.dumps({
120
+ "summary": {"total_findings": 0},
121
+ "findings": [],
122
+ "risk_score": 0,
123
+ "recommendations": [text[:500]],
124
+ "architecture_assessment": text[:1000],
125
+ "_raw_text": text[:2000],
126
+ })
68
127
 
69
128
  result = json.loads(text)
70
129
  input_tokens = getattr(usage, "prompt_tokens", 0) or 0
@@ -0,0 +1,119 @@
1
+ """Strands-based IaC Security Agent — multi-agent orchestration.
2
+
3
+ Supports two modes:
4
+ - Swarm: Agents hand off autonomously (requires tool-calling models: Bedrock, OpenAI)
5
+ - Workflow: Deterministic pipeline (works with any model including Ollama)
6
+
7
+ NOTE: Strands Ollama adapter has a known streaming bug in v1.43.0.
8
+ For Ollama, use the existing ai_agent.py (direct OpenAI client).
9
+ This module is ready for Bedrock/OpenAI models.
10
+
11
+ Usage:
12
+ from thothctl.services.ai_review.strands_agent import run_security_review
13
+
14
+ # With Bedrock (recommended for production)
15
+ report = run_security_review("us.anthropic.claude-3-5-sonnet-20241022-v2:0", ".")
16
+
17
+ # With OpenAI
18
+ report = run_security_review("openai/gpt-4-turbo", ".")
19
+ """
20
+ import json
21
+ import logging
22
+ import os
23
+ from pathlib import Path
24
+ from typing import Optional
25
+
26
+ from strands import Agent
27
+
28
+ logger = logging.getLogger(__name__)
29
+
30
+
31
+ def _get_model(model_id: str):
32
+ """Create a Strands model from a model ID string."""
33
+ if model_id.startswith("ollama/"):
34
+ from strands.models.ollama import OllamaModel
35
+ model_name = model_id.replace("ollama/", "")
36
+ host = os.environ.get("OLLAMA_HOST", "http://localhost:11434").rstrip("/v1").rstrip("/")
37
+ return OllamaModel(model_id=model_name, host=host)
38
+ elif model_id.startswith("openai/"):
39
+ from strands.models.openai import OpenAIModel
40
+ return OpenAIModel(model_id=model_id.replace("openai/", ""))
41
+ else:
42
+ # Default to Bedrock
43
+ from strands.models.bedrock import BedrockModel
44
+ return BedrockModel(model_id=model_id)
45
+
46
+
47
+ def _build_context(directory: str) -> str:
48
+ """Build IaC context from thothctl services."""
49
+ from .analyzers.context_builder import ContextBuilder
50
+ builder = ContextBuilder()
51
+ ctx = builder.build_context(directory)
52
+ return builder.format_for_ai(ctx)
53
+
54
+
55
+ def run_security_review(model_id: str, directory: str) -> str:
56
+ """Run multi-agent security review as a deterministic workflow.
57
+
58
+ Pipeline: Context → Security Analysis → Architecture Review → Recommendations
59
+ Each agent receives the previous agent's output as context.
60
+ """
61
+ os.environ["THOTH_AGENT_DIR"] = str(Path(directory).resolve())
62
+ model = _get_model(model_id)
63
+ context = _build_context(directory)
64
+
65
+ # Agent 1: Security Analyst
66
+ security_agent = Agent(
67
+ model=model,
68
+ system_prompt="""You are a security analyst. Given IaC scan findings, identify the TOP 5 most critical issues.
69
+ For each issue, include: severity, title (from scan data), resource name, file path, and a 1-line remediation.
70
+ Use ONLY the findings provided. Do NOT invent issues. Format as a numbered list.""",
71
+ )
72
+
73
+ # Agent 2: Architecture Reviewer
74
+ architecture_agent = Agent(
75
+ model=model,
76
+ system_prompt="""You are an architecture reviewer. Given security findings and IaC context, assess:
77
+ 1. Module structure quality (are modules well-organized?)
78
+ 2. Dependency risks (what's the blast radius?)
79
+ 3. Version hygiene (outdated modules?)
80
+ Provide a brief assessment (5-7 sentences).""",
81
+ )
82
+
83
+ # Agent 3: Recommendations
84
+ recommendations_agent = Agent(
85
+ model=model,
86
+ system_prompt="""You are a DevSecOps advisor. Given security findings and architecture assessment, provide:
87
+ 1. Top 3 immediate actions (with exact file:line to modify)
88
+ 2. Risk score (0-100, where 100 is critical)
89
+ 3. Whether to block the pipeline (yes/no with reason)
90
+ Be concise. Max 10 lines.""",
91
+ )
92
+
93
+ # Execute pipeline
94
+ logger.info("🔍 Agent 1: Security Analysis...")
95
+ security_result = security_agent(f"Analyze these IaC findings:\n\n{context}")
96
+
97
+ logger.info("🏗️ Agent 2: Architecture Review...")
98
+ arch_result = architecture_agent(
99
+ f"Context:\n{context}\n\nSecurity findings:\n{security_result}"
100
+ )
101
+
102
+ logger.info("💡 Agent 3: Recommendations...")
103
+ recs_result = recommendations_agent(
104
+ f"Security findings:\n{security_result}\n\nArchitecture assessment:\n{arch_result}"
105
+ )
106
+
107
+ # Combine results
108
+ report = f"""# 🤖 AI Security Review (Multi-Agent)
109
+
110
+ ## 🔍 Security Findings
111
+ {security_result}
112
+
113
+ ## 🏗️ Architecture Assessment
114
+ {arch_result}
115
+
116
+ ## 💡 Recommendations
117
+ {recs_result}
118
+ """
119
+ return report
@@ -94,16 +94,19 @@ Respond in valid JSON with this structure:
94
94
  }"""
95
95
 
96
96
  SYSTEM_FULL_ANALYSIS = """You are an expert Infrastructure as Code (IaC) security and architecture analyst.
97
- You are the AI agent for ThothCTL, an AI-Powered Infrastructure Lifecycle CLI that provides:
97
+ You are the AI agent for ThothCTL, an AI-Powered Infrastructure Lifecycle CLI.
98
98
 
99
- **Available context sources (provided when available):**
100
- - **Infrastructure Inventory**: Modules, providers, versions from Terraform Registry and private registries. Includes version status (up-to-date, outdated, deprecated).
101
- - **Security Scan Findings**: Results from Checkov, KICS, Trivy, OPA/Conftest, Terraform Compliance. Each tool covers different aspects Checkov for CIS benchmarks, Trivy for CVEs, KICS for misconfigurations, OPA for custom org policies.
102
- - **Blast Radius Analysis**: Dependency graph showing which components are affected by changes, risk scores per component, criticality ratings, and rollback plans.
103
- - **Raw IaC Source Code**: Terraform, OpenTofu, Terragrunt, CloudFormation files.
99
+ **CRITICAL RULES:**
100
+ 1. Use ONLY the scan findings provided below. Do NOT invent or hallucinate findings.
101
+ 2. Each finding MUST have the exact resource name and file_path from the scan data.
102
+ 3. If a finding says "resource: module.vpc" and "file: main.tf", use those exact values.
103
+ 4. The "title" field MUST come from the scan tool's check_name/title, not be "Untitled".
104
104
 
105
- **Enforcement context:**
106
- - ThothCTL supports "soft" (report only) and "hard" (block pipeline) enforcement modes
105
+ **Context sources provided:**
106
+ - **Security Scan Findings**: Real results from Checkov, KICS, Trivy with resource names and file paths.
107
+ - **Terraform Plans**: Shows what resources will be created/modified/deleted per stack.
108
+ - **Infrastructure Inventory**: Modules, providers, versions.
109
+ - **IaC Source Code**: Actual .tf files from the project stacks.
107
110
  - Your recommendations should indicate which findings warrant "hard" enforcement
108
111
 
109
112
  Perform a comprehensive analysis covering:
@@ -133,8 +136,9 @@ Respond in valid JSON with this structure:
133
136
  "title": "string",
134
137
  "description": "string",
135
138
  "resource": "string",
136
- "remediation": "string",
137
- "code_example": "string",
139
+ "file_path": "string (exact path where the fix must be applied, e.g. stacks/platform/data/rds/main.tf)",
140
+ "remediation": "string (what to change and WHERE in the file)",
141
+ "code_example": "string (the exact HCL code block to add/modify)",
138
142
  "compliance": ["string"],
139
143
  "source_tool": "string",
140
144
  "enforce_hard": false
@@ -144,3 +148,20 @@ Respond in valid JSON with this structure:
144
148
  "risk_score": float,
145
149
  "recommendations": ["string"]
146
150
  }"""
151
+
152
+
153
+ SYSTEM_COMPACT = """You are a senior IaC security advisor. Given scan findings and terraform code, provide:
154
+
155
+ 1. TOP 5 most critical issues with exact file path and line to fix
156
+ 2. For each issue: one HCL code snippet showing the fix
157
+ 3. Overall risk assessment (score 0-100)
158
+
159
+ Format each finding as:
160
+ ## [SEVERITY] Title
161
+ **File**: path/to/file.tf:LINE
162
+ **Fix**:
163
+ ```hcl
164
+ code here
165
+ ```
166
+
167
+ Be specific. Use the exact resources and files from the scan data."""
@@ -0,0 +1,2 @@
1
+ """Version module."""
2
+ __version__ = "0.16.4"
@@ -1,2 +0,0 @@
1
- """Version module."""
2
- __version__ = "0.16.3"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes