classifyre-cli 0.6.8__tar.gz → 0.6.10__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 (388) hide show
  1. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/.turbo/turbo-build.log +1 -1
  2. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/PKG-INFO +1 -1
  3. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/package.json +1 -1
  4. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/pyproject.toml +6 -2
  5. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/scripts/generate_models.py +2 -0
  6. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/detector.py +1 -1
  7. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/__init__.py +2 -0
  8. classifyre_cli-0.6.10/src/detectors/custom/runners/_decision.py +494 -0
  9. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_factory.py +5 -0
  10. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_llm.py +29 -208
  11. classifyre_cli-0.6.10/src/detectors/custom/runners/_provider_call.py +233 -0
  12. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/engine_version.py +2 -0
  13. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/main.py +14 -2
  14. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/models/generated_detectors.py +160 -14
  15. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/models/generated_input.py +177 -4
  16. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/sdk.py +91 -7
  17. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/rest.py +25 -0
  18. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/base.py +194 -29
  19. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/confluence/source.py +10 -2
  20. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/custom/runner.py +4 -0
  21. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/custom/source.py +6 -1
  22. classifyre_cli-0.6.10/src/sources/dremio/__init__.py +3 -0
  23. classifyre_cli-0.6.10/src/sources/dremio/client.py +466 -0
  24. classifyre_cli-0.6.10/src/sources/dremio/source.py +736 -0
  25. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/email/source.py +13 -5
  26. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/google_workspace/source.py +12 -2
  27. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/jira/source.py +9 -2
  28. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/kafka/rest.py +19 -3
  29. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/kafka/source.py +163 -50
  30. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/local_folder/source.py +78 -0
  31. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/microsoft_365/source.py +12 -3
  32. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mongodb/source.py +111 -6
  33. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/notion/source.py +10 -2
  34. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/object_storage/base.py +21 -3
  35. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/oracle/source.py +29 -0
  36. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/powerbi/source.py +12 -14
  37. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/reddit/source.py +14 -3
  38. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/servicedesk/source.py +22 -3
  39. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/slack/source.py +146 -62
  40. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/tableau/source.py +12 -14
  41. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/tabular_base.py +156 -25
  42. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/tabular_utils.py +6 -0
  43. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/wordpress/source.py +108 -28
  44. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/youtube/source.py +8 -4
  45. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/redaction.py +8 -8
  46. classifyre_cli-0.6.10/src/utils/sampling_frontier.py +689 -0
  47. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/sql_lineage.py +50 -1
  48. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/urn.py +1 -0
  49. classifyre_cli-0.6.10/tests/detectors/custom/test_decision_runner.py +665 -0
  50. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_llm_runner.py +12 -12
  51. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_custom_detector_examples_runtime.py +3 -0
  52. classifyre_cli-0.6.10/tests/test_automatic_new_first.py +474 -0
  53. classifyre_cli-0.6.10/tests/test_dremio_source.py +867 -0
  54. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_dropbox_source.py +9 -5
  55. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_google_workspace_source.py +36 -32
  56. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_hugging_face_source.py +19 -18
  57. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_kafka_source.py +130 -42
  58. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_microsoft_365_source.py +32 -21
  59. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_outputs.py +57 -0
  60. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_reddit_source.py +37 -14
  61. classifyre_cli-0.6.10/tests/test_sampling_automatic.py +272 -0
  62. classifyre_cli-0.6.10/tests/test_sampling_frontier.py +511 -0
  63. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_sandbox_source.py +34 -18
  64. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_scan_cache.py +30 -0
  65. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_slack_source.py +98 -34
  66. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_source_strategy_conformance.py +7 -5
  67. classifyre_cli-0.6.10/tests/test_tabular_automatic_sampling.py +262 -0
  68. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/uv.lock +645 -638
  69. classifyre_cli-0.6.8/tests/test_sampling_automatic.py +0 -142
  70. classifyre_cli-0.6.8/tests/test_tabular_automatic_sampling.py +0 -187
  71. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/.gitignore +0 -0
  72. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/.python-version +0 -0
  73. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/README.md +0 -0
  74. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/main.py +0 -0
  75. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/scripts/generate_runtime_packages.py +0 -0
  76. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/scripts/generate_sdk_completions.py +0 -0
  77. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/__init__.py +0 -0
  78. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/__init__.py +0 -0
  79. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/contract.py +0 -0
  80. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/preview.py +0 -0
  81. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/runner.py +0 -0
  82. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/sdk.py +0 -0
  83. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/augmentation/session.py +0 -0
  84. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/config.py +0 -0
  85. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/__init__.py +0 -0
  86. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/base.py +0 -0
  87. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/broken_links/__init__.py +0 -0
  88. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/broken_links/detector.py +0 -0
  89. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/config.py +0 -0
  90. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/content/__init__.py +0 -0
  91. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/__init__.py +0 -0
  92. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/extractor.py +0 -0
  93. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_base.py +0 -0
  94. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_custom_detector.py +0 -0
  95. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_gliner2.py +0 -0
  96. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_image_classification.py +0 -0
  97. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_object_detection.py +0 -0
  98. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_regex.py +0 -0
  99. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_tag.py +0 -0
  100. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/runners/_text_classification.py +0 -0
  101. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom/trainer.py +0 -0
  102. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/__init__.py +0 -0
  103. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/contract.py +0 -0
  104. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/files.py +0 -0
  105. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/preview.py +0 -0
  106. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/results.py +0 -0
  107. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/runner.py +0 -0
  108. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/sdk.py +0 -0
  109. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/custom_detector/session.py +0 -0
  110. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/dependencies.py +0 -0
  111. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/errors.py +0 -0
  112. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/pii/__init__.py +0 -0
  113. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/pii/detector.py +0 -0
  114. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/secrets/__init__.py +0 -0
  115. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/secrets/detector.py +0 -0
  116. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/threat/__init__.py +0 -0
  117. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/threat/code_security_detector.py +0 -0
  118. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/detectors/threat/yara_detector.py +0 -0
  119. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/file_evaluation/__init__.py +0 -0
  120. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/file_evaluation/asset_fixture.py +0 -0
  121. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/file_evaluation/runner.py +0 -0
  122. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/graph/__init__.py +0 -0
  123. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/graph/edges.py +0 -0
  124. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/models/generated_single_asset_scan_results.py +0 -0
  125. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/__init__.py +0 -0
  126. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/child.py +0 -0
  127. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/cli.py +0 -0
  128. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/cohort.py +0 -0
  129. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/contract.py +0 -0
  130. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/execute.py +0 -0
  131. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/files.py +0 -0
  132. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/groups.py +0 -0
  133. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/outputs.py +0 -0
  134. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/packages.py +0 -0
  135. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/protocol.py +0 -0
  136. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/redact.py +0 -0
  137. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/scaffold.py +0 -0
  138. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/notebook/serialize.py +0 -0
  139. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/__init__.py +0 -0
  140. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/base.py +0 -0
  141. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/console.py +0 -0
  142. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/factory.py +0 -0
  143. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/outputs/file.py +0 -0
  144. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/__init__.py +0 -0
  145. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/asset_payload_server.py +0 -0
  146. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/content_provider.py +0 -0
  147. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/detector_breaker.py +0 -0
  148. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/detector_pipeline.py +0 -0
  149. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/parsed_content_provider.py +0 -0
  150. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/payload_window.py +0 -0
  151. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/scan_cache.py +0 -0
  152. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/text_artifact.py +0 -0
  153. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/pipeline/worker_pool.py +0 -0
  154. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/__init__.py +0 -0
  155. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/asset_metadata.py +0 -0
  156. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/atlassian_common.py +0 -0
  157. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/azure_blob_storage/__init__.py +0 -0
  158. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/azure_blob_storage/source.py +0 -0
  159. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/confluence/__init__.py +0 -0
  160. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/custom/__init__.py +0 -0
  161. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/custom/env.py +0 -0
  162. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/databricks/__init__.py +0 -0
  163. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/databricks/source.py +0 -0
  164. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/delta_lake/__init__.py +0 -0
  165. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/delta_lake/source.py +0 -0
  166. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/dependencies.py +0 -0
  167. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/dropbox/__init__.py +0 -0
  168. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/dropbox/auth.py +0 -0
  169. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/dropbox/source.py +0 -0
  170. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/elasticsearch/__init__.py +0 -0
  171. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/elasticsearch/source.py +0 -0
  172. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/email/__init__.py +0 -0
  173. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/git/__init__.py +0 -0
  174. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/git/source.py +0 -0
  175. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/google_cloud_storage/__init__.py +0 -0
  176. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/google_cloud_storage/source.py +0 -0
  177. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/google_workspace/__init__.py +0 -0
  178. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/hive/__init__.py +0 -0
  179. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/hive/source.py +0 -0
  180. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/hugging_face/__init__.py +0 -0
  181. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/hugging_face/source.py +0 -0
  182. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/iceberg/__init__.py +0 -0
  183. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/iceberg/source.py +0 -0
  184. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/jira/__init__.py +0 -0
  185. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/kafka/__init__.py +0 -0
  186. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/lakehouse_base.py +0 -0
  187. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/local_folder/__init__.py +0 -0
  188. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/meilisearch/__init__.py +0 -0
  189. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/meilisearch/source.py +0 -0
  190. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/microsoft_365/__init__.py +0 -0
  191. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mongodb/__init__.py +0 -0
  192. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mssql/__init__.py +0 -0
  193. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mssql/source.py +0 -0
  194. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mysql/__init__.py +0 -0
  195. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/mysql/source.py +0 -0
  196. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/neo4j/__init__.py +0 -0
  197. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/neo4j/source.py +0 -0
  198. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/notion/__init__.py +0 -0
  199. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/notion/client.py +0 -0
  200. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/opensearch/__init__.py +0 -0
  201. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/opensearch/source.py +0 -0
  202. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/oracle/__init__.py +0 -0
  203. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/postgresql/__init__.py +0 -0
  204. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/postgresql/source.py +0 -0
  205. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/powerbi/__init__.py +0 -0
  206. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/recipe_normalizer.py +0 -0
  207. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/reddit/__init__.py +0 -0
  208. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/s3_client.py +0 -0
  209. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/s3_compatible_storage/README.md +0 -0
  210. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/s3_compatible_storage/__init__.py +0 -0
  211. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/s3_compatible_storage/source.py +0 -0
  212. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/sandbox/__init__.py +0 -0
  213. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/sandbox/source.py +0 -0
  214. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/search_engine_base.py +0 -0
  215. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/servicedesk/__init__.py +0 -0
  216. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/slack/__init__.py +0 -0
  217. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/snowflake/__init__.py +0 -0
  218. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/snowflake/source.py +0 -0
  219. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/sqlite/__init__.py +0 -0
  220. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/sqlite/source.py +0 -0
  221. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/tableau/__init__.py +0 -0
  222. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/wordpress/__init__.py +0 -0
  223. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/sources/youtube/__init__.py +0 -0
  224. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/telemetry.py +0 -0
  225. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/__init__.py +0 -0
  226. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/archive_extraction.py +0 -0
  227. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/content_extraction.py +0 -0
  228. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/dependency_groups.py +0 -0
  229. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/embedded_files.py +0 -0
  230. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/external_video.py +0 -0
  231. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/file_metadata.py +0 -0
  232. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/file_parser.py +0 -0
  233. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/file_to_images.py +0 -0
  234. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/hashing.py +0 -0
  235. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/legacy_office.py +0 -0
  236. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/payload.py +0 -0
  237. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/range_reader.py +0 -0
  238. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/resources.py +0 -0
  239. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/sampling_cursor.py +0 -0
  240. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/source_files.py +0 -0
  241. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/torch_runtime.py +0 -0
  242. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/transcription.py +0 -0
  243. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/uv_sync.py +0 -0
  244. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/validation.py +0 -0
  245. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/src/utils/video_processing.py +0 -0
  246. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/__init__.py +0 -0
  247. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/_lakehouse_fakes.py +0 -0
  248. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/conftest.py +0 -0
  249. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/__init__.py +0 -0
  250. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/broken_links/test_broken_links_detector.py +0 -0
  251. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/conftest.py +0 -0
  252. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/content/__init__.py +0 -0
  253. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/__init__.py +0 -0
  254. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/conftest.py +0 -0
  255. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_gliner2_classification.py +0 -0
  256. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_invoice_extraction.py +0 -0
  257. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_pipeline_integration.py +0 -0
  258. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_regex_runner.py +0 -0
  259. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_runner_hardening.py +0 -0
  260. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/custom/test_transformer_runners.py +0 -0
  261. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/__init__.py +0 -0
  262. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/conftest.py +0 -0
  263. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/sample_invoice.pdf +0 -0
  264. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/test_pii_chunking.py +0 -0
  265. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/test_pii_detector.py +0 -0
  266. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/test_pii_detector_extended.py +0 -0
  267. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/test_pii_regional_entities.py +0 -0
  268. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/pii/test_pii_severity.py +0 -0
  269. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/secrets/__init__.py +0 -0
  270. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/secrets/test_secrets_detector.py +0 -0
  271. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/secrets/test_secrets_detector_extended.py +0 -0
  272. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_base_detector.py +0 -0
  273. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_custom_detector_session.py +0 -0
  274. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_detector_catalog_commercial.py +0 -0
  275. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_detector_pipeline_types.py +0 -0
  276. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_detector_schema_examples.py +0 -0
  277. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_detector_types.py +0 -0
  278. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_phase2_detectors.py +0 -0
  279. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_registry.py +0 -0
  280. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/test_tag_runner.py +0 -0
  281. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/threat/__init__.py +0 -0
  282. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/threat/test_code_security_detector.py +0 -0
  283. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/detectors/threat/test_yara_detector.py +0 -0
  284. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/integration/test_wordpress_broken_links_detector.py +0 -0
  285. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/integration/test_wordpress_links_assets.py +0 -0
  286. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/pipeline/test_detector_breaker.py +0 -0
  287. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/pipeline/test_detector_outcomes.py +0 -0
  288. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/pipeline/test_detector_pipeline.py +0 -0
  289. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/pipeline/test_worker_pool.py +0 -0
  290. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_arrow_ipc_payloads.py +0 -0
  291. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_assets_metadata_catalog.py +0 -0
  292. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_contract.py +0 -0
  293. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_edges.py +0 -0
  294. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_patch.py +0 -0
  295. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_scan_cache.py +0 -0
  296. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_sdk.py +0 -0
  297. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_session.py +0 -0
  298. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_augmentation_tags_end_to_end.py +0 -0
  299. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_azure_blob_storage_source.py +0 -0
  300. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_base_source_attachment.py +0 -0
  301. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_base_source_sampling.py +0 -0
  302. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_byte_valued_fields.py +0 -0
  303. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_config.py +0 -0
  304. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_confluence_source.py +0 -0
  305. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_detector_end_to_end.py +0 -0
  306. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_detector_evaluation.py +0 -0
  307. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_detector_notebook.py +0 -0
  308. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_detector_templates.py +0 -0
  309. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_extractor.py +0 -0
  310. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_source.py +0 -0
  311. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_source_relationships.py +0 -0
  312. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_custom_source_tags_end_to_end.py +0 -0
  313. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_databricks_source.py +0 -0
  314. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_delta_lake_source.py +0 -0
  315. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_dependency_groups.py +0 -0
  316. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_detector_scope.py +0 -0
  317. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_dropbox_auth_command.py +0 -0
  318. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_elasticsearch_source.py +0 -0
  319. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_email_source.py +0 -0
  320. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_file_evaluation_runner.py +0 -0
  321. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_git_source.py +0 -0
  322. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_google_cloud_storage_source.py +0 -0
  323. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_graph_edges.py +0 -0
  324. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_hashing.py +0 -0
  325. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_hive_source.py +0 -0
  326. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_iceberg_source.py +0 -0
  327. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_jira_source.py +0 -0
  328. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_lineage_loss_reporting.py +0 -0
  329. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_local_folder_source.py +0 -0
  330. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_main.py +0 -0
  331. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_meilisearch_source.py +0 -0
  332. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_mongodb_source.py +0 -0
  333. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_mssql_source.py +0 -0
  334. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_mysql_source.py +0 -0
  335. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_neo4j_source.py +0 -0
  336. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_asset_entity.py +0 -0
  337. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_asset_extract.py +0 -0
  338. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_asset_tags.py +0 -0
  339. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_cohort.py +0 -0
  340. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_execute.py +0 -0
  341. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_files.py +0 -0
  342. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_groups.py +0 -0
  343. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_log_levels.py +0 -0
  344. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_packages.py +0 -0
  345. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_query_assets.py +0 -0
  346. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_sdk_exports.py +0 -0
  347. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_serialize.py +0 -0
  348. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notebook_templates.py +0 -0
  349. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_notion_source.py +0 -0
  350. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_object_storage_download_efficiency.py +0 -0
  351. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_opensearch_source.py +0 -0
  352. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_oracle_source.py +0 -0
  353. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_payload_window.py +0 -0
  354. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_payload_window_parquet.py +0 -0
  355. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_postgresql_source.py +0 -0
  356. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_powerbi_source.py +0 -0
  357. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_range_reading.py +0 -0
  358. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_recipe_normalizer.py +0 -0
  359. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_rest_backpressure.py +0 -0
  360. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_runtime_packages.py +0 -0
  361. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_s3_compatible_storage_source.py +0 -0
  362. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_sampling_cursor.py +0 -0
  363. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_sdk_completions.py +0 -0
  364. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_secret_redaction.py +0 -0
  365. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_semantic_declarations.py +0 -0
  366. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_servicedesk_source.py +0 -0
  367. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_snowflake_source.py +0 -0
  368. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_source_dependency_groups.py +0 -0
  369. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_sqlite_source.py +0 -0
  370. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_tableau_source.py +0 -0
  371. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_tabular_lineage.py +0 -0
  372. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_tabular_utils.py +0 -0
  373. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_torch_runtime.py +0 -0
  374. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_urn.py +0 -0
  375. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_uv_sync.py +0 -0
  376. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_wordpress_source.py +0 -0
  377. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_youtube_source.py +0 -0
  378. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/test_youtube_source_integration.py +0 -0
  379. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_archive_extraction.py +0 -0
  380. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_content_extraction.py +0 -0
  381. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_embedded_files.py +0 -0
  382. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_file_metadata.py +0 -0
  383. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_file_parser.py +0 -0
  384. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_file_to_images.py +0 -0
  385. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_legacy_office.py +0 -0
  386. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_payload.py +0 -0
  387. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_transcription.py +0 -0
  388. {classifyre_cli-0.6.8 → classifyre_cli-0.6.10}/tests/utils/test_video_processing.py +0 -0
@@ -1,3 +1,3 @@
1
1
  $ uv sync
2
- Resolved 325 packages in 134ms
2
+ Resolved 324 packages in 232ms
3
3
  Checked 51 packages in 4ms
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: classifyre-cli
3
- Version: 0.6.8
3
+ Version: 0.6.10
4
4
  Summary: Classifyre CLI — scan and classify unstructured data sources
5
5
  License: MIT
6
6
  Keywords: data,ingestion,metadata,pii,secrets,unstructured
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classifyre/cli",
3
- "version": "0.6.8",
3
+ "version": "0.6.10",
4
4
  "private": true,
5
5
  "scripts": {
6
6
  "build": "uv sync",
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "classifyre-cli"
3
- version = "0.6.8"
3
+ version = "0.6.10"
4
4
  description = "Classifyre CLI — scan and classify unstructured data sources"
5
5
  readme = "README.md"
6
6
  # Upper bound is load-bearing: onnxruntime publishes no cp315 wheels (notably
@@ -127,7 +127,11 @@ lineage = [
127
127
  "sqlglot>=25.0.0",
128
128
  ]
129
129
  llm = [
130
- "litellm>=1.86.2",
130
+ # 1.104.2 is the first release with litellm.decisions(), which the DECISION
131
+ # detector calls: one SDK entry point for every Decisions API / System One
132
+ # provider (OpenAI, TypeSafe Jev, Cloudflare Clef, Perplexity, OpenRouter,
133
+ # Strands Decider and any self-hosted /v1/systemone server).
134
+ "litellm>=1.104.2",
131
135
  # Pure-wheel PDF renderer (permissive license, no system binaries) used to
132
136
  # rasterise PDF pages to images for vision-capable LLM detectors.
133
137
  "pypdfium2>=4.30.0",
@@ -16,6 +16,7 @@ _PIPELINE_TYPE_DEFAULTS: dict[str, str] = {
16
16
  "LLMPipelineSchema": "LLM",
17
17
  "TagPipelineSchema": "TAG",
18
18
  "CodeDetectorPipelineSchema": "CODE_DETECTOR",
19
+ "DecisionPipelineSchema": "DECISION",
19
20
  }
20
21
 
21
22
  # Pipeline schema classes whose `severity` field has a string default from JSON schema
@@ -29,6 +30,7 @@ _SEVERITY_ENUM_DEFAULT_CLASSES = {
29
30
  "TextClassificationPipelineSchema": "info",
30
31
  "TagPipelineSchema": "medium",
31
32
  "CodeDetectorPipelineSchema": "medium",
33
+ "DecisionPipelineSchema": "medium",
32
34
  }
33
35
 
34
36
 
@@ -19,7 +19,7 @@ logger = logging.getLogger(__name__)
19
19
  class CustomDetector(BaseDetector):
20
20
  """Schema-driven detector backed by a pluggable runner.
21
21
 
22
- GLINER2 | REGEX | LLM | transformer run over content. TAG does not: it
22
+ GLINER2 | REGEX | LLM | DECISION | transformer run over content. TAG does not: it
23
23
  produces findings only from tags a CUSTOM connector attached to an asset,
24
24
  which the pipeline applies through ``runner.tag_finding``.
25
25
  """
@@ -14,6 +14,7 @@ from ._base import (
14
14
  _resolve_pipeline_severity,
15
15
  )
16
16
  from ._custom_detector import CustomDetectorRunner
17
+ from ._decision import DecisionRunner
17
18
  from ._factory import create_runner
18
19
  from ._gliner2 import (
19
20
  GLiNER2Runner,
@@ -37,6 +38,7 @@ __all__ = [
37
38
  "_TEXT_CONTENT_TYPES",
38
39
  "BaseRunner",
39
40
  "CustomDetectorRunner",
41
+ "DecisionRunner",
40
42
  "GLiNER2Runner",
41
43
  "ImageClassificationRunner",
42
44
  "LLMRunner",
@@ -0,0 +1,494 @@
1
+ """Decision pipeline runner — typed questions answered with probabilities.
2
+
3
+ A decision model (the Decisions API and System One family) does not write
4
+ text. It is handed the content and a list of questions and returns, for each,
5
+ a number: the probability that a yes/no condition holds, which option of a
6
+ fixed list fits, or where the content sits on a scale.
7
+
8
+ Every provider is reached through ``litellm.decisions``, which speaks both wire
9
+ formats and translates between them, so the model name alone picks the API.
10
+ This runner always sends the System One shape (``state`` plus a map of named
11
+ questions) because it is the one every provider accepts.
12
+ """
13
+
14
+ from __future__ import annotations
15
+
16
+ import logging
17
+ import os
18
+ from collections.abc import Mapping
19
+ from dataclasses import dataclass, field
20
+ from datetime import UTC, datetime
21
+ from typing import Any, Literal
22
+
23
+ # Quiet litellm's import-time provider preload warnings (bedrock/sagemaker need
24
+ # botocore, which we don't install) before the library is ever imported.
25
+ os.environ.setdefault("LITELLM_LOG", "ERROR")
26
+
27
+ from ....models.generated_detectors import (
28
+ DecisionPipelineSchema,
29
+ DecisionQuestion,
30
+ DecisionQuestionOption,
31
+ DecisionQuestionType,
32
+ Severity,
33
+ )
34
+ from ....models.generated_single_asset_scan_results import (
35
+ DetectionResult,
36
+ DetectorType,
37
+ )
38
+ from ...dependencies import require_module
39
+ from ...errors import ProviderRefusedError
40
+ from ._base import _TEXT_CONTENT_TYPES, BaseRunner
41
+ from ._provider_call import _COMPLETION_TIMEOUT_SECONDS, call_with_backoff
42
+
43
+ logger = logging.getLogger(__name__)
44
+
45
+ RUNNER = "DECISION"
46
+
47
+ # A yes/no answer is a finding once "yes" is more likely than not. A choice or
48
+ # a score always lands on exactly one answer, so its default keeps every one:
49
+ # the finding carries the model's confidence, and a threshold applied before
50
+ # recording would only hide that the model was asked.
51
+ _DEFAULT_YES_NO_THRESHOLD = 0.5
52
+ _DEFAULT_PICK_THRESHOLD = 0.0
53
+
54
+ _MIN_OPTIONS = 2
55
+ _MAX_CHOICE_OPTIONS = 255
56
+ _MAX_SCORE_LEVELS = 10
57
+
58
+ _MATCHED_CONTENT_CHARS = 320
59
+
60
+
61
+ class DecisionCallError(RuntimeError):
62
+ """Provider call failed after retries.
63
+
64
+ Carries only a string message so it survives pickling across the detector
65
+ worker-pool process boundary; the pipeline records the detector's outcome
66
+ as ERROR instead of a silent empty result.
67
+ """
68
+
69
+
70
+ class DecisionProviderRefusedError(DecisionCallError, ProviderRefusedError):
71
+ """The provider refused in a way no retry can fix (quota, auth, billing).
72
+
73
+ Raised on the first such response, never after retries. The pipeline
74
+ disables the detector for the rest of the run when it sees one.
75
+ """
76
+
77
+
78
+ class DecisionRunner(BaseRunner):
79
+ """Decision detector — asks a decision model typed questions about content."""
80
+
81
+ def __init__(
82
+ self,
83
+ schema: DecisionPipelineSchema,
84
+ detector_key: str = "",
85
+ detector_name: str = "",
86
+ ) -> None:
87
+ self._schema = schema
88
+ self._detector_key = detector_key
89
+ self._detector_name = detector_name
90
+ self._model = schema.model.strip()
91
+ _check_questions(detector_key, schema.questions)
92
+
93
+ self._litellm = require_module("litellm", "llm", ["llm"])
94
+ if not callable(getattr(self._litellm, "decisions", None)):
95
+ raise ValueError(
96
+ f"Decision detector '{detector_key}' needs litellm 1.104.2 or newer: "
97
+ "the installed version has no decisions API."
98
+ )
99
+ self._litellm.suppress_debug_info = True
100
+ logging.getLogger("LiteLLM").setLevel(logging.ERROR)
101
+ self._wire_questions = {q.name: _wire_question(q) for q in schema.questions}
102
+
103
+ def run(self, text: str) -> None: # type: ignore[override] # pragma: no cover
104
+ raise NotImplementedError("DecisionRunner uses detect() directly")
105
+
106
+ def detect(self, content: str | bytes, content_type: str) -> list[DetectionResult]:
107
+ if isinstance(content, bytes) or content_type not in _TEXT_CONTENT_TYPES:
108
+ return []
109
+ text = content.strip()
110
+ if not text:
111
+ return []
112
+ snippet = text[: self._schema.content_limit or 8000]
113
+
114
+ try:
115
+ response = self._decide(snippet)
116
+ answers = _answers_of(response)
117
+ except DecisionProviderRefusedError:
118
+ # Already names the detector, the model and the refusal. No stack
119
+ # trace: it is expected, and it will be the same on every asset.
120
+ raise
121
+ except Exception as exc:
122
+ logger.error(
123
+ "decision detector error (detector=%s, model=%s): %s",
124
+ self._detector_key,
125
+ self._model,
126
+ exc,
127
+ exc_info=True,
128
+ )
129
+ # Propagate instead of returning [] — an empty result here is
130
+ # indistinguishable from "genuinely found nothing" and would let
131
+ # the pipeline record this detector OK on an asset it never saw.
132
+ raise DecisionCallError(
133
+ f"Decision provider call failed for detector '{self._detector_key}' "
134
+ f"(model={self._model}): {exc}"
135
+ ) from None
136
+
137
+ return self._results_from_answers(snippet, answers, _served_model(response))
138
+
139
+ # ── Provider call ────────────────────────────────────────────────────────
140
+
141
+ def _decide(self, snippet: str) -> Any:
142
+ schema = self._schema
143
+ secrets = _string_map(schema.secrets)
144
+ headers = _string_map(schema.extra_headers)
145
+
146
+ def decide() -> Any:
147
+ return self._litellm.decisions(
148
+ model=self._model,
149
+ state=snippet,
150
+ questions=self._wire_questions,
151
+ # None lets litellm fall back to the provider's own environment
152
+ # variable, which is how a self-hosted server without a key and
153
+ # a deployment-wide key both work.
154
+ api_key=secrets.get("api_key") or None,
155
+ api_base=_plain(schema.api_base) or None,
156
+ extra_headers=headers or None,
157
+ timeout=_COMPLETION_TIMEOUT_SECONDS,
158
+ )
159
+
160
+ return call_with_backoff(
161
+ decide,
162
+ litellm=self._litellm,
163
+ schema=schema,
164
+ kind="decision",
165
+ detector_key=self._detector_key,
166
+ model=self._model,
167
+ refused=lambda refusal, exc: DecisionProviderRefusedError(
168
+ f"Decision provider refused detector '{self._detector_key}' "
169
+ f"(model={self._model}, {refusal}): {exc}"
170
+ ),
171
+ )
172
+
173
+ # ── Answers → findings ───────────────────────────────────────────────────
174
+
175
+ def _results_from_answers(
176
+ self,
177
+ snippet: str,
178
+ answers: Mapping[str, Mapping[str, Any]],
179
+ served_model: str | None,
180
+ ) -> list[DetectionResult]:
181
+ schema = self._schema
182
+ default_severity = schema.severity if schema.severity is not None else Severity.medium
183
+
184
+ verdicts: list[_Verdict] = []
185
+ unanswered: list[str] = []
186
+ for question in schema.questions:
187
+ answer = answers.get(question.name)
188
+ verdict = _verdict(question, answer) if answer is not None else None
189
+ if verdict is None:
190
+ unanswered.append(question.name)
191
+ else:
192
+ verdicts.append(verdict)
193
+
194
+ if unanswered:
195
+ # A model may decline one question and answer the rest. Said out
196
+ # loud, because a declined question otherwise reads as "no".
197
+ logger.warning(
198
+ "%s: the model returned no usable answer for %d question(s): %s",
199
+ self._detector_key,
200
+ len(unanswered),
201
+ ", ".join(unanswered[:10]),
202
+ )
203
+
204
+ # Every finding carries the whole set of answers from this call, in the
205
+ # shape the extraction view already renders, so a reviewer sees what
206
+ # the model said to each question and not only the one that fired.
207
+ extracted = {
208
+ "entities": {},
209
+ "classification": {v.question.name: v.summary() for v in verdicts},
210
+ "metadata": {"runner": RUNNER, "model": served_model or self._model},
211
+ }
212
+
213
+ results: list[DetectionResult] = []
214
+ suppressed: list[tuple[str, float]] = []
215
+ for verdict in verdicts:
216
+ if verdict.outcome == "suppressed":
217
+ suppressed.append((verdict.finding_type, verdict.certainty))
218
+ if verdict.outcome != "finding":
219
+ continue
220
+ results.append(
221
+ DetectionResult(
222
+ detector_type=DetectorType.CUSTOM,
223
+ finding_type=verdict.finding_type,
224
+ category="CLASSIFICATION",
225
+ severity=verdict.severity or verdict.question.severity or default_severity,
226
+ confidence=verdict.certainty,
227
+ matched_content=snippet[:_MATCHED_CONTENT_CHARS],
228
+ location=None,
229
+ custom_detector_key=self._detector_key,
230
+ custom_detector_name=self._detector_name,
231
+ detected_at=datetime.now(UTC),
232
+ metadata={
233
+ "runner": RUNNER,
234
+ "model": self._model,
235
+ "question": verdict.question.name,
236
+ "question_type": verdict.question.type.value,
237
+ "instructions": verdict.question.instructions,
238
+ "label": verdict.finding_type,
239
+ "answer": verdict.answer,
240
+ **verdict.detail,
241
+ "input": "text",
242
+ },
243
+ extracted_data=extracted,
244
+ extraction_method=RUNNER,
245
+ )
246
+ )
247
+
248
+ if suppressed:
249
+ logger.warning(
250
+ "%s: thresholds discarded %d model answer(s): %s%s. The model answered — "
251
+ "lower the question's threshold (0 records every answer with its "
252
+ "confidence, to filter downstream) if this is not what you meant.",
253
+ self._detector_key,
254
+ len(suppressed),
255
+ ", ".join(f"{label}={score:.2f}" for label, score in suppressed[:5]),
256
+ " and more" if len(suppressed) > 5 else "",
257
+ )
258
+
259
+ results.sort(key=lambda r: r.confidence, reverse=True)
260
+ return results
261
+
262
+
263
+ # ── Questions on the wire ────────────────────────────────────────────────────
264
+
265
+
266
+ def _check_questions(detector_key: str, questions: list[DecisionQuestion]) -> None:
267
+ """Refuse a question set no provider would accept, before any call is paid for."""
268
+ seen: set[str] = set()
269
+ for question in questions:
270
+ if question.name in seen:
271
+ raise ValueError(
272
+ f"Decision detector '{detector_key}' has two questions named '{question.name}'."
273
+ )
274
+ seen.add(question.name)
275
+ if question.type == DecisionQuestionType.yes_no:
276
+ continue
277
+ options = question.options or []
278
+ limit = (
279
+ _MAX_CHOICE_OPTIONS
280
+ if question.type == DecisionQuestionType.choice
281
+ else _MAX_SCORE_LEVELS
282
+ )
283
+ if not _MIN_OPTIONS <= len(options) <= limit:
284
+ raise ValueError(
285
+ f"Decision detector '{detector_key}': {question.type.value} question "
286
+ f"'{question.name}' needs {_MIN_OPTIONS} to {limit} options, got {len(options)}."
287
+ )
288
+ labels = [option.label for option in options]
289
+ if len(set(labels)) != len(labels):
290
+ raise ValueError(
291
+ f"Decision detector '{detector_key}': question '{question.name}' "
292
+ "repeats an option label."
293
+ )
294
+
295
+
296
+ def _wire_question(question: DecisionQuestion) -> dict[str, Any]:
297
+ """One question in the System One shape litellm forwards or translates."""
298
+ if question.type == DecisionQuestionType.yes_no:
299
+ return {"type": "noul", "instructions": question.instructions}
300
+ options = question.options or []
301
+ if question.type == DecisionQuestionType.choice:
302
+ return {
303
+ "type": "choice",
304
+ "instructions": question.instructions,
305
+ # A described option is sent with its description. An undescribed
306
+ # one repeats its label: null is legal for hosted providers, but a
307
+ # self-hosted server is not obliged to accept it.
308
+ "criteria": {option.label: option.description or option.label for option in options},
309
+ }
310
+ return {
311
+ "type": "score",
312
+ "instructions": question.instructions,
313
+ "criteria": [_level_text(option) for option in options],
314
+ }
315
+
316
+
317
+ def _level_text(option: DecisionQuestionOption) -> str:
318
+ return f"{option.label}: {option.description}" if option.description else option.label
319
+
320
+
321
+ # ── Answers off the wire ─────────────────────────────────────────────────────
322
+
323
+
324
+ @dataclass(frozen=True)
325
+ class _Verdict:
326
+ """What the model said to one question, and what that means as a finding.
327
+
328
+ ``outcome`` is ``finding`` when the answer is recorded, ``quiet`` when it is
329
+ the expected answer nobody asked to hear about (a "no", or an option with
330
+ ``report: false``), and ``suppressed`` when it would have been recorded but
331
+ fell below the question's threshold.
332
+ """
333
+
334
+ question: DecisionQuestion
335
+ answer: str
336
+ certainty: float
337
+ finding_type: str
338
+ outcome: Literal["finding", "quiet", "suppressed"]
339
+ severity: Severity | None = None
340
+ detail: dict[str, Any] = field(default_factory=dict)
341
+
342
+ def summary(self) -> dict[str, Any]:
343
+ """The answer as one row of the extraction view: label plus confidence."""
344
+ return {"label": self.answer, "confidence": self.certainty, **self.detail}
345
+
346
+
347
+ def _verdict(question: DecisionQuestion, answer: Mapping[str, Any]) -> _Verdict | None:
348
+ """Read one answer; None when the model did not answer in the asked type."""
349
+ if question.type == DecisionQuestionType.yes_no:
350
+ raw = _number(answer.get("noul"))
351
+ if raw is None:
352
+ return None
353
+ probability = _unit(raw)
354
+ threshold = (
355
+ question.threshold if question.threshold is not None else _DEFAULT_YES_NO_THRESHOLD
356
+ )
357
+ said_yes = probability >= threshold
358
+ return _Verdict(
359
+ question,
360
+ answer="yes" if said_yes else "no",
361
+ # How sure the model is of the answer as stated, so a "no" at 0.2
362
+ # reads as 80% no rather than 20% of something.
363
+ certainty=probability if said_yes else _unit(1.0 - probability),
364
+ finding_type=question.name,
365
+ # A "no" is never the finding: the question is asked so "yes" is.
366
+ outcome="finding" if said_yes else "quiet",
367
+ detail={"probability": probability},
368
+ )
369
+
370
+ options = question.options or []
371
+ probabilities = _number_map(answer.get("probabilities"))
372
+ threshold = question.threshold if question.threshold is not None else _DEFAULT_PICK_THRESHOLD
373
+
374
+ if question.type == DecisionQuestionType.choice:
375
+ raw_choice = answer.get("choice")
376
+ if raw_choice is None:
377
+ return None
378
+ label = _choice_label(raw_choice)
379
+ option = next((o for o in options if o.label == label), None)
380
+ if option is None:
381
+ # The model named something that was never offered. Recording it
382
+ # would invent a finding type the detector does not define.
383
+ return None
384
+ confidence = _number(answer.get("confidence"))
385
+ certainty = _unit(confidence if confidence is not None else probabilities.get(label, 0.0))
386
+ return _Verdict(
387
+ question,
388
+ answer=option.label,
389
+ certainty=certainty,
390
+ finding_type=f"{question.name}:{option.label}",
391
+ outcome=_pick_outcome(option, certainty, threshold),
392
+ severity=option.severity,
393
+ detail={"probabilities": probabilities} if probabilities else {},
394
+ )
395
+
396
+ score = _number(answer.get("score"))
397
+ if score is None or not options:
398
+ return None
399
+ # The score is the probability-weighted level, so it falls between levels.
400
+ # The level it is nearest to is the one reported.
401
+ index = min(len(options) - 1, max(0, int(score + 0.5)))
402
+ option = options[index]
403
+ confidence = _number(answer.get("confidence"))
404
+ certainty = _unit(confidence if confidence is not None else probabilities.get(str(index), 0.0))
405
+ by_label = {
406
+ options[int(key)].label: value
407
+ for key, value in probabilities.items()
408
+ if key.isdigit() and int(key) < len(options)
409
+ }
410
+ return _Verdict(
411
+ question,
412
+ answer=option.label,
413
+ certainty=certainty,
414
+ finding_type=f"{question.name}:{option.label}",
415
+ outcome=_pick_outcome(option, certainty, threshold),
416
+ severity=option.severity,
417
+ detail={
418
+ "score": round(score, 4),
419
+ "level": index,
420
+ **({"probabilities": by_label} if by_label else {}),
421
+ },
422
+ )
423
+
424
+
425
+ def _pick_outcome(
426
+ option: DecisionQuestionOption, certainty: float, threshold: float
427
+ ) -> Literal["finding", "quiet", "suppressed"]:
428
+ if option.report is False:
429
+ return "quiet"
430
+ return "finding" if certainty >= threshold else "suppressed"
431
+
432
+
433
+ def _answers_of(response: Any) -> dict[str, dict[str, Any]]:
434
+ """The response's answers as plain dicts keyed by question name."""
435
+ raw = response.get("answers") if isinstance(response, Mapping) else None
436
+ if raw is None:
437
+ raw = getattr(response, "answers", None)
438
+ if not isinstance(raw, Mapping):
439
+ raise ValueError("the provider response carries no answers")
440
+ return {str(name): _as_dict(answer) for name, answer in raw.items() if answer is not None}
441
+
442
+
443
+ def _served_model(response: Any) -> str | None:
444
+ model = response.get("model") if isinstance(response, Mapping) else None
445
+ if model is None:
446
+ model = getattr(response, "model", None)
447
+ return model if isinstance(model, str) and model.strip() else None
448
+
449
+
450
+ def _as_dict(value: Any) -> dict[str, Any]:
451
+ if isinstance(value, Mapping):
452
+ return dict(value)
453
+ dump = getattr(value, "model_dump", None)
454
+ if callable(dump):
455
+ dumped = dump()
456
+ return dict(dumped) if isinstance(dumped, Mapping) else {}
457
+ return dict(vars(value)) if hasattr(value, "__dict__") else {}
458
+
459
+
460
+ def _choice_label(value: Any) -> str:
461
+ # System One keys a boolean choice by its text; mirror that.
462
+ if isinstance(value, bool):
463
+ return "true" if value else "false"
464
+ return str(value)
465
+
466
+
467
+ def _number(value: Any) -> float | None:
468
+ if isinstance(value, bool) or not isinstance(value, int | float):
469
+ return None
470
+ return float(value)
471
+
472
+
473
+ def _number_map(value: Any) -> dict[str, float]:
474
+ if not isinstance(value, Mapping):
475
+ return {}
476
+ numbers = {str(key): _number(item) for key, item in value.items()}
477
+ return {key: round(item, 4) for key, item in numbers.items() if item is not None}
478
+
479
+
480
+ def _unit(value: float) -> float:
481
+ """Clamp to [0, 1]; a finding's confidence is stored as a probability."""
482
+ return round(min(1.0, max(0.0, value)), 4)
483
+
484
+
485
+ def _plain(value: Any) -> Any:
486
+ """Unwrap a generated RootModel wrapper to the value it holds."""
487
+ return getattr(value, "root", value)
488
+
489
+
490
+ def _string_map(value: Any) -> dict[str, str]:
491
+ if not isinstance(value, Mapping):
492
+ return {}
493
+ plain = {str(key): _plain(item) for key, item in value.items()}
494
+ return {key: item for key, item in plain.items() if isinstance(item, str) and item}
@@ -4,6 +4,7 @@ from __future__ import annotations
4
4
 
5
5
  from ....models.generated_detectors import (
6
6
  CodeDetectorPipelineSchema,
7
+ DecisionPipelineSchema,
7
8
  GLiNER2PipelineSchema,
8
9
  ImageClassificationPipelineSchema,
9
10
  LLMPipelineSchema,
@@ -14,6 +15,7 @@ from ....models.generated_detectors import (
14
15
  )
15
16
  from ._base import BaseRunner
16
17
  from ._custom_detector import CustomDetectorRunner
18
+ from ._decision import DecisionRunner
17
19
  from ._gliner2 import GLiNER2Runner
18
20
  from ._image_classification import ImageClassificationRunner
19
21
  from ._llm import LLMRunner
@@ -33,6 +35,7 @@ def create_runner(
33
35
  | ObjectDetectionPipelineSchema
34
36
  | TagPipelineSchema
35
37
  | CodeDetectorPipelineSchema
38
+ | DecisionPipelineSchema
36
39
  ),
37
40
  detector_key: str = "",
38
41
  detector_name: str = "",
@@ -48,6 +51,8 @@ def create_runner(
48
51
  return RegexRunner(schema, detector_key, detector_name)
49
52
  if isinstance(schema, LLMPipelineSchema):
50
53
  return LLMRunner(schema, detector_key, detector_name)
54
+ if isinstance(schema, DecisionPipelineSchema):
55
+ return DecisionRunner(schema, detector_key, detector_name)
51
56
  # Branched explicitly, not left to the fall-through below: a TAG schema that
52
57
  # reached the GLiNER2 default would try to load a transformer model for a
53
58
  # detector that is not supposed to run anything at all.