cycode 3.17.1.dev10__tar.gz → 3.17.2__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.
Files changed (216) hide show
  1. {cycode-3.17.1.dev10 → cycode-3.17.2}/PKG-INFO +1 -1
  2. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/__init__.py +1 -1
  3. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/__init__.py +19 -0
  4. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/_plugin_utils.py +16 -0
  5. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/claude_code.py +18 -8
  6. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/codex.py +4 -13
  7. cycode-3.17.2/cycode/cli/apps/ai_guardrails/session_start_command.py +160 -0
  8. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/maven/restore_gradle_dependencies.py +18 -4
  9. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/ai_security_manager_client.py +6 -4
  10. {cycode-3.17.1.dev10 → cycode-3.17.2}/pyproject.toml +1 -1
  11. cycode-3.17.1.dev10/cycode/cli/apps/ai_guardrails/session_start_command.py +0 -103
  12. {cycode-3.17.1.dev10 → cycode-3.17.2}/LICENCE +0 -0
  13. {cycode-3.17.1.dev10 → cycode-3.17.2}/README.md +0 -0
  14. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/__main__.py +0 -0
  15. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/__init__.py +0 -0
  16. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/app.py +0 -0
  17. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/__init__.py +0 -0
  18. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/activation_manager.py +0 -0
  19. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/__init__.py +0 -0
  20. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/command_utils.py +0 -0
  21. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/consts.py +0 -0
  22. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/hooks_manager.py +0 -0
  23. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/base.py +0 -0
  24. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/ides/cursor.py +0 -0
  25. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/install_command.py +0 -0
  26. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/__init__.py +0 -0
  27. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/consts.py +0 -0
  28. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/handlers.py +0 -0
  29. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/payload.py +0 -0
  30. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/policy.py +0 -0
  31. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/scan_command.py +0 -0
  32. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/types.py +0 -0
  33. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/scan/utils.py +0 -0
  34. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/status_command.py +0 -0
  35. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_guardrails/uninstall_command.py +0 -0
  36. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_remediation/__init__.py +0 -0
  37. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_remediation/ai_remediation_command.py +0 -0
  38. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_remediation/apply_fix.py +0 -0
  39. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ai_remediation/print_remediation.py +0 -0
  40. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/api/__init__.py +0 -0
  41. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/api/api_command.py +0 -0
  42. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/api/openapi_spec.py +0 -0
  43. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/auth/__init__.py +0 -0
  44. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/auth/auth_command.py +0 -0
  45. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/auth/auth_common.py +0 -0
  46. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/auth/auth_manager.py +0 -0
  47. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/auth/models.py +0 -0
  48. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/configure/__init__.py +0 -0
  49. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/configure/configure_command.py +0 -0
  50. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/configure/consts.py +0 -0
  51. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/configure/messages.py +0 -0
  52. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/configure/prompts.py +0 -0
  53. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ignore/__init__.py +0 -0
  54. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/ignore/ignore_command.py +0 -0
  55. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/mcp/__init__.py +0 -0
  56. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/mcp/mcp_command.py +0 -0
  57. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/__init__.py +0 -0
  58. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/report_command.py +0 -0
  59. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/__init__.py +0 -0
  60. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/common.py +0 -0
  61. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/path/__init__.py +0 -0
  62. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/path/path_command.py +0 -0
  63. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/repository_url/__init__.py +0 -0
  64. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/repository_url/repository_url_command.py +0 -0
  65. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/sbom_command.py +0 -0
  66. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report/sbom/sbom_report_file.py +0 -0
  67. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report_import/__init__.py +0 -0
  68. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report_import/report_import_command.py +0 -0
  69. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report_import/sbom/__init__.py +0 -0
  70. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/report_import/sbom/sbom_command.py +0 -0
  71. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/sca_options.py +0 -0
  72. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/__init__.py +0 -0
  73. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/aggregation_report.py +0 -0
  74. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/code_scanner.py +0 -0
  75. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/commit_history/__init__.py +0 -0
  76. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/commit_history/commit_history_command.py +0 -0
  77. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/commit_range_scanner.py +0 -0
  78. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/detection_excluder.py +0 -0
  79. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/path/__init__.py +0 -0
  80. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/path/path_command.py +0 -0
  81. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_commit/__init__.py +0 -0
  82. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_commit/pre_commit_command.py +0 -0
  83. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_push/__init__.py +0 -0
  84. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_push/pre_push_command.py +0 -0
  85. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_receive/__init__.py +0 -0
  86. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/pre_receive/pre_receive_command.py +0 -0
  87. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/remote_url_resolver.py +0 -0
  88. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/repository/__init__.py +0 -0
  89. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/repository/repository_command.py +0 -0
  90. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_ci/__init__.py +0 -0
  91. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_ci/ci_integrations.py +0 -0
  92. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_ci/scan_ci_command.py +0 -0
  93. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_command.py +0 -0
  94. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_parameters.py +0 -0
  95. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/scan/scan_result.py +0 -0
  96. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/status/__init__.py +0 -0
  97. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/status/get_cli_status.py +0 -0
  98. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/status/models.py +0 -0
  99. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/status/status_command.py +0 -0
  100. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/apps/status/version_command.py +0 -0
  101. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/cli_types.py +0 -0
  102. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/config.py +0 -0
  103. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/console.py +0 -0
  104. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/consts.py +0 -0
  105. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/__init__.py +0 -0
  106. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/custom_exceptions.py +0 -0
  107. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/handle_ai_remediation_errors.py +0 -0
  108. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/handle_auth_errors.py +0 -0
  109. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/handle_errors.py +0 -0
  110. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/handle_report_sbom_errors.py +0 -0
  111. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/exceptions/handle_scan_errors.py +0 -0
  112. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/__init__.py +0 -0
  113. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/commit_range_documents.py +0 -0
  114. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/documents_walk_ignore.py +0 -0
  115. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/file_excluder.py +0 -0
  116. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/iac/__init__.py +0 -0
  117. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/iac/tf_content_generator.py +0 -0
  118. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/models/__init__.py +0 -0
  119. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/models/in_memory_zip.py +0 -0
  120. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/path_documents.py +0 -0
  121. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/repository_documents.py +0 -0
  122. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/__init__.py +0 -0
  123. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/base_restore_dependencies.py +0 -0
  124. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/go/__init__.py +0 -0
  125. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/go/restore_go_dependencies.py +0 -0
  126. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/maven/__init__.py +0 -0
  127. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/maven/restore_maven_dependencies.py +0 -0
  128. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/__init__.py +0 -0
  129. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/restore_bun_dependencies.py +0 -0
  130. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/restore_deno_dependencies.py +0 -0
  131. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/restore_npm_dependencies.py +0 -0
  132. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/restore_pnpm_dependencies.py +0 -0
  133. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/npm/restore_yarn_dependencies.py +0 -0
  134. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/nuget/__init__.py +0 -0
  135. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/nuget/restore_nuget_dependencies.py +0 -0
  136. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/php/__init__.py +0 -0
  137. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/php/restore_composer_dependencies.py +0 -0
  138. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/python/__init__.py +0 -0
  139. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/python/restore_pipenv_dependencies.py +0 -0
  140. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/python/restore_poetry_dependencies.py +0 -0
  141. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/python/restore_uv_dependencies.py +0 -0
  142. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/ruby/__init__.py +0 -0
  143. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/ruby/restore_ruby_dependencies.py +0 -0
  144. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/sbt/__init__.py +0 -0
  145. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/sbt/restore_sbt_dependencies.py +0 -0
  146. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/sca/sca_file_collector.py +0 -0
  147. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/walk_ignore.py +0 -0
  148. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/files_collector/zip_documents.py +0 -0
  149. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/logger.py +0 -0
  150. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/main.py +0 -0
  151. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/models.py +0 -0
  152. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/__init__.py +0 -0
  153. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/console_printer.py +0 -0
  154. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/json_printer.py +0 -0
  155. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/printer_base.py +0 -0
  156. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/rich_printer.py +0 -0
  157. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/__init__.py +0 -0
  158. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/sca_table_printer.py +0 -0
  159. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/table.py +0 -0
  160. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/table_models.py +0 -0
  161. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/table_printer.py +0 -0
  162. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/tables/table_printer_base.py +0 -0
  163. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/text_printer.py +0 -0
  164. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/__init__.py +0 -0
  165. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/code_snippet_syntax.py +0 -0
  166. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/detection_data.py +0 -0
  167. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/detection_ordering/__init__.py +0 -0
  168. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/detection_ordering/common_ordering.py +0 -0
  169. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/detection_ordering/sca_ordering.py +0 -0
  170. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/printers/utils/rich_helpers.py +0 -0
  171. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/__init__.py +0 -0
  172. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/base_file_manager.py +0 -0
  173. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/config_file_manager.py +0 -0
  174. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/configuration_manager.py +0 -0
  175. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/credentials_manager.py +0 -0
  176. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/user_settings/jwt_creator.py +0 -0
  177. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/__init__.py +0 -0
  178. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/binary_utils.py +0 -0
  179. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/enum_utils.py +0 -0
  180. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/get_api_client.py +0 -0
  181. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/git_proxy.py +0 -0
  182. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/host_info.py +0 -0
  183. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/ignore_utils.py +0 -0
  184. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/jwt_utils.py +0 -0
  185. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/path_utils.py +0 -0
  186. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/progress_bar.py +0 -0
  187. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/scan_batch.py +0 -0
  188. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/scan_utils.py +0 -0
  189. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/shell_executor.py +0 -0
  190. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/string_utils.py +0 -0
  191. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/task_timer.py +0 -0
  192. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/url_utils.py +0 -0
  193. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/version_checker.py +0 -0
  194. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cli/utils/yaml_utils.py +0 -0
  195. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/config.py +0 -0
  196. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/__init__.py +0 -0
  197. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/ai_security_manager_service_config.py +0 -0
  198. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/auth_client.py +0 -0
  199. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/base_token_auth_client.py +0 -0
  200. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cli_activation_client.py +0 -0
  201. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/client_creator.py +0 -0
  202. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/config.py +0 -0
  203. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/config_dev.py +0 -0
  204. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cycode_client.py +0 -0
  205. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cycode_client_base.py +0 -0
  206. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cycode_dev_based_client.py +0 -0
  207. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cycode_oidc_based_client.py +0 -0
  208. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/cycode_token_based_client.py +0 -0
  209. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/headers.py +0 -0
  210. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/import_sbom_client.py +0 -0
  211. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/logger.py +0 -0
  212. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/models.py +0 -0
  213. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/report_client.py +0 -0
  214. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/scan_client.py +0 -0
  215. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/cyclient/scan_config_base.py +0 -0
  216. {cycode-3.17.1.dev10 → cycode-3.17.2}/cycode/logger.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cycode
3
- Version: 3.17.1.dev10
3
+ Version: 3.17.2
4
4
  Summary: Boost security in your dev lifecycle via SAST, SCA, Secrets & IaC scanning.
5
5
  License-Expression: MIT
6
6
  License-File: LICENCE
@@ -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.17.1.dev10' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
8
+ __version__ = '3.17.2' # DON'T TOUCH. Placeholder. Will be filled automatically on poetry build from Git Tag
@@ -34,6 +34,25 @@ def get_ide(name: str) -> IDE:
34
34
  return ide
35
35
 
36
36
 
37
+ def collect_all_session_contexts() -> tuple[dict[str, dict], dict]:
38
+ """Sweep every registered IDE's session context, regardless of which IDE triggered the hook.
39
+
40
+ Returns ``(config_files_by_ide, plugins)``: the global MCP config file of each IDE that has
41
+ one (keyed by IDE name), and the enabled plugins merged across IDEs (first registered IDE
42
+ wins on a duplicate plugin key - plugins are IDE-agnostic marketplace artifacts).
43
+ """
44
+ config_files_by_ide: dict[str, dict] = {}
45
+ plugins: dict = {}
46
+ for ide in IDES.values():
47
+ global_config_file, enabled_plugins = ide.get_session_context()
48
+ if global_config_file:
49
+ config_files_by_ide[ide.name] = global_config_file
50
+ for plugin_key, plugin in (enabled_plugins or {}).items():
51
+ plugins.setdefault(plugin_key, plugin)
52
+
53
+ return config_files_by_ide, plugins
54
+
55
+
37
56
  def resolve_ides(name: str) -> list[IDE]:
38
57
  """Resolve an ``--ide`` argument to one or all IDE instances.
39
58
 
@@ -15,6 +15,22 @@ from cycode.logger import get_logger
15
15
  logger = get_logger('AI Guardrails Plugins')
16
16
 
17
17
 
18
+ def resolve_cached_plugin_dir(cache_root: Path, marketplace: str, plugin_name: str) -> Optional[Path]:
19
+ """Find ``<cache_root>/<marketplace>/<plugin>/<version-or-hash>/``.
20
+
21
+ Both Claude Code and Codex cache installed plugin content in this layout (the trailing
22
+ segment is a version for Claude, a content hash for Codex). If multiple are cached, pick
23
+ the most recently modified (name as a deterministic tie-breaker).
24
+ """
25
+ base = cache_root / marketplace / plugin_name
26
+ if not base.is_dir():
27
+ return None
28
+ candidates = [d for d in base.iterdir() if d.is_dir()]
29
+ if not candidates:
30
+ return None
31
+ return max(candidates, key=lambda d: (d.stat().st_mtime, d.name))
32
+
33
+
18
34
  def load_plugin_json(path: Path) -> Optional[dict]:
19
35
  """Load a JSON file inside a plugin directory; None if missing or invalid."""
20
36
  if not path.exists():
@@ -10,6 +10,7 @@ from cycode.cli.apps.ai_guardrails.consts import CYCODE_SCAN_PROMPT_COMMAND, CYC
10
10
  from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
11
11
  build_global_config_file,
12
12
  load_plugin_json,
13
+ resolve_cached_plugin_dir,
13
14
  walk_enabled_plugins,
14
15
  )
15
16
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
@@ -164,6 +165,11 @@ def load_claude_settings(settings_path: Optional[Path] = None) -> Optional[dict]
164
165
  return None
165
166
 
166
167
 
168
+ def _plugins_cache_dir() -> Path:
169
+ """Claude Code's local plugin content cache: ``~/.claude/plugins/cache/<marketplace>/<plugin>/<version>/``."""
170
+ return Path.home() / '.claude' / 'plugins' / 'cache'
171
+
172
+
167
173
  def _resolve_marketplace_path(marketplace: dict) -> Optional[Path]:
168
174
  """Resolve filesystem path for a directory-type marketplace."""
169
175
  source = marketplace.get('source', {})
@@ -194,25 +200,29 @@ def _read_claude_plugin(plugin_dir: Path) -> tuple[dict, dict]:
194
200
  if servers:
195
201
  entry['mcp_server_names'] = list(servers.keys())
196
202
  entry['mcp_config_file_path'] = str(mcp_config_path)
197
- entry['mcp_config_file'] = json.dumps(mcp_config)
203
+ entry['mcp_config_file'] = json.dumps({'mcpServers': servers})
198
204
  return entry, servers
199
205
 
200
206
 
201
207
  def resolve_plugins(settings: dict) -> dict:
202
208
  """Walk Claude Code's ``enabledPlugins`` via the shared plugin walker.
203
209
 
204
- Each enabled plugin's marketplace is resolved through
205
- ``extraKnownMarketplaces`` to a directory; the rest of the work
206
- (manifest + ``.mcp.json``) is the shared ``_read_claude_plugin``.
210
+ Directory-type marketplaces resolve through ``extraKnownMarketplaces``; all
211
+ other source types (git, github, ...) resolve through the local plugin cache.
212
+ The rest of the work (manifest + ``.mcp.json``) is the shared ``_read_claude_plugin``.
207
213
  """
208
214
  enabled = settings.get('enabledPlugins') or {}
209
215
  marketplaces = settings.get('extraKnownMarketplaces') or {}
210
216
 
211
- def _locate(_plugin_name: str, marketplace_name: str) -> Optional[Path]:
217
+ def _locate(plugin_name: str, marketplace_name: str) -> Optional[Path]:
218
+ # Directory-type marketplaces point straight at the plugin source; every other source
219
+ # type (git, github, ...) is cloned into the local plugin cache.
212
220
  marketplace = marketplaces.get(marketplace_name)
213
- if not marketplace:
214
- return None
215
- return _resolve_marketplace_path(marketplace)
221
+ if marketplace:
222
+ marketplace_path = _resolve_marketplace_path(marketplace)
223
+ if marketplace_path is not None:
224
+ return marketplace_path
225
+ return resolve_cached_plugin_dir(_plugins_cache_dir(), marketplace_name, plugin_name)
216
226
 
217
227
  return walk_enabled_plugins(
218
228
  plugin_entries=enabled,
@@ -17,6 +17,7 @@ from cycode.cli.apps.ai_guardrails.consts import CYCODE_SCAN_PROMPT_COMMAND, CYC
17
17
  from cycode.cli.apps.ai_guardrails.ides._plugin_utils import (
18
18
  build_global_config_file,
19
19
  load_plugin_json,
20
+ resolve_cached_plugin_dir,
20
21
  walk_enabled_plugins,
21
22
  )
22
23
  from cycode.cli.apps.ai_guardrails.ides.base import IDE, DecisionAction, HookDecision
@@ -100,18 +101,8 @@ def _email_from_auth(auth_path: Optional[Path] = None) -> Optional[str]:
100
101
 
101
102
 
102
103
  def _resolve_codex_plugin_dir(plugin_name: str, marketplace: str) -> Optional[Path]:
103
- """Find ``~/.codex/plugins/cache/<marketplace>/<plugin>/<hash>/``.
104
-
105
- The trailing segment is a content hash. If multiple are cached, pick the
106
- most recently modified.
107
- """
108
- base = _codex_home() / 'plugins' / 'cache' / marketplace / plugin_name
109
- if not base.is_dir():
110
- return None
111
- candidates = [d for d in base.iterdir() if d.is_dir()]
112
- if not candidates:
113
- return None
114
- return max(candidates, key=lambda d: d.stat().st_mtime)
104
+ """Find ``~/.codex/plugins/cache/<marketplace>/<plugin>/<hash>/``."""
105
+ return resolve_cached_plugin_dir(_codex_home() / 'plugins' / 'cache', marketplace, plugin_name)
115
106
 
116
107
 
117
108
  def _read_codex_plugin(plugin_dir: Path) -> tuple[dict, dict]:
@@ -141,7 +132,7 @@ def _read_codex_plugin(plugin_dir: Path) -> tuple[dict, dict]:
141
132
  if servers:
142
133
  entry['mcp_server_names'] = list(servers.keys())
143
134
  entry['mcp_config_file_path'] = str(mcp_config_path)
144
- entry['mcp_config_file'] = json.dumps(mcp_doc)
135
+ entry['mcp_config_file'] = json.dumps({'mcpServers': servers})
145
136
  return entry, servers
146
137
 
147
138
 
@@ -0,0 +1,160 @@
1
+ """Handle AI guardrails session start: auth, conversation creation, session context."""
2
+
3
+ import hashlib
4
+ import json
5
+ import sys
6
+ import time
7
+ from pathlib import Path
8
+ from typing import TYPE_CHECKING, Annotated, Optional
9
+
10
+ import typer
11
+
12
+ from cycode.cli.apps.ai_guardrails.ides import DEFAULT_IDE_NAME, collect_all_session_contexts, get_ide
13
+ from cycode.cli.apps.ai_guardrails.scan.utils import read_stdin_text, safe_json_parse
14
+ from cycode.cli.apps.auth.auth_common import get_authorization_info
15
+ from cycode.cli.apps.auth.auth_manager import AuthManager
16
+ from cycode.cli.exceptions.handle_auth_errors import handle_auth_exception
17
+ from cycode.cli.utils.get_api_client import get_ai_security_manager_client
18
+ from cycode.cli.utils.host_info import (
19
+ get_hostname,
20
+ get_last_login_user,
21
+ get_os_version,
22
+ get_platform_name,
23
+ get_serial_number,
24
+ )
25
+ from cycode.logger import get_logger
26
+
27
+ if TYPE_CHECKING:
28
+ from cycode.cyclient.ai_security_manager_client import AISecurityManagerClient
29
+
30
+ logger = get_logger('AI Guardrails')
31
+
32
+ _SESSION_CONTEXT_CACHE_FILE = '.session-context-cache'
33
+ _SESSION_CONTEXT_TTL_SECONDS = 7 * 24 * 60 * 60
34
+
35
+
36
+ def _session_context_cache_path() -> Path:
37
+ return Path.home() / '.cycode' / _SESSION_CONTEXT_CACHE_FILE
38
+
39
+
40
+ def _session_context_digest(report: dict) -> str:
41
+ """Deterministic hash of the outgoing payload (not the raw config files, which churn)."""
42
+ canonical = json.dumps(report, sort_keys=True, separators=(',', ':'), default=str)
43
+ return hashlib.sha256(canonical.encode('utf-8')).hexdigest()
44
+
45
+
46
+ def _should_skip_report(digest: str, tenant_id: Optional[str]) -> bool:
47
+ """Skip when the same payload was already sent for this tenant and the TTL hasn't expired."""
48
+ try:
49
+ cache = json.loads(_session_context_cache_path().read_text(encoding='utf-8'))
50
+ return (
51
+ cache.get('hash') == digest
52
+ and cache.get('tenant_id') == tenant_id
53
+ and time.time() - float(cache.get('sent_at', 0)) < _SESSION_CONTEXT_TTL_SECONDS
54
+ )
55
+ except Exception:
56
+ # Missing/corrupt cache reads as a miss - over-sending is harmless
57
+ return False
58
+
59
+
60
+ def _save_report_cache(digest: str, tenant_id: Optional[str]) -> None:
61
+ try:
62
+ cache_path = _session_context_cache_path()
63
+ cache_path.parent.mkdir(parents=True, exist_ok=True)
64
+ cache_path.write_text(
65
+ json.dumps({'hash': digest, 'tenant_id': tenant_id, 'sent_at': time.time()}), encoding='utf-8'
66
+ )
67
+ except Exception as e:
68
+ logger.debug('Failed to write session context cache', exc_info=e)
69
+
70
+
71
+ def _report_session_context(
72
+ ai_client: 'AISecurityManagerClient',
73
+ user_email: Optional[str],
74
+ tenant_id: Optional[str],
75
+ ) -> None:
76
+ """Report the device + cross-IDE session context to the AI security manager. Never raises.
77
+
78
+ The device context is always reported. MCP configs are collected from every registered IDE,
79
+ not just the triggering one. Unchanged payloads are skipped via a hash cache until the TTL expires.
80
+ """
81
+ try:
82
+ config_files_by_ide, enabled_plugins = collect_all_session_contexts()
83
+ report = {
84
+ 'hostname': get_hostname(),
85
+ 'platform_name': get_platform_name(),
86
+ 'os_version': get_os_version(),
87
+ 'serial_number': get_serial_number(),
88
+ 'last_login_user': get_last_login_user(),
89
+ # Sorted by path so the digest is stable regardless of IDE registry order.
90
+ 'config_files': sorted(config_files_by_ide.values(), key=lambda f: f['path']),
91
+ 'enabled_plugins': enabled_plugins,
92
+ 'user_email': user_email,
93
+ }
94
+
95
+ digest = _session_context_digest(report)
96
+ if _should_skip_report(digest, tenant_id):
97
+ logger.debug('Session context unchanged; skipping report')
98
+ return
99
+
100
+ if ai_client.report_session_context(**report):
101
+ _save_report_cache(digest, tenant_id)
102
+ except Exception as e:
103
+ logger.debug('Failed to report session context', exc_info=e)
104
+
105
+
106
+ def session_start_command(
107
+ ctx: typer.Context,
108
+ ide: Annotated[
109
+ str,
110
+ typer.Option(
111
+ '--ide',
112
+ help='IDE that triggered the session start.',
113
+ hidden=True,
114
+ ),
115
+ ] = DEFAULT_IDE_NAME,
116
+ ) -> None:
117
+ """Handle session start: ensure auth, create conversation, report session context."""
118
+ ide_integration = get_ide(ide)
119
+
120
+ # Ensure authentication
121
+ auth_info = get_authorization_info(ctx)
122
+ if auth_info is None:
123
+ logger.debug('Not authenticated, starting authentication')
124
+ try:
125
+ AuthManager().authenticate()
126
+ except Exception as err:
127
+ handle_auth_exception(ctx, err)
128
+ return
129
+ auth_info = get_authorization_info(ctx)
130
+ else:
131
+ logger.debug('Already authenticated')
132
+
133
+ # Read stdin payload (backward compat: old hooks pipe no stdin)
134
+ if sys.stdin.isatty():
135
+ logger.debug('No stdin payload (TTY), skipping session initialization')
136
+ return
137
+
138
+ stdin_data = read_stdin_text().strip()
139
+ payload = safe_json_parse(stdin_data)
140
+ if not payload:
141
+ logger.debug('Empty or invalid stdin payload, skipping session initialization')
142
+ return
143
+
144
+ # Build session payload + initialize API client
145
+ session_payload = ide_integration.build_session_payload(payload)
146
+
147
+ try:
148
+ ai_client = get_ai_security_manager_client(ctx)
149
+ except Exception as e:
150
+ logger.debug('Failed to initialize AI security client', exc_info=e)
151
+ return
152
+
153
+ # Create conversation
154
+ try:
155
+ ai_client.create_conversation(session_payload)
156
+ except Exception as e:
157
+ logger.debug('Failed to create conversation during session start', exc_info=e)
158
+
159
+ # Report session context (device + cross-IDE MCP servers and plugins)
160
+ _report_session_context(ai_client, session_payload.ide_user_email, auth_info.tenant_id)
@@ -1,4 +1,5 @@
1
1
  import os
2
+ import platform
2
3
  import re
3
4
  from typing import Optional
4
5
 
@@ -12,19 +13,32 @@ from cycode.cli.utils.shell_executor import shell
12
13
  BUILD_GRADLE_FILE_NAME = 'build.gradle'
13
14
  BUILD_GRADLE_KTS_FILE_NAME = 'build.gradle.kts'
14
15
  BUILD_GRADLE_DEP_TREE_FILE_NAME = 'gradle-dependencies-generated.txt'
15
- BUILD_GRADLE_ALL_PROJECTS_COMMAND = ['gradle', 'projects']
16
16
  ALL_PROJECTS_REGEX = r"[+-]{3} Project '(.*?)'"
17
17
 
18
+ GRADLE_EXECUTABLE = 'gradle'
19
+ GRADLEW_FILE_NAME = 'gradlew'
20
+ GRADLEW_BAT_FILE_NAME = 'gradlew.bat'
21
+
18
22
 
19
23
  class RestoreGradleDependencies(BaseRestoreDependencies):
20
24
  def __init__(
21
25
  self, ctx: typer.Context, is_git_diff: bool, command_timeout: int, projects: Optional[set[str]] = None
22
26
  ) -> None:
23
27
  super().__init__(ctx, is_git_diff, command_timeout, create_output_file_manually=True)
28
+ self.gradle_executable = self._resolve_gradle_executable()
24
29
  if projects is None:
25
30
  projects = set()
26
31
  self.projects = self.get_all_projects() if self.is_gradle_sub_projects() else projects
27
32
 
33
+ def _resolve_gradle_executable(self) -> str:
34
+ scan_root = get_path_from_context(self.ctx)
35
+ if scan_root:
36
+ wrapper_name = GRADLEW_BAT_FILE_NAME if platform.system() == 'Windows' else GRADLEW_FILE_NAME
37
+ wrapper_path = os.path.join(scan_root, wrapper_name)
38
+ if os.path.isfile(wrapper_path):
39
+ return wrapper_path
40
+ return GRADLE_EXECUTABLE
41
+
28
42
  def is_gradle_sub_projects(self) -> bool:
29
43
  return self.ctx.obj.get('gradle_all_sub_projects', False)
30
44
 
@@ -35,7 +49,7 @@ class RestoreGradleDependencies(BaseRestoreDependencies):
35
49
  return (
36
50
  self.get_commands_for_sub_projects(manifest_file_path)
37
51
  if self.is_gradle_sub_projects()
38
- else [['gradle', 'dependencies', '-b', manifest_file_path, '-q', '--console', 'plain']]
52
+ else [[self.gradle_executable, 'dependencies', '-b', manifest_file_path, '-q', '--console', 'plain']]
39
53
  )
40
54
 
41
55
  def get_lock_file_name(self) -> str:
@@ -49,7 +63,7 @@ class RestoreGradleDependencies(BaseRestoreDependencies):
49
63
 
50
64
  def get_all_projects(self) -> set[str]:
51
65
  output = shell(
52
- command=BUILD_GRADLE_ALL_PROJECTS_COMMAND,
66
+ command=[self.gradle_executable, 'projects'],
53
67
  timeout=self.command_timeout,
54
68
  working_directory=get_path_from_context(self.ctx),
55
69
  )
@@ -62,7 +76,7 @@ class RestoreGradleDependencies(BaseRestoreDependencies):
62
76
  project_name = os.path.basename(os.path.dirname(manifest_file_path))
63
77
  project_name = f':{project_name}'
64
78
  return (
65
- [['gradle', f'{project_name}:dependencies', '-q', '--console', 'plain']]
79
+ [[self.gradle_executable, f'{project_name}:dependencies', '-q', '--console', 'plain']]
66
80
  if project_name in self.projects
67
81
  else []
68
82
  )
@@ -98,11 +98,11 @@ class AISecurityManagerClient:
98
98
  os_version: Optional[str] = None,
99
99
  serial_number: Optional[str] = None,
100
100
  last_login_user: Optional[str] = None,
101
- global_config_file: Optional[dict] = None,
101
+ config_files: Optional[list[dict]] = None,
102
102
  enabled_plugins: Optional[dict] = None,
103
103
  user_email: Optional[str] = None,
104
- ) -> None:
105
- """Report session context to the backend."""
104
+ ) -> bool:
105
+ """Report session context to the backend. Returns whether the report was accepted."""
106
106
  body: dict = {
107
107
  'hostname': hostname,
108
108
  'platform_name': platform_name,
@@ -110,12 +110,14 @@ class AISecurityManagerClient:
110
110
  'serial_number': serial_number,
111
111
  'last_login_user': last_login_user,
112
112
  'user_email': user_email,
113
- 'global_config_file': global_config_file,
113
+ 'config_files': config_files,
114
114
  'enabled_plugins': enabled_plugins,
115
115
  }
116
116
 
117
117
  try:
118
118
  self.client.post(self._build_endpoint_path(self._SESSION_CONTEXT_PATH), body=body)
119
+ return True
119
120
  except Exception as e:
120
121
  logger.debug('Failed to report session context', exc_info=e)
121
122
  # Don't fail the session if reporting fails
123
+ return False
@@ -21,7 +21,7 @@ classifiers = [
21
21
  "Programming Language :: Python :: 3.14",
22
22
  ]
23
23
  dynamic = ["dependencies"]
24
- version = "3.17.1.dev10"
24
+ version = "3.17.2"
25
25
 
26
26
  [project.scripts]
27
27
  cycode = "cycode.cli.app:app"
@@ -1,103 +0,0 @@
1
- """Handle AI guardrails session start: auth, conversation creation, session context."""
2
-
3
- import sys
4
- from typing import TYPE_CHECKING, Annotated, Optional
5
-
6
- import typer
7
-
8
- from cycode.cli.apps.ai_guardrails.ides import DEFAULT_IDE_NAME, get_ide
9
- from cycode.cli.apps.ai_guardrails.ides.base import IDE
10
- from cycode.cli.apps.ai_guardrails.scan.utils import read_stdin_text, safe_json_parse
11
- from cycode.cli.apps.auth.auth_common import get_authorization_info
12
- from cycode.cli.apps.auth.auth_manager import AuthManager
13
- from cycode.cli.exceptions.handle_auth_errors import handle_auth_exception
14
- from cycode.cli.utils.get_api_client import get_ai_security_manager_client
15
- from cycode.cli.utils.host_info import (
16
- get_hostname,
17
- get_last_login_user,
18
- get_os_version,
19
- get_platform_name,
20
- get_serial_number,
21
- )
22
- from cycode.logger import get_logger
23
-
24
- if TYPE_CHECKING:
25
- from cycode.cyclient.ai_security_manager_client import AISecurityManagerClient
26
-
27
- logger = get_logger('AI Guardrails')
28
-
29
-
30
- def _report_session_context(ai_client: 'AISecurityManagerClient', ide: IDE, user_email: Optional[str]) -> None:
31
- """Report IDE session context to the AI security manager. Never raises."""
32
- try:
33
- global_config_file, enabled_plugins = ide.get_session_context()
34
- if not global_config_file and not enabled_plugins:
35
- return
36
- ai_client.report_session_context(
37
- hostname=get_hostname(),
38
- platform_name=get_platform_name(),
39
- os_version=get_os_version(),
40
- serial_number=get_serial_number(),
41
- last_login_user=get_last_login_user(),
42
- global_config_file=global_config_file,
43
- enabled_plugins=enabled_plugins,
44
- user_email=user_email,
45
- )
46
- except Exception as e:
47
- logger.debug('Failed to report session context', exc_info=e)
48
-
49
-
50
- def session_start_command(
51
- ctx: typer.Context,
52
- ide: Annotated[
53
- str,
54
- typer.Option(
55
- '--ide',
56
- help='IDE that triggered the session start.',
57
- hidden=True,
58
- ),
59
- ] = DEFAULT_IDE_NAME,
60
- ) -> None:
61
- """Handle session start: ensure auth, create conversation, report session context."""
62
- ide_integration = get_ide(ide)
63
-
64
- # Step 1: Ensure authentication
65
- auth_info = get_authorization_info(ctx)
66
- if auth_info is None:
67
- logger.debug('Not authenticated, starting authentication')
68
- try:
69
- AuthManager().authenticate()
70
- except Exception as err:
71
- handle_auth_exception(ctx, err)
72
- return
73
- else:
74
- logger.debug('Already authenticated')
75
-
76
- # Step 2: Read stdin payload (backward compat: old hooks pipe no stdin)
77
- if sys.stdin.isatty():
78
- logger.debug('No stdin payload (TTY), skipping session initialization')
79
- return
80
-
81
- stdin_data = read_stdin_text().strip()
82
- payload = safe_json_parse(stdin_data)
83
- if not payload:
84
- logger.debug('Empty or invalid stdin payload, skipping session initialization')
85
- return
86
-
87
- # Step 3: Build session payload + initialize API client
88
- session_payload = ide_integration.build_session_payload(payload)
89
-
90
- try:
91
- ai_client = get_ai_security_manager_client(ctx)
92
- except Exception as e:
93
- logger.debug('Failed to initialize AI security client', exc_info=e)
94
- return
95
-
96
- # Step 4: Create conversation
97
- try:
98
- ai_client.create_conversation(session_payload)
99
- except Exception as e:
100
- logger.debug('Failed to create conversation during session start', exc_info=e)
101
-
102
- # Step 5: Report session context (MCP servers, enabled plugins)
103
- _report_session_context(ai_client, ide_integration, session_payload.ide_user_email)
File without changes
File without changes
File without changes