synapse-sdk 1.0.0a35__py3-none-any.whl → 2025.11.7__py3-none-any.whl

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.

Potentially problematic release.


This version of synapse-sdk might be problematic. Click here for more details.

Files changed (307) hide show
  1. synapse_sdk/__init__.py +24 -0
  2. synapse_sdk/cli/__init__.py +308 -5
  3. synapse_sdk/cli/alias/utils.py +1 -1
  4. synapse_sdk/cli/code_server.py +687 -0
  5. synapse_sdk/cli/config.py +440 -0
  6. synapse_sdk/cli/devtools.py +90 -0
  7. synapse_sdk/cli/plugin/publish.py +23 -15
  8. synapse_sdk/clients/agent/__init__.py +9 -3
  9. synapse_sdk/clients/agent/container.py +133 -0
  10. synapse_sdk/clients/agent/core.py +19 -0
  11. synapse_sdk/clients/agent/ray.py +298 -9
  12. synapse_sdk/clients/backend/__init__.py +28 -12
  13. synapse_sdk/clients/backend/annotation.py +9 -1
  14. synapse_sdk/clients/backend/core.py +31 -4
  15. synapse_sdk/clients/backend/data_collection.py +186 -0
  16. synapse_sdk/clients/backend/hitl.py +1 -1
  17. synapse_sdk/clients/backend/integration.py +4 -3
  18. synapse_sdk/clients/backend/ml.py +1 -1
  19. synapse_sdk/clients/backend/models.py +35 -1
  20. synapse_sdk/clients/base.py +309 -36
  21. synapse_sdk/clients/ray/serve.py +2 -0
  22. synapse_sdk/devtools/__init__.py +0 -0
  23. synapse_sdk/devtools/config.py +94 -0
  24. synapse_sdk/devtools/docs/.gitignore +20 -0
  25. synapse_sdk/devtools/docs/README.md +41 -0
  26. synapse_sdk/devtools/docs/blog/2019-05-28-first-blog-post.md +12 -0
  27. synapse_sdk/devtools/docs/blog/2019-05-29-long-blog-post.md +44 -0
  28. synapse_sdk/devtools/docs/blog/2021-08-01-mdx-blog-post.mdx +24 -0
  29. synapse_sdk/devtools/docs/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  30. synapse_sdk/devtools/docs/blog/2021-08-26-welcome/index.md +29 -0
  31. synapse_sdk/devtools/docs/blog/authors.yml +25 -0
  32. synapse_sdk/devtools/docs/blog/tags.yml +19 -0
  33. synapse_sdk/devtools/docs/docs/api/clients/agent.md +43 -0
  34. synapse_sdk/devtools/docs/docs/api/clients/annotation-mixin.md +378 -0
  35. synapse_sdk/devtools/docs/docs/api/clients/backend.md +420 -0
  36. synapse_sdk/devtools/docs/docs/api/clients/base.md +257 -0
  37. synapse_sdk/devtools/docs/docs/api/clients/core-mixin.md +477 -0
  38. synapse_sdk/devtools/docs/docs/api/clients/data-collection-mixin.md +422 -0
  39. synapse_sdk/devtools/docs/docs/api/clients/hitl-mixin.md +554 -0
  40. synapse_sdk/devtools/docs/docs/api/clients/index.md +391 -0
  41. synapse_sdk/devtools/docs/docs/api/clients/integration-mixin.md +571 -0
  42. synapse_sdk/devtools/docs/docs/api/clients/ml-mixin.md +578 -0
  43. synapse_sdk/devtools/docs/docs/api/clients/ray.md +342 -0
  44. synapse_sdk/devtools/docs/docs/api/index.md +52 -0
  45. synapse_sdk/devtools/docs/docs/api/plugins/categories.md +43 -0
  46. synapse_sdk/devtools/docs/docs/api/plugins/models.md +114 -0
  47. synapse_sdk/devtools/docs/docs/api/plugins/utils.md +328 -0
  48. synapse_sdk/devtools/docs/docs/categories.md +0 -0
  49. synapse_sdk/devtools/docs/docs/cli-usage.md +280 -0
  50. synapse_sdk/devtools/docs/docs/concepts/index.md +38 -0
  51. synapse_sdk/devtools/docs/docs/configuration.md +83 -0
  52. synapse_sdk/devtools/docs/docs/contributing.md +306 -0
  53. synapse_sdk/devtools/docs/docs/examples/index.md +29 -0
  54. synapse_sdk/devtools/docs/docs/faq.md +179 -0
  55. synapse_sdk/devtools/docs/docs/features/converters/index.md +455 -0
  56. synapse_sdk/devtools/docs/docs/features/index.md +24 -0
  57. synapse_sdk/devtools/docs/docs/features/utils/file.md +415 -0
  58. synapse_sdk/devtools/docs/docs/features/utils/network.md +378 -0
  59. synapse_sdk/devtools/docs/docs/features/utils/storage.md +57 -0
  60. synapse_sdk/devtools/docs/docs/features/utils/types.md +51 -0
  61. synapse_sdk/devtools/docs/docs/installation.md +94 -0
  62. synapse_sdk/devtools/docs/docs/introduction.md +47 -0
  63. synapse_sdk/devtools/docs/docs/plugins/categories/neural-net-plugins/train-action-overview.md +814 -0
  64. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  65. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  66. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  67. synapse_sdk/devtools/docs/docs/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  68. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
  69. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
  70. synapse_sdk/devtools/docs/docs/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
  71. synapse_sdk/devtools/docs/docs/plugins/export-plugins.md +1092 -0
  72. synapse_sdk/devtools/docs/docs/plugins/plugins.md +852 -0
  73. synapse_sdk/devtools/docs/docs/quickstart.md +78 -0
  74. synapse_sdk/devtools/docs/docs/troubleshooting.md +519 -0
  75. synapse_sdk/devtools/docs/docs/tutorial-basics/_category_.json +8 -0
  76. synapse_sdk/devtools/docs/docs/tutorial-basics/congratulations.md +23 -0
  77. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-blog-post.md +34 -0
  78. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-document.md +57 -0
  79. synapse_sdk/devtools/docs/docs/tutorial-basics/create-a-page.md +43 -0
  80. synapse_sdk/devtools/docs/docs/tutorial-basics/deploy-your-site.md +31 -0
  81. synapse_sdk/devtools/docs/docs/tutorial-basics/markdown-features.mdx +152 -0
  82. synapse_sdk/devtools/docs/docs/tutorial-extras/_category_.json +7 -0
  83. synapse_sdk/devtools/docs/docs/tutorial-extras/img/docsVersionDropdown.png +0 -0
  84. synapse_sdk/devtools/docs/docs/tutorial-extras/img/localeDropdown.png +0 -0
  85. synapse_sdk/devtools/docs/docs/tutorial-extras/manage-docs-versions.md +55 -0
  86. synapse_sdk/devtools/docs/docs/tutorial-extras/translate-your-site.md +88 -0
  87. synapse_sdk/devtools/docs/docusaurus.config.ts +148 -0
  88. synapse_sdk/devtools/docs/i18n/ko/code.json +325 -0
  89. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/agent.md +43 -0
  90. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/annotation-mixin.md +289 -0
  91. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/backend.md +420 -0
  92. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/base.md +257 -0
  93. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/core-mixin.md +417 -0
  94. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/data-collection-mixin.md +356 -0
  95. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/hitl-mixin.md +192 -0
  96. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/index.md +391 -0
  97. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/integration-mixin.md +479 -0
  98. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ml-mixin.md +284 -0
  99. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/clients/ray.md +342 -0
  100. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/index.md +52 -0
  101. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/api/plugins/models.md +114 -0
  102. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/categories.md +0 -0
  103. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/cli-usage.md +280 -0
  104. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/concepts/index.md +38 -0
  105. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/configuration.md +83 -0
  106. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/contributing.md +306 -0
  107. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/examples/index.md +29 -0
  108. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/faq.md +179 -0
  109. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/converters/index.md +30 -0
  110. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/index.md +24 -0
  111. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/file.md +415 -0
  112. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/network.md +378 -0
  113. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/storage.md +60 -0
  114. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/features/utils/types.md +51 -0
  115. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/installation.md +94 -0
  116. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/introduction.md +47 -0
  117. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/neural-net-plugins/train-action-overview.md +815 -0
  118. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/pre-annotation-plugin-overview.md +198 -0
  119. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-action-development.md +1645 -0
  120. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-overview.md +717 -0
  121. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/pre-annotation-plugins/to-task-template-development.md +1380 -0
  122. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-action.md +948 -0
  123. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-overview.md +544 -0
  124. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/categories/upload-plugins/upload-plugin-template.md +766 -0
  125. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/export-plugins.md +1092 -0
  126. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/plugins/plugins.md +117 -0
  127. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/quickstart.md +78 -0
  128. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current/troubleshooting.md +519 -0
  129. synapse_sdk/devtools/docs/i18n/ko/docusaurus-plugin-content-docs/current.json +34 -0
  130. synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/footer.json +42 -0
  131. synapse_sdk/devtools/docs/i18n/ko/docusaurus-theme-classic/navbar.json +18 -0
  132. synapse_sdk/devtools/docs/package-lock.json +18784 -0
  133. synapse_sdk/devtools/docs/package.json +48 -0
  134. synapse_sdk/devtools/docs/sidebars.ts +122 -0
  135. synapse_sdk/devtools/docs/src/components/HomepageFeatures/index.tsx +71 -0
  136. synapse_sdk/devtools/docs/src/components/HomepageFeatures/styles.module.css +11 -0
  137. synapse_sdk/devtools/docs/src/css/custom.css +30 -0
  138. synapse_sdk/devtools/docs/src/pages/index.module.css +23 -0
  139. synapse_sdk/devtools/docs/src/pages/index.tsx +21 -0
  140. synapse_sdk/devtools/docs/src/pages/markdown-page.md +7 -0
  141. synapse_sdk/devtools/docs/static/.nojekyll +0 -0
  142. synapse_sdk/devtools/docs/static/img/docusaurus-social-card.jpg +0 -0
  143. synapse_sdk/devtools/docs/static/img/docusaurus.png +0 -0
  144. synapse_sdk/devtools/docs/static/img/favicon.ico +0 -0
  145. synapse_sdk/devtools/docs/static/img/logo.png +0 -0
  146. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_mountain.svg +171 -0
  147. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_react.svg +170 -0
  148. synapse_sdk/devtools/docs/static/img/undraw_docusaurus_tree.svg +40 -0
  149. synapse_sdk/devtools/docs/tsconfig.json +8 -0
  150. synapse_sdk/devtools/server.py +41 -0
  151. synapse_sdk/devtools/streamlit_app/__init__.py +5 -0
  152. synapse_sdk/devtools/streamlit_app/app.py +128 -0
  153. synapse_sdk/devtools/streamlit_app/services/__init__.py +11 -0
  154. synapse_sdk/devtools/streamlit_app/services/job_service.py +233 -0
  155. synapse_sdk/devtools/streamlit_app/services/plugin_service.py +236 -0
  156. synapse_sdk/devtools/streamlit_app/services/serve_service.py +95 -0
  157. synapse_sdk/devtools/streamlit_app/ui/__init__.py +15 -0
  158. synapse_sdk/devtools/streamlit_app/ui/config_tab.py +76 -0
  159. synapse_sdk/devtools/streamlit_app/ui/deployment_tab.py +66 -0
  160. synapse_sdk/devtools/streamlit_app/ui/http_tab.py +125 -0
  161. synapse_sdk/devtools/streamlit_app/ui/jobs_tab.py +573 -0
  162. synapse_sdk/devtools/streamlit_app/ui/serve_tab.py +346 -0
  163. synapse_sdk/devtools/streamlit_app/ui/status_bar.py +118 -0
  164. synapse_sdk/devtools/streamlit_app/utils/__init__.py +40 -0
  165. synapse_sdk/devtools/streamlit_app/utils/json_viewer.py +197 -0
  166. synapse_sdk/devtools/streamlit_app/utils/log_formatter.py +38 -0
  167. synapse_sdk/devtools/streamlit_app/utils/styles.py +241 -0
  168. synapse_sdk/devtools/streamlit_app/utils/ui_components.py +289 -0
  169. synapse_sdk/devtools/streamlit_app.py +10 -0
  170. synapse_sdk/loggers.py +65 -7
  171. synapse_sdk/plugins/README.md +1340 -0
  172. synapse_sdk/plugins/categories/base.py +73 -11
  173. synapse_sdk/plugins/categories/data_validation/actions/validation.py +72 -0
  174. synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +33 -5
  175. synapse_sdk/plugins/categories/export/actions/__init__.py +3 -0
  176. synapse_sdk/plugins/categories/export/actions/export/__init__.py +28 -0
  177. synapse_sdk/plugins/categories/export/actions/export/action.py +165 -0
  178. synapse_sdk/plugins/categories/export/actions/export/enums.py +113 -0
  179. synapse_sdk/plugins/categories/export/actions/export/exceptions.py +53 -0
  180. synapse_sdk/plugins/categories/export/actions/export/models.py +74 -0
  181. synapse_sdk/plugins/categories/export/actions/export/run.py +195 -0
  182. synapse_sdk/plugins/categories/export/actions/{export.py → export/utils.py} +47 -82
  183. synapse_sdk/plugins/categories/export/templates/config.yaml +19 -1
  184. synapse_sdk/plugins/categories/export/templates/plugin/__init__.py +390 -0
  185. synapse_sdk/plugins/categories/export/templates/plugin/export.py +153 -129
  186. synapse_sdk/plugins/categories/neural_net/actions/deployment.py +9 -62
  187. synapse_sdk/plugins/categories/neural_net/actions/train.py +1062 -32
  188. synapse_sdk/plugins/categories/neural_net/actions/tune.py +534 -0
  189. synapse_sdk/plugins/categories/neural_net/templates/config.yaml +27 -5
  190. synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +26 -10
  191. synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +4 -0
  192. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/__init__.py +3 -0
  193. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation/action.py +10 -0
  194. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/__init__.py +28 -0
  195. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/action.py +145 -0
  196. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/enums.py +269 -0
  197. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/exceptions.py +14 -0
  198. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/factory.py +76 -0
  199. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/models.py +97 -0
  200. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/orchestrator.py +250 -0
  201. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/run.py +64 -0
  202. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/__init__.py +17 -0
  203. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/annotation.py +287 -0
  204. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/base.py +170 -0
  205. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/extraction.py +83 -0
  206. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/metrics.py +87 -0
  207. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/preprocessor.py +127 -0
  208. synapse_sdk/plugins/categories/pre_annotation/actions/to_task/strategies/validation.py +143 -0
  209. synapse_sdk/plugins/categories/pre_annotation/actions/to_task.py +966 -0
  210. synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +19 -0
  211. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/to_task.py +40 -0
  212. synapse_sdk/plugins/categories/upload/actions/upload/__init__.py +19 -0
  213. synapse_sdk/plugins/categories/upload/actions/upload/action.py +232 -0
  214. synapse_sdk/plugins/categories/upload/actions/upload/context.py +185 -0
  215. synapse_sdk/plugins/categories/upload/actions/upload/enums.py +471 -0
  216. synapse_sdk/plugins/categories/upload/actions/upload/exceptions.py +36 -0
  217. synapse_sdk/plugins/categories/upload/actions/upload/factory.py +138 -0
  218. synapse_sdk/plugins/categories/upload/actions/upload/models.py +203 -0
  219. synapse_sdk/plugins/categories/upload/actions/upload/orchestrator.py +183 -0
  220. synapse_sdk/plugins/categories/upload/actions/upload/registry.py +113 -0
  221. synapse_sdk/plugins/categories/upload/actions/upload/run.py +179 -0
  222. synapse_sdk/plugins/categories/upload/actions/upload/steps/__init__.py +1 -0
  223. synapse_sdk/plugins/categories/upload/actions/upload/steps/base.py +107 -0
  224. synapse_sdk/plugins/categories/upload/actions/upload/steps/cleanup.py +62 -0
  225. synapse_sdk/plugins/categories/upload/actions/upload/steps/collection.py +63 -0
  226. synapse_sdk/plugins/categories/upload/actions/upload/steps/generate.py +84 -0
  227. synapse_sdk/plugins/categories/upload/actions/upload/steps/initialize.py +82 -0
  228. synapse_sdk/plugins/categories/upload/actions/upload/steps/metadata.py +235 -0
  229. synapse_sdk/plugins/categories/upload/actions/upload/steps/organize.py +203 -0
  230. synapse_sdk/plugins/categories/upload/actions/upload/steps/upload.py +97 -0
  231. synapse_sdk/plugins/categories/upload/actions/upload/steps/validate.py +71 -0
  232. synapse_sdk/plugins/categories/upload/actions/upload/strategies/__init__.py +1 -0
  233. synapse_sdk/plugins/categories/upload/actions/upload/strategies/base.py +82 -0
  234. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/__init__.py +1 -0
  235. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/batch.py +39 -0
  236. synapse_sdk/plugins/categories/upload/actions/upload/strategies/data_unit/single.py +29 -0
  237. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/__init__.py +1 -0
  238. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/flat.py +258 -0
  239. synapse_sdk/plugins/categories/upload/actions/upload/strategies/file_discovery/recursive.py +281 -0
  240. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/__init__.py +1 -0
  241. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/excel.py +174 -0
  242. synapse_sdk/plugins/categories/upload/actions/upload/strategies/metadata/none.py +16 -0
  243. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/__init__.py +1 -0
  244. synapse_sdk/plugins/categories/upload/actions/upload/strategies/upload/sync.py +84 -0
  245. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/__init__.py +1 -0
  246. synapse_sdk/plugins/categories/upload/actions/upload/strategies/validation/default.py +60 -0
  247. synapse_sdk/plugins/categories/upload/actions/upload/utils.py +250 -0
  248. synapse_sdk/plugins/categories/upload/templates/README.md +470 -0
  249. synapse_sdk/plugins/categories/upload/templates/config.yaml +29 -2
  250. synapse_sdk/plugins/categories/upload/templates/plugin/__init__.py +294 -0
  251. synapse_sdk/plugins/categories/upload/templates/plugin/upload.py +88 -30
  252. synapse_sdk/plugins/models.py +122 -16
  253. synapse_sdk/plugins/templates/plugin-config-schema.json +406 -0
  254. synapse_sdk/plugins/templates/schema.json +491 -0
  255. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +1 -1
  256. synapse_sdk/plugins/utils/__init__.py +46 -0
  257. synapse_sdk/plugins/utils/actions.py +119 -0
  258. synapse_sdk/plugins/utils/config.py +203 -0
  259. synapse_sdk/plugins/{utils.py → utils/legacy.py} +26 -46
  260. synapse_sdk/plugins/utils/ray_gcs.py +66 -0
  261. synapse_sdk/plugins/utils/registry.py +58 -0
  262. synapse_sdk/shared/__init__.py +25 -0
  263. synapse_sdk/shared/enums.py +93 -0
  264. synapse_sdk/utils/converters/__init__.py +240 -0
  265. synapse_sdk/utils/converters/coco/__init__.py +0 -0
  266. synapse_sdk/utils/converters/coco/from_dm.py +322 -0
  267. synapse_sdk/utils/converters/coco/to_dm.py +215 -0
  268. synapse_sdk/utils/converters/dm/__init__.py +56 -0
  269. synapse_sdk/utils/converters/dm/from_v1.py +627 -0
  270. synapse_sdk/utils/converters/dm/to_v1.py +367 -0
  271. synapse_sdk/utils/converters/pascal/__init__.py +0 -0
  272. synapse_sdk/utils/converters/pascal/from_dm.py +244 -0
  273. synapse_sdk/utils/converters/pascal/to_dm.py +214 -0
  274. synapse_sdk/utils/converters/yolo/__init__.py +0 -0
  275. synapse_sdk/utils/converters/yolo/from_dm.py +384 -0
  276. synapse_sdk/utils/converters/yolo/to_dm.py +267 -0
  277. synapse_sdk/utils/dataset.py +46 -0
  278. synapse_sdk/utils/encryption.py +158 -0
  279. synapse_sdk/utils/file/__init__.py +39 -0
  280. synapse_sdk/utils/file/archive.py +32 -0
  281. synapse_sdk/utils/file/checksum.py +56 -0
  282. synapse_sdk/utils/file/chunking.py +31 -0
  283. synapse_sdk/utils/file/download.py +385 -0
  284. synapse_sdk/utils/file/encoding.py +40 -0
  285. synapse_sdk/utils/file/io.py +22 -0
  286. synapse_sdk/utils/file/video/__init__.py +29 -0
  287. synapse_sdk/utils/file/video/transcode.py +307 -0
  288. synapse_sdk/utils/{file.py → file.py.backup} +84 -2
  289. synapse_sdk/utils/http.py +138 -0
  290. synapse_sdk/utils/network.py +293 -0
  291. synapse_sdk/utils/storage/__init__.py +36 -2
  292. synapse_sdk/utils/storage/providers/__init__.py +141 -0
  293. synapse_sdk/utils/storage/providers/file_system.py +134 -0
  294. synapse_sdk/utils/storage/providers/http.py +190 -0
  295. synapse_sdk/utils/storage/providers/s3.py +54 -6
  296. synapse_sdk/utils/storage/providers/sftp.py +31 -0
  297. synapse_sdk/utils/storage/registry.py +6 -0
  298. synapse_sdk-2025.11.7.dist-info/METADATA +122 -0
  299. synapse_sdk-2025.11.7.dist-info/RECORD +386 -0
  300. {synapse_sdk-1.0.0a35.dist-info → synapse_sdk-2025.11.7.dist-info}/WHEEL +1 -1
  301. synapse_sdk/clients/backend/dataset.py +0 -102
  302. synapse_sdk/plugins/categories/upload/actions/upload.py +0 -293
  303. synapse_sdk-1.0.0a35.dist-info/METADATA +0 -47
  304. synapse_sdk-1.0.0a35.dist-info/RECORD +0 -137
  305. {synapse_sdk-1.0.0a35.dist-info → synapse_sdk-2025.11.7.dist-info}/entry_points.txt +0 -0
  306. {synapse_sdk-1.0.0a35.dist-info → synapse_sdk-2025.11.7.dist-info}/licenses/LICENSE +0 -0
  307. {synapse_sdk-1.0.0a35.dist-info → synapse_sdk-2025.11.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,170 @@
1
+ """Abstract base classes for ToTask strategies."""
2
+
3
+ from abc import ABC, abstractmethod
4
+ from typing import Any, Dict, List, Optional, Tuple
5
+
6
+ from synapse_sdk.clients.backend import BackendClient
7
+
8
+ from ..enums import AnnotationMethod
9
+ from ..models import MetricsRecord
10
+
11
+
12
+ class ToTaskContext:
13
+ """Shared context for ToTask action execution."""
14
+
15
+ def __init__(
16
+ self,
17
+ params: Dict[str, Any],
18
+ client: BackendClient,
19
+ logger: Any,
20
+ entrypoint: Any = None,
21
+ config: Optional[Dict[str, Any]] = None,
22
+ plugin_config: Optional[Dict[str, Any]] = None,
23
+ job_id: Optional[str] = None,
24
+ progress_categories: Optional[Dict[str, Any]] = None,
25
+ metrics_categories: Optional[Dict[str, Any]] = None,
26
+ project: Optional[Dict[str, Any]] = None,
27
+ data_collection: Optional[Dict[str, Any]] = None,
28
+ task_ids: Optional[List[int]] = None,
29
+ metrics: Optional[MetricsRecord] = None,
30
+ annotation_method: Optional[AnnotationMethod] = None,
31
+ ):
32
+ self.params = params
33
+ self.client = client
34
+ self.logger = logger
35
+ self.entrypoint = entrypoint
36
+ self.config = config
37
+ self.plugin_config = plugin_config
38
+ self.job_id = job_id
39
+ self.progress_categories = progress_categories
40
+ self.metrics_categories = metrics_categories
41
+ self.project = project
42
+ self.data_collection = data_collection
43
+ self.task_ids = task_ids or []
44
+ self.metrics = metrics or MetricsRecord(stand_by=0, failed=0, success=0)
45
+ self.annotation_method = annotation_method
46
+ self.temp_files: List[str] = []
47
+ self.rollback_actions: List[callable] = []
48
+
49
+ def add_temp_file(self, file_path: str):
50
+ """Track temporary files for cleanup."""
51
+ self.temp_files.append(file_path)
52
+
53
+ def add_rollback_action(self, action: callable):
54
+ """Add rollback action for error recovery."""
55
+ self.rollback_actions.append(action)
56
+
57
+ def update_metrics(self, success_count: int, failed_count: int, total_count: int):
58
+ """Update execution metrics."""
59
+ self.metrics = MetricsRecord(
60
+ stand_by=total_count - success_count - failed_count, failed=failed_count, success=success_count
61
+ )
62
+
63
+
64
+ class ValidationStrategy(ABC):
65
+ """Abstract base class for validation strategies."""
66
+
67
+ @abstractmethod
68
+ def validate(self, context: ToTaskContext) -> Dict[str, Any]:
69
+ """Validate specific aspects of the ToTask execution.
70
+
71
+ Args:
72
+ context: Shared context for the action execution
73
+
74
+ Returns:
75
+ Dict with 'success' boolean and optional 'error' message
76
+ """
77
+ pass
78
+
79
+
80
+ class AnnotationStrategy(ABC):
81
+ """Abstract base class for annotation strategies."""
82
+
83
+ @abstractmethod
84
+ def process_task(self, context: ToTaskContext, task_id: int, task_data: Dict[str, Any], **kwargs) -> Dict[str, Any]:
85
+ """Process a single task for annotation.
86
+
87
+ Args:
88
+ context: Shared context for the action execution
89
+ task_id: The task ID to process
90
+ task_data: The task data dictionary
91
+ **kwargs: Additional method-specific parameters
92
+
93
+ Returns:
94
+ Dict with 'success' boolean and optional 'error' message
95
+ """
96
+ pass
97
+
98
+
99
+ class PreProcessorStrategy(ABC):
100
+ """Abstract base class for pre-processor management strategies."""
101
+
102
+ @abstractmethod
103
+ def get_preprocessor_info(self, context: ToTaskContext, preprocessor_id: int) -> Dict[str, Any]:
104
+ """Get pre-processor information.
105
+
106
+ Args:
107
+ context: Shared context for the action execution
108
+ preprocessor_id: The pre-processor ID
109
+
110
+ Returns:
111
+ Dict with pre-processor info or error
112
+ """
113
+ pass
114
+
115
+ @abstractmethod
116
+ def ensure_preprocessor_running(self, context: ToTaskContext, preprocessor_code: str) -> Dict[str, Any]:
117
+ """Ensure pre-processor is running.
118
+
119
+ Args:
120
+ context: Shared context for the action execution
121
+ preprocessor_code: The pre-processor code
122
+
123
+ Returns:
124
+ Dict indicating success or failure
125
+ """
126
+ pass
127
+
128
+
129
+ class DataExtractionStrategy(ABC):
130
+ """Abstract base class for data extraction strategies."""
131
+
132
+ @abstractmethod
133
+ def extract_data(self, context: ToTaskContext, task_data: Dict[str, Any]) -> Tuple[Optional[str], Optional[str]]:
134
+ """Extract required data from task.
135
+
136
+ Args:
137
+ context: Shared context for the action execution
138
+ task_data: The task data dictionary
139
+
140
+ Returns:
141
+ Tuple of extracted data values
142
+ """
143
+ pass
144
+
145
+
146
+ class MetricsStrategy(ABC):
147
+ """Abstract base class for metrics strategies."""
148
+
149
+ @abstractmethod
150
+ def update_progress(self, context: ToTaskContext, current: int, total: int):
151
+ """Update progress tracking.
152
+
153
+ Args:
154
+ context: Shared context for the action execution
155
+ current: Current progress count
156
+ total: Total items to process
157
+ """
158
+ pass
159
+
160
+ @abstractmethod
161
+ def record_task_result(self, context: ToTaskContext, task_id: int, success: bool, error: Optional[str] = None):
162
+ """Record the result of processing a single task.
163
+
164
+ Args:
165
+ context: Shared context for the action execution
166
+ task_id: The task ID that was processed
167
+ success: Whether the task processing was successful
168
+ error: Error message if unsuccessful
169
+ """
170
+ pass
@@ -0,0 +1,83 @@
1
+ """Data extraction strategies for ToTask action."""
2
+
3
+ from typing import Any, Dict, Optional, Tuple
4
+
5
+ from .base import DataExtractionStrategy, ToTaskContext
6
+
7
+
8
+ class FileUrlExtractionStrategy(DataExtractionStrategy):
9
+ """Strategy for extracting file URLs from task data."""
10
+
11
+ def extract_data(self, context: ToTaskContext, task_data: Dict[str, Any]) -> str | None:
12
+ """Extract primary file URL from task data.
13
+
14
+ Args:
15
+ context: Shared context for the action execution
16
+ task_data: The task data dictionary
17
+
18
+ Returns:
19
+ str: The primary file URL or None if not found
20
+ """
21
+ try:
22
+ # This implementation follows the original _extract_primary_file_url logic
23
+ data_unit = task_data.get('data_unit')
24
+ if not data_unit:
25
+ return None
26
+
27
+ data_unit_files = data_unit.get('files', {})
28
+ if not data_unit_files:
29
+ return None
30
+
31
+ # Find primary file URL
32
+ for key in data_unit_files:
33
+ if data_unit_files[key]['is_primary']:
34
+ return data_unit_files[key]['url']
35
+
36
+ return None
37
+
38
+ except Exception as e:
39
+ context.logger.log_message_with_code(
40
+ context.logger.LogCode.DATA_EXTRACTION_FAILED
41
+ if hasattr(context.logger, 'LogCode')
42
+ else 'DATA_EXTRACTION_FAILED',
43
+ str(e),
44
+ )
45
+ return None
46
+
47
+
48
+ class InferenceDataExtractionStrategy(DataExtractionStrategy):
49
+ """Strategy for extracting inference data from task data."""
50
+
51
+ def extract_data(self, context: ToTaskContext, task_data: Dict[str, Any]) -> Tuple[Optional[str], Optional[str]]:
52
+ """Extract data needed for inference processing.
53
+
54
+ Args:
55
+ context: Shared context for the action execution
56
+ task_data: The task data dictionary
57
+
58
+ Returns:
59
+ Tuple of (primary_file_url, inference_metadata)
60
+ """
61
+ try:
62
+ # Reuse the file URL extraction logic
63
+ file_strategy = FileUrlExtractionStrategy()
64
+ primary_url = file_strategy.extract_data(context, task_data)
65
+
66
+ # Extract additional inference-specific metadata
67
+ data_unit = task_data.get('data_unit', {})
68
+ inference_metadata = {
69
+ 'data_unit_id': data_unit.get('id'),
70
+ 'task_id': task_data.get('id'),
71
+ 'additional_params': context.params.get('inference_params', {}),
72
+ }
73
+
74
+ return primary_url, str(inference_metadata) if inference_metadata else None
75
+
76
+ except Exception as e:
77
+ context.logger.log_message_with_code(
78
+ context.logger.LogCode.DATA_EXTRACTION_FAILED
79
+ if hasattr(context.logger, 'LogCode')
80
+ else 'DATA_EXTRACTION_FAILED',
81
+ str(e),
82
+ )
83
+ return None, None
@@ -0,0 +1,87 @@
1
+ """Metrics and progress tracking strategies for ToTask action."""
2
+
3
+ from typing import Optional
4
+
5
+ from ..enums import AnnotateTaskDataStatus, LogCode
6
+ from .base import MetricsStrategy, ToTaskContext
7
+
8
+
9
+ class ProgressTrackingStrategy(MetricsStrategy):
10
+ """Strategy for tracking progress and metrics during task processing."""
11
+
12
+ def update_progress(self, context: ToTaskContext, current: int, total: int):
13
+ """Update progress tracking.
14
+
15
+ Args:
16
+ context: Shared context for the action execution
17
+ current: Current progress count
18
+ total: Total items to process
19
+ """
20
+ try:
21
+ context.logger.set_progress(current, total, category='annotate_task_data')
22
+ except Exception as e:
23
+ context.logger.log_message_with_code(LogCode.PROGRESS_UPDATE_FAILED, str(e))
24
+
25
+ def record_task_result(self, context: ToTaskContext, task_id: int, success: bool, error: Optional[str] = None):
26
+ """Record the result of processing a single task.
27
+
28
+ Args:
29
+ context: Shared context for the action execution
30
+ task_id: The task ID that was processed
31
+ success: Whether the task processing was successful
32
+ error: Error message if unsuccessful
33
+ """
34
+ try:
35
+ if success:
36
+ status = AnnotateTaskDataStatus.SUCCESS
37
+ log_data = {'task_id': task_id}
38
+ else:
39
+ status = AnnotateTaskDataStatus.FAILED
40
+ log_data = {'task_id': task_id, 'error': error or 'Unknown error'}
41
+
42
+ context.logger.log_annotate_task_data(log_data, status)
43
+
44
+ except Exception as e:
45
+ context.logger.log_message_with_code(LogCode.METRICS_RECORDING_FAILED, str(e))
46
+
47
+ def update_metrics(self, context: ToTaskContext, total_tasks: int, success_count: int, failed_count: int):
48
+ """Update execution metrics.
49
+
50
+ Args:
51
+ context: Shared context for the action execution
52
+ total_tasks: Total number of tasks
53
+ success_count: Number of successful tasks
54
+ failed_count: Number of failed tasks
55
+ """
56
+ try:
57
+ stand_by_count = total_tasks - success_count - failed_count
58
+ context.update_metrics(success_count, failed_count, total_tasks)
59
+
60
+ # Update metrics in the logger
61
+ metrics_data = {
62
+ 'stand_by': stand_by_count,
63
+ 'failed': failed_count,
64
+ 'success': success_count,
65
+ }
66
+ context.logger.log_metrics(metrics_data, 'annotate_task_data')
67
+
68
+ except Exception as e:
69
+ context.logger.log_message_with_code(LogCode.METRICS_UPDATE_FAILED, str(e))
70
+
71
+ def finalize_metrics(self, context: ToTaskContext):
72
+ """Finalize metrics at the end of processing.
73
+
74
+ Args:
75
+ context: Shared context for the action execution
76
+ """
77
+ try:
78
+ metrics = context.metrics
79
+ total_tasks = len(context.task_ids)
80
+
81
+ context.logger.log_message_with_code(LogCode.ANNOTATION_COMPLETED, metrics.success, metrics.failed)
82
+
83
+ # Final progress update
84
+ self.update_progress(context, total_tasks, total_tasks)
85
+
86
+ except Exception as e:
87
+ context.logger.log_message_with_code(LogCode.METRICS_FINALIZATION_FAILED, str(e))
@@ -0,0 +1,127 @@
1
+ """Pre-processor management strategies for ToTask action."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from .base import PreProcessorStrategy, ToTaskContext
6
+
7
+
8
+ class PreProcessorManagementStrategy(PreProcessorStrategy):
9
+ """Strategy for managing pre-processor lifecycle."""
10
+
11
+ def get_preprocessor_info(self, context: ToTaskContext, preprocessor_id: int) -> Dict[str, Any]:
12
+ """Get pre-processor information from the backend.
13
+
14
+ Args:
15
+ context: Shared context for the action execution
16
+ preprocessor_id: The pre-processor ID
17
+
18
+ Returns:
19
+ Dict with pre-processor info or error
20
+ """
21
+ try:
22
+ client = context.client
23
+ pre_processor_response = client.get_plugin_release(preprocessor_id)
24
+ if isinstance(pre_processor_response, str):
25
+ return {'success': False, 'error': 'Invalid pre-processor response received'}
26
+
27
+ pre_processor: Dict[str, Any] = pre_processor_response
28
+ config = pre_processor.get('config', {})
29
+ code = config.get('code')
30
+ version = pre_processor.get('version')
31
+
32
+ if not code or not version:
33
+ return {'success': False, 'error': 'Invalid pre-processor configuration'}
34
+
35
+ return {'success': True, 'code': code, 'version': version}
36
+ except Exception as e:
37
+ return {'success': False, 'error': f'Failed to get pre-processor info: {str(e)}'}
38
+
39
+ def ensure_preprocessor_running(self, context: ToTaskContext, preprocessor_code: str) -> Dict[str, Any]:
40
+ """Ensure the pre-processor is running, restart if necessary.
41
+
42
+ Args:
43
+ context: Shared context for the action execution
44
+ preprocessor_code: The pre-processor code
45
+
46
+ Returns:
47
+ Dict indicating success or failure
48
+ """
49
+ try:
50
+ client = context.client
51
+
52
+ # Check if pre-processor is running
53
+ serve_applications_response = client.list_serve_applications(params={'plugin_code': preprocessor_code})
54
+ if isinstance(serve_applications_response, str):
55
+ return {'success': False, 'error': 'Invalid serve applications response'}
56
+
57
+ # Handle the response properly - it should be a dict with 'results' key
58
+ if not isinstance(serve_applications_response, dict):
59
+ return {'success': False, 'error': 'Unexpected serve applications response format'}
60
+
61
+ serve_applications: Dict[str, Any] = serve_applications_response
62
+ results = serve_applications.get('results', [])
63
+ running_serve_apps = [app for app in results if isinstance(app, dict) and app.get('status') == 'RUNNING']
64
+
65
+ # If not running, restart the pre-processor
66
+ if not running_serve_apps:
67
+ restart_result = self._restart_preprocessor(context, preprocessor_code)
68
+ if not restart_result['success']:
69
+ return restart_result
70
+
71
+ # Verify restart was successful
72
+ serve_applications_response = client.list_serve_applications(params={'plugin_code': preprocessor_code})
73
+ if isinstance(serve_applications_response, str):
74
+ return {'success': False, 'error': 'Failed to verify pre-processor restart'}
75
+
76
+ serve_applications = serve_applications_response
77
+ results = serve_applications.get('results', [])
78
+ running_serve_apps = [
79
+ app for app in results if isinstance(app, dict) and app.get('status') == 'RUNNING'
80
+ ]
81
+
82
+ if not running_serve_apps:
83
+ return {'success': False, 'error': 'Pre-processor failed to start after restart'}
84
+
85
+ return {'success': True}
86
+
87
+ except Exception as e:
88
+ return {'success': False, 'error': f'Failed to ensure pre-processor running: {str(e)}'}
89
+
90
+ def _restart_preprocessor(self, context: ToTaskContext, preprocessor_code: str) -> Dict[str, Any]:
91
+ """Restart the pre-processor.
92
+
93
+ Args:
94
+ context: Shared context for the action execution
95
+ preprocessor_code: The pre-processor code
96
+
97
+ Returns:
98
+ Dict indicating success or failure
99
+ """
100
+ try:
101
+ client = context.client
102
+
103
+ # Start the serve application
104
+ inference_options = context.config.get('inference_options', {})
105
+ serve_application_deployment_payload = {
106
+ 'agent': context.params.get('agent') if context.params else None,
107
+ 'action': 'deployment',
108
+ 'params': {
109
+ 'num_cpus': inference_options.get('required_cpu_count', 2),
110
+ 'num_gpus': inference_options.get('required_gpu_count', 1),
111
+ },
112
+ 'debug': True,
113
+ }
114
+
115
+ deployment_result = client.run_plugin(
116
+ preprocessor_code,
117
+ serve_application_deployment_payload,
118
+ )
119
+
120
+ deployment_job_id = deployment_result.get('job_id')
121
+ if not deployment_job_id:
122
+ return {'success': False, 'error': 'No deployment job ID returned'}
123
+
124
+ return {'success': True, 'error': 'Pre-processor restarted successfully'}
125
+
126
+ except Exception as e:
127
+ return {'success': False, 'error': f'Failed to restart pre-processor: {str(e)}'}
@@ -0,0 +1,143 @@
1
+ """Validation strategies for ToTask action."""
2
+
3
+ from typing import Any, Dict
4
+
5
+ from ..enums import LogCode
6
+ from .base import ToTaskContext, ValidationStrategy
7
+
8
+
9
+ class ProjectValidationStrategy(ValidationStrategy):
10
+ """Strategy for validating project and data collection."""
11
+
12
+ def validate(self, context: ToTaskContext) -> Dict[str, Any]:
13
+ """Validate project and data collection exist and are accessible.
14
+
15
+ Args:
16
+ context: Shared context for the action execution
17
+
18
+ Returns:
19
+ Dict with 'success' boolean and optional 'error' message
20
+ """
21
+ try:
22
+ client = context.client
23
+ project_id = context.params['project']
24
+
25
+ # Validate project response
26
+ project_response = client.get_project(project_id)
27
+ if isinstance(project_response, str):
28
+ context.logger.log_message_with_code(LogCode.INVALID_PROJECT_RESPONSE)
29
+ return {'success': False, 'error': 'Invalid project response received'}
30
+
31
+ project: Dict[str, Any] = project_response
32
+ context.project = project
33
+
34
+ # Validate data collection exists
35
+ data_collection_id = project.get('data_collection')
36
+ if not data_collection_id:
37
+ context.logger.log_message_with_code(LogCode.NO_DATA_COLLECTION)
38
+ return {'success': False, 'error': 'Project does not have a data collection'}
39
+
40
+ # Validate data collection response
41
+ data_collection_response = client.get_data_collection(data_collection_id)
42
+ if isinstance(data_collection_response, str):
43
+ context.logger.log_message_with_code(LogCode.INVALID_DATA_COLLECTION_RESPONSE)
44
+ return {'success': False, 'error': 'Invalid data collection response received'}
45
+
46
+ data_collection: Dict[str, Any] = data_collection_response
47
+ context.data_collection = data_collection
48
+
49
+ return {'success': True}
50
+
51
+ except Exception as e:
52
+ error_msg = f'Project validation failed: {str(e)}'
53
+ context.logger.log_message_with_code(LogCode.VALIDATION_FAILED, error_msg)
54
+ return {'success': False, 'error': error_msg}
55
+
56
+
57
+ class TaskValidationStrategy(ValidationStrategy):
58
+ """Strategy for validating and discovering tasks."""
59
+
60
+ def validate(self, context: ToTaskContext) -> Dict[str, Any]:
61
+ """Discover and validate tasks for processing.
62
+
63
+ Args:
64
+ context: Shared context for the action execution
65
+
66
+ Returns:
67
+ Dict with 'success' boolean and optional 'error' message
68
+ """
69
+ try:
70
+ client = context.client
71
+
72
+ # Build task query parameters
73
+ task_ids_query_params = {
74
+ 'project': context.params['project'],
75
+ 'fields': 'id',
76
+ }
77
+ if context.params.get('task_filters'):
78
+ task_ids_query_params.update(context.params['task_filters'])
79
+
80
+ # Get tasks
81
+ task_ids_generator, task_ids_count = client.list_tasks(params=task_ids_query_params, list_all=True)
82
+ task_ids = [
83
+ int(item.get('id', 0)) for item in task_ids_generator if isinstance(item, dict) and item.get('id')
84
+ ]
85
+
86
+ # Validate tasks found
87
+ if not task_ids_count:
88
+ context.logger.log_message_with_code(LogCode.NO_TASKS_FOUND)
89
+ return {'success': False, 'error': 'No tasks found to annotate'}
90
+
91
+ context.task_ids = task_ids
92
+ return {'success': True, 'task_count': len(task_ids)}
93
+
94
+ except Exception as e:
95
+ error_msg = f'Task validation failed: {str(e)}'
96
+ context.logger.log_message_with_code(LogCode.VALIDATION_FAILED, error_msg)
97
+ return {'success': False, 'error': error_msg}
98
+
99
+
100
+ class TargetSpecificationValidationStrategy(ValidationStrategy):
101
+ """Strategy for validating target specification for file annotation."""
102
+
103
+ def validate(self, context: ToTaskContext) -> Dict[str, Any]:
104
+ """Validate target specification exists in file specifications.
105
+
106
+ Args:
107
+ context: Shared context for the action execution
108
+
109
+ Returns:
110
+ Dict with 'success' boolean and optional 'error' message
111
+ """
112
+ try:
113
+ # Only validate if using FILE annotation method
114
+ from ..enums import AnnotationMethod
115
+
116
+ if context.annotation_method != AnnotationMethod.FILE:
117
+ return {'success': True}
118
+
119
+ target_specification_name = context.params.get('target_specification_name')
120
+ if not target_specification_name:
121
+ context.logger.log_message_with_code(LogCode.TARGET_SPEC_REQUIRED)
122
+ return {'success': False, 'error': 'Target specification name is required for file annotation method'}
123
+
124
+ # Check if target specification exists in file specifications
125
+ if not context.data_collection:
126
+ return {'success': False, 'error': 'Data collection not available for validation'}
127
+
128
+ file_specifications = context.data_collection.get('file_specifications', [])
129
+ target_spec_exists = any(spec.get('name') == target_specification_name for spec in file_specifications)
130
+
131
+ if not target_spec_exists:
132
+ context.logger.log_message_with_code(LogCode.TARGET_SPEC_NOT_FOUND, target_specification_name)
133
+ return {
134
+ 'success': False,
135
+ 'error': f"Target specification '{target_specification_name}' not found in file specifications",
136
+ }
137
+
138
+ return {'success': True}
139
+
140
+ except Exception as e:
141
+ error_msg = f'Target specification validation failed: {str(e)}'
142
+ context.logger.log_message_with_code(LogCode.VALIDATION_FAILED, error_msg)
143
+ return {'success': False, 'error': error_msg}