thothctl 0.18.4__tar.gz → 0.18.6__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.18.4 → thothctl-0.18.6}/PKG-INFO +1 -1
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/ai-review/README.md +65 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/inventory_iac.md +27 -37
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/analyze.py +3 -1
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/orchestrate.py +10 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/dashboard/dashboard_service.py +18 -29
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/dashboard/data_loader.py +66 -8
- thothctl-0.18.6/src/thothctl/utils/common/templates/dashboard.html +254 -0
- thothctl-0.18.6/src/thothctl/version.py +2 -0
- thothctl-0.18.4/src/thothctl/utils/common/templates/dashboard.html +0 -633
- thothctl-0.18.4/src/thothctl/version.py +0 -2
- {thothctl-0.18.4 → thothctl-0.18.6}/.devcontainer/Dockerfile +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.devcontainer/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.devcontainer/devcontainer.json +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.github/workflows/docs.yml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.github/workflows/python-publish.yml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.gitignore +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.pre-commit-config.yaml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/.readthedocs.yaml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/Dockerfile +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/LICENSE +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/catalog/catalog-info.yaml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/dashboard/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/ai-review/agent_specifications.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/ai-review/agentcore.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/blast-radius.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/check_environment.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/check_iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/check_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/check_project_iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/check_space.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/cost-analysis-quick-reference.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/cost-analysis.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/customizing_rules.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/deps-advanced.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/deps.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/drift-detection.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/check/plan.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/document/customizing_docs.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/document/document_iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/document/document_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/document/iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/document/use_cases.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/generate/generate_components.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/generate/generate_stacks.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/init/init.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/init/init_space.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/CHANGELOG.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/frameworks/terraform.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/frameworks/terragrunt.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/inventory/inventory_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/list/list_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/list/list_projects.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/list/list_spaces.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/mcp/mcp.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/project_cleanup.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/project_convert.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/project_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/project_upgrade.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/project/use_cases.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/remove/remove_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/remove/remove_project.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/remove/remove_space.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/scan/iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/scan/scan_iac.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/scan/scan_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/scan/use_cases.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/commands/upgrade/upgrade_overview.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/concepts.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/cross_platform_support.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/framework_architecture.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/infrasctructure_composition.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/policy_as_code.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/roadmap_fdi.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/software_architecture.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/space_configuration.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/ai_dlc.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/check_command.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/devsecops_quickstart.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/devsecops_sdlc.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/inventory_command.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/platform_engineering_templates.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/space_management.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/framework/use_cases/tasks/create_template.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/iac_devsecops_use_case.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/automate_tasks_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/commnad_init.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/create_component.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/create_inventory.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/doc_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/document_project_code.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/framework/thothforge-framework.svg +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/framework/thothfr.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/iacpeerbot_summary.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/icon-light.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/icon.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/init_project.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/inventory_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/notification_img.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/report_dependencies.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/report_dependencies_summary.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/restore_inventory_version.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/reuse_project_pattern.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/scan_code.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/scan_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/stable/scan_report_example.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/sync_wk_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/transform_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/update_inventory_version.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/validate_command.png +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/validate_environment.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/img/validate_project.gif +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/includes/abbreviations.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/index.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/installation/linux_installation.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/installation/windows_installation.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/javascripts/tablesort.js +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/mcp.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/navigation.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/quick_start.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/requirements.txt +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/stylesheets/extra-enhanced.css +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/stylesheets/extra.css +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/telemetry.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/template_engine/cli_commands_audit.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/template_engine/for_developers.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/template_engine/for_platform_engineers.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/template_engine/github_templates.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/template_engine/template_engine.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/troubleshooting/linux_troubleshooting.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/troubleshooting/macos_troubleshooting.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/troubleshooting/troubleshooting.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/docs/troubleshooting/windows_troubleshooting.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/mkdocs.yaml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/pyproject.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/scripts/run_mcp_server.sh +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/application/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/autocomplete.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/apply_fix.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/configure.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/configure_decisions.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/decide.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/history.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/improve.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/override.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/report.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/ai_review/commands/serve.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/environment.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/iac.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/project/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/project/iac.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/check/commands/project.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/dashboard/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/dashboard/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/dashboard/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/dashboard/commands/launch.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/document/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/document/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/document/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/document/commands/iac.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/generate/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/generate/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/generate/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/generate/commands/component.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/generate/commands/stacks.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/commands/env.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/commands/project.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/commands/space.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/init/commands/template.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/inventory/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/inventory/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/inventory/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/inventory/commands/check.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/inventory/commands/iac.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/list/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/list/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/list/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/list/commands/projects.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/list/commands/spaces.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/commands/register.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/commands/server.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/commands/status.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/mcp/commands/stop.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/commands/bootstrap.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/commands/cleanup.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/commands/convert.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/project/commands/upgrade.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/remove/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/remove/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/remove/project.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/remove/space.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/scan/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/scan/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/scan/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/scan/commands/iac.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/commands/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/commands/activate.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/commands/show.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/space/commands/update.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/commands/upgrade/cli.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/.thothcf.setup.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/.thothcf_home.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/.thothcf_module.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/.thothcf_project.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/.thothcf_template_parameters.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/common.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/common/terragrunt/.thothcf_project.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/constants.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/default_values.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/defaults.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/settings.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/template_config.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/template_configs.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/templates.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/config/validation.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/cli_ui.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/commands.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/config.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/azure_devops/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/azure_devops/get_azure_devops.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/azure_devops/pull_request_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/github/get_github.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/github/pull_request_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/integrate_messages_services/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/integrate_messages_services/microsoft_teams.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/integrate_messages_services/sent_message_teams.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/pattern_names.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/pr_comments/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/integrations/pr_comments/pr_comment_publisher.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/logger.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/telemetry.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/core/version_tools.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/domain/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/domain/interfaces/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/domain/models/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/mcp/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/mcp/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/mcp/server.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/agentcore/agentcore.json +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/ai_agent.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/analyzers/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/analyzers/code_reviewer.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/analyzers/context_builder.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/analyzers/report_analyzer.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/analyzers/risk_assessor.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/bedrock_agent_api.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/config/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/config/ai_settings.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/config/decision_rules.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/decision_engine.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/main.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/memory.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/orchestrator.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/pr_decision_publisher.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/azure_provider.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/bedrock_agent_provider.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/bedrock_provider.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/ollama_provider.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/providers/openai_provider.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/safety/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/safety/safety_guard.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/strands_agent.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/tracing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/cost_tracker.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/fix_patterns.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/fix_prompts.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/formatters.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/ai_review/utils/prompts.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/environment/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/environment/check_environment.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/org_policy_loader.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/blast_radius_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/check_origin_version.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/check_project_structure.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/cost_analyzer.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/models/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/models/cloudformation_mapper.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/models/cost_models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/aws_pricing_client.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/base_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/apigateway_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/bedrock_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/cloudwatch_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/dynamodb_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/ebs_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/ec2_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/ecs_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/eip_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/eks_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/elb_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/free_resources_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/kms_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/lambda_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/msk_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/rds_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/s3_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/secrets_manager_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/pricing/providers/vpc_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/cost/unified_cost_report.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/drift_ai.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/drift_history.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/drift_policy.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/drift_report.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/drift_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/drift/models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/risk_assessment.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/project/validate_project_structure.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/rule_merger.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/check/stack_optimizer/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/dashboard/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/create_documentation.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/files_content.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/files_scan.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/iac_documentation.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/iac_grunt_graph.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/document/iac_grunt_info.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_stacks/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_stacks/config_generator.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_stacks/remote_config_generation.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_stacks/stack_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_stacks/templates/terragrunt.hcl.j2 +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/config.yaml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/create_code.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/create_component.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/create_component_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/create_stacks.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/create_template.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/files_content.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/github_template_loader.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/generate/create_template/project_templates.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/environment/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/environment/install_tools.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/project/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/project/project.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/space/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/space/example_space.toml +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/space/local_registry.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/init/space/space.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/changelog_parser.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/inventory_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/module_compatibility_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/report_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/schema_compatibility_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/terragrunt_parser.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/update_versions.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/inventory/version_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/mcp/README.md +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/mcp/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/mcp/simple_http_server.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/mcp/stdio_server.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/bootstrap/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/bootstrap/bootstrap_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/cleanup/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/cleanup/clean_project.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/cleanup/clean_space.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/conversion_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/get_project_data.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/post_init.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/project_converter.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/project_defaults.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/convert/set_project_parameters.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/create_terramate/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/create_terramate/create_terramate_stacks.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/create_terramate/detect_changes_stacks.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/create_terramate/manage_terramate_stacks.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/upgrade/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/project/upgrade/upgrade_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/compliance_review.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/import_reports.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/report_parser.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/sarif_output.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scan_history.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scan_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/checkov.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/kics.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/opa.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/scan_reports.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/scanners.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/terraform_compliance.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/tfsec.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/services/scan/scanners/trivy.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/templates/reports/inventory_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/templates/reports/inventory_report.js +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/templates/unified_report_styles.css +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/banner.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/create_compliance_html_reports.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/create_html_reports.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/delete_directory.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/fix_report_styling.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/render_scan_report.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/report_html_utils.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/index_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/individual_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/simple_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/unified_report_styles.css +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/unified_scan_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/unified_simple_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/common/templates/xunit_report.html +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/crypto.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/manage_backend_resources/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/manage_backend_resources/manage_backend_resources.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/modules_ops/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/modules_ops/terraform_module_details.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/modules_ops/terraform_modules_fetcher.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/platform_utils.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/analyze_terraform_plan.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/graph_manager.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/graph_terragrunt_dependencies.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/process_terraform_file.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/process_hcl/risk_analyzing_terraform_plan.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/sync_workspaces/__init__.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/sync_workspaces/sync_terraform_workspaces.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/sync_workspaces/sync_terragrunt_workspaces.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/template_loader.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/utils/thoth_colors.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/src/thothctl/wellcome_banner.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/conftest.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_agentcore_entrypoint.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_aws_pricing_client.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_azure_devops_pr_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_bedrock_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_cdk_language_selection.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_context_steering.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_cost_analyzer.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_cost_models.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_cost_pr_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_dashboard_loading_fix.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_dashboard_service.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_drift.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_drift_detection.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_ec2_pricing.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_github_pr_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_iac_cost_integration.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_inventory_pr_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_kics_scanner.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_mermaid_edge_labels.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_new_cost_providers.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_parallel_scan.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_platform_utils.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_pr_comment_publisher.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_provider_source_url_fix.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_provider_versions.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_scan_pr_comments.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_space_command.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_space_management.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_stack_optimizer.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_template_url_fix.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tests/test_terragrunt_parser.py +0 -0
- {thothctl-0.18.4 → thothctl-0.18.6}/tox.ini +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: thothctl
|
|
3
|
-
Version: 0.18.
|
|
3
|
+
Version: 0.18.6
|
|
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
|
|
@@ -541,6 +541,71 @@ The `improve` command includes 13 built-in fix patterns that work without AI:
|
|
|
541
541
|
| `CKV_AWS_116` | Add Lambda dead letter config |
|
|
542
542
|
| `CKV_AWS_272` | Enable Lambda code signing |
|
|
543
543
|
|
|
544
|
+
## Token Usage & Cost Tracking
|
|
545
|
+
|
|
546
|
+
Every AI interaction reports token consumption (input/output) and estimated cost in the command output:
|
|
547
|
+
|
|
548
|
+
```
|
|
549
|
+
💰 Today's AI cost: $0.0234 (3 requests, ↑12,450 in / ↓3,210 out tokens)
|
|
550
|
+
```
|
|
551
|
+
|
|
552
|
+
### Per-Command Output
|
|
553
|
+
|
|
554
|
+
| Command | Token Info Shown |
|
|
555
|
+
|---------|-----------------|
|
|
556
|
+
| `analyze` | Daily totals: cost, requests, input/output tokens |
|
|
557
|
+
| `orchestrate` | Per-run: cost, input/output tokens, model used |
|
|
558
|
+
| `report` | Full breakdown by period, provider, and model |
|
|
559
|
+
|
|
560
|
+
### Cost Report
|
|
561
|
+
|
|
562
|
+
```bash
|
|
563
|
+
# Daily summary
|
|
564
|
+
thothctl ai-review report --period daily
|
|
565
|
+
|
|
566
|
+
# Monthly breakdown
|
|
567
|
+
thothctl ai-review report --period monthly
|
|
568
|
+
|
|
569
|
+
# Export to JSON
|
|
570
|
+
thothctl ai-review report --period monthly --export costs.json
|
|
571
|
+
```
|
|
572
|
+
|
|
573
|
+
Output:
|
|
574
|
+
```
|
|
575
|
+
┌────────────────────┬──────────────┐
|
|
576
|
+
│ Metric │ Value │
|
|
577
|
+
├────────────────────┼──────────────┤
|
|
578
|
+
│ Total Cost │ $0.1240 │
|
|
579
|
+
│ Total Requests │ 12 │
|
|
580
|
+
│ Input Tokens │ 45,200 │
|
|
581
|
+
│ Output Tokens │ 8,340 │
|
|
582
|
+
└────────────────────┴──────────────┘
|
|
583
|
+
```
|
|
584
|
+
|
|
585
|
+
### Budget Controls
|
|
586
|
+
|
|
587
|
+
```bash
|
|
588
|
+
# Set daily and monthly limits
|
|
589
|
+
thothctl ai-review configure --daily-limit 50 --monthly-budget 200
|
|
590
|
+
```
|
|
591
|
+
|
|
592
|
+
| Control | Default | Description |
|
|
593
|
+
|---------|---------|-------------|
|
|
594
|
+
| Daily limit | $100 | Max spend per day |
|
|
595
|
+
| Monthly budget | $200 | Max spend per month |
|
|
596
|
+
| Auto fallback | true | Falls back to pattern-based fixes when budget exceeded |
|
|
597
|
+
|
|
598
|
+
Cost logs are stored at `.thothctl/ai_costs/<date>.jsonl` (one JSON record per API call).
|
|
599
|
+
|
|
600
|
+
### Supported Pricing
|
|
601
|
+
|
|
602
|
+
| Provider | Tracked | Notes |
|
|
603
|
+
|----------|---------|-------|
|
|
604
|
+
| OpenAI | ✅ | GPT-3.5, GPT-4, GPT-4 Turbo |
|
|
605
|
+
| Bedrock | ✅ | Claude 3 Sonnet, Haiku |
|
|
606
|
+
| Azure OpenAI | ✅ | Same as OpenAI pricing |
|
|
607
|
+
| Ollama | ✅ (zero cost) | Local models — no API charges |
|
|
608
|
+
|
|
544
609
|
## MCP Integration
|
|
545
610
|
|
|
546
611
|
The AI review is exposed as an MCP tool (`thothctl_ai_review`) for AI assistant interoperability:
|
|
@@ -6,10 +6,9 @@ The `thothctl inventory iac` command creates, updates, and manages an inventory
|
|
|
6
6
|
|
|
7
7
|
## Recent Improvements ✨
|
|
8
8
|
|
|
9
|
-
- **🎯
|
|
9
|
+
- **🎯 Independent Version Checking**: Separate flags for module versions (`-cv`) and provider versions (`-cpv`) — check what you need
|
|
10
10
|
- **🎨 Modern HTML Reports**: Professional styling with Inter font, gradients, and responsive design
|
|
11
11
|
- **📊 Enhanced Provider Analysis**: Comprehensive provider version tracking with status indicators
|
|
12
|
-
- **🚀 Intelligent Automation**: Automatic provider checking when version checking is enabled
|
|
13
12
|
- **📱 Responsive Design**: Reports work perfectly on desktop, tablet, and mobile devices
|
|
14
13
|
|
|
15
14
|
## Command Options
|
|
@@ -20,33 +19,21 @@ Usage: thothctl inventory iac [OPTIONS]
|
|
|
20
19
|
Create a inventory about IaC modules composition for terraform/tofu/terragrunt projects
|
|
21
20
|
|
|
22
21
|
Options:
|
|
23
|
-
-
|
|
24
|
-
|
|
25
|
-
--
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
--check-providers Check and report provider information for
|
|
29
|
-
each stack (automatically enabled with
|
|
30
|
-
--check-versions)
|
|
31
|
-
--complete Include .terraform and .terragrunt-cache
|
|
32
|
-
folders in analysis (complete analysis)
|
|
33
|
-
-ft, --framework-type [auto|terraform|terragrunt|terraform-terragrunt]
|
|
34
|
-
Framework type to analyze (auto for
|
|
35
|
-
automatic detection)
|
|
22
|
+
-cv, --check-versions Check latest versions for modules
|
|
23
|
+
-cpv, --check-provider-versions Check latest versions for providers
|
|
24
|
+
--check-providers Check and report provider information for each stack
|
|
25
|
+
-ft, --framework-type [auto|terraform|terragrunt|terraform-terragrunt|module|cdkv2]
|
|
26
|
+
Framework type to analyze (auto for automatic detection)
|
|
36
27
|
-r, --report-type [html|json|cyclonedx|all]
|
|
37
|
-
Type of report to generate
|
|
38
|
-
generates OWASP CycloneDX SBOM format)
|
|
28
|
+
Type of report to generate
|
|
39
29
|
-iact, --inventory-action [create|update|restore]
|
|
40
30
|
Action for inventory tasks
|
|
41
|
-
-auto, --auto-approve Use with --update_dependencies option for
|
|
42
|
-
auto approve updating dependencies.
|
|
43
|
-
-updep, --update-dependencies-path
|
|
44
|
-
Pass the inventory json file path for
|
|
45
|
-
updating dependencies.
|
|
46
|
-
-cv, --check-versions Check latest versions for modules and
|
|
47
|
-
providers (includes provider version
|
|
48
|
-
checking)
|
|
49
31
|
-iph, --inventory-path PATH Path for saving inventory reports
|
|
32
|
+
-pj, --project-name TEXT Custom project name for the report
|
|
33
|
+
--provider-tool [tofu|terraform]
|
|
34
|
+
Tool to use for checking providers (default: tofu)
|
|
35
|
+
--complete Include .terraform and .terragrunt-cache in analysis
|
|
36
|
+
-auto, --auto-approve Auto approve updating dependencies
|
|
50
37
|
--post-to-pr Post inventory summary as a PR comment
|
|
51
38
|
(Azure DevOps or GitHub)
|
|
52
39
|
--vcs-provider [auto|azure_repos|github]
|
|
@@ -67,18 +54,21 @@ thothctl inventory iac
|
|
|
67
54
|
|
|
68
55
|
This creates an inventory of all IaC components in the current directory and generates a **modern HTML report** in the default location (`./Reports/Inventory`).
|
|
69
56
|
|
|
70
|
-
### Create an Inventory with Version Checking
|
|
57
|
+
### Create an Inventory with Version Checking
|
|
71
58
|
|
|
72
59
|
```bash
|
|
73
|
-
|
|
74
|
-
|
|
60
|
+
# Check module versions only
|
|
61
|
+
thothctl inventory iac -cv
|
|
75
62
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
63
|
+
# Check provider versions only
|
|
64
|
+
thothctl inventory iac -cpv
|
|
65
|
+
|
|
66
|
+
# Check both module and provider versions
|
|
67
|
+
thothctl inventory iac -cv -cpv
|
|
68
|
+
|
|
69
|
+
# Provider info without version lookup
|
|
70
|
+
thothctl inventory iac --check-providers
|
|
71
|
+
```
|
|
82
72
|
|
|
83
73
|
### Generate Different Report Types
|
|
84
74
|
|
|
@@ -100,7 +90,7 @@ thothctl inventory iac --report-type all
|
|
|
100
90
|
|
|
101
91
|
```bash
|
|
102
92
|
thothctl inventory iac \
|
|
103
|
-
|
|
93
|
+
-cv -cpv \
|
|
104
94
|
--inventory-path ./docs/infrastructure \
|
|
105
95
|
--project-name "Production Infrastructure"
|
|
106
96
|
```
|
|
@@ -129,10 +119,10 @@ ThothCTL now supports generating **CycloneDX Software Bill of Materials (SBOM)**
|
|
|
129
119
|
### Example:
|
|
130
120
|
```bash
|
|
131
121
|
# Generate CycloneDX SBOM for security audit
|
|
132
|
-
thothctl inventory iac
|
|
122
|
+
thothctl inventory iac -cv -cpv --report-type cyclonedx
|
|
133
123
|
|
|
134
124
|
# Complete analysis with all formats including SBOM
|
|
135
|
-
thothctl inventory iac
|
|
125
|
+
thothctl inventory iac -cv -cpv --report-type all
|
|
136
126
|
```
|
|
137
127
|
|
|
138
128
|
The CycloneDX report includes:
|
|
@@ -61,7 +61,9 @@ class AnalyzeCommand(ClickCommand):
|
|
|
61
61
|
if cost_report["total_cost"] > 0:
|
|
62
62
|
self.ui.print_info(
|
|
63
63
|
f"💰 Today's AI cost: ${cost_report['total_cost']:.4f} "
|
|
64
|
-
f"({cost_report['total_requests']} requests
|
|
64
|
+
f"({cost_report['total_requests']} requests, "
|
|
65
|
+
f"↑{cost_report['total_input_tokens']:,} in / "
|
|
66
|
+
f"↓{cost_report['total_output_tokens']:,} out tokens)"
|
|
65
67
|
)
|
|
66
68
|
|
|
67
69
|
except ImportError as e:
|
|
@@ -91,6 +91,16 @@ class OrchestrateCommand(ClickCommand):
|
|
|
91
91
|
json.dump(data, f, indent=2, default=str)
|
|
92
92
|
self.ui.print_success(f"Full results saved to {output}")
|
|
93
93
|
|
|
94
|
+
# Show token usage
|
|
95
|
+
if hasattr(result, 'cost') and result.cost:
|
|
96
|
+
cost = result.cost
|
|
97
|
+
self.ui.print_info(
|
|
98
|
+
f"💰 Usage: ${cost.get('total_cost', 0):.4f} | "
|
|
99
|
+
f"↑{cost.get('input_tokens', 0):,} in / "
|
|
100
|
+
f"↓{cost.get('output_tokens', 0):,} out tokens | "
|
|
101
|
+
f"Model: {cost.get('model', 'unknown')}"
|
|
102
|
+
)
|
|
103
|
+
|
|
94
104
|
def _display_security(self, data):
|
|
95
105
|
summary = data.get("summary", {})
|
|
96
106
|
table = Table(title="🔒 Security Agent")
|
|
@@ -27,35 +27,6 @@ class DashboardService:
|
|
|
27
27
|
def _setup_routes(self):
|
|
28
28
|
"""Setup FastAPI routes for the dashboard."""
|
|
29
29
|
|
|
30
|
-
@self.app.get("/minimal", response_class=HTMLResponse)
|
|
31
|
-
async def minimal_test():
|
|
32
|
-
"""Minimal test page to isolate JavaScript issues."""
|
|
33
|
-
return '''<!DOCTYPE html>
|
|
34
|
-
<html>
|
|
35
|
-
<head><title>Test</title></head>
|
|
36
|
-
<body>
|
|
37
|
-
<h1>Minimal Test Page</h1>
|
|
38
|
-
<div id="test">Loading...</div>
|
|
39
|
-
<script>
|
|
40
|
-
console.log('Script started');
|
|
41
|
-
document.addEventListener('DOMContentLoaded', function() {
|
|
42
|
-
console.log('DOM loaded');
|
|
43
|
-
document.getElementById('test').innerHTML = 'JavaScript Working!';
|
|
44
|
-
});
|
|
45
|
-
console.log('Script ended');
|
|
46
|
-
</script>
|
|
47
|
-
</body>
|
|
48
|
-
</html>'''
|
|
49
|
-
|
|
50
|
-
@self.app.get("/debug", response_class=HTMLResponse)
|
|
51
|
-
async def debug_page():
|
|
52
|
-
"""Debug test page."""
|
|
53
|
-
try:
|
|
54
|
-
with open('/home/labvel/projects/tools/ThothForge/thothctl/debug_dashboard.html') as f:
|
|
55
|
-
return f.read()
|
|
56
|
-
except FileNotFoundError:
|
|
57
|
-
return "<html><body><h1>Debug file not found</h1></body></html>"
|
|
58
|
-
|
|
59
30
|
@self.app.get("/", response_class=HTMLResponse)
|
|
60
31
|
async def dashboard():
|
|
61
32
|
"""Main dashboard page."""
|
|
@@ -123,6 +94,24 @@ class DashboardService:
|
|
|
123
94
|
except Exception as e:
|
|
124
95
|
logger.error(f"Refresh API error: {e}")
|
|
125
96
|
raise HTTPException(status_code=500, detail=str(e))
|
|
97
|
+
|
|
98
|
+
@self.app.get("/api/drift")
|
|
99
|
+
async def api_drift():
|
|
100
|
+
"""API endpoint for drift detection data."""
|
|
101
|
+
try:
|
|
102
|
+
return self.data_loader.get_drift_data()
|
|
103
|
+
except Exception as e:
|
|
104
|
+
logger.error(f"Drift API error: {e}")
|
|
105
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
106
|
+
|
|
107
|
+
@self.app.get("/api/ai-usage")
|
|
108
|
+
async def api_ai_usage():
|
|
109
|
+
"""API endpoint for AI token/cost usage."""
|
|
110
|
+
try:
|
|
111
|
+
return self.data_loader.get_ai_usage()
|
|
112
|
+
except Exception as e:
|
|
113
|
+
logger.error(f"AI usage API error: {e}")
|
|
114
|
+
raise HTTPException(status_code=500, detail=str(e))
|
|
126
115
|
|
|
127
116
|
def _get_dashboard_template(self) -> str:
|
|
128
117
|
"""Get the dashboard HTML template."""
|
|
@@ -164,21 +164,79 @@ class DashboardDataLoader:
|
|
|
164
164
|
return {
|
|
165
165
|
"message": "No risk analysis available.",
|
|
166
166
|
"action": "Run project check to generate blast radius analysis",
|
|
167
|
-
"command": "thothctl check
|
|
167
|
+
"command": "thothctl check iac -type blast-radius --recursive"
|
|
168
168
|
}
|
|
169
169
|
|
|
170
170
|
except json.JSONDecodeError:
|
|
171
|
+
return {"error": "Invalid blast radius file format", "action": "Regenerate", "command": "thothctl check iac -type blast-radius --recursive"}
|
|
172
|
+
except Exception as e:
|
|
173
|
+
return {"error": f"Error loading risk data: {str(e)}"}
|
|
174
|
+
|
|
175
|
+
def get_drift_data(self) -> Dict[str, Any]:
|
|
176
|
+
"""Load from existing drift detection reports."""
|
|
177
|
+
cache_key = "drift"
|
|
178
|
+
if self._is_cache_valid(cache_key):
|
|
179
|
+
return self.cache[cache_key]["data"]
|
|
180
|
+
|
|
181
|
+
try:
|
|
182
|
+
drift_files = list(self.reports_dir.glob("**/drift_*.json"))
|
|
183
|
+
if drift_files:
|
|
184
|
+
latest_file = max(drift_files, key=lambda f: f.stat().st_mtime)
|
|
185
|
+
with open(latest_file, "r", encoding="utf-8") as f:
|
|
186
|
+
data = json.load(f)
|
|
187
|
+
self._cache_data(cache_key, data)
|
|
188
|
+
return data
|
|
189
|
+
|
|
171
190
|
return {
|
|
172
|
-
"
|
|
173
|
-
"action": "
|
|
174
|
-
"command": "thothctl check
|
|
191
|
+
"message": "No drift data available.",
|
|
192
|
+
"action": "Run drift detection",
|
|
193
|
+
"command": "thothctl check iac -type drift --recursive"
|
|
175
194
|
}
|
|
176
195
|
except Exception as e:
|
|
177
|
-
return {
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
196
|
+
return {"error": f"Error loading drift data: {str(e)}"}
|
|
197
|
+
|
|
198
|
+
def get_ai_usage(self) -> Dict[str, Any]:
|
|
199
|
+
"""Load AI usage/cost data from cost logs."""
|
|
200
|
+
cache_key = "ai_usage"
|
|
201
|
+
if self._is_cache_valid(cache_key):
|
|
202
|
+
return self.cache[cache_key]["data"]
|
|
203
|
+
|
|
204
|
+
try:
|
|
205
|
+
from datetime import date as date_mod
|
|
206
|
+
cost_dir = Path(".thothctl/ai_costs")
|
|
207
|
+
if not cost_dir.exists():
|
|
208
|
+
return {
|
|
209
|
+
"message": "No AI usage data.",
|
|
210
|
+
"action": "Run AI review to generate usage logs",
|
|
211
|
+
"command": "thothctl ai-review analyze -d ."
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
records = []
|
|
215
|
+
month_prefix = date_mod.today().strftime("%Y-%m")
|
|
216
|
+
for log_file in sorted(cost_dir.glob(f"{month_prefix}*.jsonl")):
|
|
217
|
+
with open(log_file) as f:
|
|
218
|
+
for line in f:
|
|
219
|
+
if line.strip():
|
|
220
|
+
records.append(json.loads(line.strip()))
|
|
221
|
+
|
|
222
|
+
if not records:
|
|
223
|
+
return {"message": "No AI usage this month.", "records": []}
|
|
224
|
+
|
|
225
|
+
total_cost = sum(r.get("cost", 0) for r in records)
|
|
226
|
+
total_input = sum(r.get("input_tokens", 0) for r in records)
|
|
227
|
+
total_output = sum(r.get("output_tokens", 0) for r in records)
|
|
228
|
+
|
|
229
|
+
data = {
|
|
230
|
+
"total_cost": total_cost,
|
|
231
|
+
"total_requests": len(records),
|
|
232
|
+
"total_input_tokens": total_input,
|
|
233
|
+
"total_output_tokens": total_output,
|
|
234
|
+
"records": records[-20:], # Last 20 records
|
|
181
235
|
}
|
|
236
|
+
self._cache_data(cache_key, data)
|
|
237
|
+
return data
|
|
238
|
+
except Exception as e:
|
|
239
|
+
return {"error": f"Error loading AI usage: {str(e)}"}
|
|
182
240
|
|
|
183
241
|
def _is_cache_valid(self, key: str) -> bool:
|
|
184
242
|
"""Check if cached data is still valid."""
|
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>ThothCTL Dashboard</title>
|
|
7
|
+
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700&display=swap" rel="stylesheet">
|
|
8
|
+
<style>
|
|
9
|
+
:root {
|
|
10
|
+
--primary: #007bff; --secondary: #6c757d; --success: #28a745;
|
|
11
|
+
--warning: #ffc107; --danger: #dc3545; --info: #17a2b8;
|
|
12
|
+
--bg: #f8f9fa; --dark: #343a40; --radius: 8px;
|
|
13
|
+
--shadow: 0 2px 8px rgba(0,0,0,0.08);
|
|
14
|
+
}
|
|
15
|
+
* { margin:0; padding:0; box-sizing:border-box; }
|
|
16
|
+
body {
|
|
17
|
+
font-family: 'Inter', system-ui, sans-serif;
|
|
18
|
+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
|
19
|
+
min-height: 100vh; padding: 20px; color: var(--dark);
|
|
20
|
+
}
|
|
21
|
+
body.dark-mode { background: #1a1a2e; }
|
|
22
|
+
body.dark-mode .container { background: #16213e; color: #e0e0e0; }
|
|
23
|
+
body.dark-mode .nav-header { background: linear-gradient(135deg, #0f3460, #1a1a2e); }
|
|
24
|
+
body.dark-mode .card { background: #1a1a2e; border-color: #2a2a4e; }
|
|
25
|
+
body.dark-mode .data-table th { background: #0f3460; }
|
|
26
|
+
body.dark-mode .data-table td { border-color: #2a2a4e; }
|
|
27
|
+
|
|
28
|
+
.container { max-width:1400px; margin:0 auto; background:#fff; border-radius:var(--radius); box-shadow:var(--shadow); overflow:hidden; }
|
|
29
|
+
.nav-header { background:linear-gradient(135deg, var(--primary), #0056b3); color:#fff; padding:20px 30px; position:sticky; top:0; z-index:100; }
|
|
30
|
+
.nav-title { font-size:1.6rem; font-weight:700; }
|
|
31
|
+
.nav-subtitle { font-size:0.85rem; opacity:0.85; margin:4px 0 12px; }
|
|
32
|
+
.nav-menu { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
|
|
33
|
+
.nav-link { color:rgba(255,255,255,0.85); text-decoration:none; padding:6px 14px; border-radius:20px; font-size:0.8rem; font-weight:500; cursor:pointer; transition:all .2s; }
|
|
34
|
+
.nav-link:hover, .nav-link.active { background:rgba(255,255,255,0.2); color:#fff; }
|
|
35
|
+
.nav-actions { margin-left:auto; display:flex; gap:8px; }
|
|
36
|
+
.btn { padding:6px 12px; border:none; border-radius:16px; cursor:pointer; font-size:0.75rem; font-weight:500; transition:all .2s; }
|
|
37
|
+
.btn-refresh { background:var(--success); color:#fff; }
|
|
38
|
+
.btn-export { background:rgba(255,255,255,0.2); color:#fff; }
|
|
39
|
+
.btn:hover { transform:translateY(-1px); opacity:0.9; }
|
|
40
|
+
|
|
41
|
+
.content-section { padding:24px 30px; display:none; }
|
|
42
|
+
.content-section.active { display:block; }
|
|
43
|
+
.section-title { font-size:1.3rem; font-weight:600; color:var(--primary); margin-bottom:16px; }
|
|
44
|
+
|
|
45
|
+
.summary-grid { display:grid; grid-template-columns:repeat(auto-fit, minmax(180px,1fr)); gap:16px; margin-bottom:24px; }
|
|
46
|
+
.card { background:#fff; padding:20px; border-radius:var(--radius); text-align:center; box-shadow:var(--shadow); border-left:4px solid var(--primary); cursor:pointer; transition:all .2s; }
|
|
47
|
+
.card:hover { transform:translateY(-2px); box-shadow:0 4px 16px rgba(0,0,0,0.12); }
|
|
48
|
+
.card-number { font-size:2rem; font-weight:700; color:var(--primary); }
|
|
49
|
+
.card-label { font-size:0.75rem; color:var(--secondary); text-transform:uppercase; letter-spacing:0.5px; margin-top:4px; }
|
|
50
|
+
|
|
51
|
+
.data-table { width:100%; border-collapse:collapse; margin:16px 0; font-size:0.85rem; }
|
|
52
|
+
.data-table th { background:linear-gradient(135deg, var(--primary), #0056b3); color:#fff; padding:10px 12px; text-align:left; font-weight:600; }
|
|
53
|
+
.data-table td { padding:10px 12px; border-bottom:1px solid #e9ecef; }
|
|
54
|
+
.data-table tr:hover { background:#f8f9fa; }
|
|
55
|
+
|
|
56
|
+
.badge { display:inline-block; padding:2px 8px; border-radius:10px; font-size:0.7rem; font-weight:600; }
|
|
57
|
+
.badge-success { background:#d4edda; color:#155724; }
|
|
58
|
+
.badge-warning { background:#fff3cd; color:#856404; }
|
|
59
|
+
.badge-danger { background:#f8d7da; color:#721c24; }
|
|
60
|
+
.badge-info { background:#d1ecf1; color:#0c5460; }
|
|
61
|
+
|
|
62
|
+
.message { padding:20px; text-align:center; color:var(--secondary); }
|
|
63
|
+
.message code { background:#e9ecef; padding:2px 6px; border-radius:4px; font-size:0.8rem; }
|
|
64
|
+
.error { background:#f8d7da; color:#721c24; padding:12px; border-radius:var(--radius); border-left:4px solid var(--danger); }
|
|
65
|
+
|
|
66
|
+
@media (max-width:768px) { body { padding:8px; } .content-section { padding:16px; } .nav-menu { gap:4px; } }
|
|
67
|
+
@media print { .nav-header { position:static; } .nav-actions { display:none; } body { background:#fff; padding:0; } }
|
|
68
|
+
</style>
|
|
69
|
+
</head>
|
|
70
|
+
<body>
|
|
71
|
+
<div class="container">
|
|
72
|
+
<div class="nav-header">
|
|
73
|
+
<div class="nav-title">🚀 ThothCTL Dashboard</div>
|
|
74
|
+
<div class="nav-subtitle">Infrastructure Lifecycle Console</div>
|
|
75
|
+
<nav class="nav-menu">
|
|
76
|
+
<a class="nav-link active" data-section="overview">📊 Overview</a>
|
|
77
|
+
<a class="nav-link" data-section="inventory">📦 Inventory</a>
|
|
78
|
+
<a class="nav-link" data-section="security">🔒 Scan</a>
|
|
79
|
+
<a class="nav-link" data-section="costs">💰 Costs</a>
|
|
80
|
+
<a class="nav-link" data-section="risks">💥 Blast Radius</a>
|
|
81
|
+
<a class="nav-link" data-section="drift">🔍 Drift</a>
|
|
82
|
+
<a class="nav-link" data-section="ai">🤖 AI Usage</a>
|
|
83
|
+
<div class="nav-actions">
|
|
84
|
+
<button class="btn btn-refresh" onclick="refreshAll()">🔄 Refresh</button>
|
|
85
|
+
<button class="btn btn-export" onclick="window.print()">📄 Export</button>
|
|
86
|
+
<button class="btn btn-export" onclick="toggleDark()">🌙</button>
|
|
87
|
+
</div>
|
|
88
|
+
</nav>
|
|
89
|
+
</div>
|
|
90
|
+
|
|
91
|
+
<section id="overview" class="content-section active"><h2 class="section-title">📊 Overview</h2><div id="overview-content"><div class="message">Loading...</div></div></section>
|
|
92
|
+
<section id="inventory" class="content-section"><h2 class="section-title">📦 Infrastructure Inventory</h2><div id="inventory-content"><div class="message">Loading...</div></div></section>
|
|
93
|
+
<section id="security" class="content-section"><h2 class="section-title">🔒 Security Scan Results</h2><div id="security-content"><div class="message">Loading...</div></div></section>
|
|
94
|
+
<section id="costs" class="content-section"><h2 class="section-title">💰 Cost Analysis</h2><div id="costs-content"><div class="message">Loading...</div></div></section>
|
|
95
|
+
<section id="risks" class="content-section"><h2 class="section-title">💥 Blast Radius</h2><div id="risks-content"><div class="message">Loading...</div></div></section>
|
|
96
|
+
<section id="drift" class="content-section"><h2 class="section-title">🔍 Drift Detection</h2><div id="drift-content"><div class="message">Loading...</div></div></section>
|
|
97
|
+
<section id="ai" class="content-section"><h2 class="section-title">🤖 AI Token Usage</h2><div id="ai-content"><div class="message">Loading...</div></div></section>
|
|
98
|
+
</div>
|
|
99
|
+
|
|
100
|
+
<script>
|
|
101
|
+
const D = {};
|
|
102
|
+
|
|
103
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
104
|
+
if (localStorage.getItem('darkMode')==='true') { document.body.classList.add('dark-mode'); }
|
|
105
|
+
document.querySelectorAll('.nav-link[data-section]').forEach(link => {
|
|
106
|
+
link.addEventListener('click', () => {
|
|
107
|
+
document.querySelectorAll('.nav-link').forEach(l=>l.classList.remove('active'));
|
|
108
|
+
document.querySelectorAll('.content-section').forEach(s=>s.classList.remove('active'));
|
|
109
|
+
link.classList.add('active');
|
|
110
|
+
document.getElementById(link.dataset.section).classList.add('active');
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
loadAll();
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
function toggleDark() {
|
|
117
|
+
document.body.classList.toggle('dark-mode');
|
|
118
|
+
localStorage.setItem('darkMode', document.body.classList.contains('dark-mode'));
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
async function refreshAll() { await fetch('/api/refresh'); loadAll(); }
|
|
122
|
+
|
|
123
|
+
async function loadAll() {
|
|
124
|
+
const endpoints = {inventory:'/api/inventory', security:'/api/scan-results', costs:'/api/cost-analysis', risks:'/api/blast-radius', drift:'/api/drift', ai:'/api/ai-usage'};
|
|
125
|
+
const results = await Promise.allSettled(Object.entries(endpoints).map(async ([k,url]) => {
|
|
126
|
+
const r = await fetch(url); D[k] = await r.json(); return k;
|
|
127
|
+
}));
|
|
128
|
+
renderOverview(); renderInventory(); renderSecurity(); renderCosts(); renderRisks(); renderDrift(); renderAI();
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function msg(text, cmd) { return `<div class="message">${text}${cmd ? '<br><code>'+cmd+'</code>' : ''}</div>`; }
|
|
132
|
+
function err(data) { return data && (data.error || data.message); }
|
|
133
|
+
|
|
134
|
+
function renderOverview() {
|
|
135
|
+
const inv = D.inventory||{}, sec = D.security||{}, cost = D.costs||{}, risk = D.risks||{}, drift = D.drift||{}, ai = D.ai||{};
|
|
136
|
+
const comps = Array.isArray(inv.components) ? inv.components.length : (inv.stacks ? inv.stacks.length : 0);
|
|
137
|
+
const issues = sec.summary ? sec.summary.total_issues : 0;
|
|
138
|
+
const monthly = typeof cost.total_monthly_cost === 'number' ? cost.total_monthly_cost.toFixed(2) : '—';
|
|
139
|
+
const riskLvl = risk.risk_level || risk.overall_risk || '—';
|
|
140
|
+
const drifted = drift.total_drifted || (drift.results ? drift.results.reduce((a,r)=>a+(r.drifted_resources||[]).length,0) : 0);
|
|
141
|
+
const aiCost = typeof ai.total_cost === 'number' ? '$'+ai.total_cost.toFixed(4) : '—';
|
|
142
|
+
document.getElementById('overview-content').innerHTML = `
|
|
143
|
+
<div class="summary-grid">
|
|
144
|
+
<div class="card" onclick="nav('inventory')"><div class="card-number">${comps}</div><div class="card-label">Components</div></div>
|
|
145
|
+
<div class="card" onclick="nav('security')" style="border-color:var(--danger)"><div class="card-number" style="color:var(--danger)">${issues}</div><div class="card-label">Security Issues</div></div>
|
|
146
|
+
<div class="card" onclick="nav('costs')" style="border-color:var(--warning)"><div class="card-number" style="color:var(--warning)">$${monthly}</div><div class="card-label">Monthly Cost</div></div>
|
|
147
|
+
<div class="card" onclick="nav('risks')" style="border-color:var(--info)"><div class="card-number" style="color:var(--info)">${riskLvl}</div><div class="card-label">Risk Level</div></div>
|
|
148
|
+
<div class="card" onclick="nav('drift')" style="border-color:#9c27b0"><div class="card-number" style="color:#9c27b0">${drifted}</div><div class="card-label">Drifted Resources</div></div>
|
|
149
|
+
<div class="card" onclick="nav('ai')" style="border-color:#00bcd4"><div class="card-number" style="color:#00bcd4">${aiCost}</div><div class="card-label">AI Cost (Month)</div></div>
|
|
150
|
+
</div>`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function nav(section) { document.querySelector(`[data-section="${section}"]`).click(); }
|
|
154
|
+
|
|
155
|
+
function renderInventory() {
|
|
156
|
+
const d = D.inventory;
|
|
157
|
+
if (!d || err(d)) { document.getElementById('inventory-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
158
|
+
const stacks = d.stacks || d.components || [];
|
|
159
|
+
if (!stacks.length) { document.getElementById('inventory-content').innerHTML = msg('No components found'); return; }
|
|
160
|
+
let html = `<div class="summary-grid"><div class="card"><div class="card-number">${stacks.length}</div><div class="card-label">Stacks</div></div></div>`;
|
|
161
|
+
html += '<table class="data-table"><thead><tr><th>Stack</th><th>Modules</th><th>Providers</th></tr></thead><tbody>';
|
|
162
|
+
stacks.forEach(s => {
|
|
163
|
+
const name = s.stack || s.name || 'unknown';
|
|
164
|
+
const mods = s.modules ? s.modules.length : (s.components ? s.components.length : 0);
|
|
165
|
+
const provs = s.providers ? s.providers.length : 0;
|
|
166
|
+
html += `<tr><td><strong>${name}</strong></td><td>${mods}</td><td>${provs}</td></tr>`;
|
|
167
|
+
});
|
|
168
|
+
html += '</tbody></table>';
|
|
169
|
+
document.getElementById('inventory-content').innerHTML = html;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function renderSecurity() {
|
|
173
|
+
const d = D.security;
|
|
174
|
+
if (!d || err(d)) { document.getElementById('security-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
175
|
+
const issues = d.summary ? d.summary.total_issues : 0;
|
|
176
|
+
const reports = d.reports || [];
|
|
177
|
+
let html = `<div class="summary-grid"><div class="card" style="border-color:var(--danger)"><div class="card-number" style="color:var(--danger)">${issues}</div><div class="card-label">Total Issues</div></div><div class="card"><div class="card-number">${reports.length}</div><div class="card-label">Reports</div></div></div>`;
|
|
178
|
+
if (reports.length) {
|
|
179
|
+
html += '<table class="data-table"><thead><tr><th>Report</th><th>Type</th><th>Date</th><th>Size</th></tr></thead><tbody>';
|
|
180
|
+
reports.slice(0,20).forEach(r => {
|
|
181
|
+
html += `<tr><td>${r.file}</td><td><span class="badge badge-info">${r.type||'—'}</span></td><td>${r.timestamp ? new Date(r.timestamp).toLocaleDateString() : '—'}</td><td>${r.size ? (r.size/1024).toFixed(1)+'KB' : '—'}</td></tr>`;
|
|
182
|
+
});
|
|
183
|
+
html += '</tbody></table>';
|
|
184
|
+
}
|
|
185
|
+
document.getElementById('security-content').innerHTML = html;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function renderCosts() {
|
|
189
|
+
const d = D.costs;
|
|
190
|
+
if (!d || err(d)) { document.getElementById('costs-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
191
|
+
const monthly = d.total_monthly_cost||0, annual = d.total_annual_cost||0;
|
|
192
|
+
let html = `<div class="summary-grid"><div class="card" style="border-color:var(--warning)"><div class="card-number" style="color:var(--warning)">$${monthly.toFixed(2)}</div><div class="card-label">Monthly</div></div><div class="card" style="border-color:var(--danger)"><div class="card-number" style="color:var(--danger)">$${annual.toFixed(2)}</div><div class="card-label">Annual</div></div></div>`;
|
|
193
|
+
if (d.cost_breakdown_by_service) {
|
|
194
|
+
html += '<table class="data-table"><thead><tr><th>Service</th><th>Monthly Cost</th></tr></thead><tbody>';
|
|
195
|
+
Object.entries(d.cost_breakdown_by_service).sort((a,b)=>b[1]-a[1]).forEach(([svc,cost]) => {
|
|
196
|
+
html += `<tr><td>${svc}</td><td>$${cost.toFixed(2)}</td></tr>`;
|
|
197
|
+
});
|
|
198
|
+
html += '</tbody></table>';
|
|
199
|
+
}
|
|
200
|
+
if (d.recommendations && d.recommendations.length) {
|
|
201
|
+
html += '<h3 style="margin:16px 0 8px">💡 Recommendations</h3><ul style="padding-left:20px">';
|
|
202
|
+
d.recommendations.forEach(r => html += `<li style="margin:4px 0">${r}</li>`);
|
|
203
|
+
html += '</ul>';
|
|
204
|
+
}
|
|
205
|
+
document.getElementById('costs-content').innerHTML = html;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
function renderRisks() {
|
|
209
|
+
const d = D.risks;
|
|
210
|
+
if (!d || err(d)) { document.getElementById('risks-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
211
|
+
const riskColor = {'LOW':'var(--success)','MEDIUM':'var(--warning)','HIGH':'var(--danger)','CRITICAL':'var(--danger)'}[d.risk_level?.toUpperCase()]||'var(--info)';
|
|
212
|
+
let html = `<div class="summary-grid"><div class="card" style="border-color:${riskColor}"><div class="card-number" style="color:${riskColor}">${d.risk_level||'—'}</div><div class="card-label">Risk Level</div></div><div class="card"><div class="card-number">${d.change_type||'—'}</div><div class="card-label">Change Type</div></div><div class="card"><div class="card-number">${d.affected_components||d.total_components||0}</div><div class="card-label">Affected</div></div></div>`;
|
|
213
|
+
if (d.recommendations && d.recommendations.length) {
|
|
214
|
+
html += '<h3 style="margin:16px 0 8px">📋 Recommendations</h3><ul style="padding-left:20px">';
|
|
215
|
+
d.recommendations.forEach(r => html += `<li style="margin:4px 0">${r}</li>`);
|
|
216
|
+
html += '</ul>';
|
|
217
|
+
}
|
|
218
|
+
document.getElementById('risks-content').innerHTML = html;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
function renderDrift() {
|
|
222
|
+
const d = D.drift;
|
|
223
|
+
if (!d || err(d)) { document.getElementById('drift-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
224
|
+
const results = d.results || [];
|
|
225
|
+
const totalDrifted = results.reduce((a,r)=>a+(r.drifted_resources||[]).length, 0);
|
|
226
|
+
const coverage = d.iac_coverage_percentage != null ? d.iac_coverage_percentage.toFixed(1)+'%' : '—';
|
|
227
|
+
let html = `<div class="summary-grid"><div class="card" style="border-color:#9c27b0"><div class="card-number" style="color:#9c27b0">${totalDrifted}</div><div class="card-label">Drifted Resources</div></div><div class="card"><div class="card-number">${coverage}</div><div class="card-label">IaC Coverage</div></div><div class="card"><div class="card-number">${results.length}</div><div class="card-label">Stacks Checked</div></div></div>`;
|
|
228
|
+
if (totalDrifted > 0) {
|
|
229
|
+
html += '<table class="data-table"><thead><tr><th>Resource</th><th>Type</th><th>Drift Type</th><th>Severity</th></tr></thead><tbody>';
|
|
230
|
+
results.forEach(r => (r.drifted_resources||[]).forEach(res => {
|
|
231
|
+
const sevClass = {'critical':'badge-danger','high':'badge-danger','medium':'badge-warning','low':'badge-info'}[res.severity]||'badge-info';
|
|
232
|
+
html += `<tr><td>${res.address||'—'}</td><td>${res.resource_type||'—'}</td><td>${res.drift_type||'—'}</td><td><span class="badge ${sevClass}">${res.severity||'—'}</span></td></tr>`;
|
|
233
|
+
}));
|
|
234
|
+
html += '</tbody></table>';
|
|
235
|
+
}
|
|
236
|
+
document.getElementById('drift-content').innerHTML = html;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function renderAI() {
|
|
240
|
+
const d = D.ai;
|
|
241
|
+
if (!d || err(d)) { document.getElementById('ai-content').innerHTML = msg(d?.error||d?.message||'No data', d?.command); return; }
|
|
242
|
+
let html = `<div class="summary-grid"><div class="card" style="border-color:#00bcd4"><div class="card-number" style="color:#00bcd4">$${(d.total_cost||0).toFixed(4)}</div><div class="card-label">Total Cost</div></div><div class="card"><div class="card-number">${d.total_requests||0}</div><div class="card-label">Requests</div></div><div class="card"><div class="card-number">${(d.total_input_tokens||0).toLocaleString()}</div><div class="card-label">Input Tokens</div></div><div class="card"><div class="card-number">${(d.total_output_tokens||0).toLocaleString()}</div><div class="card-label">Output Tokens</div></div></div>`;
|
|
243
|
+
if (d.records && d.records.length) {
|
|
244
|
+
html += '<table class="data-table"><thead><tr><th>Time</th><th>Provider</th><th>Model</th><th>In</th><th>Out</th><th>Cost</th></tr></thead><tbody>';
|
|
245
|
+
d.records.slice().reverse().forEach(r => {
|
|
246
|
+
html += `<tr><td>${r.timestamp ? new Date(r.timestamp).toLocaleString() : '—'}</td><td>${r.provider||'—'}</td><td>${r.model||'—'}</td><td>${(r.input_tokens||0).toLocaleString()}</td><td>${(r.output_tokens||0).toLocaleString()}</td><td>$${(r.cost||0).toFixed(4)}</td></tr>`;
|
|
247
|
+
});
|
|
248
|
+
html += '</tbody></table>';
|
|
249
|
+
}
|
|
250
|
+
document.getElementById('ai-content').innerHTML = html;
|
|
251
|
+
}
|
|
252
|
+
</script>
|
|
253
|
+
</body>
|
|
254
|
+
</html>
|