@ngocsangairvds/vsaf 3.1.27 → 3.2.1
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.
- package/package.json +2 -2
- package/src/global.js +70 -10
- package/tools/skills/vds-scripts-skill/.openskills.json +6 -0
- package/tools/skills/vds-scripts-skill/QUALITY.md +44 -0
- package/tools/skills/vds-scripts-skill/SKILL.md +135 -0
- package/tools/skills/vds-scripts-skill/references/audit-commands.md +171 -0
- package/tools/skills/vds-scripts-skill/references/capability-index.md +34 -0
- package/tools/skills/vds-scripts-skill/references/development-commands.md +12 -0
- package/tools/skills/vds-scripts-skill/references/google-sheets.md +73 -0
- package/tools/skills/vds-scripts-skill/references/integration-commands.md +17 -0
- package/tools/skills/vds-scripts-skill/references/platform-bootstrap.md +31 -0
- package/tools/skills/vds-scripts-skill/references/specialist-routing.md +14 -0
- package/tools/skills/vds-scripts-skill/references/validation-commands.md +15 -0
- package/tools/skills/vsaf-build/SKILL.md +32 -2
- package/tools/skills/vsaf-ship/SKILL.md +41 -10
- package/tools/skills/vsaf-test/SKILL.md +8 -0
- package/tools/vds-scripts/.mcp.json +11 -0
- package/tools/vds-scripts/.secrets.baseline +133 -0
- package/tools/vds-scripts/AGENTS.md +152 -0
- package/tools/vds-scripts/CLAUDE.md +101 -0
- package/tools/vds-scripts/CLI_COMMAND_OPTIMIZATION.md +156 -0
- package/tools/vds-scripts/PACKAGE_P125B_IMPLEMENTATION_SUMMARY.md +131 -0
- package/tools/vds-scripts/PROJECT_COMPLETION_SUMMARY.md +45 -0
- package/tools/vds-scripts/README.md +97 -0
- package/tools/vds-scripts/bitbucket_manifest_mapping.toml +34 -0
- package/tools/vds-scripts/bitbucket_orchestrator/ARCHITECTURE_ANALYSIS.md +258 -0
- package/tools/vds-scripts/bitbucket_orchestrator/BITBUCKET_API_PRACTICES.md +393 -0
- package/tools/vds-scripts/bitbucket_orchestrator/EVALUATION_REPORT.md +61 -0
- package/tools/vds-scripts/bitbucket_orchestrator/FEATURES.md +908 -0
- package/tools/vds-scripts/bitbucket_orchestrator/README.md +687 -0
- package/tools/vds-scripts/bitbucket_orchestrator/pyproject.toml +40 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/__init__.py +20 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/async_client.py +657 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/cli.py +2108 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/client.py +2534 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/config.py +171 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/errors.py +67 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/factory.py +185 -0
- package/tools/vds-scripts/bitbucket_orchestrator/src/vds_bitbucket_orchestrator/protocols.py +244 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/__init__.py +8 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/conftest.py +65 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_advanced_search.py +151 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_async_client.py +546 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_branch_permissions.py +145 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_cli.py +115 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client.py +157 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_branch_conditions.py +79 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_advanced.py +163 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_code_file.py +32 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_deployment_environments.py +194 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_issues.py +164 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pipelines_advanced.py +179 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_pr_blockers.py +119 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_client_repository_variables.py +156 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code.py +98 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_advanced.py +282 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_code_insights.py +335 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_conditions.py +147 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_config.py +131 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_deployment_env.py +352 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_factory.py +371 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_fork_operations.py +204 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_issue_cli.py +261 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pipeline_advanced.py +270 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_pr_blocker.py +204 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_protocols.py +334 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_settings.py +343 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_repo_variables.py +270 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_webhooks.py +189 -0
- package/tools/vds-scripts/bitbucket_orchestrator/tests/test_workspace.py +233 -0
- package/tools/vds-scripts/bitbucket_orchestrator/uv.lock +742 -0
- package/tools/vds-scripts/confluence_orchestrator/Dockerfile +19 -0
- package/tools/vds-scripts/confluence_orchestrator/README.md +412 -0
- package/tools/vds-scripts/confluence_orchestrator/SYNC_SCRIPTS.md +127 -0
- package/tools/vds-scripts/confluence_orchestrator/SYNC_STANDARDIZATION.md +108 -0
- package/tools/vds-scripts/confluence_orchestrator/pyproject.toml +48 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/__init__.py +20 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/cli.py +2532 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/config.py +175 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content.py +290 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/content_v2.py +94 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/crawl_tree.py +1835 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/errors.py +80 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/eventing.py +109 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/http.py +1114 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/orchestration.py +165 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/reporting.py +78 -0
- package/tools/vds-scripts/confluence_orchestrator/src/confluence_orchestrator/tree.py +121 -0
- package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_from_markdown.py +213 -0
- package/tools/vds-scripts/confluence_orchestrator/sync_pdfs_to_confluence.py +305 -0
- package/tools/vds-scripts/confluence_orchestrator/sync_png_attachments.py +305 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/__init__.py +0 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/conftest.py +8 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_content.py +224 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_advanced_search.py +188 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_cache_management.py +247 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_cli.py +499 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_config.py +83 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_content.py +186 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_content_flags.py +27 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_crawl_tree.py +2250 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_draft_management.py +223 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing.py +71 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_chaos.py +37 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_rate_limit.py +44 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_eventing_timeout.py +49 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_export.py +230 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_history.py +204 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_http.py +117 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_orchestration.py +91 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_reporting.py +24 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_search_cql.py +34 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_space_management.py +237 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_space_permissions.py +332 -0
- package/tools/vds-scripts/confluence_orchestrator/tests/test_user_group_management.py +388 -0
- package/tools/vds-scripts/confluence_orchestrator/uv.lock +1023 -0
- package/tools/vds-scripts/git_orchestrator/ENHANCEMENT_SUMMARY.md +119 -0
- package/tools/vds-scripts/git_orchestrator/README.md +280 -0
- package/tools/vds-scripts/git_orchestrator/VERIFICATION_REPORT.md +152 -0
- package/tools/vds-scripts/git_orchestrator/pyproject.toml +35 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__init__.py +7 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/__main__.py +4 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/cli.py +847 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/logging_config.py +63 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/manifest.py +129 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/orchestrator.py +819 -0
- package/tools/vds-scripts/git_orchestrator/src/vds_git_orchestrator/reporting.py +53 -0
- package/tools/vds-scripts/git_orchestrator/tests/__init__.py +0 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_cli_settings.py +21 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_integration.py +74 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_manifest.py +79 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_orchestrator.py +204 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_public_api.py +236 -0
- package/tools/vds-scripts/git_orchestrator/tests/test_resilience.py +345 -0
- package/tools/vds-scripts/git_orchestrator/uv.lock +271 -0
- package/tools/vds-scripts/jira_orchestrator/README.md +770 -0
- package/tools/vds-scripts/jira_orchestrator/pyproject.toml +39 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/__init__.py +1 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/adapter.py +1320 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/cli.py +2271 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/config.py +138 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/errors.py +67 -0
- package/tools/vds-scripts/jira_orchestrator/src/vds_jira_orchestrator/reporting.py +65 -0
- package/tools/vds-scripts/jira_orchestrator/tests/__init__.py +1 -0
- package/tools/vds-scripts/jira_orchestrator/tests/conftest.py +86 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_agile_list_payloads.py +54 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_bulk_operations.py +69 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_components.py +57 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_createmeta.py +45 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_dashboard.py +117 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_issue_properties.py +54 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_permissions_compat.py +42 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_reindex.py +42 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_remote_links.py +76 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_transitions.py +91 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_user_management.py +110 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_version_management.py +133 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_adapter_watchers.py +41 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_advanced_search.py +164 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_agile.py +256 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_application_properties.py +193 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_backlog.py +91 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_bulk_operations.py +277 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_cli.py +106 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_components.py +106 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_config.py +164 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_dashboard.py +122 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_discover_fields.py +207 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_filter_management.py +333 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_issue_archiving.py +164 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_issue_links.py +257 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_issue_properties.py +171 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_link_types.py +314 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_parse_set.py +37 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_permissions.py +273 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_reindex.py +81 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_remote_links.py +254 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_security_schemes.py +170 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_transitions_changelog.py +114 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_user_management.py +226 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_version_management.py +339 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_watchers.py +101 -0
- package/tools/vds-scripts/jira_orchestrator/tests/test_worklog.py +223 -0
- package/tools/vds-scripts/jira_orchestrator/uv.lock +738 -0
- package/tools/vds-scripts/mcp_server/Dockerfile +34 -0
- package/tools/vds-scripts/mcp_server/README.md +140 -0
- package/tools/vds-scripts/mcp_server/pyproject.toml +42 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/__init__.py +4 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/config.py +36 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/server.py +66 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/__init__.py +14 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/bitbucket_tools.py +47 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/confluence_tools.py +59 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/git_tools.py +71 -0
- package/tools/vds-scripts/mcp_server/src/vds_mcp_server/tools/jira_tools.py +63 -0
- package/tools/vds-scripts/mcp_server/tests/__init__.py +2 -0
- package/tools/vds-scripts/mcp_server/tests/conftest.py +29 -0
- package/tools/vds-scripts/mcp_server/tests/unit/__init__.py +2 -0
- package/tools/vds-scripts/mcp_server/tests/unit/test_bitbucket_tools.py +25 -0
- package/tools/vds-scripts/mcp_server/tests/unit/test_confluence_tools.py +25 -0
- package/tools/vds-scripts/mcp_server/tests/unit/test_git_tools.py +32 -0
- package/tools/vds-scripts/mcp_server/tests/unit/test_jira_tools.py +32 -0
- package/tools/vds-scripts/mcp_server/tests/verification/__init__.py +2 -0
- package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_confluence_tools.py +40 -0
- package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_jira_tools.py +37 -0
- package/tools/vds-scripts/mcp_server/tests/verification/test_mcp_tool_registration.py +47 -0
- package/tools/vds-scripts/mcp_server/uv.lock +1032 -0
- package/tools/vds-scripts/mypy.ini +5 -0
- package/tools/vds-scripts/pyproject.toml +29 -0
- package/tools/vds-scripts/repo-manifest.yaml +273 -0
- package/tools/vds-scripts/repo-manifest.yaml.example +25 -0
- package/tools/vds-scripts/scripts/BRD-Validation-API.postman_collection.json +706 -0
- package/tools/vds-scripts/scripts/BRD-Validation-README.md +308 -0
- package/tools/vds-scripts/scripts/README.md +162 -0
- package/tools/vds-scripts/scripts/bootstrap_uv.sh +30 -0
- package/tools/vds-scripts/scripts/brd-validation-environment.json +51 -0
- package/tools/vds-scripts/scripts/brd-validation-test-results.json +13023 -0
- package/tools/vds-scripts/scripts/brd_coverage_report.json +276 -0
- package/tools/vds-scripts/scripts/create_memory_session.py +35 -0
- package/tools/vds-scripts/scripts/deployment/load_docker_images_offline.sh +90 -0
- package/tools/vds-scripts/scripts/final_completion_report.md +139 -0
- package/tools/vds-scripts/scripts/folder_structure_report.json +321 -0
- package/tools/vds-scripts/scripts/generate_completion_report.py +125 -0
- package/tools/vds-scripts/scripts/generate_intellij_modules.py +150 -0
- package/tools/vds-scripts/scripts/link_integrity_report.json +807 -0
- package/tools/vds-scripts/scripts/move_audit_artifact_pages.py +255 -0
- package/tools/vds-scripts/scripts/move_audit_artifact_pages_rest.py +165 -0
- package/tools/vds-scripts/scripts/move_wrong_dept_pages.py +216 -0
- package/tools/vds-scripts/scripts/save_intellij_memories.py +120 -0
- package/tools/vds-scripts/scripts/save_memories_to_vds_ai.py +83 -0
- package/tools/vds-scripts/scripts/save_memories_vds_style.py +129 -0
- package/tools/vds-scripts/scripts/search_intellij_memories.py +50 -0
- package/tools/vds-scripts/scripts/setup_intellij_workspace.py +65 -0
- package/tools/vds-scripts/scripts/target-state-automation/README.md +89 -0
- package/tools/vds-scripts/scripts/target-state-automation/confluence_sync_coordinator.sh +27 -0
- package/tools/vds-scripts/scripts/target-state-automation/coordination.sh +114 -0
- package/tools/vds-scripts/scripts/target-state-automation/diagram_coordinator.sh +25 -0
- package/tools/vds-scripts/scripts/target-state-automation/docs_root.sh +22 -0
- package/tools/vds-scripts/scripts/target-state-automation/generate_diagrams.sh +22 -0
- package/tools/vds-scripts/scripts/target-state-automation/markdown_coordinator.sh +25 -0
- package/tools/vds-scripts/scripts/target-state-automation/progress_dashboard.sh +17 -0
- package/tools/vds-scripts/scripts/target-state-automation/schema_coordinator.sh +25 -0
- package/tools/vds-scripts/scripts/target-state-automation/sync_confluence.sh +30 -0
- package/tools/vds-scripts/scripts/target-state-automation/update_dependencies.sh +19 -0
- package/tools/vds-scripts/scripts/target-state-automation/validate_links.sh +86 -0
- package/tools/vds-scripts/scripts/target-state-automation/validate_markdown.sh +52 -0
- package/tools/vds-scripts/scripts/target-state-automation/validate_schemas.sh +26 -0
- package/tools/vds-scripts/scripts/target-state-automation/validate_structure.sh +98 -0
- package/tools/vds-scripts/scripts/update_modules_xml.py +190 -0
- package/tools/vds-scripts/scripts/uv-workspace-alignment-verification-2026-03-25.md +128 -0
- package/tools/vds-scripts/scripts/validate_brd_coverage.py +179 -0
- package/tools/vds-scripts/scripts/validate_folder_structure.py +240 -0
- package/tools/vds-scripts/scripts/validate_link_integrity.py +272 -0
- package/tools/vds-scripts/scripts/vds_sh_helpers.sh +180 -0
- package/tools/vds-scripts/scripts/verification/phase2_portable_paths_ubuntu_docker.sh +26 -0
- package/tools/vds-scripts/scripts/worktree_uv.sh +48 -0
- package/tools/vds-scripts/uv.lock +8 -0
- package/tools/vds-scripts/vds_cli/README.md +126 -0
- package/tools/vds-scripts/vds_cli/VERIFICATION_REPORT.md +41 -0
- package/tools/vds-scripts/vds_cli/pyproject.toml +38 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/__init__.py +3 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/cli.py +173 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/docs_sync.py +1203 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/env.py +41 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/__init__.py +3 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/google_sheets_orchestrator/google_sheets_orchestrator.py +198 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/router.py +93 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/sync_api.py +647 -0
- package/tools/vds-scripts/vds_cli/src/vds_cli/sync_service.py +266 -0
- package/tools/vds-scripts/vds_cli/tests/__init__.py +2 -0
- package/tools/vds-scripts/vds_cli/tests/conftest.py +49 -0
- package/tools/vds-scripts/vds_cli/tests/unit/__init__.py +2 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_cli.py +143 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_docs_sync.py +422 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_env.py +51 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_router.py +72 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_sync_api.py +357 -0
- package/tools/vds-scripts/vds_cli/tests/unit/test_sync_service.py +160 -0
- package/tools/vds-scripts/vds_cli/tests/verification/__init__.py +2 -0
- package/tools/vds-scripts/vds_cli/tests/verification/test_bitbucket_real.py +33 -0
- package/tools/vds-scripts/vds_cli/tests/verification/test_confluence_real.py +35 -0
- package/tools/vds-scripts/vds_cli/tests/verification/test_jira_real.py +41 -0
- package/tools/vds-scripts/vds_cli/uv.lock +524 -0
- package/tools/vds-scripts/vds_cli_common/README.md +190 -0
- package/tools/vds-scripts/vds_cli_common/pyproject.toml +92 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/__init__.py +34 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/completers.py +139 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/context.py +201 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/env.py +119 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/errors.py +318 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/output.py +284 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/paths.py +78 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/testing.py +213 -0
- package/tools/vds-scripts/vds_cli_common/src/vds_cli_common/version.py +85 -0
- package/tools/vds-scripts/vds_cli_common/tests/__init__.py +1 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_completers.py +148 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_context.py +192 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_env.py +102 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_errors.py +186 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_output.py +229 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_paths.py +61 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_testing.py +138 -0
- package/tools/vds-scripts/vds_cli_common/tests/test_version.py +64 -0
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
"""Shared environment loader for VDS scripts."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import os
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from vds_cli_common.paths import get_default_env_paths, get_shared_env_path
|
|
9
|
+
|
|
10
|
+
DEFAULT_ENV_PATHS = get_default_env_paths()
|
|
11
|
+
|
|
12
|
+
DEFAULT_AUDIT_ENV_DEFAULTS: tuple[tuple[str, str], ...] = (
|
|
13
|
+
("VDS_AUDIT_STATE_DSN", "postgresql://localhost:5432/vds_audit"),
|
|
14
|
+
("VDS_AUDIT_LLM__AGENT_RUNTIME_MODE", "pydanticai"),
|
|
15
|
+
("VDS_AUDIT_LLM__DSPY_RUNTIME_RETRY_ATTEMPTS", "3"),
|
|
16
|
+
("VDS_AUDIT_LLM__DSPY_RUNTIME_RETRY_BACKOFF_SECONDS", "0"),
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def _parse_env_file(path: Path) -> dict[str, str]:
|
|
21
|
+
values: dict[str, str] = {}
|
|
22
|
+
if not path.exists():
|
|
23
|
+
return values
|
|
24
|
+
for raw_line in path.read_text(encoding="utf-8").splitlines():
|
|
25
|
+
line = raw_line.strip()
|
|
26
|
+
if not line or line.startswith("#"):
|
|
27
|
+
continue
|
|
28
|
+
if line.startswith("export "):
|
|
29
|
+
line = line[7:].lstrip()
|
|
30
|
+
if "=" not in line:
|
|
31
|
+
continue
|
|
32
|
+
key, value = line.split("=", 1)
|
|
33
|
+
key = key.strip()
|
|
34
|
+
value = value.strip()
|
|
35
|
+
if value and value[0] == value[-1] and value[0] in {"'", '"'}:
|
|
36
|
+
value = value[1:-1]
|
|
37
|
+
if key:
|
|
38
|
+
values[key] = value
|
|
39
|
+
return values
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
def _render_default_env_content(defaults: tuple[tuple[str, str], ...]) -> str:
|
|
43
|
+
lines = [
|
|
44
|
+
"# Auto-generated default environment for VDS scripts.",
|
|
45
|
+
"# Safe defaults only; replace values for your environment as needed.",
|
|
46
|
+
"",
|
|
47
|
+
]
|
|
48
|
+
for key, value in defaults:
|
|
49
|
+
lines.append(f"{key}={value}")
|
|
50
|
+
lines.append("")
|
|
51
|
+
lines.append("# Optional credentials")
|
|
52
|
+
lines.append("# ANTHROPIC_API_KEY=")
|
|
53
|
+
lines.append("# OPENAI_API_KEY=")
|
|
54
|
+
lines.append("# VDS_USERNAME=")
|
|
55
|
+
lines.append("# VDS_PASSWORD=")
|
|
56
|
+
lines.append("# VDS_AUDIT_LANGGRAPH__POSTGRES_DSN=postgresql://user:password@host:5432/database")
|
|
57
|
+
lines.append("")
|
|
58
|
+
return "\n".join(lines)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def ensure_shared_env(
|
|
62
|
+
path: Path | None = None,
|
|
63
|
+
*,
|
|
64
|
+
defaults: tuple[tuple[str, str], ...] = DEFAULT_AUDIT_ENV_DEFAULTS,
|
|
65
|
+
) -> Path:
|
|
66
|
+
"""Ensure shared env file exists and contains required default keys.
|
|
67
|
+
|
|
68
|
+
Existing values are never overwritten.
|
|
69
|
+
"""
|
|
70
|
+
env_path = path or get_shared_env_path()
|
|
71
|
+
env_path.parent.mkdir(parents=True, exist_ok=True)
|
|
72
|
+
|
|
73
|
+
if not env_path.exists():
|
|
74
|
+
env_path.write_text(_render_default_env_content(defaults), encoding="utf-8")
|
|
75
|
+
return env_path
|
|
76
|
+
|
|
77
|
+
existing = _parse_env_file(env_path)
|
|
78
|
+
missing = [(key, value) for key, value in defaults if key not in existing]
|
|
79
|
+
if not missing:
|
|
80
|
+
return env_path
|
|
81
|
+
|
|
82
|
+
with env_path.open("a", encoding="utf-8") as handle:
|
|
83
|
+
handle.write("\n# Added missing VDS defaults\n")
|
|
84
|
+
for key, value in missing:
|
|
85
|
+
handle.write(f"{key}={value}\n")
|
|
86
|
+
return env_path
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def load_shared_env(
|
|
90
|
+
path: Path | None = None,
|
|
91
|
+
override: bool = False,
|
|
92
|
+
*,
|
|
93
|
+
ensure_defaults: bool = True,
|
|
94
|
+
extra_paths: tuple[Path, ...] | None = None,
|
|
95
|
+
) -> dict[str, str]:
|
|
96
|
+
"""Load VDS env files into os.environ."""
|
|
97
|
+
primary_path = path or get_shared_env_path()
|
|
98
|
+
if ensure_defaults:
|
|
99
|
+
ensure_shared_env(primary_path)
|
|
100
|
+
|
|
101
|
+
env_paths = (path,) if path is not None else get_default_env_paths()
|
|
102
|
+
if extra_paths:
|
|
103
|
+
env_paths = tuple(env_paths) + tuple(extra_paths)
|
|
104
|
+
merged: dict[str, str] = {}
|
|
105
|
+
for env_path in env_paths:
|
|
106
|
+
for key, value in _parse_env_file(env_path).items():
|
|
107
|
+
merged.setdefault(key, value)
|
|
108
|
+
for key, value in merged.items():
|
|
109
|
+
if override or key not in os.environ:
|
|
110
|
+
os.environ[key] = value
|
|
111
|
+
return merged
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
__all__ = [
|
|
115
|
+
"DEFAULT_AUDIT_ENV_DEFAULTS",
|
|
116
|
+
"DEFAULT_ENV_PATHS",
|
|
117
|
+
"ensure_shared_env",
|
|
118
|
+
"load_shared_env",
|
|
119
|
+
]
|
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
"""Error handling for VDS CLIs.
|
|
2
|
+
|
|
3
|
+
This module provides:
|
|
4
|
+
- ExitCodes: Standard exit codes for all VDS CLIs
|
|
5
|
+
- ErrorHandler: Unified error handling with suggestions and hints
|
|
6
|
+
|
|
7
|
+
Usage:
|
|
8
|
+
from vds_cli_common import ErrorHandler, ExitCodes
|
|
9
|
+
|
|
10
|
+
handler = ErrorHandler(output_manager, valid_commands=["search", "count"])
|
|
11
|
+
|
|
12
|
+
try:
|
|
13
|
+
result = operation()
|
|
14
|
+
except PermissionError:
|
|
15
|
+
handler.handle_permission_error("Access denied", required_role="admin")
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
from __future__ import annotations
|
|
19
|
+
|
|
20
|
+
import difflib
|
|
21
|
+
from enum import IntEnum
|
|
22
|
+
from typing import TYPE_CHECKING, NoReturn
|
|
23
|
+
|
|
24
|
+
import typer
|
|
25
|
+
|
|
26
|
+
from vds_cli_common.paths import get_shared_env_path
|
|
27
|
+
|
|
28
|
+
if TYPE_CHECKING:
|
|
29
|
+
from .output import OutputManager
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class ExitCodes(IntEnum):
|
|
33
|
+
"""Standard exit codes for all VDS CLIs.
|
|
34
|
+
|
|
35
|
+
These codes provide consistent exit status across all CLIs,
|
|
36
|
+
making it easier to handle errors in scripts and automation.
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
SUCCESS = 0
|
|
40
|
+
"""Operation completed successfully."""
|
|
41
|
+
|
|
42
|
+
GENERAL_ERROR = 1
|
|
43
|
+
"""Unspecified error occurred."""
|
|
44
|
+
|
|
45
|
+
USAGE_ERROR = 2
|
|
46
|
+
"""Invalid arguments or bad command."""
|
|
47
|
+
|
|
48
|
+
CONFIG_ERROR = 3
|
|
49
|
+
"""Missing environment variables or bad configuration."""
|
|
50
|
+
|
|
51
|
+
AUTH_ERROR = 4
|
|
52
|
+
"""Invalid credentials or expired token."""
|
|
53
|
+
|
|
54
|
+
PERMISSION_ERROR = 5
|
|
55
|
+
"""403 Forbidden - insufficient rights."""
|
|
56
|
+
|
|
57
|
+
NOT_FOUND_ERROR = 6
|
|
58
|
+
"""404 Not Found - resource doesn't exist."""
|
|
59
|
+
|
|
60
|
+
NETWORK_ERROR = 7
|
|
61
|
+
"""Connection failed or timeout."""
|
|
62
|
+
|
|
63
|
+
VALIDATION_ERROR = 8
|
|
64
|
+
"""Invalid input data."""
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
class ErrorHandler:
|
|
68
|
+
"""Unified error handling for VDS CLIs.
|
|
69
|
+
|
|
70
|
+
Provides:
|
|
71
|
+
- Consistent error formatting
|
|
72
|
+
- Typo suggestions for commands
|
|
73
|
+
- Actionable hints for common errors
|
|
74
|
+
- Proper exit codes
|
|
75
|
+
|
|
76
|
+
Args:
|
|
77
|
+
output: OutputManager instance for error output
|
|
78
|
+
valid_commands: List of valid commands for typo suggestions
|
|
79
|
+
"""
|
|
80
|
+
|
|
81
|
+
def __init__(
|
|
82
|
+
self,
|
|
83
|
+
output: OutputManager,
|
|
84
|
+
valid_commands: list[str] | None = None,
|
|
85
|
+
) -> None:
|
|
86
|
+
"""Initialize ErrorHandler.
|
|
87
|
+
|
|
88
|
+
Args:
|
|
89
|
+
output: OutputManager for error output
|
|
90
|
+
valid_commands: Optional list of valid commands for suggestions
|
|
91
|
+
"""
|
|
92
|
+
self.output = output
|
|
93
|
+
self.valid_commands = valid_commands or []
|
|
94
|
+
|
|
95
|
+
def suggest_command(self, typo: str, cutoff: float = 0.6) -> str | None:
|
|
96
|
+
"""Suggest a valid command based on fuzzy matching.
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
typo: The mistyped command
|
|
100
|
+
cutoff: Minimum similarity ratio (0.0 to 1.0)
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Best matching command or None if no match found
|
|
104
|
+
"""
|
|
105
|
+
matches = difflib.get_close_matches(
|
|
106
|
+
typo,
|
|
107
|
+
self.valid_commands,
|
|
108
|
+
n=1,
|
|
109
|
+
cutoff=cutoff,
|
|
110
|
+
)
|
|
111
|
+
return matches[0] if matches else None
|
|
112
|
+
|
|
113
|
+
def handle_unknown_command(self, command: str) -> NoReturn:
|
|
114
|
+
"""Handle unknown command with suggestion.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
command: The unknown command
|
|
118
|
+
|
|
119
|
+
Raises:
|
|
120
|
+
typer.Exit: Always exits with USAGE_ERROR
|
|
121
|
+
"""
|
|
122
|
+
suggestion = self.suggest_command(command)
|
|
123
|
+
|
|
124
|
+
hint = None
|
|
125
|
+
if suggestion:
|
|
126
|
+
hint = f"Did you mean: [cyan]{suggestion}[/cyan]?"
|
|
127
|
+
elif self.valid_commands:
|
|
128
|
+
available = ", ".join(self.valid_commands[:5])
|
|
129
|
+
hint = f"Available commands: {available}"
|
|
130
|
+
|
|
131
|
+
self.output.output_error(
|
|
132
|
+
f"Unknown command: '{command}'",
|
|
133
|
+
hint=hint,
|
|
134
|
+
)
|
|
135
|
+
raise typer.Exit(ExitCodes.USAGE_ERROR)
|
|
136
|
+
|
|
137
|
+
def handle_config_error(
|
|
138
|
+
self,
|
|
139
|
+
message: str,
|
|
140
|
+
*,
|
|
141
|
+
missing_vars: list[str] | None = None,
|
|
142
|
+
config_path: str | None = None,
|
|
143
|
+
) -> NoReturn:
|
|
144
|
+
"""Handle configuration error with guidance.
|
|
145
|
+
|
|
146
|
+
Args:
|
|
147
|
+
message: Error message
|
|
148
|
+
missing_vars: List of missing environment variable names
|
|
149
|
+
config_path: Path to configuration file
|
|
150
|
+
|
|
151
|
+
Raises:
|
|
152
|
+
typer.Exit: Always exits with CONFIG_ERROR
|
|
153
|
+
"""
|
|
154
|
+
resolved_config_path = config_path or str(get_shared_env_path())
|
|
155
|
+
details: dict[str, str] = {"config_file": resolved_config_path}
|
|
156
|
+
if missing_vars:
|
|
157
|
+
details["missing_variables"] = ", ".join(missing_vars)
|
|
158
|
+
|
|
159
|
+
self.output.output_error(
|
|
160
|
+
message,
|
|
161
|
+
hint=f"Check your configuration at {resolved_config_path}",
|
|
162
|
+
details=details,
|
|
163
|
+
)
|
|
164
|
+
raise typer.Exit(ExitCodes.CONFIG_ERROR)
|
|
165
|
+
|
|
166
|
+
def handle_auth_error(
|
|
167
|
+
self,
|
|
168
|
+
message: str,
|
|
169
|
+
*,
|
|
170
|
+
service: str = "API",
|
|
171
|
+
) -> NoReturn:
|
|
172
|
+
"""Handle authentication error.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
message: Error message
|
|
176
|
+
service: Name of the service (for hint)
|
|
177
|
+
|
|
178
|
+
Raises:
|
|
179
|
+
typer.Exit: Always exits with AUTH_ERROR
|
|
180
|
+
"""
|
|
181
|
+
self.output.output_error(
|
|
182
|
+
message,
|
|
183
|
+
hint=f"Verify your {service} credentials in {get_shared_env_path()}",
|
|
184
|
+
details={"service": service},
|
|
185
|
+
)
|
|
186
|
+
raise typer.Exit(ExitCodes.AUTH_ERROR)
|
|
187
|
+
|
|
188
|
+
def handle_permission_error(
|
|
189
|
+
self,
|
|
190
|
+
message: str,
|
|
191
|
+
*,
|
|
192
|
+
required_role: str | None = None,
|
|
193
|
+
current_role: str | None = None,
|
|
194
|
+
) -> NoReturn:
|
|
195
|
+
"""Handle permission error with role information.
|
|
196
|
+
|
|
197
|
+
Args:
|
|
198
|
+
message: Error message
|
|
199
|
+
required_role: Role required for the operation
|
|
200
|
+
current_role: User's current role
|
|
201
|
+
|
|
202
|
+
Raises:
|
|
203
|
+
typer.Exit: Always exits with PERMISSION_ERROR
|
|
204
|
+
"""
|
|
205
|
+
details: dict[str, str] = {}
|
|
206
|
+
if required_role:
|
|
207
|
+
details["required_role"] = required_role
|
|
208
|
+
if current_role:
|
|
209
|
+
details["current_role"] = current_role
|
|
210
|
+
|
|
211
|
+
hint = "Request elevated access from your administrator"
|
|
212
|
+
if required_role:
|
|
213
|
+
hint = f"Required role: {required_role}. Contact admin for access."
|
|
214
|
+
|
|
215
|
+
self.output.output_error(message, hint=hint, details=details)
|
|
216
|
+
raise typer.Exit(ExitCodes.PERMISSION_ERROR)
|
|
217
|
+
|
|
218
|
+
def handle_network_error(
|
|
219
|
+
self,
|
|
220
|
+
message: str,
|
|
221
|
+
*,
|
|
222
|
+
url: str | None = None,
|
|
223
|
+
) -> NoReturn:
|
|
224
|
+
"""Handle network/connection error.
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
message: Error message
|
|
228
|
+
url: URL that failed to connect
|
|
229
|
+
|
|
230
|
+
Raises:
|
|
231
|
+
typer.Exit: Always exits with NETWORK_ERROR
|
|
232
|
+
"""
|
|
233
|
+
hints = [
|
|
234
|
+
"Check your VPN connection",
|
|
235
|
+
"Verify the service URL is correct",
|
|
236
|
+
"Ensure network connectivity",
|
|
237
|
+
]
|
|
238
|
+
|
|
239
|
+
details: dict[str, str] = {}
|
|
240
|
+
if url:
|
|
241
|
+
details["url"] = url
|
|
242
|
+
|
|
243
|
+
self.output.output_error(
|
|
244
|
+
message,
|
|
245
|
+
hint=" | ".join(hints),
|
|
246
|
+
details=details,
|
|
247
|
+
)
|
|
248
|
+
raise typer.Exit(ExitCodes.NETWORK_ERROR)
|
|
249
|
+
|
|
250
|
+
def handle_not_found(
|
|
251
|
+
self,
|
|
252
|
+
resource_type: str,
|
|
253
|
+
resource_id: str,
|
|
254
|
+
) -> NoReturn:
|
|
255
|
+
"""Handle resource not found error.
|
|
256
|
+
|
|
257
|
+
Args:
|
|
258
|
+
resource_type: Type of resource (e.g., "Index", "Page")
|
|
259
|
+
resource_id: ID or name of the resource
|
|
260
|
+
|
|
261
|
+
Raises:
|
|
262
|
+
typer.Exit: Always exits with NOT_FOUND_ERROR
|
|
263
|
+
"""
|
|
264
|
+
self.output.output_error(
|
|
265
|
+
f"{resource_type} not found: '{resource_id}'",
|
|
266
|
+
hint=f"Verify the {resource_type.lower()} exists and you have access",
|
|
267
|
+
)
|
|
268
|
+
raise typer.Exit(ExitCodes.NOT_FOUND_ERROR)
|
|
269
|
+
|
|
270
|
+
def handle_validation_error(
|
|
271
|
+
self,
|
|
272
|
+
message: str,
|
|
273
|
+
*,
|
|
274
|
+
field: str | None = None,
|
|
275
|
+
expected: str | None = None,
|
|
276
|
+
) -> NoReturn:
|
|
277
|
+
"""Handle input validation error.
|
|
278
|
+
|
|
279
|
+
Args:
|
|
280
|
+
message: Error message
|
|
281
|
+
field: Field that failed validation
|
|
282
|
+
expected: Expected value or format
|
|
283
|
+
|
|
284
|
+
Raises:
|
|
285
|
+
typer.Exit: Always exits with VALIDATION_ERROR
|
|
286
|
+
"""
|
|
287
|
+
details: dict[str, str] = {}
|
|
288
|
+
if field:
|
|
289
|
+
details["field"] = field
|
|
290
|
+
if expected:
|
|
291
|
+
details["expected"] = expected
|
|
292
|
+
|
|
293
|
+
self.output.output_error(
|
|
294
|
+
message,
|
|
295
|
+
hint="Check your input and try again",
|
|
296
|
+
details=details,
|
|
297
|
+
)
|
|
298
|
+
raise typer.Exit(ExitCodes.VALIDATION_ERROR)
|
|
299
|
+
|
|
300
|
+
def handle_general_error(
|
|
301
|
+
self,
|
|
302
|
+
message: str,
|
|
303
|
+
*,
|
|
304
|
+
hint: str | None = None,
|
|
305
|
+
details: dict[str, str] | None = None,
|
|
306
|
+
) -> NoReturn:
|
|
307
|
+
"""Handle general error with optional hint and details.
|
|
308
|
+
|
|
309
|
+
Args:
|
|
310
|
+
message: Error message
|
|
311
|
+
hint: Optional hint for resolution
|
|
312
|
+
details: Optional additional details
|
|
313
|
+
|
|
314
|
+
Raises:
|
|
315
|
+
typer.Exit: Always exits with GENERAL_ERROR
|
|
316
|
+
"""
|
|
317
|
+
self.output.output_error(message, hint=hint, details=details)
|
|
318
|
+
raise typer.Exit(ExitCodes.GENERAL_ERROR)
|