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.
- synapse_sdk/__init__.py +24 -0
- synapse_sdk/cli/__init__.py +9 -8
- synapse_sdk/cli/agent/__init__.py +25 -0
- synapse_sdk/cli/agent/config.py +104 -0
- synapse_sdk/cli/agent/select.py +197 -0
- synapse_sdk/cli/auth.py +104 -0
- synapse_sdk/cli/main.py +1025 -0
- synapse_sdk/cli/plugin/__init__.py +58 -0
- synapse_sdk/cli/plugin/create.py +566 -0
- synapse_sdk/cli/plugin/job.py +196 -0
- synapse_sdk/cli/plugin/publish.py +322 -0
- synapse_sdk/cli/plugin/run.py +131 -0
- synapse_sdk/cli/plugin/test.py +200 -0
- synapse_sdk/clients/README.md +239 -0
- synapse_sdk/clients/__init__.py +5 -0
- synapse_sdk/clients/_template.py +266 -0
- synapse_sdk/clients/agent/__init__.py +84 -29
- synapse_sdk/clients/agent/async_ray.py +289 -0
- synapse_sdk/clients/agent/container.py +83 -0
- synapse_sdk/clients/agent/plugin.py +101 -0
- synapse_sdk/clients/agent/ray.py +296 -39
- synapse_sdk/clients/backend/__init__.py +152 -12
- synapse_sdk/clients/backend/annotation.py +164 -22
- synapse_sdk/clients/backend/core.py +101 -0
- synapse_sdk/clients/backend/data_collection.py +292 -0
- synapse_sdk/clients/backend/hitl.py +87 -0
- synapse_sdk/clients/backend/integration.py +374 -46
- synapse_sdk/clients/backend/ml.py +134 -22
- synapse_sdk/clients/backend/models.py +247 -0
- synapse_sdk/clients/base.py +538 -59
- synapse_sdk/clients/exceptions.py +35 -7
- synapse_sdk/clients/pipeline/__init__.py +5 -0
- synapse_sdk/clients/pipeline/client.py +636 -0
- synapse_sdk/clients/protocols.py +178 -0
- synapse_sdk/clients/utils.py +86 -8
- synapse_sdk/clients/validation.py +58 -0
- synapse_sdk/enums.py +76 -0
- synapse_sdk/exceptions.py +168 -0
- synapse_sdk/integrations/__init__.py +74 -0
- synapse_sdk/integrations/_base.py +119 -0
- synapse_sdk/integrations/_context.py +53 -0
- synapse_sdk/integrations/ultralytics/__init__.py +78 -0
- synapse_sdk/integrations/ultralytics/_callbacks.py +126 -0
- synapse_sdk/integrations/ultralytics/_patches.py +124 -0
- synapse_sdk/loggers.py +476 -95
- synapse_sdk/mcp/MCP.md +69 -0
- synapse_sdk/mcp/__init__.py +48 -0
- synapse_sdk/mcp/__main__.py +6 -0
- synapse_sdk/mcp/config.py +349 -0
- synapse_sdk/mcp/prompts/__init__.py +4 -0
- synapse_sdk/mcp/resources/__init__.py +4 -0
- synapse_sdk/mcp/server.py +1352 -0
- synapse_sdk/mcp/tools/__init__.py +6 -0
- synapse_sdk/plugins/__init__.py +133 -9
- synapse_sdk/plugins/action.py +229 -0
- synapse_sdk/plugins/actions/__init__.py +82 -0
- synapse_sdk/plugins/actions/dataset/__init__.py +37 -0
- synapse_sdk/plugins/actions/dataset/action.py +471 -0
- synapse_sdk/plugins/actions/export/__init__.py +55 -0
- synapse_sdk/plugins/actions/export/action.py +183 -0
- synapse_sdk/plugins/actions/export/context.py +59 -0
- synapse_sdk/plugins/actions/inference/__init__.py +84 -0
- synapse_sdk/plugins/actions/inference/action.py +285 -0
- synapse_sdk/plugins/actions/inference/context.py +81 -0
- synapse_sdk/plugins/actions/inference/deployment.py +322 -0
- synapse_sdk/plugins/actions/inference/serve.py +252 -0
- synapse_sdk/plugins/actions/train/__init__.py +54 -0
- synapse_sdk/plugins/actions/train/action.py +326 -0
- synapse_sdk/plugins/actions/train/context.py +57 -0
- synapse_sdk/plugins/actions/upload/__init__.py +49 -0
- synapse_sdk/plugins/actions/upload/action.py +165 -0
- synapse_sdk/plugins/actions/upload/context.py +61 -0
- synapse_sdk/plugins/config.py +98 -0
- synapse_sdk/plugins/context/__init__.py +109 -0
- synapse_sdk/plugins/context/env.py +113 -0
- synapse_sdk/plugins/datasets/__init__.py +113 -0
- synapse_sdk/plugins/datasets/converters/__init__.py +76 -0
- synapse_sdk/plugins/datasets/converters/base.py +347 -0
- synapse_sdk/plugins/datasets/converters/yolo/__init__.py +9 -0
- synapse_sdk/plugins/datasets/converters/yolo/from_dm.py +468 -0
- synapse_sdk/plugins/datasets/converters/yolo/to_dm.py +381 -0
- synapse_sdk/plugins/datasets/formats/__init__.py +82 -0
- synapse_sdk/plugins/datasets/formats/dm.py +351 -0
- synapse_sdk/plugins/datasets/formats/yolo.py +240 -0
- synapse_sdk/plugins/decorators.py +83 -0
- synapse_sdk/plugins/discovery.py +790 -0
- synapse_sdk/plugins/docs/ACTION_DEV_GUIDE.md +933 -0
- synapse_sdk/plugins/docs/ARCHITECTURE.md +1225 -0
- synapse_sdk/plugins/docs/LOGGING_SYSTEM.md +683 -0
- synapse_sdk/plugins/docs/OVERVIEW.md +531 -0
- synapse_sdk/plugins/docs/PIPELINE_GUIDE.md +145 -0
- synapse_sdk/plugins/docs/README.md +513 -0
- synapse_sdk/plugins/docs/STEP.md +656 -0
- synapse_sdk/plugins/enums.py +70 -10
- synapse_sdk/plugins/errors.py +92 -0
- synapse_sdk/plugins/executors/__init__.py +43 -0
- synapse_sdk/plugins/executors/local.py +99 -0
- synapse_sdk/plugins/executors/ray/__init__.py +18 -0
- synapse_sdk/plugins/executors/ray/base.py +282 -0
- synapse_sdk/plugins/executors/ray/job.py +298 -0
- synapse_sdk/plugins/executors/ray/jobs_api.py +511 -0
- synapse_sdk/plugins/executors/ray/packaging.py +137 -0
- synapse_sdk/plugins/executors/ray/pipeline.py +792 -0
- synapse_sdk/plugins/executors/ray/task.py +257 -0
- synapse_sdk/plugins/models/__init__.py +26 -0
- synapse_sdk/plugins/models/logger.py +173 -0
- synapse_sdk/plugins/models/pipeline.py +25 -0
- synapse_sdk/plugins/pipelines/__init__.py +81 -0
- synapse_sdk/plugins/pipelines/action_pipeline.py +417 -0
- synapse_sdk/plugins/pipelines/context.py +107 -0
- synapse_sdk/plugins/pipelines/display.py +311 -0
- synapse_sdk/plugins/runner.py +114 -0
- synapse_sdk/plugins/schemas/__init__.py +19 -0
- synapse_sdk/plugins/schemas/results.py +152 -0
- synapse_sdk/plugins/steps/__init__.py +63 -0
- synapse_sdk/plugins/steps/base.py +128 -0
- synapse_sdk/plugins/steps/context.py +90 -0
- synapse_sdk/plugins/steps/orchestrator.py +128 -0
- synapse_sdk/plugins/steps/registry.py +103 -0
- synapse_sdk/plugins/steps/utils/__init__.py +20 -0
- synapse_sdk/plugins/steps/utils/logging.py +85 -0
- synapse_sdk/plugins/steps/utils/timing.py +71 -0
- synapse_sdk/plugins/steps/utils/validation.py +68 -0
- synapse_sdk/plugins/templates/__init__.py +50 -0
- synapse_sdk/plugins/templates/base/.gitignore.j2 +26 -0
- synapse_sdk/plugins/templates/base/.synapseignore.j2 +11 -0
- synapse_sdk/plugins/templates/base/README.md.j2 +26 -0
- synapse_sdk/plugins/templates/base/plugin/__init__.py.j2 +1 -0
- synapse_sdk/plugins/templates/base/pyproject.toml.j2 +14 -0
- synapse_sdk/plugins/templates/base/requirements.txt.j2 +1 -0
- synapse_sdk/plugins/templates/custom/plugin/main.py.j2 +18 -0
- synapse_sdk/plugins/templates/data_validation/plugin/validate.py.j2 +32 -0
- synapse_sdk/plugins/templates/export/plugin/export.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/inference.py.j2 +36 -0
- synapse_sdk/plugins/templates/neural_net/plugin/train.py.j2 +33 -0
- synapse_sdk/plugins/templates/post_annotation/plugin/post_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/pre_annotation/plugin/pre_annotate.py.j2 +32 -0
- synapse_sdk/plugins/templates/smart_tool/plugin/auto_label.py.j2 +44 -0
- synapse_sdk/plugins/templates/upload/plugin/upload.py.j2 +35 -0
- synapse_sdk/plugins/testing/__init__.py +25 -0
- synapse_sdk/plugins/testing/sample_actions.py +98 -0
- synapse_sdk/plugins/types.py +206 -0
- synapse_sdk/plugins/upload.py +595 -64
- synapse_sdk/plugins/utils.py +325 -37
- synapse_sdk/shared/__init__.py +25 -0
- synapse_sdk/utils/__init__.py +1 -0
- synapse_sdk/utils/auth.py +74 -0
- synapse_sdk/utils/file/__init__.py +58 -0
- synapse_sdk/utils/file/archive.py +449 -0
- synapse_sdk/utils/file/checksum.py +167 -0
- synapse_sdk/utils/file/download.py +286 -0
- synapse_sdk/utils/file/io.py +129 -0
- synapse_sdk/utils/file/requirements.py +36 -0
- synapse_sdk/utils/network.py +168 -0
- synapse_sdk/utils/storage/__init__.py +238 -0
- synapse_sdk/utils/storage/config.py +188 -0
- synapse_sdk/utils/storage/errors.py +52 -0
- synapse_sdk/utils/storage/providers/__init__.py +13 -0
- synapse_sdk/utils/storage/providers/base.py +76 -0
- synapse_sdk/utils/storage/providers/gcs.py +168 -0
- synapse_sdk/utils/storage/providers/http.py +250 -0
- synapse_sdk/utils/storage/providers/local.py +126 -0
- synapse_sdk/utils/storage/providers/s3.py +177 -0
- synapse_sdk/utils/storage/providers/sftp.py +208 -0
- synapse_sdk/utils/storage/registry.py +125 -0
- synapse_sdk/utils/websocket.py +99 -0
- synapse_sdk-2026.1.1b2.dist-info/METADATA +715 -0
- synapse_sdk-2026.1.1b2.dist-info/RECORD +172 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/WHEEL +1 -1
- synapse_sdk-2026.1.1b2.dist-info/licenses/LICENSE +201 -0
- locale/en/LC_MESSAGES/messages.mo +0 -0
- locale/en/LC_MESSAGES/messages.po +0 -39
- locale/ko/LC_MESSAGES/messages.mo +0 -0
- locale/ko/LC_MESSAGES/messages.po +0 -34
- synapse_sdk/cli/create_plugin.py +0 -10
- synapse_sdk/clients/agent/core.py +0 -7
- synapse_sdk/clients/agent/service.py +0 -15
- synapse_sdk/clients/backend/dataset.py +0 -51
- synapse_sdk/clients/ray/__init__.py +0 -6
- synapse_sdk/clients/ray/core.py +0 -22
- synapse_sdk/clients/ray/serve.py +0 -20
- synapse_sdk/i18n.py +0 -35
- synapse_sdk/plugins/categories/__init__.py +0 -0
- synapse_sdk/plugins/categories/base.py +0 -235
- synapse_sdk/plugins/categories/data_validation/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/actions/validation.py +0 -10
- synapse_sdk/plugins/categories/data_validation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/data_validation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/data_validation/templates/plugin/validation.py +0 -5
- synapse_sdk/plugins/categories/decorators.py +0 -13
- synapse_sdk/plugins/categories/export/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/export/actions/export.py +0 -10
- synapse_sdk/plugins/categories/import/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/import/actions/import.py +0 -10
- synapse_sdk/plugins/categories/neural_net/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/actions/deployment.py +0 -45
- synapse_sdk/plugins/categories/neural_net/actions/inference.py +0 -18
- synapse_sdk/plugins/categories/neural_net/actions/test.py +0 -10
- synapse_sdk/plugins/categories/neural_net/actions/train.py +0 -143
- synapse_sdk/plugins/categories/neural_net/templates/config.yaml +0 -12
- synapse_sdk/plugins/categories/neural_net/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/neural_net/templates/plugin/inference.py +0 -4
- synapse_sdk/plugins/categories/neural_net/templates/plugin/test.py +0 -2
- synapse_sdk/plugins/categories/neural_net/templates/plugin/train.py +0 -14
- synapse_sdk/plugins/categories/post_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/actions/post_annotation.py +0 -10
- synapse_sdk/plugins/categories/post_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/post_annotation/templates/plugin/post_annotation.py +0 -3
- synapse_sdk/plugins/categories/pre_annotation/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/actions/pre_annotation.py +0 -10
- synapse_sdk/plugins/categories/pre_annotation/templates/config.yaml +0 -3
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/pre_annotation/templates/plugin/pre_annotation.py +0 -3
- synapse_sdk/plugins/categories/registry.py +0 -16
- synapse_sdk/plugins/categories/smart_tool/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/actions/auto_label.py +0 -37
- synapse_sdk/plugins/categories/smart_tool/templates/config.yaml +0 -7
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/__init__.py +0 -0
- synapse_sdk/plugins/categories/smart_tool/templates/plugin/auto_label.py +0 -11
- synapse_sdk/plugins/categories/templates.py +0 -32
- synapse_sdk/plugins/cli/__init__.py +0 -21
- synapse_sdk/plugins/cli/publish.py +0 -37
- synapse_sdk/plugins/cli/run.py +0 -67
- synapse_sdk/plugins/exceptions.py +0 -22
- synapse_sdk/plugins/models.py +0 -121
- synapse_sdk/plugins/templates/cookiecutter.json +0 -11
- synapse_sdk/plugins/templates/hooks/post_gen_project.py +0 -3
- synapse_sdk/plugins/templates/hooks/pre_prompt.py +0 -21
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.env.dist +0 -24
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.gitignore +0 -27
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/.pre-commit-config.yaml +0 -7
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/README.md +0 -5
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/config.yaml +0 -6
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/main.py +0 -4
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/plugin/__init__.py +0 -0
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/pyproject.toml +0 -13
- synapse_sdk/plugins/templates/synapse-{{cookiecutter.plugin_code}}-plugin/requirements.txt +0 -1
- synapse_sdk/shared/enums.py +0 -8
- synapse_sdk/utils/debug.py +0 -5
- synapse_sdk/utils/file.py +0 -87
- synapse_sdk/utils/module_loading.py +0 -29
- synapse_sdk/utils/pydantic/__init__.py +0 -0
- synapse_sdk/utils/pydantic/config.py +0 -4
- synapse_sdk/utils/pydantic/errors.py +0 -33
- synapse_sdk/utils/pydantic/validators.py +0 -7
- synapse_sdk/utils/storage.py +0 -91
- synapse_sdk/utils/string.py +0 -11
- synapse_sdk-1.0.0a11.dist-info/LICENSE +0 -21
- synapse_sdk-1.0.0a11.dist-info/METADATA +0 -43
- synapse_sdk-1.0.0a11.dist-info/RECORD +0 -111
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/entry_points.txt +0 -0
- {synapse_sdk-1.0.0a11.dist-info → synapse_sdk-2026.1.1b2.dist-info}/top_level.txt +0 -0
|
@@ -1,63 +1,391 @@
|
|
|
1
|
-
|
|
1
|
+
"""Integration client mixin for plugin, job, and storage operations."""
|
|
2
2
|
|
|
3
|
+
from __future__ import annotations
|
|
3
4
|
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
return self._post(path)
|
|
5
|
+
from collections.abc import Generator
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import TYPE_CHECKING, Any
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
from synapse_sdk.clients.backend.models import (
|
|
10
|
+
Agent,
|
|
11
|
+
PluginReleaseCreateRequest,
|
|
12
|
+
PluginRunRequest,
|
|
13
|
+
ServeApplicationCreateRequest,
|
|
14
|
+
Storage,
|
|
15
|
+
UpdateJobRequest,
|
|
16
|
+
)
|
|
17
|
+
from synapse_sdk.utils.file.io import convert_file_to_base64
|
|
12
18
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
return self._post(path, data=data)
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from synapse_sdk.clients.protocols import ClientProtocol
|
|
16
21
|
|
|
17
|
-
def update_plugin(self, pk, data):
|
|
18
|
-
path = f'plugins/{pk}/'
|
|
19
|
-
return self._put(path, data=data)
|
|
20
22
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return self._post(path, data=data)
|
|
23
|
+
class IntegrationClientMixin:
|
|
24
|
+
"""Mixin for integration-related API endpoints.
|
|
24
25
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
return self._get(path, params=params)
|
|
26
|
+
Provides methods for managing plugins, jobs, logs, and serve applications.
|
|
27
|
+
"""
|
|
28
28
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
return self._post(path, data=data, files=files)
|
|
29
|
+
# -------------------------------------------------------------------------
|
|
30
|
+
# Agent Operations
|
|
31
|
+
# -------------------------------------------------------------------------
|
|
33
32
|
|
|
34
|
-
def
|
|
35
|
-
|
|
36
|
-
|
|
33
|
+
def list_agents(
|
|
34
|
+
self: ClientProtocol,
|
|
35
|
+
params: dict[str, Any] | None = None,
|
|
36
|
+
) -> list[Agent]:
|
|
37
|
+
"""List available agents.
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
return self._get(path, params=params)
|
|
39
|
+
Args:
|
|
40
|
+
params: Optional query parameters for filtering.
|
|
41
41
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
42
|
+
Returns:
|
|
43
|
+
List of Agent objects.
|
|
44
|
+
"""
|
|
45
|
+
response = self._get('agents/', params=params)
|
|
46
|
+
results = response.get('results', [])
|
|
47
|
+
agents = []
|
|
48
|
+
for item in results:
|
|
49
|
+
agent = Agent.model_validate(item)
|
|
50
|
+
# Extract token from node_install_script if not set
|
|
51
|
+
if not agent.token:
|
|
52
|
+
agent.token = agent.extract_token()
|
|
53
|
+
agents.append(agent)
|
|
54
|
+
return agents
|
|
45
55
|
|
|
46
|
-
def
|
|
47
|
-
|
|
48
|
-
return self._get(path)
|
|
56
|
+
def health_check_agent(self: ClientProtocol, agent_token: str) -> dict[str, Any]:
|
|
57
|
+
"""Check agent health and connectivity.
|
|
49
58
|
|
|
50
|
-
|
|
51
|
-
|
|
59
|
+
Args:
|
|
60
|
+
agent_token: Agent authentication token.
|
|
52
61
|
|
|
53
|
-
|
|
62
|
+
Returns:
|
|
63
|
+
Agent health status and metadata.
|
|
64
|
+
"""
|
|
65
|
+
return self._post(f'agents/{agent_token}/connect/')
|
|
66
|
+
|
|
67
|
+
# -------------------------------------------------------------------------
|
|
68
|
+
# Plugin Operations
|
|
69
|
+
# -------------------------------------------------------------------------
|
|
70
|
+
|
|
71
|
+
def get_plugin(self: ClientProtocol, plugin_id: int) -> dict[str, Any]:
|
|
72
|
+
"""Get plugin details by ID.
|
|
73
|
+
|
|
74
|
+
Args:
|
|
75
|
+
plugin_id: Plugin ID.
|
|
76
|
+
|
|
77
|
+
Returns:
|
|
78
|
+
Plugin data including configuration and releases.
|
|
79
|
+
"""
|
|
80
|
+
return self._get(f'plugins/{plugin_id}/')
|
|
81
|
+
|
|
82
|
+
def create_plugin(self: ClientProtocol, data: dict[str, Any]) -> dict[str, Any]:
|
|
83
|
+
"""Create a new plugin.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
data: Plugin creation data (name, category, etc.).
|
|
87
|
+
|
|
88
|
+
Returns:
|
|
89
|
+
Created plugin data.
|
|
90
|
+
"""
|
|
91
|
+
return self._post('plugins/', data=data)
|
|
92
|
+
|
|
93
|
+
def update_plugin(
|
|
94
|
+
self: ClientProtocol,
|
|
95
|
+
plugin_id: int,
|
|
96
|
+
data: dict[str, Any],
|
|
97
|
+
) -> dict[str, Any]:
|
|
98
|
+
"""Update an existing plugin.
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
plugin_id: Plugin ID to update.
|
|
102
|
+
data: Fields to update.
|
|
103
|
+
|
|
104
|
+
Returns:
|
|
105
|
+
Updated plugin data.
|
|
106
|
+
"""
|
|
107
|
+
return self._put(f'plugins/{plugin_id}/', data=data)
|
|
108
|
+
|
|
109
|
+
def run_plugin(
|
|
110
|
+
self: ClientProtocol,
|
|
111
|
+
plugin: int | str,
|
|
112
|
+
data: dict[str, Any],
|
|
113
|
+
) -> dict[str, Any]:
|
|
114
|
+
"""Run a plugin action.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
plugin: Plugin ID or code.
|
|
118
|
+
data: Run parameters including action, agent, and params.
|
|
119
|
+
|
|
120
|
+
Returns:
|
|
121
|
+
Job data or direct result.
|
|
122
|
+
|
|
123
|
+
Example:
|
|
124
|
+
>>> client.run_plugin('yolov8', {
|
|
125
|
+
... 'agent': 1,
|
|
126
|
+
... 'action': 'deployment',
|
|
127
|
+
... 'params': {'num_cpus': 8},
|
|
128
|
+
... })
|
|
129
|
+
"""
|
|
130
|
+
return self._post(
|
|
131
|
+
f'plugins/{plugin}/run/',
|
|
132
|
+
request_model=PluginRunRequest,
|
|
133
|
+
data=data,
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# -------------------------------------------------------------------------
|
|
137
|
+
# Plugin Release Operations
|
|
138
|
+
# -------------------------------------------------------------------------
|
|
139
|
+
|
|
140
|
+
def get_plugin_release(
|
|
141
|
+
self: ClientProtocol,
|
|
142
|
+
release_id: int,
|
|
143
|
+
*,
|
|
144
|
+
params: dict[str, Any] | None = None,
|
|
145
|
+
) -> dict[str, Any]:
|
|
146
|
+
"""Get plugin release details by ID.
|
|
147
|
+
|
|
148
|
+
Args:
|
|
149
|
+
release_id: Plugin release ID.
|
|
150
|
+
params: Optional query parameters.
|
|
151
|
+
|
|
152
|
+
Returns:
|
|
153
|
+
Plugin release data including config and requirements.
|
|
154
|
+
"""
|
|
155
|
+
return self._get(f'plugin_releases/{release_id}/', params=params)
|
|
156
|
+
|
|
157
|
+
def create_plugin_release(
|
|
158
|
+
self: ClientProtocol,
|
|
159
|
+
data: dict[str, Any],
|
|
160
|
+
*,
|
|
161
|
+
file: str | Path | None = None,
|
|
162
|
+
) -> dict[str, Any]:
|
|
163
|
+
"""Create a new plugin release.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
data: Release data (plugin, version, config, requirements).
|
|
167
|
+
file: Optional plugin archive file to upload.
|
|
168
|
+
|
|
169
|
+
Returns:
|
|
170
|
+
Created plugin release data.
|
|
171
|
+
|
|
172
|
+
Example:
|
|
173
|
+
>>> client.create_plugin_release(
|
|
174
|
+
... {'plugin': 123, 'version': '1.0.0'},
|
|
175
|
+
... file='/path/to/plugin.zip'
|
|
176
|
+
... )
|
|
177
|
+
"""
|
|
178
|
+
files = None
|
|
179
|
+
if file is not None:
|
|
180
|
+
files = {'file': file}
|
|
181
|
+
|
|
182
|
+
return self._post(
|
|
183
|
+
'plugin_releases/',
|
|
184
|
+
request_model=PluginReleaseCreateRequest,
|
|
185
|
+
data=data,
|
|
186
|
+
files=files,
|
|
187
|
+
)
|
|
188
|
+
|
|
189
|
+
# -------------------------------------------------------------------------
|
|
190
|
+
# Job Operations
|
|
191
|
+
# -------------------------------------------------------------------------
|
|
192
|
+
|
|
193
|
+
def get_job(
|
|
194
|
+
self: ClientProtocol,
|
|
195
|
+
job_id: int | str,
|
|
196
|
+
*,
|
|
197
|
+
params: dict[str, Any] | None = None,
|
|
198
|
+
) -> dict[str, Any]:
|
|
199
|
+
"""Get job details by ID.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
job_id: Job ID (integer or UUID string).
|
|
203
|
+
params: Optional query parameters.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
Job data including status and progress.
|
|
207
|
+
"""
|
|
208
|
+
return self._get(f'jobs/{job_id}/', params=params)
|
|
209
|
+
|
|
210
|
+
def list_jobs(
|
|
211
|
+
self: ClientProtocol,
|
|
212
|
+
params: dict[str, Any] | None = None,
|
|
213
|
+
) -> dict[str, Any]:
|
|
214
|
+
"""List jobs with optional filtering.
|
|
215
|
+
|
|
216
|
+
Args:
|
|
217
|
+
params: Query parameters (status, plugin, etc.).
|
|
218
|
+
|
|
219
|
+
Returns:
|
|
220
|
+
Paginated job list.
|
|
221
|
+
"""
|
|
222
|
+
return self._get('jobs/', params=params)
|
|
223
|
+
|
|
224
|
+
def update_job(
|
|
225
|
+
self: ClientProtocol,
|
|
226
|
+
job_id: int,
|
|
227
|
+
data: dict[str, Any],
|
|
228
|
+
) -> dict[str, Any]:
|
|
229
|
+
"""Update job status and data.
|
|
230
|
+
|
|
231
|
+
Args:
|
|
232
|
+
job_id: Job ID to update.
|
|
233
|
+
data: Update payload (status, progress_record, metrics_record, etc.).
|
|
234
|
+
|
|
235
|
+
Returns:
|
|
236
|
+
Updated job data.
|
|
237
|
+
|
|
238
|
+
Example:
|
|
239
|
+
>>> client.update_job(123, {
|
|
240
|
+
... 'status': 'running',
|
|
241
|
+
... 'progress_record': {'step': 5, 'total': 100}
|
|
242
|
+
... })
|
|
243
|
+
"""
|
|
244
|
+
return self._patch(
|
|
245
|
+
f'jobs/{job_id}/',
|
|
246
|
+
request_model=UpdateJobRequest,
|
|
247
|
+
data=data,
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
def list_job_console_logs(self: ClientProtocol, job_id: int) -> dict[str, Any]:
|
|
251
|
+
"""Get console logs for a job.
|
|
252
|
+
|
|
253
|
+
Args:
|
|
254
|
+
job_id: Job ID.
|
|
255
|
+
|
|
256
|
+
Returns:
|
|
257
|
+
Console log entries.
|
|
258
|
+
"""
|
|
259
|
+
return self._get(f'jobs/{job_id}/console_logs/')
|
|
260
|
+
|
|
261
|
+
def tail_job_console_logs(
|
|
262
|
+
self: ClientProtocol,
|
|
263
|
+
job_id: int | str,
|
|
264
|
+
) -> Generator[str, None, None]:
|
|
265
|
+
"""Stream console logs for a running job.
|
|
266
|
+
|
|
267
|
+
Yields log lines as they become available.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
job_id: Job ID (integer or UUID string) to tail.
|
|
271
|
+
|
|
272
|
+
Yields:
|
|
273
|
+
Log lines as strings.
|
|
274
|
+
|
|
275
|
+
Example:
|
|
276
|
+
>>> for line in client.tail_job_console_logs('abc-123'):
|
|
277
|
+
... print(line)
|
|
278
|
+
"""
|
|
279
|
+
# Use async endpoint for streaming
|
|
280
|
+
# The async endpoint is at /async/jobs/{id}/tail_console_logs/
|
|
281
|
+
base = self.base_url.rstrip('/')
|
|
282
|
+
url = f'{base}/async/jobs/{job_id}/tail_console_logs/'
|
|
54
283
|
headers = self._get_headers()
|
|
55
284
|
|
|
56
|
-
response = self.requests_session.get(
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
285
|
+
response = self.requests_session.get(
|
|
286
|
+
url,
|
|
287
|
+
headers=headers,
|
|
288
|
+
stream=True,
|
|
289
|
+
timeout=(self.timeout['connect'], None), # No read timeout for streaming
|
|
290
|
+
)
|
|
291
|
+
response.raise_for_status()
|
|
292
|
+
|
|
293
|
+
yield from response.iter_lines(decode_unicode=True)
|
|
294
|
+
|
|
295
|
+
# -------------------------------------------------------------------------
|
|
296
|
+
# Log Operations
|
|
297
|
+
# -------------------------------------------------------------------------
|
|
298
|
+
|
|
299
|
+
def create_logs(
|
|
300
|
+
self: ClientProtocol,
|
|
301
|
+
data: dict[str, Any] | list[dict[str, Any]],
|
|
302
|
+
) -> dict[str, Any]:
|
|
303
|
+
"""Create log entries with optional file attachments.
|
|
304
|
+
|
|
305
|
+
File fields are automatically converted to base64 data URIs.
|
|
306
|
+
|
|
307
|
+
Args:
|
|
308
|
+
data: Single log entry or list of entries.
|
|
309
|
+
|
|
310
|
+
Returns:
|
|
311
|
+
Created log entries response.
|
|
312
|
+
|
|
313
|
+
Example:
|
|
314
|
+
>>> client.create_logs({
|
|
315
|
+
... 'message': 'Training complete',
|
|
316
|
+
... 'level': 'info',
|
|
317
|
+
... 'file': '/path/to/result.png' # Auto-converted to base64
|
|
318
|
+
... })
|
|
319
|
+
"""
|
|
320
|
+
# Normalize to list
|
|
321
|
+
items = data if isinstance(data, list) else [data]
|
|
322
|
+
|
|
323
|
+
# Convert file fields to base64
|
|
324
|
+
for item in items:
|
|
325
|
+
if 'file' in item and item['file']:
|
|
326
|
+
file_path = item['file']
|
|
327
|
+
if not isinstance(file_path, str) or not file_path.startswith('data:'):
|
|
328
|
+
item['file'] = convert_file_to_base64(file_path)
|
|
329
|
+
|
|
330
|
+
return self._post('logs/', data=items if len(items) > 1 else items[0])
|
|
331
|
+
|
|
332
|
+
# -------------------------------------------------------------------------
|
|
333
|
+
# Serve Application Operations
|
|
334
|
+
# -------------------------------------------------------------------------
|
|
335
|
+
|
|
336
|
+
def create_serve_application(
|
|
337
|
+
self: ClientProtocol,
|
|
338
|
+
data: dict[str, Any],
|
|
339
|
+
) -> dict[str, Any]:
|
|
340
|
+
"""Create a Ray Serve application.
|
|
341
|
+
|
|
342
|
+
Args:
|
|
343
|
+
data: Application config (name, plugin_release, action, params).
|
|
344
|
+
|
|
345
|
+
Returns:
|
|
346
|
+
Created serve application data.
|
|
347
|
+
"""
|
|
348
|
+
return self._post(
|
|
349
|
+
'serve_applications/',
|
|
350
|
+
request_model=ServeApplicationCreateRequest,
|
|
351
|
+
data=data,
|
|
352
|
+
)
|
|
353
|
+
|
|
354
|
+
def list_serve_applications(
|
|
355
|
+
self: ClientProtocol,
|
|
356
|
+
params: dict[str, Any] | None = None,
|
|
357
|
+
*,
|
|
358
|
+
list_all: bool = False,
|
|
359
|
+
) -> dict[str, Any] | tuple[Any, int]:
|
|
360
|
+
"""List Ray Serve applications.
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
params: Query parameters for filtering.
|
|
364
|
+
list_all: If True, returns (generator, count).
|
|
365
|
+
|
|
366
|
+
Returns:
|
|
367
|
+
Paginated list or (generator, count).
|
|
368
|
+
"""
|
|
369
|
+
return self._list('serve_applications/', params=params, list_all=list_all)
|
|
370
|
+
|
|
371
|
+
# -------------------------------------------------------------------------
|
|
372
|
+
# Storage Operations
|
|
373
|
+
# -------------------------------------------------------------------------
|
|
374
|
+
|
|
375
|
+
def get_storage(self: ClientProtocol, storage_id: int) -> Storage:
|
|
376
|
+
"""Get storage configuration by ID.
|
|
377
|
+
|
|
378
|
+
Args:
|
|
379
|
+
storage_id: Storage ID.
|
|
380
|
+
|
|
381
|
+
Returns:
|
|
382
|
+
Storage model with provider configuration.
|
|
383
|
+
"""
|
|
384
|
+
response = self._get(
|
|
385
|
+
f'storages/{storage_id}/',
|
|
386
|
+
params={'with_configuration': 'true'},
|
|
387
|
+
)
|
|
388
|
+
return Storage.model_validate(response)
|
|
389
|
+
|
|
60
390
|
|
|
61
|
-
|
|
62
|
-
path = 'logs/'
|
|
63
|
-
return self._post(path, data=data)
|
|
391
|
+
__all__ = ['IntegrationClientMixin']
|
|
@@ -1,29 +1,141 @@
|
|
|
1
|
-
|
|
2
|
-
from synapse_sdk.clients.utils import get_default_url_conversion
|
|
1
|
+
"""ML client mixin for model and ground truth operations."""
|
|
3
2
|
|
|
3
|
+
from __future__ import annotations
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
path = 'models/'
|
|
8
|
-
return self._get(path, params=params)
|
|
5
|
+
from pathlib import Path
|
|
6
|
+
from typing import TYPE_CHECKING, Any
|
|
9
7
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
8
|
+
from synapse_sdk.clients.backend.models import ModelCreateRequest
|
|
9
|
+
|
|
10
|
+
if TYPE_CHECKING:
|
|
11
|
+
from synapse_sdk.clients.protocols import ClientProtocol
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class MLClientMixin:
|
|
15
|
+
"""Mixin for ML-related API endpoints.
|
|
16
|
+
|
|
17
|
+
Provides methods for managing models and ground truth data.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
def list_models(
|
|
21
|
+
self: ClientProtocol,
|
|
22
|
+
params: dict[str, Any] | None = None,
|
|
23
|
+
) -> dict[str, Any]:
|
|
24
|
+
"""List models with optional filtering.
|
|
25
|
+
|
|
26
|
+
Args:
|
|
27
|
+
params: Query parameters for filtering.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Paginated model list.
|
|
31
|
+
"""
|
|
32
|
+
return self._get('models/', params=params)
|
|
33
|
+
|
|
34
|
+
def get_model(
|
|
35
|
+
self: ClientProtocol,
|
|
36
|
+
model_id: int,
|
|
37
|
+
*,
|
|
38
|
+
params: dict[str, Any] | None = None,
|
|
39
|
+
url_conversion: dict[str, Any] | None = None,
|
|
40
|
+
) -> dict[str, Any]:
|
|
41
|
+
"""Get model details by ID.
|
|
42
|
+
|
|
43
|
+
Args:
|
|
44
|
+
model_id: Model ID.
|
|
45
|
+
params: Optional query parameters.
|
|
46
|
+
url_conversion: URL-to-path conversion config.
|
|
47
|
+
|
|
48
|
+
Returns:
|
|
49
|
+
Model data including file URL and metadata.
|
|
50
|
+
"""
|
|
51
|
+
if url_conversion is None:
|
|
52
|
+
url_conversion = {'files_fields': ['file'], 'is_list': False}
|
|
53
|
+
|
|
54
|
+
return self._get(
|
|
55
|
+
f'models/{model_id}/',
|
|
56
|
+
params=params,
|
|
57
|
+
url_conversion=url_conversion,
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
def create_model(
|
|
61
|
+
self: ClientProtocol,
|
|
62
|
+
data: dict[str, Any],
|
|
63
|
+
*,
|
|
64
|
+
file: str | Path | None = None,
|
|
65
|
+
) -> dict[str, Any]:
|
|
66
|
+
"""Create a new model with file upload.
|
|
67
|
+
|
|
68
|
+
Large files are automatically uploaded using chunked upload.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
data: Model metadata (name, plugin, version, etc.).
|
|
72
|
+
file: Model file to upload (uses chunked upload).
|
|
73
|
+
|
|
74
|
+
Returns:
|
|
75
|
+
Created model data.
|
|
76
|
+
|
|
77
|
+
Example:
|
|
78
|
+
>>> client.create_model(
|
|
79
|
+
... {'name': 'My Model', 'plugin': 123},
|
|
80
|
+
... file='/path/to/model.pt'
|
|
81
|
+
... )
|
|
82
|
+
"""
|
|
83
|
+
# Handle file upload via chunked upload
|
|
84
|
+
if file is not None:
|
|
85
|
+
path = Path(file)
|
|
86
|
+
if not path.exists():
|
|
87
|
+
raise FileNotFoundError(f'Model file not found: {path}')
|
|
88
|
+
|
|
89
|
+
# Upload file in chunks
|
|
90
|
+
upload_result = self.create_chunked_upload(path)
|
|
91
|
+
data['chunked_upload'] = upload_result['id']
|
|
92
|
+
|
|
93
|
+
return self._post(
|
|
94
|
+
'models/',
|
|
95
|
+
request_model=ModelCreateRequest,
|
|
96
|
+
data=data,
|
|
14
97
|
)
|
|
15
|
-
return self._get(path, params=params, url_conversion=url_conversion)
|
|
16
98
|
|
|
17
|
-
def
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
99
|
+
def list_ground_truth_events(
|
|
100
|
+
self: ClientProtocol,
|
|
101
|
+
params: dict[str, Any] | None = None,
|
|
102
|
+
*,
|
|
103
|
+
url_conversion: dict[str, Any] | None = None,
|
|
104
|
+
list_all: bool = False,
|
|
105
|
+
) -> dict[str, Any] | tuple[Any, int]:
|
|
106
|
+
"""List ground truth events.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
params: Query parameters for filtering.
|
|
110
|
+
url_conversion: URL-to-path conversion config.
|
|
111
|
+
list_all: If True, returns (generator, count).
|
|
112
|
+
|
|
113
|
+
Returns:
|
|
114
|
+
Paginated list or (generator, count).
|
|
115
|
+
"""
|
|
116
|
+
if url_conversion is None:
|
|
117
|
+
url_conversion = {'files_fields': ['files']}
|
|
118
|
+
|
|
119
|
+
return self._list(
|
|
120
|
+
'sdk/ground_truth_events/',
|
|
121
|
+
params=params,
|
|
122
|
+
url_conversion=url_conversion,
|
|
123
|
+
list_all=list_all,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
def get_ground_truth_version(
|
|
127
|
+
self: ClientProtocol,
|
|
128
|
+
version_id: int,
|
|
129
|
+
) -> dict[str, Any]:
|
|
130
|
+
"""Get ground truth dataset version by ID.
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
version_id: Version ID.
|
|
134
|
+
|
|
135
|
+
Returns:
|
|
136
|
+
Version data including file manifest.
|
|
137
|
+
"""
|
|
138
|
+
return self._get(f'ground_truth_dataset_versions/{version_id}/')
|
|
21
139
|
|
|
22
|
-
def create_serve_application(self, data):
|
|
23
|
-
path = 'serve_applications/'
|
|
24
|
-
return self._post(path, data=data)
|
|
25
140
|
|
|
26
|
-
|
|
27
|
-
path = 'ground_truth_events/'
|
|
28
|
-
url_conversion = get_default_url_conversion(url_conversion, files_fields=['files'])
|
|
29
|
-
return self._list(path, params=params, url_conversion=url_conversion, list_all=list_all)
|
|
141
|
+
__all__ = ['MLClientMixin']
|