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.
- {thothctl-0.16.3 → thothctl-0.16.4}/PKG-INFO +1 -1
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/ai_agent.py +30 -2
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +7 -1
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/context_builder.py +77 -27
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/ai_settings.py +1 -1
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/ollama_provider.py +63 -4
- thothctl-0.16.4/src/thothctl/services/ai_review/strands_agent.py +119 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/prompts.py +31 -10
- thothctl-0.16.4/src/thothctl/version.py +2 -0
- thothctl-0.16.3/src/thothctl/version.py +0 -2
- {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/Dockerfile +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.devcontainer/devcontainer.json +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.github/workflows/docs.yml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.github/workflows/python-publish.yml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.gitignore +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.pre-commit-config.yaml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/.readthedocs.yaml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_API_FINAL_REPORT.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_API_IMPLEMENTATION_PLAN.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/AWS_PRICING_REFACTOR_REPORT.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/Dockerfile +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/LICENSE +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/TECHNICAL_DEBT_METRICS.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/catalog/catalog-info.yaml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/dashboard/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/agent_specifications.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/agentcore.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/blast-radius.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_environment.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_project_iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/check_space.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/cost-analysis.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/customizing_rules.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/deps-advanced.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/deps.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/drift-detection.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/plan.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/customizing_docs.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/document_iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/document_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/document/use_cases.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/generate/generate_components.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/generate/generate_stacks.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/init/init.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/init/init_space.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/CHANGELOG.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/inventory_iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/inventory/inventory_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_projects.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/list/list_spaces.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/mcp/mcp.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_cleanup.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_convert.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/project_upgrade.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/project/use_cases.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_project.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/remove/remove_space.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/scan_iac.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/scan_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/scan/use_cases.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/concepts.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/cross_platform_support.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/framework_architecture.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/infrasctructure_composition.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/policy_as_code.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/roadmap_fdi.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/software_architecture.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/space_configuration.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/ai_dlc.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/check_command.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/inventory_command.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/space_management.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/use_cases/tasks/create_template.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/iac_devsecops_use_case.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/automate_tasks_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/commnad_init.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/create_component.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/create_inventory.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/doc_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/document_project_code.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/framework/thothforge-framework.svg +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/framework/thothfr.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/iacpeerbot_summary.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/icon-light.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/icon.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/init_project.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/inventory_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/notification_img.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/report_dependencies.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/report_dependencies_summary.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/restore_inventory_version.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/reuse_project_pattern.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/scan_code.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/scan_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/sync_wk_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/transform_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/update_inventory_version.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_command.png +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_environment.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/img/validate_project.gif +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/includes/abbreviations.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/index.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/installation/linux_installation.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/installation/windows_installation.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/javascripts/tablesort.js +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/mcp.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/navigation.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/quick_start.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/requirements.txt +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/stylesheets/extra-enhanced.css +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/stylesheets/extra.css +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/telemetry.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/cli_commands_audit.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/for_developers.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/for_platform_engineers.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/github_templates.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/template_engine/template_engine.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/linux_troubleshooting.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/macos_troubleshooting.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/troubleshooting.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/docs/troubleshooting/windows_troubleshooting.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/mkdocs.yaml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/pyproject.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/scripts/run_mcp_server.sh +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/application/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/autocomplete.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/history.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/override.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/report.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/environment.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/iac.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project/iac.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/check/commands/project.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/document/commands/iac.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/component.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/generate/commands/stacks.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/env.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/project.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/space.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/init/commands/template.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/check.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/inventory/commands/iac.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/projects.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/list/commands/spaces.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/register.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/server.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/status.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/mcp/commands/stop.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/cleanup.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/convert.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/project/commands/upgrade.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/project.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/remove/space.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/scan/commands/iac.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/activate.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/space/commands/update.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/commands/upgrade/cli.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf.setup.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_home.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_module.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_project.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/common.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/constants.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/default_values.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/defaults.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/settings.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/template_config.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/template_configs.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/templates.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/config/validation.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/cli_ui.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/commands.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/config.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/github/get_github.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pattern_names.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/logger.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/telemetry.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/core/version_tools.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/interfaces/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/domain/models/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/mcp/server.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/decision_engine.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/main.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/memory.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/orchestrator.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/azure_provider.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/openai_provider.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/tracing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/environment/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/environment/check_environment.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/org_policy_loader.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/check_origin_version.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/check_project_structure.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/drift/models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/risk_assessment.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/check/rule_merger.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/dashboard/data_loader.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/create_documentation.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/files_content.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/files_scan.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_documentation.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/document/iac_grunt_info.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/config.yaml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_code.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_component.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/create_template.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/files_content.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/environment/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/environment/install_tools.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/project/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/project/project.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/example_space.toml +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/local_registry.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/init/space/space.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/changelog_parser.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/inventory_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/report_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/update_versions.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/inventory/version_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/README.md +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/amazon_q_server.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/example.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/mcp/simple_http_server.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/conversion_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/get_project_data.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/post_init.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/project_converter.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/project_defaults.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/upgrade/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/compliance_review.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/import_reports.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/report_parser.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/sarif_output.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scan_history.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scan_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/checkov.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/kics.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/opa.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/scanners.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/scan/scanners/trivy.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/reports/inventory_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/reports/inventory_report.js +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/templates/unified_report_styles.css +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/banner.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/create_html_reports.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/delete_directory.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/fix_report_styling.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/render_scan_report.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/report_html_utils.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/dashboard.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/index_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/individual_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/simple_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_scan_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/crypto.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/platform_utils.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/template_loader.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/utils/thoth_colors.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/wellcome_banner.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/conftest.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_agentcore_entrypoint.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_aws_pricing_client.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_azure_devops_pr_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_bedrock_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cdk_language_selection.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_context_steering.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_analyzer.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_models.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_cost_pr_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_dashboard_loading_fix.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_dashboard_service.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_drift.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_drift_detection.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_ec2_pricing.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_github_pr_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_iac_cost_integration.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_inventory_pr_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_kics_scanner.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_mermaid_edge_labels.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_new_cost_providers.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_parallel_scan.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_platform_utils.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_pr_comment_publisher.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_provider_source_url_fix.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_provider_versions.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_scan_pr_comments.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_space_command.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_space_management.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_template_url_fix.py +0 -0
- {thothctl-0.16.3 → thothctl-0.16.4}/tests/test_terragrunt_parser.py +0 -0
- {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
|
+
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
|
-
|
|
103
|
-
|
|
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 {
|
{thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/code_reviewer.py
RENAMED
|
@@ -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"
|
|
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))
|
{thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/analyzers/context_builder.py
RENAMED
|
@@ -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
|
|
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 =
|
|
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
|
|
187
|
+
"""Check for existing scan reports at project root."""
|
|
169
188
|
try:
|
|
170
|
-
from
|
|
189
|
+
from .report_analyzer import ReportAnalyzer
|
|
171
190
|
|
|
172
191
|
analyzer = ReportAnalyzer()
|
|
173
|
-
reports_dir = Path(ctx.directory) / "Reports"
|
|
174
192
|
|
|
175
|
-
#
|
|
176
|
-
|
|
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
|
-
|
|
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
|
|
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 =
|
|
21
|
+
max_tokens: int = 8000
|
|
22
22
|
temperature: float = 0.1
|
|
23
23
|
api_key: str = ""
|
|
24
24
|
region: str = "us-east-1"
|
{thothctl-0.16.3 → thothctl-0.16.4}/src/thothctl/services/ai_review/providers/ollama_provider.py
RENAMED
|
@@ -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
|
-
|
|
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("
|
|
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
|
|
97
|
+
You are the AI agent for ThothCTL, an AI-Powered Infrastructure Lifecycle CLI.
|
|
98
98
|
|
|
99
|
-
**
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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
|
-
**
|
|
106
|
-
-
|
|
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
|
-
"
|
|
137
|
-
"
|
|
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."""
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/ai-review/agent_specifications.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{thothctl-0.16.3 → thothctl-0.16.4}/docs/framework/commands/check/cost-analysis-quick-reference.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|