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,351 @@
1
+ """DatamakerV1 and DatamakerV2 format Pydantic models.
2
+
3
+ Supports both schema versions:
4
+ - DMv1: Event-based, per-assignment structure (annotations keyed by asset)
5
+ - DMv2: Collection-based, organized by media type (images array)
6
+
7
+ Version must be explicitly specified when using converters.
8
+ """
9
+
10
+ from __future__ import annotations
11
+
12
+ from enum import StrEnum
13
+
14
+ from pydantic import BaseModel, Field
15
+
16
+
17
+ class DMVersion(StrEnum):
18
+ """DataMaker schema version."""
19
+
20
+ V1 = 'v1'
21
+ V2 = 'v2'
22
+
23
+
24
+ # =============================================================================
25
+ # Shared Types
26
+ # =============================================================================
27
+
28
+
29
+ class DMAttribute(BaseModel):
30
+ """Attribute on an annotation (shared between v1/v2).
31
+
32
+ Attributes:
33
+ name: Attribute name.
34
+ value: Attribute value (string, number, boolean, or list).
35
+ """
36
+
37
+ name: str
38
+ value: str | int | float | bool | list[str]
39
+
40
+
41
+ # =============================================================================
42
+ # DataMaker V1 Models (Event-based, per-assignment)
43
+ # =============================================================================
44
+
45
+
46
+ class DMv1Classification(BaseModel):
47
+ """V1 classification as flat key-value pairs.
48
+
49
+ Structure defined by admin but stored flat.
50
+ """
51
+
52
+ model_config = {'extra': 'allow'}
53
+
54
+
55
+ class DMv1AnnotationBase(BaseModel):
56
+ """V1 base annotation object.
57
+
58
+ Attributes:
59
+ id: Unique annotation ID.
60
+ tool: Name of the tool used.
61
+ isLocked: Whether annotation is locked.
62
+ isVisible: Whether annotation is visible.
63
+ classification: Flat key-value classification attributes.
64
+ """
65
+
66
+ id: str
67
+ tool: str
68
+ isLocked: bool = False
69
+ isVisible: bool = True
70
+ classification: DMv1Classification | None = None
71
+
72
+ model_config = {'extra': 'allow'}
73
+
74
+
75
+ class DMv1RelationItem(BaseModel):
76
+ """V1 relation (edge) between annotations.
77
+
78
+ Attributes:
79
+ id: Unique relation ID.
80
+ tool: Always 'relation'.
81
+ annotationId: Source annotation ID.
82
+ targetAnnotationId: Target annotation ID.
83
+ classification: Attributes assigned to the relation.
84
+ """
85
+
86
+ id: str
87
+ tool: str = 'relation'
88
+ isLocked: bool = False
89
+ isVisible: bool = True
90
+ annotationId: str
91
+ targetAnnotationId: str
92
+ classification: DMv1Classification | None = None
93
+
94
+
95
+ class DMv1GroupMemberItem(BaseModel):
96
+ """V1 group member with optional hierarchy.
97
+
98
+ Attributes:
99
+ annotationId: ID of annotation in group.
100
+ children: Sub-groups or hierarchical structure.
101
+ """
102
+
103
+ annotationId: str
104
+ children: list[DMv1GroupMemberItem] = Field(default_factory=list)
105
+
106
+
107
+ class DMv1AnnotationGroupItem(BaseModel):
108
+ """V1 annotation group.
109
+
110
+ Attributes:
111
+ id: Unique group ID.
112
+ tool: Always 'annotationGroup'.
113
+ classification: Group classification.
114
+ annotationList: List of group members.
115
+ """
116
+
117
+ id: str
118
+ tool: str = 'annotationGroup'
119
+ isLocked: bool = False
120
+ classification: DMv1Classification | None = None
121
+ annotationList: list[DMv1GroupMemberItem] = Field(default_factory=list)
122
+
123
+
124
+ class DMv1AnnotationDataItem(BaseModel):
125
+ """V1 supplementary annotation data (frames, model results).
126
+
127
+ Attributes:
128
+ frameIndex: Frame number for video/time-series.
129
+ section: Start/end frame range.
130
+ input: Prompt input.
131
+ output: Model output.
132
+ """
133
+
134
+ frameIndex: int | None = None
135
+ section: dict[str, int] | None = None # {startFrame, endFrame}
136
+ input: str | None = None
137
+ output: str | None = None
138
+
139
+
140
+ class DMv1Dataset(BaseModel):
141
+ """DataMaker V1 dataset schema (event-based).
142
+
143
+ Per-assignment structure with annotations keyed by asset.
144
+
145
+ Attributes:
146
+ assignmentId: Optional job identifier.
147
+ extra: Asset-level additional metadata.
148
+ annotations: Annotations per asset (Record<string, AnnotationBase[]>).
149
+ relations: Relationships between annotations.
150
+ annotationGroups: Grouping information.
151
+ annotationsData: Supplementary data (frames, model results).
152
+
153
+ Example:
154
+ >>> dataset = DMv1Dataset(
155
+ ... assignmentId='job-123',
156
+ ... annotations={'image_0': [annotation1, annotation2]},
157
+ ... )
158
+ """
159
+
160
+ assignmentId: str | None = None
161
+ extra: dict | None = None
162
+ annotations: dict[str, list[DMv1AnnotationBase]] = Field(default_factory=dict)
163
+ relations: dict[str, list[DMv1RelationItem]] = Field(default_factory=dict)
164
+ annotationGroups: dict[str, list[DMv1AnnotationGroupItem]] = Field(default_factory=dict)
165
+ annotationsData: dict[str, list[DMv1AnnotationDataItem]] = Field(default_factory=dict)
166
+
167
+
168
+ # =============================================================================
169
+ # DataMaker V2 Models (Collection-based, organized by media type)
170
+ # =============================================================================
171
+
172
+
173
+ class DMv2AnnotationBase(BaseModel):
174
+ """V2 base annotation with id, classification, and attrs.
175
+
176
+ Attributes:
177
+ id: Unique annotation ID (alphanumeric, typically 10 chars).
178
+ classification: Class label for this annotation.
179
+ attrs: Optional list of attributes.
180
+ """
181
+
182
+ id: str = Field(pattern=r'^[a-zA-Z0-9_-]+$')
183
+ classification: str
184
+ attrs: list[DMAttribute] = Field(default_factory=list)
185
+
186
+
187
+ class DMv2BoundingBox(DMv2AnnotationBase):
188
+ """V2 bounding box annotation.
189
+
190
+ Attributes:
191
+ data: [x, y, width, height] in absolute pixel coordinates.
192
+ """
193
+
194
+ data: tuple[float, float, float, float]
195
+
196
+
197
+ class DMv2Polygon(DMv2AnnotationBase):
198
+ """V2 polygon annotation.
199
+
200
+ Attributes:
201
+ data: List of [x, y] points forming the polygon.
202
+ """
203
+
204
+ data: list[tuple[float, float]]
205
+
206
+
207
+ class DMv2Polyline(DMv2AnnotationBase):
208
+ """V2 polyline annotation (open path).
209
+
210
+ Attributes:
211
+ data: List of [x, y] points forming the polyline.
212
+ """
213
+
214
+ data: list[tuple[float, float]]
215
+
216
+
217
+ class DMv2Keypoint(DMv2AnnotationBase):
218
+ """V2 single keypoint annotation.
219
+
220
+ Attributes:
221
+ data: [x, y] coordinate.
222
+ """
223
+
224
+ data: tuple[float, float]
225
+
226
+
227
+ class DMv2Relation(DMv2AnnotationBase):
228
+ """V2 relation annotation linking two annotations.
229
+
230
+ Attributes:
231
+ data: [from_id, to_id] annotation IDs.
232
+ """
233
+
234
+ data: tuple[str, str]
235
+
236
+
237
+ class DMv2Group(DMv2AnnotationBase):
238
+ """V2 group annotation containing multiple annotation IDs.
239
+
240
+ Attributes:
241
+ data: List of annotation IDs in the group.
242
+ """
243
+
244
+ data: list[str]
245
+
246
+
247
+ class DMv2ImageItem(BaseModel):
248
+ """V2 container for 2D image annotations.
249
+
250
+ Groups all annotation types for a single image.
251
+ """
252
+
253
+ bounding_box: list[DMv2BoundingBox] = Field(default_factory=list)
254
+ polygon: list[DMv2Polygon] = Field(default_factory=list)
255
+ polyline: list[DMv2Polyline] = Field(default_factory=list)
256
+ keypoint: list[DMv2Keypoint] = Field(default_factory=list)
257
+ relation: list[DMv2Relation] = Field(default_factory=list)
258
+ group: list[DMv2Group] = Field(default_factory=list)
259
+
260
+
261
+ class DMv2Dataset(BaseModel):
262
+ """DataMaker V2 dataset schema (collection-based).
263
+
264
+ Organized by media type with typed annotation arrays.
265
+
266
+ Attributes:
267
+ classification: Mapping of tool types to available class labels.
268
+ images: List of image annotation containers.
269
+
270
+ Example:
271
+ >>> dataset = DMv2Dataset(
272
+ ... classification={'bounding_box': ['car', 'person']},
273
+ ... images=[DMv2ImageItem(bounding_box=[...])],
274
+ ... )
275
+ >>> class_names = dataset.get_class_names('bounding_box')
276
+ """
277
+
278
+ classification: dict[str, list[str]] = Field(default_factory=dict)
279
+ images: list[DMv2ImageItem] = Field(default_factory=list)
280
+
281
+ def get_class_names(self, tool: str = 'bounding_box') -> list[str]:
282
+ """Get class names for a specific annotation tool.
283
+
284
+ Args:
285
+ tool: Tool type (e.g., 'bounding_box', 'polygon').
286
+
287
+ Returns:
288
+ List of class names for the tool.
289
+ """
290
+ return self.classification.get(tool, [])
291
+
292
+ def get_all_class_names(self) -> list[str]:
293
+ """Get all unique class names across all tools.
294
+
295
+ Returns:
296
+ Sorted list of unique class names.
297
+ """
298
+ all_classes: set[str] = set()
299
+ for classes in self.classification.values():
300
+ all_classes.update(classes)
301
+ return sorted(all_classes)
302
+
303
+
304
+ # =============================================================================
305
+ # Aliases for backward compatibility / convenience
306
+ # =============================================================================
307
+
308
+ # Default to V2 models for convenience
309
+ DMBoundingBox = DMv2BoundingBox
310
+ DMPolygon = DMv2Polygon
311
+ DMPolyline = DMv2Polyline
312
+ DMKeypoint = DMv2Keypoint
313
+ DMRelation = DMv2Relation
314
+ DMGroup = DMv2Group
315
+ DMImageItem = DMv2ImageItem
316
+ DMDataset = DMv2Dataset
317
+
318
+
319
+ __all__ = [
320
+ # Version enum
321
+ 'DMVersion',
322
+ # Shared
323
+ 'DMAttribute',
324
+ # V1 Models
325
+ 'DMv1AnnotationBase',
326
+ 'DMv1AnnotationDataItem',
327
+ 'DMv1AnnotationGroupItem',
328
+ 'DMv1Classification',
329
+ 'DMv1Dataset',
330
+ 'DMv1GroupMemberItem',
331
+ 'DMv1RelationItem',
332
+ # V2 Models
333
+ 'DMv2AnnotationBase',
334
+ 'DMv2BoundingBox',
335
+ 'DMv2Dataset',
336
+ 'DMv2Group',
337
+ 'DMv2ImageItem',
338
+ 'DMv2Keypoint',
339
+ 'DMv2Polygon',
340
+ 'DMv2Polyline',
341
+ 'DMv2Relation',
342
+ # Aliases (default to V2)
343
+ 'DMBoundingBox',
344
+ 'DMDataset',
345
+ 'DMGroup',
346
+ 'DMImageItem',
347
+ 'DMKeypoint',
348
+ 'DMPolygon',
349
+ 'DMPolyline',
350
+ 'DMRelation',
351
+ ]
@@ -0,0 +1,240 @@
1
+ """YOLO format Pydantic models.
2
+
3
+ Supports standard YOLO detection format with normalized coordinates.
4
+ """
5
+
6
+ from __future__ import annotations
7
+
8
+ from pathlib import Path
9
+
10
+ from pydantic import BaseModel, Field
11
+
12
+
13
+ class YOLOAnnotation(BaseModel):
14
+ """Single YOLO annotation line.
15
+
16
+ YOLO format uses normalized center coordinates:
17
+ `class_id cx cy w h`
18
+
19
+ All coordinates are normalized to [0, 1] range.
20
+
21
+ Attributes:
22
+ class_id: Class index (0-based).
23
+ cx: Normalized center x coordinate.
24
+ cy: Normalized center y coordinate.
25
+ w: Normalized width.
26
+ h: Normalized height.
27
+ """
28
+
29
+ class_id: int = Field(ge=0)
30
+ cx: float = Field(ge=0, le=1)
31
+ cy: float = Field(ge=0, le=1)
32
+ w: float = Field(ge=0, le=1)
33
+ h: float = Field(ge=0, le=1)
34
+
35
+ def to_line(self) -> str:
36
+ """Convert to YOLO label line format.
37
+
38
+ Returns:
39
+ String in format: `class_id cx cy w h`
40
+ """
41
+ return f'{self.class_id} {self.cx:.6f} {self.cy:.6f} {self.w:.6f} {self.h:.6f}'
42
+
43
+ @classmethod
44
+ def from_line(cls, line: str) -> YOLOAnnotation:
45
+ """Parse from YOLO label line.
46
+
47
+ Args:
48
+ line: String in format: `class_id cx cy w h`
49
+
50
+ Returns:
51
+ YOLOAnnotation instance.
52
+ """
53
+ parts = line.strip().split()
54
+ return cls(
55
+ class_id=int(parts[0]),
56
+ cx=float(parts[1]),
57
+ cy=float(parts[2]),
58
+ w=float(parts[3]),
59
+ h=float(parts[4]),
60
+ )
61
+
62
+ def to_absolute(self, width: int, height: int) -> tuple[float, float, float, float]:
63
+ """Convert to absolute pixel coordinates.
64
+
65
+ Args:
66
+ width: Image width in pixels.
67
+ height: Image height in pixels.
68
+
69
+ Returns:
70
+ Tuple of (x, y, w, h) in absolute coordinates.
71
+ """
72
+ abs_w = self.w * width
73
+ abs_h = self.h * height
74
+ abs_x = (self.cx * width) - (abs_w / 2)
75
+ abs_y = (self.cy * height) - (abs_h / 2)
76
+ return abs_x, abs_y, abs_w, abs_h
77
+
78
+ @classmethod
79
+ def from_absolute(
80
+ cls,
81
+ class_id: int,
82
+ x: float,
83
+ y: float,
84
+ w: float,
85
+ h: float,
86
+ img_width: int,
87
+ img_height: int,
88
+ ) -> YOLOAnnotation:
89
+ """Create from absolute pixel coordinates.
90
+
91
+ Args:
92
+ class_id: Class index.
93
+ x: Top-left x coordinate.
94
+ y: Top-left y coordinate.
95
+ w: Box width.
96
+ h: Box height.
97
+ img_width: Image width in pixels.
98
+ img_height: Image height in pixels.
99
+
100
+ Returns:
101
+ YOLOAnnotation with normalized coordinates.
102
+ """
103
+ cx = (x + w / 2) / img_width
104
+ cy = (y + h / 2) / img_height
105
+ nw = w / img_width
106
+ nh = h / img_height
107
+ return cls(class_id=class_id, cx=cx, cy=cy, w=nw, h=nh)
108
+
109
+
110
+ class YOLODatasetConfig(BaseModel):
111
+ """YOLO dataset.yaml configuration.
112
+
113
+ Standard YOLO dataset configuration file structure.
114
+
115
+ Attributes:
116
+ path: Root path to dataset.
117
+ train: Relative path to training images.
118
+ val: Relative path to validation images.
119
+ test: Optional relative path to test images.
120
+ nc: Number of classes.
121
+ names: List of class names.
122
+ """
123
+
124
+ path: str = '.'
125
+ train: str = 'train/images'
126
+ val: str = 'valid/images'
127
+ test: str | None = None
128
+ nc: int
129
+ names: list[str]
130
+
131
+ def to_yaml(self) -> str:
132
+ """Convert to YAML string.
133
+
134
+ Returns:
135
+ YAML-formatted string for dataset.yaml.
136
+ """
137
+ lines = [
138
+ f'path: {self.path}',
139
+ f'train: {self.train}',
140
+ f'val: {self.val}',
141
+ ]
142
+ if self.test:
143
+ lines.append(f'test: {self.test}')
144
+ lines.extend([
145
+ '',
146
+ f'nc: {self.nc}',
147
+ f'names: {self.names}',
148
+ '',
149
+ ])
150
+ return '\n'.join(lines)
151
+
152
+ @classmethod
153
+ def from_yaml(cls, yaml_path: Path | str) -> YOLODatasetConfig:
154
+ """Load from YAML file.
155
+
156
+ Args:
157
+ yaml_path: Path to dataset.yaml file.
158
+
159
+ Returns:
160
+ YOLODatasetConfig instance.
161
+ """
162
+ import yaml
163
+
164
+ with open(yaml_path) as f:
165
+ data = yaml.safe_load(f)
166
+
167
+ return cls(
168
+ path=data.get('path', '.'),
169
+ train=data.get('train', 'train/images'),
170
+ val=data.get('val', 'valid/images'),
171
+ test=data.get('test'),
172
+ nc=data['nc'],
173
+ names=data['names'],
174
+ )
175
+
176
+
177
+ class YOLOImage(BaseModel):
178
+ """YOLO image with its label file content.
179
+
180
+ Represents a single image and its annotations.
181
+
182
+ Attributes:
183
+ image_path: Path to the image file.
184
+ annotations: List of YOLO annotations.
185
+ """
186
+
187
+ image_path: Path
188
+ annotations: list[YOLOAnnotation] = Field(default_factory=list)
189
+
190
+ def to_label_content(self) -> str:
191
+ """Convert annotations to label file content.
192
+
193
+ Returns:
194
+ Newline-separated YOLO annotation lines.
195
+ """
196
+ return '\n'.join(ann.to_line() for ann in self.annotations)
197
+
198
+ @classmethod
199
+ def from_label_file(cls, image_path: Path, label_path: Path) -> YOLOImage:
200
+ """Load from image and label file pair.
201
+
202
+ Args:
203
+ image_path: Path to image file.
204
+ label_path: Path to corresponding label file.
205
+
206
+ Returns:
207
+ YOLOImage instance.
208
+ """
209
+ annotations = []
210
+ if label_path.exists():
211
+ for line in label_path.read_text().strip().splitlines():
212
+ if line.strip():
213
+ annotations.append(YOLOAnnotation.from_line(line))
214
+ return cls(image_path=image_path, annotations=annotations)
215
+
216
+
217
+ class YOLODataset(BaseModel):
218
+ """Full YOLO dataset structure.
219
+
220
+ Contains configuration and images for all splits.
221
+
222
+ Attributes:
223
+ config: Dataset configuration (dataset.yaml content).
224
+ train_images: Training images with annotations.
225
+ val_images: Validation images with annotations.
226
+ test_images: Test images with annotations (optional).
227
+ """
228
+
229
+ config: YOLODatasetConfig
230
+ train_images: list[YOLOImage] = Field(default_factory=list)
231
+ val_images: list[YOLOImage] = Field(default_factory=list)
232
+ test_images: list[YOLOImage] = Field(default_factory=list)
233
+
234
+
235
+ __all__ = [
236
+ 'YOLOAnnotation',
237
+ 'YOLODataset',
238
+ 'YOLODatasetConfig',
239
+ 'YOLOImage',
240
+ ]
@@ -0,0 +1,83 @@
1
+ from __future__ import annotations
2
+
3
+ from functools import wraps
4
+ from typing import Any, Callable, TypeVar
5
+
6
+ from pydantic import BaseModel
7
+
8
+ from synapse_sdk.plugins.enums import PluginCategory
9
+
10
+ F = TypeVar('F', bound=Callable[..., Any])
11
+
12
+
13
+ def action(
14
+ name: str | None = None,
15
+ description: str = '',
16
+ params: type[BaseModel] | None = None,
17
+ result: type[BaseModel] | None = None,
18
+ category: PluginCategory | None = None,
19
+ ) -> Callable[[F], F]:
20
+ """Decorator to register a function as a plugin action.
21
+
22
+ Use this decorator to define function-based actions. The decorated function
23
+ should accept (params, context) arguments where params is a Pydantic model
24
+ instance and context is a RunContext.
25
+
26
+ Args:
27
+ name: Action name (defaults to function name).
28
+ description: Human-readable description of the action.
29
+ params: Pydantic model class for parameter validation.
30
+ result: Pydantic model class for result validation (optional).
31
+ category: Plugin category for grouping actions (optional).
32
+
33
+ Returns:
34
+ Decorated function with action metadata attached.
35
+
36
+ Example (without result schema):
37
+ >>> from pydantic import BaseModel
38
+ >>> from synapse_sdk.plugins.decorators import action
39
+ >>>
40
+ >>> class TrainParams(BaseModel):
41
+ ... epochs: int = 10
42
+ >>>
43
+ >>> @action(params=TrainParams, description='Train a model')
44
+ ... def train(params: TrainParams, context: RunContext) -> dict:
45
+ ... return {'epochs_trained': params.epochs}
46
+
47
+ Example (with result schema):
48
+ >>> class TrainResult(BaseModel):
49
+ ... weights_path: str
50
+ ... final_loss: float
51
+ >>>
52
+ >>> @action(params=TrainParams, result=TrainResult)
53
+ ... def train(params: TrainParams, context: RunContext) -> TrainResult:
54
+ ... return TrainResult(weights_path='/model.pt', final_loss=0.05)
55
+ >>>
56
+ >>> # Access action metadata
57
+ >>> train._action_name # 'train'
58
+ >>> train._action_params # TrainParams
59
+ >>> train._action_result # TrainResult
60
+ >>> train._action_category # PluginCategory.NEURAL_NET
61
+ """
62
+
63
+ def decorator(func: F) -> F:
64
+ action_name = name or func.__name__
65
+
66
+ @wraps(func)
67
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
68
+ return func(*args, **kwargs)
69
+
70
+ # Attach action metadata
71
+ wrapper._is_action = True # type: ignore[attr-defined]
72
+ wrapper._action_name = action_name # type: ignore[attr-defined]
73
+ wrapper._action_description = description # type: ignore[attr-defined]
74
+ wrapper._action_params = params # type: ignore[attr-defined]
75
+ wrapper._action_result = result # type: ignore[attr-defined]
76
+ wrapper._action_category = category # type: ignore[attr-defined]
77
+
78
+ return wrapper # type: ignore[return-value]
79
+
80
+ return decorator
81
+
82
+
83
+ __all__ = ['action']