cycode 3.22.2.dev2__tar.gz → 3.22.2.dev3__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.
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/PKG-INFO +1 -1
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/__init__.py +1 -1
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/__init__.py +16 -0
- cycode-3.22.2.dev3/cycode/cli/apps/ai_guardrails/ides/_skill_utils.py +103 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/base.py +14 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/claude_code.py +22 -2
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/codex.py +15 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/copilot.py +15 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/cursor.py +9 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/session_start_command.py +12 -3
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/ai_security_manager_client.py +2 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/pyproject.toml +1 -1
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/LICENCE +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/README.md +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/__main__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/app.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/activation_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/detach.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/handlers.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/api/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/api/api_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/api/openapi_spec.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/auth/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/auth/auth_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/auth/auth_common.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/auth/auth_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/auth/models.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/configure/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/configure/configure_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/configure/consts.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/configure/messages.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/configure/prompts.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ignore/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ignore/ignore_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/mcp/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/mcp/mcp_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/report_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/common.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/path/path_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/report_import_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/sca_options.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/aggregation_report.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/code_scanner.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/detection_excluder.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/path/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/path/path_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/repository/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_parameters.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/scan_result.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/status/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/status/get_cli_status.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/status/models.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/status/status_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/status/version_command.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/cli_types.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/config.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/console.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/consts.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/custom_exceptions.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/handle_errors.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/commit_range_documents.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/file_excluder.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/iac/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/models/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/path_documents.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/repository_documents.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/restore_bun_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/php/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/python/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/python/restore_pip_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/python/restore_uv_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/sca/sca_file_collector.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/walk_ignore.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/files_collector/zip_documents.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/logger.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/main.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/models.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/console_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/json_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/printer_base.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/rich_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/table.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/table_models.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/table_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/tables/table_printer_base.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/text_printer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/detection_data.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/rich_helpers.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/sca_ossf.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/printers/utils/sca_policy_details.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/base_file_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/config_file_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/configuration_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/credentials_manager.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/user_settings/jwt_creator.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/binary_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/enum_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/get_api_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/git_proxy.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/host_info.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/ignore_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/jwt_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/path_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/progress_bar.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/scan_batch.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/scan_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/shell_executor.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/string_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/task_timer.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/trust_store.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/url_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/version_checker.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/utils/yaml_utils.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/config.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/__init__.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/auth_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/base_token_auth_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cli_activation_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/client_creator.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/config.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/config_dev.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cycode_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cycode_client_base.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cycode_dev_based_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/cycode_token_based_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/headers.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/import_sbom_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/logger.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/models.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/report_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/scan_client.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cyclient/scan_config_base.py +0 -0
- {cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/logger.py +0 -0
|
@@ -5,4 +5,4 @@ import time as _time
|
|
|
5
5
|
# end-to-end scan duration from the moment the user actually triggered it.
|
|
6
6
|
_BOOT_WALL: float = _time.time()
|
|
7
7
|
|
|
8
|
-
__version__ = '3.22.2.
|
|
8
|
+
__version__ = '3.22.2.dev3' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
|
|
@@ -54,6 +54,22 @@ def collect_all_session_contexts() -> tuple[dict[str, dict], dict]:
|
|
|
54
54
|
return config_files_by_ide, plugins
|
|
55
55
|
|
|
56
56
|
|
|
57
|
+
def collect_all_skills() -> list[dict]:
|
|
58
|
+
"""Sweep every registered IDE's user-scope skills, regardless of which IDE triggered the hook.
|
|
59
|
+
|
|
60
|
+
Returns ``[{"path", "content"}]`` deduplicated by path and sorted, so two IDEs sharing a skills
|
|
61
|
+
directory report it once and the session-context digest stays stable across registry order.
|
|
62
|
+
Skills a plugin ships are not here - those ride on their plugin entry, which carries the
|
|
63
|
+
marketplace provenance.
|
|
64
|
+
"""
|
|
65
|
+
skills_by_path: dict[str, dict] = {}
|
|
66
|
+
for ide in IDES.values():
|
|
67
|
+
for skill in ide.get_skills():
|
|
68
|
+
skills_by_path.setdefault(skill['path'], skill)
|
|
69
|
+
|
|
70
|
+
return [skills_by_path[path] for path in sorted(skills_by_path)]
|
|
71
|
+
|
|
72
|
+
|
|
57
73
|
def resolve_ides(name: str) -> list[IDE]:
|
|
58
74
|
"""Resolve an ``--ide`` argument to one or all IDE instances.
|
|
59
75
|
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""Shared skill-collection helpers for IDE integrations.
|
|
2
|
+
|
|
3
|
+
A skill is a directory holding a ``SKILL.md``: ``<skills root>/<skill name>/SKILL.md``.
|
|
4
|
+
The same layout is used for user-scope skills (``~/.claude/skills/``) and for the skills a
|
|
5
|
+
plugin ships (``<plugin dir>/skills/``), so one walker serves both.
|
|
6
|
+
|
|
7
|
+
Unlike an MCP config - a small JSON file at a known path - a ``SKILL.md`` body is unbounded
|
|
8
|
+
prose, and the number of installed skills is unbounded too. Both are capped here rather than
|
|
9
|
+
downstream: the whole session-context report is one request, so an oversized skill would cost
|
|
10
|
+
the device its MCP inventory as well.
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from pathlib import Path
|
|
14
|
+
from typing import Optional
|
|
15
|
+
|
|
16
|
+
from cycode.logger import get_logger
|
|
17
|
+
|
|
18
|
+
logger = get_logger('AI Guardrails Skills')
|
|
19
|
+
|
|
20
|
+
SKILL_FILE_NAME = 'SKILL.md'
|
|
21
|
+
|
|
22
|
+
# Where a plugin keeps its skills, relative to the plugin directory. A property of the plugin format
|
|
23
|
+
# rather than of any one IDE, so Claude Code, Codex and Copilot plugins all use it.
|
|
24
|
+
PLUGIN_SKILLS_SUBDIR = 'skills'
|
|
25
|
+
|
|
26
|
+
# A skill is instructions, not data. Anything larger is not a skill we can usefully inventory,
|
|
27
|
+
# and sending it would push the one-request report toward the API's body limit.
|
|
28
|
+
MAX_SKILL_FILE_BYTES = 256 * 1024
|
|
29
|
+
|
|
30
|
+
# Per skills root, not per device: a developer with more installed skills than this in one place
|
|
31
|
+
# is an outlier we would rather truncate than let define the payload size.
|
|
32
|
+
MAX_SKILLS_PER_ROOT = 200
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _read_skill_file(skill_file: Path) -> Optional[dict]:
|
|
36
|
+
"""Read one ``SKILL.md`` into the session-context file shape, or None if unusable."""
|
|
37
|
+
try:
|
|
38
|
+
size = skill_file.stat().st_size
|
|
39
|
+
except OSError as e:
|
|
40
|
+
logger.debug('Failed to stat skill file, %s', {'path': str(skill_file)}, exc_info=e)
|
|
41
|
+
return None
|
|
42
|
+
|
|
43
|
+
if size > MAX_SKILL_FILE_BYTES:
|
|
44
|
+
logger.debug(
|
|
45
|
+
'Skill file exceeds the size cap; skipping, %s',
|
|
46
|
+
{'path': str(skill_file), 'size': size, 'cap': MAX_SKILL_FILE_BYTES},
|
|
47
|
+
)
|
|
48
|
+
return None
|
|
49
|
+
|
|
50
|
+
try:
|
|
51
|
+
content = skill_file.read_text(encoding='utf-8')
|
|
52
|
+
except Exception as e:
|
|
53
|
+
logger.debug('Failed to read skill file, %s', {'path': str(skill_file)}, exc_info=e)
|
|
54
|
+
return None
|
|
55
|
+
|
|
56
|
+
if not content.strip():
|
|
57
|
+
return None
|
|
58
|
+
|
|
59
|
+
return {'path': str(skill_file), 'content': content}
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def walk_skill_dirs(skills_root: Path) -> list[dict]:
|
|
63
|
+
"""Collect every ``<skills_root>/<name>/SKILL.md`` as ``{"path", "content"}``.
|
|
64
|
+
|
|
65
|
+
Exactly one directory level is scanned. A skill directory may hold nested references and
|
|
66
|
+
scripts, but its ``SKILL.md`` always sits at the top of it, so there is nothing to recurse
|
|
67
|
+
into - which is also what keeps this bounded without a depth cap.
|
|
68
|
+
|
|
69
|
+
Results are sorted by path: the session-context report is deduplicated by hashing the whole
|
|
70
|
+
payload, so an unstable order would re-send an unchanged inventory.
|
|
71
|
+
"""
|
|
72
|
+
if not skills_root.is_dir():
|
|
73
|
+
return []
|
|
74
|
+
|
|
75
|
+
try:
|
|
76
|
+
skill_dirs = sorted(d for d in skills_root.iterdir() if d.is_dir())
|
|
77
|
+
except OSError as e:
|
|
78
|
+
logger.debug('Failed to list skills root, %s', {'path': str(skills_root)}, exc_info=e)
|
|
79
|
+
return []
|
|
80
|
+
|
|
81
|
+
skills: list[dict] = []
|
|
82
|
+
for skill_dir in skill_dirs:
|
|
83
|
+
if len(skills) >= MAX_SKILLS_PER_ROOT:
|
|
84
|
+
logger.debug(
|
|
85
|
+
'Skills root exceeds the count cap; truncating, %s',
|
|
86
|
+
{'path': str(skills_root), 'cap': MAX_SKILLS_PER_ROOT},
|
|
87
|
+
)
|
|
88
|
+
break
|
|
89
|
+
|
|
90
|
+
skill = _read_skill_file(skill_dir / SKILL_FILE_NAME)
|
|
91
|
+
if skill:
|
|
92
|
+
skills.append(skill)
|
|
93
|
+
|
|
94
|
+
return skills
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def walk_plugin_skills(plugin_dir: Path) -> list[dict]:
|
|
98
|
+
"""Collect the skills a plugin ships, from ``<plugin_dir>/skills/<name>/SKILL.md``.
|
|
99
|
+
|
|
100
|
+
Shared by every IDE with a plugin system: the layout belongs to the plugin format, so a plugin
|
|
101
|
+
shipping skills is inventoried whichever IDE loaded it.
|
|
102
|
+
"""
|
|
103
|
+
return walk_skill_dirs(plugin_dir / PLUGIN_SKILLS_SUBDIR)
|
|
@@ -189,3 +189,17 @@ class IDE(ABC):
|
|
|
189
189
|
Override to surface MCP/plugin inventory.
|
|
190
190
|
"""
|
|
191
191
|
return None, {}
|
|
192
|
+
|
|
193
|
+
def get_skills(self) -> list[dict]:
|
|
194
|
+
"""Return the IDE's user-scope skills as ``[{"path", "content"}]``.
|
|
195
|
+
|
|
196
|
+
A skill is a ``SKILL.md`` under a per-skill directory. Raw content is returned rather
|
|
197
|
+
than parsed frontmatter: the backend owns parsing, because the device connectors that
|
|
198
|
+
read these files off endpoints can only ever return raw content.
|
|
199
|
+
|
|
200
|
+
Kept separate from ``get_session_context`` rather than folded into its
|
|
201
|
+
``global_config_file`` slot, which is normalized to an MCP server map.
|
|
202
|
+
|
|
203
|
+
Default: ``[]`` (the IDE has no skill system). Override to surface skills.
|
|
204
|
+
"""
|
|
205
|
+
return []
|
|
@@ -13,6 +13,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
|
|
|
13
13
|
resolve_cached_plugin_dir,
|
|
14
14
|
walk_enabled_plugins,
|
|
15
15
|
)
|
|
16
|
+
from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
|
|
16
17
|
from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
|
|
17
18
|
from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
|
|
18
19
|
from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
|
|
@@ -169,6 +170,15 @@ def load_claude_settings(settings_path: Optional[Path] = None) -> Optional[dict]
|
|
|
169
170
|
return None
|
|
170
171
|
|
|
171
172
|
|
|
173
|
+
def _claude_skills_dir() -> Path:
|
|
174
|
+
"""Claude Code's user-scope skills: ``~/.claude/skills/<name>/SKILL.md``.
|
|
175
|
+
|
|
176
|
+
A function, not a module constant: resolving ``Path.home()`` at import time pins the directory to
|
|
177
|
+
whatever home the process started with, which a test filesystem then cannot redirect.
|
|
178
|
+
"""
|
|
179
|
+
return Path.home() / '.claude' / 'skills'
|
|
180
|
+
|
|
181
|
+
|
|
172
182
|
def _plugins_cache_dir() -> Path:
|
|
173
183
|
"""Claude Code's local plugin content cache: ``~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/``."""
|
|
174
184
|
return Path.home() / '.claude' / 'plugins' / 'cache'
|
|
@@ -187,10 +197,11 @@ def _resolve_marketplace_path(marketplace: dict) -> Optional[Path]:
|
|
|
187
197
|
|
|
188
198
|
|
|
189
199
|
def _read_claude_plugin(plugin_dir: Path) -> tuple[dict, dict]:
|
|
190
|
-
"""Read one Claude Code plugin's manifest
|
|
200
|
+
"""Read one Claude Code plugin's manifest, MCP servers and skills.
|
|
191
201
|
|
|
192
202
|
Claude hardcodes the MCP file at ``<plugin_dir>/.mcp.json`` and always
|
|
193
|
-
wraps it as ``{"mcpServers": {...}}
|
|
203
|
+
wraps it as ``{"mcpServers": {...}}``, and a plugin's skills at
|
|
204
|
+
``<plugin_dir>/skills/<name>/SKILL.md``.
|
|
194
205
|
"""
|
|
195
206
|
manifest = load_plugin_json(plugin_dir / '.claude-plugin' / 'plugin.json') or {}
|
|
196
207
|
entry: dict = {}
|
|
@@ -198,6 +209,12 @@ def _read_claude_plugin(plugin_dir: Path) -> tuple[dict, dict]:
|
|
|
198
209
|
if field in manifest:
|
|
199
210
|
entry[field] = manifest[field]
|
|
200
211
|
|
|
212
|
+
# Attached to the plugin entry rather than the top-level skills list so the backend keeps the
|
|
213
|
+
# plugin provenance (marketplace, plugin, version) that a marketplace-installed skill has.
|
|
214
|
+
skill_files = walk_plugin_skills(plugin_dir)
|
|
215
|
+
if skill_files:
|
|
216
|
+
entry['skill_files'] = skill_files
|
|
217
|
+
|
|
201
218
|
mcp_config_path = plugin_dir / '.mcp.json'
|
|
202
219
|
mcp_config = load_plugin_json(mcp_config_path) or {}
|
|
203
220
|
servers: dict = mcp_config.get('mcpServers') or {}
|
|
@@ -387,3 +404,6 @@ class ClaudeCode(IDE):
|
|
|
387
404
|
enriched_plugins = resolve_plugins(settings) if settings else {}
|
|
388
405
|
|
|
389
406
|
return global_config_file, enriched_plugins
|
|
407
|
+
|
|
408
|
+
def get_skills(self) -> list[dict]:
|
|
409
|
+
return walk_skill_dirs(_claude_skills_dir())
|
|
@@ -20,6 +20,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
|
|
|
20
20
|
resolve_cached_plugin_dir,
|
|
21
21
|
walk_enabled_plugins,
|
|
22
22
|
)
|
|
23
|
+
from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
|
|
23
24
|
from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
|
|
24
25
|
from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
|
|
25
26
|
from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
|
|
@@ -53,6 +54,11 @@ def _codex_home() -> Path:
|
|
|
53
54
|
return Path.home() / _CONFIG_DIR_NAME
|
|
54
55
|
|
|
55
56
|
|
|
57
|
+
def _codex_skills_dir() -> Path:
|
|
58
|
+
"""User-scope Codex skills directory (honors ``$CODEX_HOME``)."""
|
|
59
|
+
return _codex_home() / 'skills'
|
|
60
|
+
|
|
61
|
+
|
|
56
62
|
def _codex_config_toml_path(scope: str, repo_path: Optional[Path] = None) -> Path:
|
|
57
63
|
"""Return the Codex ``config.toml`` path for the given scope."""
|
|
58
64
|
if scope == 'repo' and repo_path:
|
|
@@ -121,6 +127,12 @@ def _read_codex_plugin(plugin_dir: Path) -> tuple[dict, dict]:
|
|
|
121
127
|
if field in manifest:
|
|
122
128
|
entry[field] = manifest[field]
|
|
123
129
|
|
|
130
|
+
# Same plugin-format layout as every other IDE's plugins, so a plugin shipping skills is
|
|
131
|
+
# inventoried whichever IDE loaded it.
|
|
132
|
+
skill_files = walk_plugin_skills(plugin_dir)
|
|
133
|
+
if skill_files:
|
|
134
|
+
entry['skill_files'] = skill_files
|
|
135
|
+
|
|
124
136
|
mcp_ref = manifest.get('mcpServers')
|
|
125
137
|
if not mcp_ref:
|
|
126
138
|
return entry, {}
|
|
@@ -304,3 +316,6 @@ class Codex(IDE):
|
|
|
304
316
|
global_config_file = build_global_config_file(config_path, config.get('mcp_servers'))
|
|
305
317
|
enriched_plugins = _resolve_codex_plugins(config)
|
|
306
318
|
return global_config_file, enriched_plugins
|
|
319
|
+
|
|
320
|
+
def get_skills(self) -> list[dict]:
|
|
321
|
+
return walk_skill_dirs(_codex_skills_dir())
|
|
@@ -37,6 +37,7 @@ from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
|
|
|
37
37
|
load_plugin_json,
|
|
38
38
|
walk_enabled_plugins,
|
|
39
39
|
)
|
|
40
|
+
from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_plugin_skills, walk_skill_dirs
|
|
40
41
|
from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
|
|
41
42
|
from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
|
|
42
43
|
from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
|
|
@@ -105,6 +106,11 @@ def _copilot_home() -> Path:
|
|
|
105
106
|
return Path.home() / '.copilot'
|
|
106
107
|
|
|
107
108
|
|
|
109
|
+
def _copilot_skills_dir() -> Path:
|
|
110
|
+
"""User-scope Copilot skills directory (honors ``$COPILOT_HOME``)."""
|
|
111
|
+
return _copilot_home() / 'skills'
|
|
112
|
+
|
|
113
|
+
|
|
108
114
|
def _vscode_agent_plugins_dir() -> Path:
|
|
109
115
|
# Resolved at call time (not a module-level Path constant): on py<=3.10 a Path
|
|
110
116
|
# instance binds its filesystem accessor at creation, which breaks fake-fs tests
|
|
@@ -178,6 +184,12 @@ def _read_copilot_plugin(plugin_dir: Path) -> tuple[dict, dict]:
|
|
|
178
184
|
if field in manifest:
|
|
179
185
|
entry[field] = manifest[field]
|
|
180
186
|
|
|
187
|
+
# Same plugin-format layout as every other IDE's plugins, so a plugin shipping skills is
|
|
188
|
+
# inventoried whichever IDE loaded it.
|
|
189
|
+
skill_files = walk_plugin_skills(plugin_dir)
|
|
190
|
+
if skill_files:
|
|
191
|
+
entry['skill_files'] = skill_files
|
|
192
|
+
|
|
181
193
|
mcp_ref = manifest.get('mcpServers')
|
|
182
194
|
mcp_config_path = plugin_dir / mcp_ref if isinstance(mcp_ref, str) else plugin_dir / '.mcp.json'
|
|
183
195
|
mcp_doc = load_plugin_json(mcp_config_path) or {}
|
|
@@ -481,3 +493,6 @@ class Copilot(IDE):
|
|
|
481
493
|
build_global_config_file(_vscode_mcp_config_path(), config.get('servers')) if config else None
|
|
482
494
|
)
|
|
483
495
|
return global_config_file, _collect_installed_plugins()
|
|
496
|
+
|
|
497
|
+
def get_skills(self) -> list[dict]:
|
|
498
|
+
return walk_skill_dirs(_copilot_skills_dir())
|
|
@@ -7,6 +7,7 @@ from typing import ClassVar, Optional
|
|
|
7
7
|
|
|
8
8
|
from cycode.cli.apps.ai_guardrails.consts import CYCODE_SCAN_PROMPT_COMMAND, CYCODE_SESSION_START_COMMAND
|
|
9
9
|
from cycode.cli.apps.ai_guardrails.ides._plugin_utils import build_global_config_file
|
|
10
|
+
from cycode.cli.apps.ai_guardrails.ides._skill_utils import walk_skill_dirs
|
|
10
11
|
from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
|
|
11
12
|
from cycode.cli.apps.ai_guardrails.scan.payload import AIHookPayload
|
|
12
13
|
from cycode.cli.apps.ai_guardrails.scan.types import AiHookEventType
|
|
@@ -45,6 +46,11 @@ def _cursor_mcp_config_path() -> Path:
|
|
|
45
46
|
return Path.home() / '.cursor' / _MCP_CONFIG_FILENAME
|
|
46
47
|
|
|
47
48
|
|
|
49
|
+
def _cursor_skills_dir() -> Path:
|
|
50
|
+
"""User-scope Cursor skills directory (``~/.cursor/skills``, all platforms)."""
|
|
51
|
+
return Path.home() / '.cursor' / 'skills'
|
|
52
|
+
|
|
53
|
+
|
|
48
54
|
def _load_cursor_mcp_config(config_path: Optional[Path] = None) -> Optional[dict]:
|
|
49
55
|
"""Load and parse `~/.cursor/mcp.json`. Returns None if missing/invalid."""
|
|
50
56
|
path = config_path or _cursor_mcp_config_path()
|
|
@@ -125,3 +131,6 @@ class Cursor(IDE):
|
|
|
125
131
|
config_path = _cursor_mcp_config_path()
|
|
126
132
|
global_config_file = build_global_config_file(config_path, config.get('mcpServers'))
|
|
127
133
|
return global_config_file, {}
|
|
134
|
+
|
|
135
|
+
def get_skills(self) -> list[dict]:
|
|
136
|
+
return walk_skill_dirs(_cursor_skills_dir())
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/session_start_command.py
RENAMED
|
@@ -9,7 +9,12 @@ from typing import TYPE_CHECKING, Annotated, Optional
|
|
|
9
9
|
|
|
10
10
|
import typer
|
|
11
11
|
|
|
12
|
-
from cycode.cli.apps.ai_guardrails.ides import
|
|
12
|
+
from cycode.cli.apps.ai_guardrails.ides import (
|
|
13
|
+
DEFAULT_IDE_NAME,
|
|
14
|
+
collect_all_session_contexts,
|
|
15
|
+
collect_all_skills,
|
|
16
|
+
get_ide,
|
|
17
|
+
)
|
|
13
18
|
from cycode.cli.apps.ai_guardrails.scan.utils import read_stdin_text, safe_json_parse
|
|
14
19
|
from cycode.cli.apps.auth.auth_common import get_authorization_info
|
|
15
20
|
from cycode.cli.apps.auth.auth_manager import AuthManager
|
|
@@ -75,8 +80,9 @@ def _report_session_context(
|
|
|
75
80
|
) -> None:
|
|
76
81
|
"""Report the device + cross-IDE session context to the AI security manager. Never raises.
|
|
77
82
|
|
|
78
|
-
The device context is always reported. MCP configs are collected from every
|
|
79
|
-
not just the triggering one. Unchanged payloads are skipped via a hash cache
|
|
83
|
+
The device context is always reported. MCP configs and skills are collected from every
|
|
84
|
+
registered IDE, not just the triggering one. Unchanged payloads are skipped via a hash cache
|
|
85
|
+
until the TTL expires.
|
|
80
86
|
"""
|
|
81
87
|
try:
|
|
82
88
|
config_files_by_ide, enabled_plugins = collect_all_session_contexts()
|
|
@@ -89,6 +95,9 @@ def _report_session_context(
|
|
|
89
95
|
# Sorted by path so the digest is stable regardless of IDE registry order.
|
|
90
96
|
'config_files': sorted(config_files_by_ide.values(), key=lambda f: f['path']),
|
|
91
97
|
'enabled_plugins': enabled_plugins,
|
|
98
|
+
# Already deduplicated and sorted by path, for the same digest-stability reason.
|
|
99
|
+
# Editing a skill body changes the digest and so re-reports the device's inventory.
|
|
100
|
+
'skill_files': collect_all_skills(),
|
|
92
101
|
'user_email': user_email,
|
|
93
102
|
}
|
|
94
103
|
|
|
@@ -101,6 +101,7 @@ class AISecurityManagerClient:
|
|
|
101
101
|
last_login_user: Optional[str] = None,
|
|
102
102
|
config_files: Optional[list[dict]] = None,
|
|
103
103
|
enabled_plugins: Optional[dict] = None,
|
|
104
|
+
skill_files: Optional[list[dict]] = None,
|
|
104
105
|
user_email: Optional[str] = None,
|
|
105
106
|
) -> bool:
|
|
106
107
|
"""Report session context to the backend. Returns whether the report was accepted."""
|
|
@@ -113,6 +114,7 @@ class AISecurityManagerClient:
|
|
|
113
114
|
'user_email': user_email,
|
|
114
115
|
'config_files': config_files,
|
|
115
116
|
'enabled_plugins': enabled_plugins,
|
|
117
|
+
'skill_files': skill_files,
|
|
116
118
|
}
|
|
117
119
|
|
|
118
120
|
try:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/scan/scan_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_guardrails/uninstall_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/ai_remediation_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/ai_remediation/print_remediation.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report/sbom/repository_url/__init__.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/report_import_command.py
RENAMED
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/report_import/sbom/sbom_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cycode-3.22.2.dev2 → cycode-3.22.2.dev3}/cycode/cli/apps/scan/repository/repository_command.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|