thothctl 0.14.2__tar.gz → 0.14.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.14.2 → thothctl-0.14.4}/PKG-INFO +1 -1
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/CHANGELOG.md +9 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/inventory_iac.md +46 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/ai_agent.py +54 -58
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/decision_engine.py +55 -48
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/main.py +16 -9
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/memory.py +14 -9
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/orchestrator.py +79 -59
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/azure_provider.py +20 -17
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +15 -6
- thothctl-0.14.4/src/thothctl/services/ai_review/providers/bedrock_provider.py +69 -0
- thothctl-0.14.4/src/thothctl/services/ai_review/providers/ollama_provider.py +79 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/openai_provider.py +20 -17
- thothctl-0.14.4/src/thothctl/services/ai_review/tracing.py +123 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/inventory_service.py +15 -6
- thothctl-0.14.4/src/thothctl/version.py +2 -0
- thothctl-0.14.2/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -67
- thothctl-0.14.2/src/thothctl/services/ai_review/providers/ollama_provider.py +0 -80
- thothctl-0.14.2/src/thothctl/version.py +0 -2
- {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/Dockerfile +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.devcontainer/devcontainer.json +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.github/workflows/python-publish.yml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.gitignore +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.pre-commit-config.yaml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/.readthedocs.yaml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_API_FINAL_REPORT.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_API_IMPLEMENTATION_PLAN.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/AWS_PRICING_REFACTOR_REPORT.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/Dockerfile +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/LICENSE +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/TECHNICAL_DEBT_METRICS.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/catalog/catalog-info.yaml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/dashboard/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/ai-review/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/ai-review/agentcore.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/blast-radius.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_environment.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_project_iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/check_space.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/cost-analysis.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/deps-advanced.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/deps.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/drift-detection.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/check/plan.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/document_iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/document_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/document/use_cases.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/generate/generate_components.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/generate/generate_stacks.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/init/init.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/init/init_space.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/inventory/inventory_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_projects.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/list/list_spaces.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/mcp/mcp.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_cleanup.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_convert.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/project_upgrade.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/project/use_cases.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_project.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/remove/remove_space.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/scan_iac.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/scan_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/scan/use_cases.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/concepts.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/cross_platform_support.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/framework_architecture.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/infrasctructure_composition.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/software_architecture.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/space_configuration.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/ai_dlc.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/check_command.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/inventory_command.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/space_management.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/framework/use_cases/tasks/create_template.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/iac_devsecops_use_case.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/automate_tasks_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/commnad_init.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/create_component.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/create_inventory.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/doc_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/document_project_code.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/framework/thothforge-framework.svg +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/framework/thothfr.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/iacpeerbot_summary.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/init_project.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/inventory_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/notification_img.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/report_dependencies.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/report_dependencies_summary.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/restore_inventory_version.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/reuse_project_pattern.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/scan_code.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/scan_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/sync_wk_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/transform_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/update_inventory_version.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_command.png +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_environment.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/img/validate_project.gif +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/includes/abbreviations.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/index.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/installation/windows_installation.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/javascripts/tablesort.js +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/mcp.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/navigation.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/quick_start.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/requirements.txt +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/stylesheets/extra-enhanced.css +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/stylesheets/extra.css +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/telemetry.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/template_engine/github_templates.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/template_engine/template_engine.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/linux_troubleshooting.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/macos_troubleshooting.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/troubleshooting.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/docs/troubleshooting/windows_troubleshooting.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/mkdocs.yaml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/pyproject.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/scripts/run_mcp_server.sh +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/application/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/autocomplete.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/analyze.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/history.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/orchestrate.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/override.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/report.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/environment.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/iac.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project/iac.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/check/commands/project.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/document/commands/iac.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/component.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/generate/commands/stacks.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/env.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/project.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/init/commands/space.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/check.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/inventory/commands/iac.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/projects.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/list/commands/spaces.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/register.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/server.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/status.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/mcp/commands/stop.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/cleanup.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/convert.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/project/commands/upgrade.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/project.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/remove/space.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/commands/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/scan/commands/iac.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/commands/upgrade/cli.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf.setup.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_home.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_module.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_project.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/common.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/constants.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/default_values.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/defaults.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/models.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/settings.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/template_config.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/template_configs.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/templates.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/config/validation.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/cli_ui.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/commands.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/config.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/github/get_github.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pattern_names.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/logger.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/telemetry.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/core/version_tools.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/interfaces/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/domain/models/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/mcp/server.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/context_builder.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/ai_settings.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/utils/prompts.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/environment/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/environment/check_environment.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/check_origin_version.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/check_project_structure.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/drift/models.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/risk_assessment.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/dashboard_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/dashboard/data_loader.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/create_documentation.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/files_content.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/files_scan.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_documentation.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/document/iac_grunt_info.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/config.yaml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_code.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_component.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/create_template.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/files_content.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/environment/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/environment/install_tools.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/project/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/project/project.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/example_space.toml +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/local_registry.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space_config.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/init/space/space_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/changelog_parser.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/models.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/report_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/update_versions.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/inventory/version_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/README.md +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/amazon_q_server.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/example.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/mcp/simple_http_server.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/conversion_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/get_project_data.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/post_init.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/project_converter.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/project_defaults.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/upgrade/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/compliance_review.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/import_reports.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scan_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/checkov.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/kics.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/opa.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/scanners.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/scan/scanners/trivy.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/reports/inventory_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/reports/inventory_report.js +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/templates/unified_report_styles.css +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/banner.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/create_html_reports.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/delete_directory.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/fix_report_styling.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/report_html_utils.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/dashboard.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/index_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/individual_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/simple_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/crypto.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/platform_utils.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/template_loader.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/utils/thoth_colors.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/wellcome_banner.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/conftest.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_agentcore_entrypoint.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_aws_pricing_client.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_azure_devops_pr_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_bedrock_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cdk_language_selection.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_context_steering.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_analyzer.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_models.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_cost_pr_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_dashboard_loading_fix.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_dashboard_service.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_drift.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_drift_detection.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_ec2_pricing.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_github_pr_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_iac_cost_integration.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_inventory_pr_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_kics_scanner.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_mermaid_edge_labels.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_new_cost_providers.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_parallel_scan.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_platform_utils.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_pr_comment_publisher.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_provider_source_url_fix.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_provider_versions.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_scan_pr_comments.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_space_command.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_space_config.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_template_url_fix.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tests/test_terragrunt_parser.py +0 -0
- {thothctl-0.14.2 → thothctl-0.14.4}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thothctl
|
|
3
|
-
Version: 0.14.
|
|
3
|
+
Version: 0.14.4
|
|
4
4
|
Summary: A CLI for Developer Control Plane. Accelerate your cloud IaC deployments.
|
|
5
5
|
Project-URL: Homepage, https://github.com/thothforge/thothctl
|
|
6
6
|
Author-email: Alejandro Velez <velez94@pm.me>
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
# ThothCTL Inventory Command Changelog
|
|
2
2
|
|
|
3
|
+
## Version 0.14.3 - May 2026
|
|
4
|
+
|
|
5
|
+
### 🔧 Fix: Weighted Technical Debt Scoring
|
|
6
|
+
|
|
7
|
+
- **Weighted formula**: Modules now carry 70% weight and providers 30% in debt score calculation
|
|
8
|
+
- **Fairer scoring**: A single outdated provider no longer inflates the score disproportionately
|
|
9
|
+
- **Consistent thresholds**: CDK risk levels aligned with the main formula (70/50/30)
|
|
10
|
+
- **Rationale**: Providers may be intentionally pinned (e.g., a module tested against a specific provider version), so they should not dominate the debt score
|
|
11
|
+
|
|
3
12
|
## Version 0.4.0 - July 2025
|
|
4
13
|
|
|
5
14
|
### 🎯 Major Improvements
|
|
@@ -197,6 +197,52 @@ The reports now include comprehensive provider data:
|
|
|
197
197
|
- **Module Context**: Which module uses the provider
|
|
198
198
|
- **Status**: Current, Outdated, or Unknown
|
|
199
199
|
|
|
200
|
+
## Technical Debt Scoring 📊
|
|
201
|
+
|
|
202
|
+
When `--check-versions` is enabled, ThothCTL calculates a **technical debt score** that reflects how outdated your infrastructure is.
|
|
203
|
+
|
|
204
|
+
### Weighted Formula
|
|
205
|
+
|
|
206
|
+
The debt score uses a weighted approach that separates module health from provider health:
|
|
207
|
+
|
|
208
|
+
```
|
|
209
|
+
module_debt = outdated_modules / total_modules (weight: 70%)
|
|
210
|
+
provider_debt = outdated_providers / total_providers (weight: 30%)
|
|
211
|
+
|
|
212
|
+
debt_score = (module_debt × 0.7 + provider_debt × 0.3) × 100 + breaking_changes_penalty
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Why weighted?** Modules define your architecture and are the primary source of risk. Providers are dependencies that may be intentionally pinned (e.g., a latest module tested against a specific provider version). A single outdated provider should not inflate the score disproportionately.
|
|
216
|
+
|
|
217
|
+
### Breaking Changes Penalty
|
|
218
|
+
|
|
219
|
+
Each module or provider with detected breaking changes adds **+5 points** to the debt score (capped at 100%).
|
|
220
|
+
|
|
221
|
+
### Risk Levels
|
|
222
|
+
|
|
223
|
+
| Debt Score | Risk Level | Meaning |
|
|
224
|
+
|-----------|------------|---------|
|
|
225
|
+
| ≥ 70% | **Critical** | Immediate action required |
|
|
226
|
+
| ≥ 50% | **High** | Plan upgrades soon |
|
|
227
|
+
| ≥ 30% | **Medium** | Schedule maintenance |
|
|
228
|
+
| < 30% | **Low** | Infrastructure is well-maintained |
|
|
229
|
+
|
|
230
|
+
### Examples
|
|
231
|
+
|
|
232
|
+
| Scenario | Score | Risk |
|
|
233
|
+
|----------|-------|------|
|
|
234
|
+
| 2 modules current, 1/2 providers outdated | 15% | Low |
|
|
235
|
+
| 2/4 modules outdated, providers current | 35% | Medium |
|
|
236
|
+
| All modules and providers outdated | 100% | Critical |
|
|
237
|
+
| Everything current | 0% | Low |
|
|
238
|
+
|
|
239
|
+
### Recommendations
|
|
240
|
+
|
|
241
|
+
The system auto-generates actionable recommendations based on the metrics:
|
|
242
|
+
- Update outdated modules/providers
|
|
243
|
+
- Review components with breaking changes before upgrading
|
|
244
|
+
- Confirmation when infrastructure is well-maintained (score < 20%)
|
|
245
|
+
|
|
200
246
|
## Framework Type Options
|
|
201
247
|
|
|
202
248
|
### Auto-detect Framework (Default)
|
|
@@ -20,6 +20,7 @@ from .utils.prompts import (
|
|
|
20
20
|
SYSTEM_FULL_ANALYSIS,
|
|
21
21
|
)
|
|
22
22
|
from .utils.fix_prompts import SYSTEM_FIX_GENERATOR
|
|
23
|
+
from .tracing import span
|
|
23
24
|
|
|
24
25
|
logger = logging.getLogger(__name__)
|
|
25
26
|
|
|
@@ -82,35 +83,37 @@ class AIReviewAgent:
|
|
|
82
83
|
Calls InventoryService, ScanService, BlastRadiusService, and collects
|
|
83
84
|
raw code to give the LLM a complete picture of the IaC project.
|
|
84
85
|
"""
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
86
|
+
with span("ai_agent.analyze_directory", {"directory": directory}) as s:
|
|
87
|
+
logger.info(f"Building rich context for {directory}")
|
|
88
|
+
ctx = self.context_builder.build_context(directory)
|
|
89
|
+
|
|
90
|
+
basic_risk = None
|
|
91
|
+
if ctx.scan_results.get("total_findings", 0) > 0:
|
|
92
|
+
basic_risk = self.risk_assessor.assess_risk(ctx.scan_results)
|
|
93
|
+
|
|
94
|
+
if not self.cost_tracker.check_budget():
|
|
95
|
+
logger.warning("Budget limit reached")
|
|
96
|
+
s.set_attribute("budget_exceeded", True)
|
|
97
|
+
if basic_risk:
|
|
98
|
+
return self._basic_analysis(ctx.scan_results, basic_risk)
|
|
99
|
+
return self._empty_result()
|
|
100
|
+
|
|
101
|
+
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)
|
|
104
|
+
|
|
105
|
+
result["_context"] = {
|
|
106
|
+
"project_type": ctx.project_type,
|
|
107
|
+
"modules_found": len(ctx.modules),
|
|
108
|
+
"providers_found": len(ctx.providers),
|
|
109
|
+
"scan_findings": ctx.scan_results.get("total_findings", 0),
|
|
110
|
+
"blast_radius_components": ctx.blast_radius.get("total_components", 0),
|
|
111
|
+
"code_files": len(ctx.code_files),
|
|
112
|
+
"collection_notes": ctx.errors,
|
|
113
|
+
}
|
|
114
|
+
s.set_attribute("findings", ctx.scan_results.get("total_findings", 0))
|
|
115
|
+
s.set_attribute("code_files", len(ctx.code_files))
|
|
116
|
+
return result
|
|
114
117
|
|
|
115
118
|
def review_code(self, directory: str) -> Dict[str, Any]:
|
|
116
119
|
"""Review raw IaC code with AI (no thothctl service context)."""
|
|
@@ -129,38 +132,31 @@ class AIReviewAgent:
|
|
|
129
132
|
|
|
130
133
|
def generate_fixes(self, directory: str, scan_results: Dict = None,
|
|
131
134
|
severity_filter: str = None) -> Dict[str, Any]:
|
|
132
|
-
"""Generate actionable code fixes for scan findings.
|
|
135
|
+
"""Generate actionable code fixes for scan findings."""
|
|
136
|
+
with span("ai_agent.generate_fixes", {"directory": directory, "severity_filter": severity_filter or "all"}) as s:
|
|
137
|
+
if not scan_results:
|
|
138
|
+
analyzer = ReportAnalyzer()
|
|
139
|
+
reports_dir = Path(directory) / "Reports"
|
|
140
|
+
if reports_dir.exists():
|
|
141
|
+
scan_results = analyzer.parse_scan_results(str(reports_dir))
|
|
142
|
+
else:
|
|
143
|
+
analysis = self.analyze_directory(directory)
|
|
144
|
+
return self._fixes_from_analysis(analysis, directory)
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
scan_results: Pre-parsed scan results (or auto-collected)
|
|
137
|
-
severity_filter: Only fix findings at this severity or above
|
|
138
|
-
"""
|
|
139
|
-
# Collect scan results if not provided
|
|
140
|
-
if not scan_results:
|
|
141
|
-
analyzer = ReportAnalyzer()
|
|
142
|
-
reports_dir = Path(directory) / "Reports"
|
|
143
|
-
if reports_dir.exists():
|
|
144
|
-
scan_results = analyzer.parse_scan_results(str(reports_dir))
|
|
145
|
-
else:
|
|
146
|
-
# Run analysis to get findings
|
|
147
|
-
analysis = self.analyze_directory(directory)
|
|
148
|
-
return self._fixes_from_analysis(analysis, directory)
|
|
149
|
-
|
|
150
|
-
if scan_results.get("total_findings", 0) == 0:
|
|
151
|
-
return {"fixes": [], "skipped": [], "summary": {"total_findings": 0, "fixes_generated": 0, "skipped": 0}}
|
|
152
|
-
|
|
153
|
-
# Collect affected code files
|
|
154
|
-
code_files = self.code_reviewer.collect_code_for_review(directory)
|
|
146
|
+
if scan_results.get("total_findings", 0) == 0:
|
|
147
|
+
return {"fixes": [], "skipped": [], "summary": {"total_findings": 0, "fixes_generated": 0, "skipped": 0}}
|
|
155
148
|
|
|
156
|
-
|
|
157
|
-
|
|
149
|
+
code_files = self.code_reviewer.collect_code_for_review(directory)
|
|
150
|
+
|
|
151
|
+
if not self.cost_tracker.check_budget():
|
|
152
|
+
s.set_attribute("fallback", "pattern_fixes")
|
|
153
|
+
return self._pattern_fixes(scan_results, code_files, severity_filter)
|
|
158
154
|
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
155
|
+
content = self._format_fix_request(scan_results, code_files, severity_filter)
|
|
156
|
+
result = self._call_ai(SYSTEM_FIX_GENERATOR, content, "generate_fixes",
|
|
157
|
+
fallback=lambda: self._pattern_fixes(scan_results, code_files, severity_filter))
|
|
158
|
+
s.set_attribute("fixes_generated", len(result.get("fixes", [])))
|
|
159
|
+
return result
|
|
164
160
|
|
|
165
161
|
def _format_fix_request(self, scan_results: Dict, code_files: Dict,
|
|
166
162
|
severity_filter: str = None) -> str:
|
|
@@ -6,6 +6,7 @@ from typing import Dict, Any, List, Optional
|
|
|
6
6
|
|
|
7
7
|
from .config.decision_rules import DecisionRules, BLOCKING_PATTERNS
|
|
8
8
|
from .safety.safety_guard import SafetyGuard
|
|
9
|
+
from .tracing import span
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__name__)
|
|
11
12
|
|
|
@@ -40,59 +41,65 @@ class DecisionEngine:
|
|
|
40
41
|
repository: str = "", pr_id: str = "",
|
|
41
42
|
pr_context: Optional[Dict] = None) -> DecisionResult:
|
|
42
43
|
"""Evaluate analysis results and return a decision."""
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
risk_score, critical, high, medium, has_blocking, findings,
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
# Safety gate
|
|
64
|
-
if decision != Decision.COMMENT and repository:
|
|
65
|
-
allowed, safety_reason = self.safety.can_take_action(
|
|
66
|
-
decision.value, confidence, repository, pr_context,
|
|
44
|
+
with span("decision_engine.evaluate", {"repository": repository, "pr_id": pr_id}) as s:
|
|
45
|
+
summary = analysis.get("summary", {})
|
|
46
|
+
risk_score = float(analysis.get("risk_score", 50))
|
|
47
|
+
findings = analysis.get("findings", [])
|
|
48
|
+
recommendations = analysis.get("recommendations", [])
|
|
49
|
+
|
|
50
|
+
critical = summary.get("critical", 0)
|
|
51
|
+
high = summary.get("high", 0)
|
|
52
|
+
medium = summary.get("medium", 0)
|
|
53
|
+
low = summary.get("low", 0)
|
|
54
|
+
|
|
55
|
+
findings_summary = {"critical": critical, "high": high, "medium": medium, "low": low}
|
|
56
|
+
|
|
57
|
+
has_blocking = self._has_blocking_patterns(findings)
|
|
58
|
+
|
|
59
|
+
decision, confidence, reason = self._compute_decision(
|
|
60
|
+
risk_score, critical, high, medium, has_blocking, findings,
|
|
67
61
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
confidence
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
62
|
+
|
|
63
|
+
if decision != Decision.COMMENT and repository:
|
|
64
|
+
allowed, safety_reason = self.safety.can_take_action(
|
|
65
|
+
decision.value, confidence, repository, pr_context,
|
|
66
|
+
)
|
|
67
|
+
if not allowed:
|
|
68
|
+
s.set_attribute("decision", "comment")
|
|
69
|
+
s.set_attribute("blocked_by_safety", True)
|
|
70
|
+
s.set_attribute("safety_reason", safety_reason)
|
|
71
|
+
s.set_attribute("risk_score", risk_score)
|
|
72
|
+
return DecisionResult(
|
|
73
|
+
decision=Decision.COMMENT,
|
|
74
|
+
confidence=confidence,
|
|
75
|
+
reason=reason,
|
|
76
|
+
risk_score=risk_score,
|
|
77
|
+
findings_summary=findings_summary,
|
|
78
|
+
recommendations=recommendations,
|
|
79
|
+
blocked_by_safety=True,
|
|
80
|
+
safety_reason=safety_reason,
|
|
81
|
+
)
|
|
82
|
+
|
|
83
|
+
if decision != Decision.COMMENT and repository:
|
|
84
|
+
self.safety.record_action(
|
|
85
|
+
action=decision.value, repository=repository,
|
|
86
|
+
pr_id=pr_id, confidence=confidence, reason=reason,
|
|
78
87
|
)
|
|
79
88
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
89
|
+
s.set_attribute("decision", decision.value)
|
|
90
|
+
s.set_attribute("confidence", confidence)
|
|
91
|
+
s.set_attribute("risk_score", risk_score)
|
|
92
|
+
s.set_attribute("has_blocking_patterns", has_blocking)
|
|
93
|
+
|
|
94
|
+
return DecisionResult(
|
|
95
|
+
decision=decision,
|
|
96
|
+
confidence=confidence,
|
|
97
|
+
reason=reason,
|
|
98
|
+
risk_score=risk_score,
|
|
99
|
+
findings_summary=findings_summary,
|
|
100
|
+
recommendations=recommendations,
|
|
85
101
|
)
|
|
86
102
|
|
|
87
|
-
return DecisionResult(
|
|
88
|
-
decision=decision,
|
|
89
|
-
confidence=confidence,
|
|
90
|
-
reason=reason,
|
|
91
|
-
risk_score=risk_score,
|
|
92
|
-
findings_summary=findings_summary,
|
|
93
|
-
recommendations=recommendations,
|
|
94
|
-
)
|
|
95
|
-
|
|
96
103
|
def _compute_decision(self, risk_score: float, critical: int, high: int,
|
|
97
104
|
medium: int, has_blocking: bool,
|
|
98
105
|
findings: List[Dict]) -> tuple:
|
|
@@ -27,6 +27,8 @@ from typing import Any, Dict
|
|
|
27
27
|
from fastapi import FastAPI, Request
|
|
28
28
|
from fastapi.responses import JSONResponse
|
|
29
29
|
|
|
30
|
+
from .tracing import span
|
|
31
|
+
|
|
30
32
|
logger = logging.getLogger(__name__)
|
|
31
33
|
|
|
32
34
|
app = FastAPI(title="ThothCTL AgentCore Agent", version="0.13.2")
|
|
@@ -62,15 +64,20 @@ async def invocations(request: Request):
|
|
|
62
64
|
if not mode:
|
|
63
65
|
mode = _detect_mode(prompt)
|
|
64
66
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
67
|
+
with span("invocations", {"mode": mode, "directory": directory,
|
|
68
|
+
"provider": provider, "repository": repository,
|
|
69
|
+
"run_id": run_id}) as s:
|
|
70
|
+
try:
|
|
71
|
+
result = _dispatch(
|
|
72
|
+
mode=mode, directory=directory, provider=provider, model=model,
|
|
73
|
+
roles=roles, repository=repository, run_id=run_id, prompt=prompt,
|
|
74
|
+
)
|
|
75
|
+
s.set_attribute("result.status", "ok")
|
|
76
|
+
return JSONResponse(content={"result": result})
|
|
77
|
+
except Exception as e:
|
|
78
|
+
logger.exception("Invocation failed")
|
|
79
|
+
s.set_attribute("result.status", "error")
|
|
80
|
+
return JSONResponse(status_code=500, content={"error": str(e)})
|
|
74
81
|
|
|
75
82
|
|
|
76
83
|
# ── Existing REST endpoints (kept for direct API use) ───────────────
|
|
@@ -18,6 +18,8 @@ from datetime import datetime, timezone
|
|
|
18
18
|
from pathlib import Path
|
|
19
19
|
from typing import Any, Dict, List, Optional
|
|
20
20
|
|
|
21
|
+
from .tracing import span
|
|
22
|
+
|
|
21
23
|
logger = logging.getLogger(__name__)
|
|
22
24
|
|
|
23
25
|
LOCAL_SESSIONS_DIR = ".thothctl/ai_sessions"
|
|
@@ -101,18 +103,21 @@ class AgentMemory:
|
|
|
101
103
|
|
|
102
104
|
def save_analysis(self, repo: str, analysis: Dict[str, Any], run_id: str = "") -> None:
|
|
103
105
|
key = self._scoped_key(repo, "analysis", run_id)
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
106
|
+
with span("memory.save_analysis", {"repo": repo, "run_id": run_id, "backend": self.mode}):
|
|
107
|
+
data = {
|
|
108
|
+
"timestamp": datetime.now(timezone.utc).isoformat(),
|
|
109
|
+
"repo": repo,
|
|
110
|
+
"run_id": run_id,
|
|
111
|
+
"analysis": analysis,
|
|
112
|
+
}
|
|
113
|
+
self._backend.write(key, data)
|
|
111
114
|
|
|
112
115
|
def load_analysis(self, repo: str, run_id: str = "") -> Optional[Dict[str, Any]]:
|
|
113
116
|
key = self._scoped_key(repo, "analysis", run_id)
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
with span("memory.load_analysis", {"repo": repo, "run_id": run_id, "backend": self.mode}) as s:
|
|
118
|
+
data = self._backend.read(key)
|
|
119
|
+
s.set_attribute("cache_hit", data is not None)
|
|
120
|
+
return data.get("analysis") if data else None
|
|
116
121
|
|
|
117
122
|
# -- Session history (per session ID) --
|
|
118
123
|
|
|
@@ -25,6 +25,7 @@ from .config.ai_settings import AISettings, ProviderConfig
|
|
|
25
25
|
from .analyzers.context_builder import ContextBuilder, IaCContext
|
|
26
26
|
from .utils.cost_tracker import CostTracker
|
|
27
27
|
from .memory import AgentMemory, MemoryConfig
|
|
28
|
+
from .tracing import span
|
|
28
29
|
|
|
29
30
|
logger = logging.getLogger(__name__)
|
|
30
31
|
|
|
@@ -123,39 +124,48 @@ class AgentOrchestrator:
|
|
|
123
124
|
if roles is None:
|
|
124
125
|
roles = [AgentRole.SECURITY, AgentRole.ARCHITECTURE]
|
|
125
126
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
127
|
+
with span("orchestrator.run_agents", {
|
|
128
|
+
"directory": directory,
|
|
129
|
+
"roles": [r.value for r in roles],
|
|
130
|
+
"repository": repository,
|
|
131
|
+
"run_id": run_id,
|
|
132
|
+
}) as s:
|
|
133
|
+
# Build shared context once
|
|
134
|
+
logger.info(f"Building context for {directory}")
|
|
135
|
+
ctx = self.context_builder.build_context(directory)
|
|
136
|
+
|
|
137
|
+
# Enrich context with previous analysis from memory
|
|
138
|
+
if repository:
|
|
139
|
+
previous = self.memory.load_analysis(repository, run_id=run_id)
|
|
140
|
+
if previous:
|
|
141
|
+
ctx.errors.append(f"Previous analysis loaded from memory ({repository})")
|
|
142
|
+
self._inject_previous_context(ctx, previous)
|
|
143
|
+
|
|
144
|
+
# Create tasks for requested roles
|
|
145
|
+
tasks = self._create_tasks(ctx, roles)
|
|
146
|
+
|
|
147
|
+
if not self.cost_tracker.check_budget():
|
|
148
|
+
logger.warning("Budget exceeded — running offline agents only")
|
|
149
|
+
s.set_attribute("budget_exceeded", True)
|
|
150
|
+
return self._offline_result(ctx, roles)
|
|
151
|
+
|
|
152
|
+
# Execute agents (parallel where possible)
|
|
153
|
+
result = OrchestratorResult()
|
|
154
|
+
self._execute_tasks(tasks, result)
|
|
155
|
+
|
|
156
|
+
# If decision was requested, run it last with merged context
|
|
157
|
+
if AgentRole.DECISION in roles:
|
|
158
|
+
self._run_decision(result, ctx)
|
|
159
|
+
|
|
160
|
+
result.cost = self.cost_tracker.get_cost_report("daily")
|
|
161
|
+
|
|
162
|
+
# Persist results to memory
|
|
163
|
+
if repository:
|
|
164
|
+
self._save_to_memory(repository, result, run_id=run_id)
|
|
165
|
+
|
|
166
|
+
s.set_attribute("agents_executed", len(tasks))
|
|
167
|
+
s.set_attribute("errors", len(result.errors))
|
|
168
|
+
return result
|
|
159
169
|
|
|
160
170
|
def run_single_agent(self, directory: str, role: AgentRole) -> Dict[str, Any]:
|
|
161
171
|
"""Run a single specialized agent."""
|
|
@@ -212,22 +222,23 @@ class AgentOrchestrator:
|
|
|
212
222
|
if not tasks:
|
|
213
223
|
return
|
|
214
224
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
225
|
+
with span("orchestrator.execute_tasks", {"task_count": len(tasks), "parallel": self.max_parallel > 1}):
|
|
226
|
+
if self.max_parallel <= 1 or len(tasks) == 1:
|
|
227
|
+
for task in tasks:
|
|
228
|
+
self._run_task(task, result)
|
|
229
|
+
else:
|
|
230
|
+
with ThreadPoolExecutor(max_workers=min(self.max_parallel, len(tasks))) as pool:
|
|
231
|
+
futures = {pool.submit(self._call_ai, task): task for task in tasks}
|
|
232
|
+
for future in as_completed(futures):
|
|
233
|
+
task = futures[future]
|
|
234
|
+
try:
|
|
235
|
+
ai_result = future.result()
|
|
236
|
+
if task.post_process:
|
|
237
|
+
ai_result = task.post_process(ai_result)
|
|
238
|
+
setattr(result, task.role.value, ai_result)
|
|
239
|
+
except Exception as e:
|
|
240
|
+
logger.error(f"Agent {task.role.value} failed: {e}")
|
|
241
|
+
result.errors.append(f"{task.role.value}: {e}")
|
|
231
242
|
|
|
232
243
|
def _run_task(self, task: AgentTask, result: OrchestratorResult):
|
|
233
244
|
"""Run a single task synchronously."""
|
|
@@ -242,16 +253,25 @@ class AgentOrchestrator:
|
|
|
242
253
|
|
|
243
254
|
def _call_ai(self, task: AgentTask) -> Dict[str, Any]:
|
|
244
255
|
"""Send task to AI provider and track cost."""
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
256
|
+
with span("orchestrator.call_ai", {
|
|
257
|
+
"agent.role": task.role.value,
|
|
258
|
+
"provider": self._provider.name,
|
|
259
|
+
"model": self._provider.model,
|
|
260
|
+
}) as s:
|
|
261
|
+
ai_result = self._provider.analyze(task.system_prompt, task.context)
|
|
262
|
+
usage = ai_result.pop("_usage", {})
|
|
263
|
+
input_tokens = usage.get("input_tokens", 0)
|
|
264
|
+
output_tokens = usage.get("output_tokens", 0)
|
|
265
|
+
s.set_attribute("tokens.input", input_tokens)
|
|
266
|
+
s.set_attribute("tokens.output", output_tokens)
|
|
267
|
+
self.cost_tracker.record_usage(
|
|
268
|
+
provider=self._provider.name,
|
|
269
|
+
model=self._provider.model,
|
|
270
|
+
input_tokens=input_tokens,
|
|
271
|
+
output_tokens=output_tokens,
|
|
272
|
+
operation=f"agent_{task.role.value}",
|
|
273
|
+
)
|
|
274
|
+
return ai_result
|
|
255
275
|
|
|
256
276
|
def _run_decision(self, result: OrchestratorResult, ctx: IaCContext):
|
|
257
277
|
"""Run decision agent using merged results from other agents."""
|
{thothctl-0.14.2 → thothctl-0.14.4}/src/thothctl/services/ai_review/providers/azure_provider.py
RENAMED
|
@@ -4,6 +4,7 @@ import logging
|
|
|
4
4
|
from typing import Dict, Any
|
|
5
5
|
|
|
6
6
|
from ..config.ai_settings import ProviderConfig
|
|
7
|
+
from ..tracing import span
|
|
7
8
|
|
|
8
9
|
logger = logging.getLogger(__name__)
|
|
9
10
|
|
|
@@ -35,23 +36,25 @@ class AzureOpenAIProvider:
|
|
|
35
36
|
|
|
36
37
|
def analyze(self, system_prompt: str, user_content: str) -> Dict[str, Any]:
|
|
37
38
|
"""Send analysis request to Azure OpenAI and return parsed JSON response."""
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
39
|
+
with span("provider.azure.analyze", {"model": self.model}) as s:
|
|
40
|
+
response = self.client.chat.completions.create(
|
|
41
|
+
model=self.model,
|
|
42
|
+
messages=[
|
|
43
|
+
{"role": "system", "content": system_prompt},
|
|
44
|
+
{"role": "user", "content": user_content},
|
|
45
|
+
],
|
|
46
|
+
max_tokens=self.max_tokens,
|
|
47
|
+
temperature=self.temperature,
|
|
48
|
+
response_format={"type": "json_object"},
|
|
49
|
+
)
|
|
50
|
+
usage = response.usage
|
|
51
|
+
result = json.loads(response.choices[0].message.content)
|
|
52
|
+
input_tokens = usage.prompt_tokens
|
|
53
|
+
output_tokens = usage.completion_tokens
|
|
54
|
+
result["_usage"] = {"input_tokens": input_tokens, "output_tokens": output_tokens}
|
|
55
|
+
s.set_attribute("tokens.input", input_tokens)
|
|
56
|
+
s.set_attribute("tokens.output", output_tokens)
|
|
57
|
+
return result
|
|
55
58
|
|
|
56
59
|
@property
|
|
57
60
|
def name(self) -> str:
|