synapse-sdk 1.0.0a11__py3-none-any.whl → 2026.1.1b2__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 (261) hide show
  1. synapse_sdk/__init__.py +24 -0
  2. synapse_sdk/cli/__init__.py +9 -8
  3. synapse_sdk/cli/agent/__init__.py +25 -0
  4. synapse_sdk/cli/agent/config.py +104 -0
  5. synapse_sdk/cli/agent/select.py +197 -0
  6. synapse_sdk/cli/auth.py +104 -0
  7. synapse_sdk/cli/main.py +1025 -0
  8. synapse_sdk/cli/plugin/__init__.py +58 -0
  9. synapse_sdk/cli/plugin/create.py +566 -0
  10. synapse_sdk/cli/plugin/job.py +196 -0
  11. synapse_sdk/cli/plugin/publish.py +322 -0
  12. synapse_sdk/cli/plugin/run.py +131 -0
  13. synapse_sdk/cli/plugin/test.py +200 -0
  14. synapse_sdk/clients/README.md +239 -0
  15. synapse_sdk/clients/__init__.py +5 -0
  16. synapse_sdk/clients/_template.py +266 -0
  17. synapse_sdk/clients/agent/__init__.py +84 -29
  18. synapse_sdk/clients/agent/async_ray.py +289 -0
  19. synapse_sdk/clients/agent/container.py +83 -0
  20. synapse_sdk/clients/agent/plugin.py +101 -0
  21. synapse_sdk/clients/agent/ray.py +296 -39
  22. synapse_sdk/clients/backend/__init__.py +152 -12
  23. synapse_sdk/clients/backend/annotation.py +164 -22
  24. synapse_sdk/clients/backend/core.py +101 -0
  25. synapse_sdk/clients/backend/data_collection.py +292 -0
  26. synapse_sdk/clients/backend/hitl.py +87 -0
  27. synapse_sdk/clients/backend/integration.py +374 -46
  28. synapse_sdk/clients/backend/ml.py +134 -22
  29. synapse_sdk/clients/backend/models.py +247 -0
  30. synapse_sdk/clients/base.py +538 -59
  31. synapse_sdk/clients/exceptions.py +35 -7
  32. synapse_sdk/clients/pipeline/__init__.py +5 -0
  33. synapse_sdk/clients/pipeline/client.py +636 -0
  34. synapse_sdk/clients/protocols.py +178 -0
  35. synapse_sdk/clients/utils.py +86 -8
  36. synapse_sdk/clients/validation.py +58 -0
  37. synapse_sdk/enums.py +76 -0
  38. synapse_sdk/exceptions.py +168 -0
  39. synapse_sdk/integrations/__init__.py +74 -0
  40. synapse_sdk/integrations/_base.py +119 -0
  41. synapse_sdk/integrations/_context.py +53 -0
  42. synapse_sdk/integrations/ultralytics/__init__.py +78 -0
  43. synapse_sdk/integrations/ultralytics/_callbacks.py +126 -0
  44. synapse_sdk/integrations/ultralytics/_patches.py +124 -0
  45. synapse_sdk/loggers.py +476 -95
  46. synapse_sdk/mcp/MCP.md +69 -0
  47. synapse_sdk/mcp/__init__.py +48 -0
  48. synapse_sdk/mcp/__main__.py +6 -0
  49. synapse_sdk/mcp/config.py +349 -0
  50. synapse_sdk/mcp/prompts/__init__.py +4 -0
  51. synapse_sdk/mcp/resources/__init__.py +4 -0
  52. synapse_sdk/mcp/server.py +1352 -0
  53. synapse_sdk/mcp/tools/__init__.py +6 -0
  54. synapse_sdk/plugins/__init__.py +133 -9
  55. synapse_sdk/plugins/action.py +229 -0
  56. synapse_sdk/plugins/actions/__init__.py +82 -0
  57. synapse_sdk/plugins/actions/dataset/__init__.py +37 -0
  58. synapse_sdk/plugins/actions/dataset/action.py +471 -0
  59. synapse_sdk/plugins/actions/export/__init__.py +55 -0
  60. synapse_sdk/plugins/actions/export/action.py +183 -0
  61. synapse_sdk/plugins/actions/export/context.py +59 -0
  62. synapse_sdk/plugins/actions/inference/__init__.py +84 -0
  63. synapse_sdk/plugins/actions/inference/action.py +285 -0
  64. synapse_sdk/plugins/actions/inference/context.py +81 -0
  65. synapse_sdk/plugins/actions/inference/deployment.py +322 -0
  66. synapse_sdk/plugins/actions/inference/serve.py +252 -0
  67. synapse_sdk/plugins/actions/train/__init__.py +54 -0
  68. synapse_sdk/plugins/actions/train/action.py +326 -0
  69. synapse_sdk/plugins/actions/train/context.py +57 -0
  70. synapse_sdk/plugins/actions/upload/__init__.py +49 -0
  71. synapse_sdk/plugins/actions/upload/action.py +165 -0
  72. synapse_sdk/plugins/actions/upload/context.py +61 -0
  73. synapse_sdk/plugins/config.py +98 -0
  74. synapse_sdk/plugins/context/__init__.py +109 -0
  75. synapse_sdk/plugins/context/env.py +113 -0
  76. synapse_sdk/plugins/datasets/__init__.py +113 -0
  77. synapse_sdk/plugins/datasets/converters/__init__.py +76 -0
  78. synapse_sdk/plugins/datasets/converters/base.py +347 -0
  79. synapse_sdk/plugins/datasets/converters/yolo/__init__.py +9 -0
  80. synapse_sdk/plugins/datasets/converters/yolo/from_dm.py +468 -0
  81. synapse_sdk/plugins/datasets/converters/yolo/to_dm.py +381 -0
  82. synapse_sdk/plugins/datasets/formats/__init__.py +82 -0
  83. synapse_sdk/plugins/datasets/formats/dm.py +351 -0
  84. synapse_sdk/plugins/datasets/formats/yolo.py +240 -0
  85. synapse_sdk/plugins/decorators.py +83 -0
  86. synapse_sdk/plugins/discovery.py +790 -0
  87. synapse_sdk/plugins/docs/ACTION_DEV_GUIDE.md +933 -0
  88. synapse_sdk/plugins/docs/ARCHITECTURE.md +1225 -0
  89. synapse_sdk/plugins/docs/LOGGING_SYSTEM.md +683 -0
  90. synapse_sdk/plugins/docs/OVERVIEW.md +531 -0
  91. synapse_sdk/plugins/docs/PIPELINE_GUIDE.md +145 -0
  92. synapse_sdk/plugins/docs/README.md +513 -0
  93. synapse_sdk/plugins/docs/STEP.md +656 -0
  94. synapse_sdk/plugins/enums.py +70 -10
  95. synapse_sdk/plugins/errors.py +92 -0
  96. synapse_sdk/plugins/executors/__init__.py +43 -0
  97. synapse_sdk/plugins/executors/local.py +99 -0
  98. synapse_sdk/plugins/executors/ray/__init__.py +18 -0
  99. synapse_sdk/plugins/executors/ray/base.py +282 -0
  100. synapse_sdk/plugins/executors/ray/job.py +298 -0
  101. synapse_sdk/plugins/executors/ray/jobs_api.py +511 -0
  102. synapse_sdk/plugins/executors/ray/packaging.py +137 -0
  103. synapse_sdk/plugins/executors/ray/pipeline.py +792 -0
  104. synapse_sdk/plugins/executors/ray/task.py +257 -0
  105. synapse_sdk/plugins/models/__init__.py +26 -0
  106. synapse_sdk/plugins/models/logger.py +173 -0
  107. synapse_sdk/plugins/models/pipeline.py +25 -0
  108. synapse_sdk/plugins/pipelines/__init__.py +81 -0
  109. synapse_sdk/plugins/pipelines/action_pipeline.py +417 -0
  110. synapse_sdk/plugins/pipelines/context.py +107 -0
  111. synapse_sdk/plugins/pipelines/display.py +311 -0
  112. synapse_sdk/plugins/runner.py +114 -0
  113. synapse_sdk/plugins/schemas/__init__.py +19 -0
  114. synapse_sdk/plugins/schemas/results.py +152 -0
  115. synapse_sdk/plugins/steps/__init__.py +63 -0
  116. synapse_sdk/plugins/steps/base.py +128 -0
  117. synapse_sdk/plugins/steps/context.py +90 -0
  118. synapse_sdk/plugins/steps/orchestrator.py +128 -0
  119. synapse_sdk/plugins/steps/registry.py +103 -0
  120. synapse_sdk/plugins/steps/utils/__init__.py +20 -0
  121. synapse_sdk/plugins/steps/utils/logging.py +85 -0
  122. synapse_sdk/plugins/steps/utils/timing.py +71 -0
  123. synapse_sdk/plugins/steps/utils/validation.py +68 -0
  124. synapse_sdk/plugins/templates/__init__.py +50 -0
  125. synapse_sdk/plugins/templates/base/.gitignore.j2 +26 -0
  126. synapse_sdk/plugins/templates/base/.synapseignore.j2 +11 -0
  127. synapse_sdk/plugins/templates/base/README.md.j2 +26 -0
  128. synapse_sdk/plugins/templates/base/plugin/__init__.py.j2 +1 -0
  129. synapse_sdk/plugins/templates/base/pyproject.toml.j2 +14 -0
  130. synapse_sdk/plugins/templates/base/requirements.txt.j2 +1 -0
  131. synapse_sdk/plugins/templates/custom/plugin/main.py.j2 +18 -0
  132. synapse_sdk/plugins/templates/data_validation/plugin/validate.py.j2 +32 -0
  133. synapse_sdk/plugins/templates/export/plugin/export.py.j2 +36 -0
  134. synapse_sdk/plugins/templates/neural_net/plugin/inference.py.j2 +36 -0
  135. synapse_sdk/plugins/templates/neural_net/plugin/train.py.j2 +33 -0
  136. synapse_sdk/plugins/templates/post_annotation/plugin/post_annotate.py.j2 +32 -0
  137. synapse_sdk/plugins/templates/pre_annotation/plugin/pre_annotate.py.j2 +32 -0
  138. synapse_sdk/plugins/templates/smart_tool/plugin/auto_label.py.j2 +44 -0
  139. synapse_sdk/plugins/templates/upload/plugin/upload.py.j2 +35 -0
  140. synapse_sdk/plugins/testing/__init__.py +25 -0
  141. synapse_sdk/plugins/testing/sample_actions.py +98 -0
  142. synapse_sdk/plugins/types.py +206 -0
  143. synapse_sdk/plugins/upload.py +595 -64
  144. synapse_sdk/plugins/utils.py +325 -37
  145. synapse_sdk/shared/__init__.py +25 -0
  146. synapse_sdk/utils/__init__.py +1 -0
  147. synapse_sdk/utils/auth.py +74 -0
  148. synapse_sdk/utils/file/__init__.py +58 -0
  149. synapse_sdk/utils/file/archive.py +449 -0
  150. synapse_sdk/utils/file/checksum.py +167 -0
  151. synapse_sdk/utils/file/download.py +286 -0
  152. synapse_sdk/utils/file/io.py +129 -0
  153. synapse_sdk/utils/file/requirements.py +36 -0
  154. synapse_sdk/utils/network.py +168 -0
  155. synapse_sdk/utils/storage/__init__.py +238 -0
  156. synapse_sdk/utils/storage/config.py +188 -0
  157. synapse_sdk/utils/storage/errors.py +52 -0
  158. synapse_sdk/utils/storage/providers/__init__.py +13 -0
  159. synapse_sdk/utils/storage/providers/base.py +76 -0
  160. synapse_sdk/utils/storage/providers/gcs.py +168 -0
  161. synapse_sdk/utils/storage/providers/http.py +250 -0
  162. synapse_sdk/utils/storage/providers/local.py +126 -0
  163. synapse_sdk/utils/storage/providers/s3.py +177 -0
  164. synapse_sdk/utils/storage/providers/sftp.py +208 -0
  165. synapse_sdk/utils/storage/registry.py +125 -0
  166. synapse_sdk/utils/websocket.py +99 -0
  167. synapse_sdk-2026.1.1b2.dist-info/METADATA +715 -0
  168. synapse_sdk-2026.1.1b2.dist-info/RECORD +172 -0
  169. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/WHEEL +1 -1
  170. synapse_sdk-2026.1.1b2.dist-info/licenses/LICENSE +201 -0
  171. locale/en/LC_MESSAGES/messages.mo +0 -0
  172. locale/en/LC_MESSAGES/messages.po +0 -39
  173. locale/ko/LC_MESSAGES/messages.mo +0 -0
  174. locale/ko/LC_MESSAGES/messages.po +0 -34
  175. synapse_sdk/cli/create_plugin.py +0 -10
  176. synapse_sdk/clients/agent/core.py +0 -7
  177. synapse_sdk/clients/agent/service.py +0 -15
  178. synapse_sdk/clients/backend/dataset.py +0 -51
  179. synapse_sdk/clients/ray/__init__.py +0 -6
  180. synapse_sdk/clients/ray/core.py +0 -22
  181. synapse_sdk/clients/ray/serve.py +0 -20
  182. synapse_sdk/i18n.py +0 -35
  183. synapse_sdk/plugins/categories/__init__.py +0 -0
  184. synapse_sdk/plugins/categories/base.py +0 -235
  185. synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
  186. synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
  187. synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -10
  188. synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -3
  189. synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
  190. synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -5
  191. synapse_sdk/plugins/categories/decorators.py +0 -13
  192. synapse_sdk/plugins/categories/export/__init__.py +0 -0
  193. synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
  194. synapse_sdk/plugins/categories/export/actions/export.py +0 -10
  195. synapse_sdk/plugins/categories/import/__init__.py +0 -0
  196. synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
  197. synapse_sdk/plugins/categories/import/actions/import.py +0 -10
  198. synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
  199. synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
  200. synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -45
  201. synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -18
  202. synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -10
  203. synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -143
  204. synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -12
  205. synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
  206. synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -4
  207. synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -2
  208. synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -14
  209. synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
  210. synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
  211. synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -10
  212. synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -3
  213. synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
  214. synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -3
  215. synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
  216. synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
  217. synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -10
  218. synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -3
  219. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
  220. synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -3
  221. synapse_sdk/plugins/categories/registry.py +0 -16
  222. synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
  223. synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
  224. synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -37
  225. synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -7
  226. synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
  227. synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -11
  228. synapse_sdk/plugins/categories/templates.py +0 -32
  229. synapse_sdk/plugins/cli/__init__.py +0 -21
  230. synapse_sdk/plugins/cli/publish.py +0 -37
  231. synapse_sdk/plugins/cli/run.py +0 -67
  232. synapse_sdk/plugins/exceptions.py +0 -22
  233. synapse_sdk/plugins/models.py +0 -121
  234. synapse_sdk/plugins/templates/cookiecutter.json +0 -11
  235. synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -3
  236. synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -21
  237. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
  238. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
  239. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -27
  240. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -7
  241. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -5
  242. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -6
  243. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
  244. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
  245. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -13
  246. synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -1
  247. synapse_sdk/shared/enums.py +0 -8
  248. synapse_sdk/utils/debug.py +0 -5
  249. synapse_sdk/utils/file.py +0 -87
  250. synapse_sdk/utils/module_loading.py +0 -29
  251. synapse_sdk/utils/pydantic/__init__.py +0 -0
  252. synapse_sdk/utils/pydantic/config.py +0 -4
  253. synapse_sdk/utils/pydantic/errors.py +0 -33
  254. synapse_sdk/utils/pydantic/validators.py +0 -7
  255. synapse_sdk/utils/storage.py +0 -91
  256. synapse_sdk/utils/string.py +0 -11
  257. synapse_sdk-1.0.0a11.dist-info/LICENSE +0 -21
  258. synapse_sdk-1.0.0a11.dist-info/METADATA +0 -43
  259. synapse_sdk-1.0.0a11.dist-info/RECORD +0 -111
  260. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/entry_points.txt +0 -0
  261. {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,257 @@
1
+ """Ray Actor executor for plugin actions."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from pathlib import Path
6
+ from typing import TYPE_CHECKING, Any, Literal
7
+
8
+ from synapse_sdk.plugins.context import PluginEnvironment
9
+ from synapse_sdk.plugins.enums import PackageManager
10
+ from synapse_sdk.plugins.errors import ExecutionError
11
+ from synapse_sdk.plugins.executors.ray.base import BaseRayExecutor, read_requirements
12
+
13
+ if TYPE_CHECKING:
14
+ from synapse_sdk.plugins.action import BaseAction
15
+
16
+
17
+ class RayActorExecutor(BaseRayExecutor):
18
+ """Ray Actor based synchronous task execution.
19
+
20
+ Executes actions using a persistent Ray Actor. Best for fast startup
21
+ with pre-warmed workers. The actor maintains state across executions
22
+ and methods are executed serially within each actor.
23
+
24
+ Example:
25
+ >>> executor = RayActorExecutor(
26
+ ... ray_address='auto',
27
+ ... working_dir='/path/to/plugin', # Auto-reads requirements.txt
28
+ ... )
29
+ >>> result = executor.execute(TrainAction, {'epochs': 10})
30
+ >>> # Reuse the same actor for subsequent executions
31
+ >>> result2 = executor.execute(InferAction, {'batch_size': 32})
32
+ """
33
+
34
+ def __init__(
35
+ self,
36
+ env: PluginEnvironment | dict[str, Any] | None = None,
37
+ job_id: str | None = None,
38
+ *,
39
+ ray_address: str = 'auto',
40
+ runtime_env: dict[str, Any] | None = None,
41
+ working_dir: str | Path | None = None,
42
+ requirements_file: str | Path | None = None,
43
+ package_manager: PackageManager | Literal['pip', 'uv'] = PackageManager.PIP,
44
+ package_manager_options: list[str] | None = None,
45
+ wheels_dir: str = 'wheels',
46
+ num_cpus: int | None = None,
47
+ num_gpus: int | None = None,
48
+ include_sdk: bool = False,
49
+ ) -> None:
50
+ """Initialize Ray actor executor.
51
+
52
+ Args:
53
+ env: Environment config for the action. If None, loads from os.environ.
54
+ job_id: Optional job identifier for tracking.
55
+ ray_address: Ray cluster address. Defaults to 'auto'.
56
+ runtime_env: Ray runtime environment config (pip packages, working_dir, env_vars).
57
+ working_dir: Plugin working directory. Sets runtime_env['working_dir'] and
58
+ auto-reads requirements.txt if requirements_file is not specified.
59
+ requirements_file: Path to requirements.txt. If None and working_dir is set,
60
+ looks for requirements.txt in working_dir.
61
+ package_manager: Package manager to use ('pip' or 'uv'). Defaults to 'pip'.
62
+ package_manager_options: Additional options for the package manager.
63
+ For uv: defaults to ['--no-cache']. For pip: defaults to ['--upgrade'].
64
+ wheels_dir: Directory containing .whl files relative to working_dir (default: 'wheels').
65
+ num_cpus: Number of CPUs to request for the actor.
66
+ num_gpus: Number of GPUs to request for the actor.
67
+ include_sdk: If True, bundle local SDK with upload (for development).
68
+ """
69
+ super().__init__(
70
+ env=env,
71
+ runtime_env=runtime_env,
72
+ working_dir=working_dir,
73
+ requirements_file=requirements_file,
74
+ package_manager=package_manager,
75
+ package_manager_options=package_manager_options,
76
+ wheels_dir=wheels_dir,
77
+ ray_address=ray_address,
78
+ include_sdk=include_sdk,
79
+ )
80
+ self._job_id = job_id
81
+ self._num_cpus = num_cpus
82
+ self._num_gpus = num_gpus
83
+ self._actor: Any | None = None
84
+
85
+ def _get_or_create_actor(self) -> Any:
86
+ """Get existing actor or create a new one."""
87
+ import ray
88
+
89
+ if self._actor is not None:
90
+ return self._actor
91
+
92
+ self._ray_init()
93
+
94
+ # Build remote options
95
+ remote_options: dict[str, Any] = {'runtime_env': self._build_runtime_env()}
96
+ if self._num_cpus is not None:
97
+ remote_options['num_cpus'] = self._num_cpus
98
+ if self._num_gpus is not None:
99
+ remote_options['num_gpus'] = self._num_gpus
100
+
101
+ # Create the actor class dynamically with ray.remote
102
+ ActionExecutorActor = ray.remote(**remote_options)(_ActionExecutorActor)
103
+ self._actor = ActionExecutorActor.remote(self._job_id)
104
+ return self._actor
105
+
106
+ def execute(
107
+ self,
108
+ action_cls: type[BaseAction] | str,
109
+ params: dict[str, Any],
110
+ **kwargs: Any,
111
+ ) -> Any:
112
+ """Execute action using the Ray actor.
113
+
114
+ Args:
115
+ action_cls: BaseAction subclass or entrypoint string (e.g., 'plugin.test.TestAction').
116
+ params: Parameters dict to validate and pass.
117
+ **kwargs: Ignored (for protocol compatibility).
118
+
119
+ Returns:
120
+ Action result from execute().
121
+
122
+ Raises:
123
+ ValidationError: If params fail validation.
124
+ ExecutionError: If action execution fails.
125
+ """
126
+ import ray
127
+ from ray.exceptions import RayActorError, RayTaskError
128
+
129
+ # Convert class to entrypoint string for remote import
130
+ if isinstance(action_cls, str):
131
+ entrypoint = action_cls
132
+ else:
133
+ entrypoint = f'{action_cls.__module__}.{action_cls.__name__}'
134
+
135
+ actor = self._get_or_create_actor()
136
+
137
+ try:
138
+ return ray.get(actor.run_action.remote(entrypoint, params))
139
+ except (RayTaskError, RayActorError) as e:
140
+ # Actor may have died, reset it for next call
141
+ self._actor = None
142
+ cause = getattr(e, 'cause', e)
143
+ raise ExecutionError(f'Ray actor execution failed: {cause}') from e
144
+
145
+ def shutdown(self) -> None:
146
+ """Shutdown the actor."""
147
+ import ray
148
+
149
+ if self._actor is not None:
150
+ ray.kill(self._actor)
151
+ self._actor = None
152
+
153
+
154
+ class _ActionExecutorActor:
155
+ """Ray Actor that executes plugin actions.
156
+
157
+ This actor maintains state across executions and provides
158
+ serial execution guarantees for methods called on it.
159
+ """
160
+
161
+ def __init__(self, job_id: str | None = None) -> None:
162
+ """Initialize the actor.
163
+
164
+ Args:
165
+ job_id: Optional job identifier for tracking.
166
+ """
167
+ self._job_id = job_id
168
+
169
+ def run_action(
170
+ self,
171
+ entrypoint: str,
172
+ params: dict[str, Any],
173
+ ) -> Any:
174
+ """Execute an action within this actor.
175
+
176
+ Args:
177
+ entrypoint: Action entrypoint string (e.g., 'plugin.test.TestAction').
178
+ params: Parameters dict to validate and pass.
179
+
180
+ Returns:
181
+ Action result from execute().
182
+
183
+ Raises:
184
+ ValidationError: If params fail validation.
185
+ ExecutionError: If action execution fails.
186
+ """
187
+ import importlib
188
+ import logging
189
+ import os
190
+ import sys
191
+
192
+ # Configure logging to ensure ConsoleLogger output is visible
193
+ # This is needed because Ray workers don't have logging configured by default
194
+ logging.basicConfig(
195
+ level=logging.INFO,
196
+ format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
197
+ force=True, # Override any existing config
198
+ )
199
+
200
+ from synapse_sdk.loggers import ConsoleLogger
201
+ from synapse_sdk.plugins.action import NoResult, validate_result
202
+ from synapse_sdk.plugins.context import RuntimeContext
203
+ from synapse_sdk.plugins.errors import ExecutionError, ValidationError
204
+ from synapse_sdk.utils.auth import create_backend_client
205
+
206
+ # Dynamically import action class from entrypoint
207
+ try:
208
+ # Ensure working directory is in sys.path (Ray should do this, but be explicit)
209
+ cwd = os.getcwd()
210
+ if cwd not in sys.path:
211
+ sys.path.insert(0, cwd)
212
+
213
+ module_path, class_name = entrypoint.rsplit('.', 1)
214
+ module = importlib.import_module(module_path)
215
+ action_cls = getattr(module, class_name)
216
+ except Exception as e:
217
+ raise ExecutionError(f'Failed to import action {entrypoint}: {e}') from e
218
+
219
+ # Validate params
220
+ try:
221
+ validated_params = action_cls.params_model.model_validate(params)
222
+ except Exception as e:
223
+ raise ValidationError(f'Parameter validation failed: {e}') from e
224
+
225
+ # Try to create BackendClient from environment/credentials
226
+ client = create_backend_client()
227
+
228
+ # Build context (inside actor)
229
+ logger = ConsoleLogger()
230
+ ctx = RuntimeContext(
231
+ logger=logger,
232
+ env=dict(os.environ),
233
+ job_id=self._job_id,
234
+ client=client,
235
+ )
236
+
237
+ # Execute
238
+ action = action_cls(validated_params, ctx)
239
+ try:
240
+ result = action.execute()
241
+ except Exception as e:
242
+ logger.finish()
243
+ raise ExecutionError(f'Action execution failed: {e}') from e
244
+
245
+ # Validate result with warning-only mode
246
+ result_model = getattr(action_cls, 'result_model', NoResult)
247
+ if result_model is not NoResult:
248
+ result = validate_result(result, result_model, logger)
249
+
250
+ logger.finish()
251
+ return result
252
+
253
+
254
+ # Keep old name as alias for backwards compatibility
255
+ RayTaskExecutor = RayActorExecutor
256
+
257
+ __all__ = ['RayActorExecutor', 'RayTaskExecutor', 'read_requirements']
@@ -0,0 +1,26 @@
1
+ """Plugin models module."""
2
+
3
+ from synapse_sdk.plugins.models.logger import (
4
+ ActionProgress,
5
+ Checkpoint,
6
+ LogEntry,
7
+ LoggerBackend,
8
+ LogLevel,
9
+ PipelineProgress,
10
+ ProgressData,
11
+ )
12
+ from synapse_sdk.plugins.models.pipeline import ActionStatus, RunStatus
13
+
14
+ __all__ = [
15
+ # pipeline.py
16
+ 'RunStatus',
17
+ 'ActionStatus',
18
+ # logger.py
19
+ 'LogLevel',
20
+ 'ProgressData',
21
+ 'LogEntry',
22
+ 'LoggerBackend',
23
+ 'ActionProgress',
24
+ 'PipelineProgress',
25
+ 'Checkpoint',
26
+ ]
@@ -0,0 +1,173 @@
1
+ """Logger models and enums.
2
+
3
+ This module re-exports core logger types from synapse_sdk.loggers
4
+ and defines additional logger-related models.
5
+ """
6
+
7
+ from __future__ import annotations
8
+
9
+ from dataclasses import dataclass, field
10
+ from datetime import datetime
11
+ from enum import Enum
12
+ from typing import TYPE_CHECKING, Any
13
+
14
+ # Re-export core logger types from loggers.py to avoid circular imports
15
+ from synapse_sdk.loggers import LogEntry, LoggerBackend, ProgressData
16
+
17
+ if TYPE_CHECKING:
18
+ from synapse_sdk.plugins.models.pipeline import ActionStatus
19
+
20
+ __all__ = [
21
+ 'LogLevel',
22
+ 'ProgressData',
23
+ 'LogEntry',
24
+ 'LoggerBackend',
25
+ 'ActionProgress',
26
+ 'PipelineProgress',
27
+ 'Checkpoint',
28
+ ]
29
+
30
+
31
+ class LogLevel(str, Enum):
32
+ """Log level for logger."""
33
+
34
+ DEBUG = 'debug'
35
+ INFO = 'info'
36
+ WARNING = 'warning'
37
+ ERROR = 'error'
38
+ CRITICAL = 'critical'
39
+
40
+
41
+ @dataclass
42
+ class ActionProgress:
43
+ """Progress state for a single action."""
44
+
45
+ name: str
46
+ status: ActionStatus = None # type: ignore[assignment]
47
+ progress: float = 0.0
48
+ progress_category: str | None = None
49
+ message: str | None = None
50
+ metrics: dict[str, Any] = field(default_factory=dict)
51
+ started_at: datetime | None = None
52
+ completed_at: datetime | None = None
53
+ error: str | None = None
54
+
55
+ def __post_init__(self) -> None:
56
+ # Lazy import to avoid circular imports
57
+ if self.status is None:
58
+ from synapse_sdk.plugins.models.pipeline import ActionStatus
59
+
60
+ self.status = ActionStatus.PENDING
61
+
62
+ def to_dict(self) -> dict[str, Any]:
63
+ """Convert to dictionary for API serialization."""
64
+ return {
65
+ 'name': self.name,
66
+ 'status': self.status.value,
67
+ 'progress': self.progress,
68
+ 'progress_category': self.progress_category,
69
+ 'message': self.message,
70
+ 'metrics': self.metrics,
71
+ 'started_at': self.started_at.isoformat() if self.started_at else None,
72
+ 'completed_at': self.completed_at.isoformat() if self.completed_at else None,
73
+ 'error': self.error,
74
+ }
75
+
76
+ @classmethod
77
+ def from_dict(cls, data: dict[str, Any]) -> ActionProgress:
78
+ """Create from dictionary."""
79
+ from synapse_sdk.plugins.models.pipeline import ActionStatus
80
+
81
+ return cls(
82
+ name=data['name'],
83
+ status=ActionStatus(data['status']),
84
+ progress=data.get('progress', 0.0),
85
+ progress_category=data.get('progress_category'),
86
+ message=data.get('message'),
87
+ metrics=data.get('metrics', {}),
88
+ started_at=datetime.fromisoformat(data['started_at']) if data.get('started_at') else None,
89
+ completed_at=datetime.fromisoformat(data['completed_at']) if data.get('completed_at') else None,
90
+ error=data.get('error'),
91
+ )
92
+
93
+
94
+ @dataclass
95
+ class PipelineProgress:
96
+ """Overall pipeline progress state."""
97
+
98
+ run_id: str
99
+ status: Any = None # RunStatus, but lazy loaded
100
+ actions: dict[str, ActionProgress] = field(default_factory=dict)
101
+ current_action: str | None = None
102
+ started_at: datetime | None = None
103
+ completed_at: datetime | None = None
104
+ error: str | None = None
105
+
106
+ def __post_init__(self) -> None:
107
+ if self.status is None:
108
+ from synapse_sdk.plugins.models.pipeline import RunStatus
109
+
110
+ self.status = RunStatus.PENDING
111
+
112
+ @property
113
+ def overall_progress(self) -> float:
114
+ """Calculate overall progress across all actions."""
115
+ if not self.actions:
116
+ return 0.0
117
+ return sum(a.progress for a in self.actions.values()) / len(self.actions)
118
+
119
+ @property
120
+ def completed_actions(self) -> int:
121
+ """Count completed actions."""
122
+ from synapse_sdk.plugins.models.pipeline import ActionStatus
123
+
124
+ return sum(1 for a in self.actions.values() if a.status == ActionStatus.COMPLETED)
125
+
126
+ def to_dict(self) -> dict[str, Any]:
127
+ """Convert to dictionary for API serialization."""
128
+ return {
129
+ 'run_id': self.run_id,
130
+ 'status': self.status.value,
131
+ 'actions': {k: v.to_dict() for k, v in self.actions.items()},
132
+ 'current_action': self.current_action,
133
+ 'overall_progress': self.overall_progress,
134
+ 'completed_actions': self.completed_actions,
135
+ 'total_actions': len(self.actions),
136
+ 'started_at': self.started_at.isoformat() if self.started_at else None,
137
+ 'completed_at': self.completed_at.isoformat() if self.completed_at else None,
138
+ 'error': self.error,
139
+ }
140
+
141
+ @classmethod
142
+ def from_dict(cls, data: dict[str, Any]) -> PipelineProgress:
143
+ """Create from dictionary."""
144
+ from synapse_sdk.plugins.models.pipeline import RunStatus
145
+
146
+ return cls(
147
+ run_id=data['run_id'],
148
+ status=RunStatus(data['status']),
149
+ actions={k: ActionProgress.from_dict(v) for k, v in data.get('actions', {}).items()},
150
+ current_action=data.get('current_action'),
151
+ started_at=datetime.fromisoformat(data['started_at']) if data.get('started_at') else None,
152
+ completed_at=datetime.fromisoformat(data['completed_at']) if data.get('completed_at') else None,
153
+ error=data.get('error'),
154
+ )
155
+
156
+
157
+ @dataclass
158
+ class Checkpoint:
159
+ """Checkpoint for pipeline state persistence."""
160
+
161
+ run_id: str
162
+ action_name: str
163
+ result: Any
164
+ created_at: datetime = field(default_factory=datetime.now)
165
+
166
+ def to_dict(self) -> dict[str, Any]:
167
+ """Convert to dictionary for serialization."""
168
+ return {
169
+ 'run_id': self.run_id,
170
+ 'action_name': self.action_name,
171
+ 'result': self.result,
172
+ 'created_at': self.created_at.isoformat(),
173
+ }
@@ -0,0 +1,25 @@
1
+ """Pipeline status enums."""
2
+
3
+ from enum import Enum
4
+
5
+ __all__ = ['RunStatus', 'ActionStatus']
6
+
7
+
8
+ class RunStatus(str, Enum):
9
+ """Status of a pipeline run."""
10
+
11
+ PENDING = 'pending'
12
+ RUNNING = 'running'
13
+ COMPLETED = 'completed'
14
+ FAILED = 'failed'
15
+ CANCELLED = 'cancelled'
16
+
17
+
18
+ class ActionStatus(str, Enum):
19
+ """Status of an individual action."""
20
+
21
+ PENDING = 'pending'
22
+ RUNNING = 'running'
23
+ COMPLETED = 'completed'
24
+ FAILED = 'failed'
25
+ SKIPPED = 'skipped'
@@ -0,0 +1,81 @@
1
+ """Pipeline patterns for Synapse SDK.
2
+
3
+ This module provides various pipeline execution patterns:
4
+ - ActionPipeline: Chain actions with input/output schema validation
5
+ - PipelineContext: Shared working directory for pipeline actions
6
+ - Progress models: Track pipeline and action progress
7
+ - steps: Sequential step-based workflows with rollback support (for internal use)
8
+
9
+ Example:
10
+ >>> from synapse_sdk.plugins.pipelines import ActionPipeline, PipelineContext
11
+ >>>
12
+ >>> # Unix pipe style: Download | Convert | Train
13
+ >>> pipeline = ActionPipeline([
14
+ ... DownloadDatasetAction,
15
+ ... ConvertDatasetAction,
16
+ ... TrainAction,
17
+ ... ])
18
+ >>>
19
+ >>> result = pipeline.execute(params, ctx)
20
+ """
21
+
22
+ from synapse_sdk.plugins.models.logger import (
23
+ ActionProgress,
24
+ Checkpoint,
25
+ LogEntry,
26
+ LogLevel,
27
+ PipelineProgress,
28
+ )
29
+ from synapse_sdk.plugins.models.pipeline import ActionStatus, RunStatus
30
+ from synapse_sdk.plugins.pipelines.action_pipeline import (
31
+ ActionPipeline,
32
+ SchemaIncompatibleError,
33
+ )
34
+ from synapse_sdk.plugins.pipelines.context import PipelineContext
35
+ from synapse_sdk.plugins.pipelines.display import (
36
+ display_progress,
37
+ display_progress_async,
38
+ print_progress_summary,
39
+ )
40
+
41
+ # Import from new canonical location (not deprecated pipelines.steps)
42
+ from synapse_sdk.plugins.steps import (
43
+ BaseStep,
44
+ BaseStepContext,
45
+ LoggingStep,
46
+ Orchestrator,
47
+ StepRegistry,
48
+ StepResult,
49
+ TimingStep,
50
+ ValidationStep,
51
+ )
52
+
53
+ __all__ = [
54
+ # Action Pipeline (recommended)
55
+ 'ActionPipeline',
56
+ 'SchemaIncompatibleError',
57
+ # Pipeline Context
58
+ 'PipelineContext',
59
+ # Display Utilities
60
+ 'display_progress',
61
+ 'display_progress_async',
62
+ 'print_progress_summary',
63
+ # Progress Models
64
+ 'ActionProgress',
65
+ 'ActionStatus',
66
+ 'Checkpoint',
67
+ 'LogEntry',
68
+ 'LogLevel',
69
+ 'PipelineProgress',
70
+ 'RunStatus',
71
+ # Steps - Core (internal)
72
+ 'BaseStep',
73
+ 'BaseStepContext',
74
+ 'Orchestrator',
75
+ 'StepRegistry',
76
+ 'StepResult',
77
+ # Steps - Utilities
78
+ 'LoggingStep',
79
+ 'TimingStep',
80
+ 'ValidationStep',
81
+ ]