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
|
@@ -0,0 +1,636 @@
|
|
|
1
|
+
"""Pipeline Service Client for communicating with dev-api.
|
|
2
|
+
|
|
3
|
+
This client provides methods to interact with the pipeline orchestration
|
|
4
|
+
backend for registering pipelines, creating runs, and reporting progress.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import logging
|
|
11
|
+
from collections.abc import AsyncIterator, Iterator
|
|
12
|
+
from datetime import datetime
|
|
13
|
+
from typing import Any
|
|
14
|
+
|
|
15
|
+
import httpx
|
|
16
|
+
|
|
17
|
+
from synapse_sdk.plugins.models.logger import (
|
|
18
|
+
ActionProgress,
|
|
19
|
+
LogEntry,
|
|
20
|
+
PipelineProgress,
|
|
21
|
+
)
|
|
22
|
+
from synapse_sdk.plugins.models.pipeline import RunStatus
|
|
23
|
+
|
|
24
|
+
logger = logging.getLogger(__name__)
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class PipelineServiceClient:
|
|
28
|
+
"""Client for the Pipeline Service API.
|
|
29
|
+
|
|
30
|
+
Provides methods to manage pipelines, runs, progress, checkpoints, and logs.
|
|
31
|
+
|
|
32
|
+
Attributes:
|
|
33
|
+
base_url: Base URL of the pipeline service.
|
|
34
|
+
timeout: Request timeout in seconds.
|
|
35
|
+
|
|
36
|
+
Example:
|
|
37
|
+
>>> client = PipelineServiceClient("http://localhost:8100")
|
|
38
|
+
>>> pipeline = client.create_pipeline(
|
|
39
|
+
... name="YOLO Training",
|
|
40
|
+
... actions=[{"name": "download", "entrypoint": "plugin.download.DownloadAction"}]
|
|
41
|
+
... )
|
|
42
|
+
>>> run = client.create_run(pipeline["id"], params={"dataset_id": 123})
|
|
43
|
+
>>> client.report_progress(run["id"], current_action="download", status="running")
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
def __init__(
|
|
47
|
+
self,
|
|
48
|
+
base_url: str = 'http://localhost:8100',
|
|
49
|
+
timeout: float = 30.0,
|
|
50
|
+
):
|
|
51
|
+
"""Initialize the pipeline service client.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
base_url: Base URL of the pipeline service.
|
|
55
|
+
timeout: Request timeout in seconds.
|
|
56
|
+
"""
|
|
57
|
+
self.base_url = base_url.rstrip('/')
|
|
58
|
+
self.timeout = timeout
|
|
59
|
+
self._client: httpx.Client | None = None
|
|
60
|
+
|
|
61
|
+
@property
|
|
62
|
+
def client(self) -> httpx.Client:
|
|
63
|
+
"""Get or create the HTTP client."""
|
|
64
|
+
if self._client is None:
|
|
65
|
+
self._client = httpx.Client(
|
|
66
|
+
base_url=self.base_url,
|
|
67
|
+
timeout=self.timeout,
|
|
68
|
+
headers={'Content-Type': 'application/json'},
|
|
69
|
+
)
|
|
70
|
+
return self._client
|
|
71
|
+
|
|
72
|
+
def close(self) -> None:
|
|
73
|
+
"""Close the HTTP client."""
|
|
74
|
+
if self._client is not None:
|
|
75
|
+
self._client.close()
|
|
76
|
+
self._client = None
|
|
77
|
+
|
|
78
|
+
def __enter__(self) -> 'PipelineServiceClient':
|
|
79
|
+
return self
|
|
80
|
+
|
|
81
|
+
def __exit__(self, *args: Any) -> None:
|
|
82
|
+
self.close()
|
|
83
|
+
|
|
84
|
+
# -------------------------------------------------------------------------
|
|
85
|
+
# Pipeline CRUD
|
|
86
|
+
# -------------------------------------------------------------------------
|
|
87
|
+
|
|
88
|
+
def create_pipeline(
|
|
89
|
+
self,
|
|
90
|
+
name: str,
|
|
91
|
+
actions: list[dict[str, Any]],
|
|
92
|
+
description: str | None = None,
|
|
93
|
+
) -> dict[str, Any]:
|
|
94
|
+
"""Create a new pipeline definition.
|
|
95
|
+
|
|
96
|
+
Args:
|
|
97
|
+
name: Pipeline name.
|
|
98
|
+
actions: List of action definitions, each with 'name' and 'entrypoint'.
|
|
99
|
+
description: Optional pipeline description.
|
|
100
|
+
|
|
101
|
+
Returns:
|
|
102
|
+
Created pipeline data including 'id'.
|
|
103
|
+
"""
|
|
104
|
+
payload = {
|
|
105
|
+
'name': name,
|
|
106
|
+
'actions': actions,
|
|
107
|
+
'description': description,
|
|
108
|
+
}
|
|
109
|
+
response = self.client.post('/api/v1/pipelines/', json=payload)
|
|
110
|
+
response.raise_for_status()
|
|
111
|
+
return response.json()
|
|
112
|
+
|
|
113
|
+
def get_pipeline(self, pipeline_id: str) -> dict[str, Any]:
|
|
114
|
+
"""Get a pipeline by ID.
|
|
115
|
+
|
|
116
|
+
Args:
|
|
117
|
+
pipeline_id: Pipeline identifier.
|
|
118
|
+
|
|
119
|
+
Returns:
|
|
120
|
+
Pipeline data.
|
|
121
|
+
"""
|
|
122
|
+
response = self.client.get(f'/api/v1/pipelines/{pipeline_id}')
|
|
123
|
+
response.raise_for_status()
|
|
124
|
+
return response.json()
|
|
125
|
+
|
|
126
|
+
def list_pipelines(self, skip: int = 0, limit: int = 100) -> list[dict[str, Any]]:
|
|
127
|
+
"""List all pipelines.
|
|
128
|
+
|
|
129
|
+
Args:
|
|
130
|
+
skip: Number of records to skip.
|
|
131
|
+
limit: Maximum number of records to return.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
List of pipeline data.
|
|
135
|
+
"""
|
|
136
|
+
response = self.client.get('/api/v1/pipelines/', params={'skip': skip, 'limit': limit})
|
|
137
|
+
response.raise_for_status()
|
|
138
|
+
return response.json()
|
|
139
|
+
|
|
140
|
+
def delete_pipeline(self, pipeline_id: str) -> None:
|
|
141
|
+
"""Delete a pipeline.
|
|
142
|
+
|
|
143
|
+
Args:
|
|
144
|
+
pipeline_id: Pipeline identifier.
|
|
145
|
+
"""
|
|
146
|
+
response = self.client.delete(f'/api/v1/pipelines/{pipeline_id}')
|
|
147
|
+
response.raise_for_status()
|
|
148
|
+
|
|
149
|
+
# -------------------------------------------------------------------------
|
|
150
|
+
# Run Management
|
|
151
|
+
# -------------------------------------------------------------------------
|
|
152
|
+
|
|
153
|
+
def create_run(
|
|
154
|
+
self,
|
|
155
|
+
pipeline_id: str,
|
|
156
|
+
params: dict[str, Any] | None = None,
|
|
157
|
+
work_dir: str | None = None,
|
|
158
|
+
) -> dict[str, Any]:
|
|
159
|
+
"""Create a new run for a pipeline.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
pipeline_id: Pipeline to run.
|
|
163
|
+
params: Initial parameters for the run.
|
|
164
|
+
work_dir: Working directory path.
|
|
165
|
+
|
|
166
|
+
Returns:
|
|
167
|
+
Created run data including 'id' and initial progress.
|
|
168
|
+
"""
|
|
169
|
+
payload: dict[str, Any] = {}
|
|
170
|
+
if params is not None:
|
|
171
|
+
payload['params'] = params
|
|
172
|
+
if work_dir is not None:
|
|
173
|
+
payload['work_dir'] = work_dir
|
|
174
|
+
|
|
175
|
+
response = self.client.post(f'/api/v1/pipelines/{pipeline_id}/runs/', json=payload)
|
|
176
|
+
response.raise_for_status()
|
|
177
|
+
return response.json()
|
|
178
|
+
|
|
179
|
+
def get_run(self, run_id: str) -> dict[str, Any]:
|
|
180
|
+
"""Get a run by ID.
|
|
181
|
+
|
|
182
|
+
Args:
|
|
183
|
+
run_id: Run identifier.
|
|
184
|
+
|
|
185
|
+
Returns:
|
|
186
|
+
Run data including status and progress.
|
|
187
|
+
"""
|
|
188
|
+
response = self.client.get(f'/api/v1/runs/{run_id}')
|
|
189
|
+
response.raise_for_status()
|
|
190
|
+
return response.json()
|
|
191
|
+
|
|
192
|
+
def list_runs(
|
|
193
|
+
self,
|
|
194
|
+
status: str | None = None,
|
|
195
|
+
skip: int = 0,
|
|
196
|
+
limit: int = 100,
|
|
197
|
+
) -> list[dict[str, Any]]:
|
|
198
|
+
"""List all runs, optionally filtered by status.
|
|
199
|
+
|
|
200
|
+
Args:
|
|
201
|
+
status: Filter by run status.
|
|
202
|
+
skip: Number of records to skip.
|
|
203
|
+
limit: Maximum number of records to return.
|
|
204
|
+
|
|
205
|
+
Returns:
|
|
206
|
+
List of run data.
|
|
207
|
+
"""
|
|
208
|
+
params: dict[str, Any] = {'skip': skip, 'limit': limit}
|
|
209
|
+
if status:
|
|
210
|
+
params['status_filter'] = status
|
|
211
|
+
response = self.client.get('/api/v1/runs/', params=params)
|
|
212
|
+
response.raise_for_status()
|
|
213
|
+
return response.json()
|
|
214
|
+
|
|
215
|
+
def update_run(
|
|
216
|
+
self,
|
|
217
|
+
run_id: str,
|
|
218
|
+
status: str | None = None,
|
|
219
|
+
result: dict[str, Any] | None = None,
|
|
220
|
+
error: str | None = None,
|
|
221
|
+
) -> dict[str, Any]:
|
|
222
|
+
"""Update a run's status or result.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
run_id: Run identifier.
|
|
226
|
+
status: New status.
|
|
227
|
+
result: Final result data.
|
|
228
|
+
error: Error message if failed.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
Updated run data.
|
|
232
|
+
"""
|
|
233
|
+
payload: dict[str, Any] = {}
|
|
234
|
+
if status is not None:
|
|
235
|
+
payload['status'] = status
|
|
236
|
+
if result is not None:
|
|
237
|
+
payload['result'] = result
|
|
238
|
+
if error is not None:
|
|
239
|
+
payload['error'] = error
|
|
240
|
+
|
|
241
|
+
response = self.client.patch(f'/api/v1/runs/{run_id}', json=payload)
|
|
242
|
+
response.raise_for_status()
|
|
243
|
+
return response.json()
|
|
244
|
+
|
|
245
|
+
def delete_run(self, run_id: str) -> None:
|
|
246
|
+
"""Delete a run.
|
|
247
|
+
|
|
248
|
+
Args:
|
|
249
|
+
run_id: Run identifier.
|
|
250
|
+
"""
|
|
251
|
+
response = self.client.delete(f'/api/v1/runs/{run_id}')
|
|
252
|
+
response.raise_for_status()
|
|
253
|
+
|
|
254
|
+
# -------------------------------------------------------------------------
|
|
255
|
+
# Progress Reporting
|
|
256
|
+
# -------------------------------------------------------------------------
|
|
257
|
+
|
|
258
|
+
def report_progress(
|
|
259
|
+
self,
|
|
260
|
+
run_id: str,
|
|
261
|
+
current_action: str | None = None,
|
|
262
|
+
current_action_index: int | None = None,
|
|
263
|
+
status: str | None = None,
|
|
264
|
+
action_progress: ActionProgress | dict[str, Any] | None = None,
|
|
265
|
+
error: str | None = None,
|
|
266
|
+
) -> dict[str, Any]:
|
|
267
|
+
"""Report progress update for a run.
|
|
268
|
+
|
|
269
|
+
Args:
|
|
270
|
+
run_id: Run identifier.
|
|
271
|
+
current_action: Name of current action.
|
|
272
|
+
current_action_index: Index of current action.
|
|
273
|
+
status: Overall run status.
|
|
274
|
+
action_progress: Progress for the current action.
|
|
275
|
+
error: Error message if any.
|
|
276
|
+
|
|
277
|
+
Returns:
|
|
278
|
+
Updated run data.
|
|
279
|
+
"""
|
|
280
|
+
payload: dict[str, Any] = {}
|
|
281
|
+
if current_action is not None:
|
|
282
|
+
payload['current_action'] = current_action
|
|
283
|
+
if current_action_index is not None:
|
|
284
|
+
payload['current_action_index'] = current_action_index
|
|
285
|
+
if status is not None:
|
|
286
|
+
payload['status'] = status
|
|
287
|
+
if action_progress is not None:
|
|
288
|
+
if isinstance(action_progress, ActionProgress):
|
|
289
|
+
payload['action_progress'] = action_progress.to_dict()
|
|
290
|
+
else:
|
|
291
|
+
payload['action_progress'] = action_progress
|
|
292
|
+
if error is not None:
|
|
293
|
+
payload['error'] = error
|
|
294
|
+
|
|
295
|
+
response = self.client.post(f'/api/v1/runs/{run_id}/progress', json=payload)
|
|
296
|
+
response.raise_for_status()
|
|
297
|
+
return response.json()
|
|
298
|
+
|
|
299
|
+
def get_progress(self, run_id: str) -> PipelineProgress:
|
|
300
|
+
"""Get current progress for a run.
|
|
301
|
+
|
|
302
|
+
Args:
|
|
303
|
+
run_id: Run identifier.
|
|
304
|
+
|
|
305
|
+
Returns:
|
|
306
|
+
PipelineProgress object with current state.
|
|
307
|
+
"""
|
|
308
|
+
response = self.client.get(f'/api/v1/runs/{run_id}/progress')
|
|
309
|
+
response.raise_for_status()
|
|
310
|
+
data = response.json()
|
|
311
|
+
|
|
312
|
+
# Map API response to PipelineProgress
|
|
313
|
+
return PipelineProgress(
|
|
314
|
+
run_id=data['run_id'],
|
|
315
|
+
pipeline_id=data.get('pipeline_id', ''),
|
|
316
|
+
status=RunStatus(data.get('status', 'pending')),
|
|
317
|
+
current_action=data.get('current_action'),
|
|
318
|
+
current_action_index=data.get('current_action_index', 0),
|
|
319
|
+
actions=[ActionProgress.from_dict(a) for a in data.get('progress', [])],
|
|
320
|
+
started_at=datetime.fromisoformat(data['started_at']) if data.get('started_at') else None,
|
|
321
|
+
completed_at=datetime.fromisoformat(data['completed_at']) if data.get('completed_at') else None,
|
|
322
|
+
error=data.get('error'),
|
|
323
|
+
)
|
|
324
|
+
|
|
325
|
+
# -------------------------------------------------------------------------
|
|
326
|
+
# Checkpoints
|
|
327
|
+
# -------------------------------------------------------------------------
|
|
328
|
+
|
|
329
|
+
def create_checkpoint(
|
|
330
|
+
self,
|
|
331
|
+
run_id: str,
|
|
332
|
+
action_name: str,
|
|
333
|
+
action_index: int,
|
|
334
|
+
status: str,
|
|
335
|
+
params_snapshot: dict[str, Any] | None = None,
|
|
336
|
+
result: dict[str, Any] | None = None,
|
|
337
|
+
artifacts_path: str | None = None,
|
|
338
|
+
) -> dict[str, Any]:
|
|
339
|
+
"""Create a checkpoint for a run.
|
|
340
|
+
|
|
341
|
+
Args:
|
|
342
|
+
run_id: Run identifier.
|
|
343
|
+
action_name: Name of the action.
|
|
344
|
+
action_index: Index of the action.
|
|
345
|
+
status: Action status at checkpoint.
|
|
346
|
+
params_snapshot: Parameters at time of checkpoint.
|
|
347
|
+
result: Result from the action if completed.
|
|
348
|
+
artifacts_path: Path to saved artifacts.
|
|
349
|
+
|
|
350
|
+
Returns:
|
|
351
|
+
Created checkpoint data.
|
|
352
|
+
"""
|
|
353
|
+
payload = {
|
|
354
|
+
'action_name': action_name,
|
|
355
|
+
'action_index': action_index,
|
|
356
|
+
'status': status,
|
|
357
|
+
'params_snapshot': params_snapshot,
|
|
358
|
+
'result': result,
|
|
359
|
+
'artifacts_path': artifacts_path,
|
|
360
|
+
}
|
|
361
|
+
response = self.client.post(f'/api/v1/runs/{run_id}/checkpoints/', json=payload)
|
|
362
|
+
response.raise_for_status()
|
|
363
|
+
return response.json()
|
|
364
|
+
|
|
365
|
+
def get_checkpoints(self, run_id: str) -> list[dict[str, Any]]:
|
|
366
|
+
"""Get all checkpoints for a run.
|
|
367
|
+
|
|
368
|
+
Args:
|
|
369
|
+
run_id: Run identifier.
|
|
370
|
+
|
|
371
|
+
Returns:
|
|
372
|
+
List of checkpoint data.
|
|
373
|
+
"""
|
|
374
|
+
response = self.client.get(f'/api/v1/runs/{run_id}/checkpoints/')
|
|
375
|
+
response.raise_for_status()
|
|
376
|
+
return response.json()
|
|
377
|
+
|
|
378
|
+
def get_latest_checkpoint(self, run_id: str) -> dict[str, Any] | None:
|
|
379
|
+
"""Get the latest checkpoint for a run.
|
|
380
|
+
|
|
381
|
+
Args:
|
|
382
|
+
run_id: Run identifier.
|
|
383
|
+
|
|
384
|
+
Returns:
|
|
385
|
+
Latest checkpoint data or None if no checkpoints.
|
|
386
|
+
"""
|
|
387
|
+
try:
|
|
388
|
+
response = self.client.get(f'/api/v1/runs/{run_id}/checkpoints/latest')
|
|
389
|
+
response.raise_for_status()
|
|
390
|
+
return response.json()
|
|
391
|
+
except httpx.HTTPStatusError as e:
|
|
392
|
+
if e.response.status_code == 404:
|
|
393
|
+
return None
|
|
394
|
+
raise
|
|
395
|
+
|
|
396
|
+
def get_checkpoint_by_action(self, run_id: str, action_name: str) -> dict[str, Any] | None:
|
|
397
|
+
"""Get checkpoint for a specific action.
|
|
398
|
+
|
|
399
|
+
Args:
|
|
400
|
+
run_id: Run identifier.
|
|
401
|
+
action_name: Action name.
|
|
402
|
+
|
|
403
|
+
Returns:
|
|
404
|
+
Checkpoint data or None if not found.
|
|
405
|
+
"""
|
|
406
|
+
try:
|
|
407
|
+
response = self.client.get(f'/api/v1/runs/{run_id}/checkpoints/{action_name}')
|
|
408
|
+
response.raise_for_status()
|
|
409
|
+
return response.json()
|
|
410
|
+
except httpx.HTTPStatusError as e:
|
|
411
|
+
if e.response.status_code == 404:
|
|
412
|
+
return None
|
|
413
|
+
raise
|
|
414
|
+
|
|
415
|
+
# -------------------------------------------------------------------------
|
|
416
|
+
# Logs
|
|
417
|
+
# -------------------------------------------------------------------------
|
|
418
|
+
|
|
419
|
+
def append_logs(
|
|
420
|
+
self,
|
|
421
|
+
run_id: str,
|
|
422
|
+
entries: list[LogEntry] | list[dict[str, Any]],
|
|
423
|
+
) -> list[dict[str, Any]]:
|
|
424
|
+
"""Append log entries for a run.
|
|
425
|
+
|
|
426
|
+
Args:
|
|
427
|
+
run_id: Run identifier.
|
|
428
|
+
entries: List of log entries.
|
|
429
|
+
|
|
430
|
+
Returns:
|
|
431
|
+
Created log entries.
|
|
432
|
+
"""
|
|
433
|
+
# Convert LogEntry objects to dicts
|
|
434
|
+
entry_dicts = []
|
|
435
|
+
for entry in entries:
|
|
436
|
+
if isinstance(entry, LogEntry):
|
|
437
|
+
entry_dicts.append({
|
|
438
|
+
'message': entry.message,
|
|
439
|
+
'level': entry.level.value,
|
|
440
|
+
'action_name': entry.action_name,
|
|
441
|
+
})
|
|
442
|
+
else:
|
|
443
|
+
entry_dicts.append(entry)
|
|
444
|
+
|
|
445
|
+
payload = {'entries': entry_dicts}
|
|
446
|
+
response = self.client.post(f'/api/v1/runs/{run_id}/logs/', json=payload)
|
|
447
|
+
response.raise_for_status()
|
|
448
|
+
return response.json()
|
|
449
|
+
|
|
450
|
+
def get_logs(
|
|
451
|
+
self,
|
|
452
|
+
run_id: str,
|
|
453
|
+
action_name: str | None = None,
|
|
454
|
+
level: str | None = None,
|
|
455
|
+
since: datetime | None = None,
|
|
456
|
+
limit: int = 1000,
|
|
457
|
+
) -> list[dict[str, Any]]:
|
|
458
|
+
"""Get logs for a run with optional filters.
|
|
459
|
+
|
|
460
|
+
Args:
|
|
461
|
+
run_id: Run identifier.
|
|
462
|
+
action_name: Filter by action name.
|
|
463
|
+
level: Filter by log level.
|
|
464
|
+
since: Only return logs after this time.
|
|
465
|
+
limit: Maximum number of logs to return.
|
|
466
|
+
|
|
467
|
+
Returns:
|
|
468
|
+
List of log entries.
|
|
469
|
+
"""
|
|
470
|
+
params: dict[str, Any] = {'limit': limit}
|
|
471
|
+
if action_name:
|
|
472
|
+
params['action_name'] = action_name
|
|
473
|
+
if level:
|
|
474
|
+
params['level'] = level
|
|
475
|
+
if since:
|
|
476
|
+
params['since'] = since.isoformat()
|
|
477
|
+
|
|
478
|
+
response = self.client.get(f'/api/v1/runs/{run_id}/logs/', params=params)
|
|
479
|
+
response.raise_for_status()
|
|
480
|
+
return response.json()
|
|
481
|
+
|
|
482
|
+
# -------------------------------------------------------------------------
|
|
483
|
+
# Progress Streaming
|
|
484
|
+
# -------------------------------------------------------------------------
|
|
485
|
+
|
|
486
|
+
def stream_progress(
|
|
487
|
+
self,
|
|
488
|
+
run_id: str,
|
|
489
|
+
timeout: float = 3600.0,
|
|
490
|
+
) -> 'Iterator[PipelineProgress]':
|
|
491
|
+
"""Stream progress updates via SSE.
|
|
492
|
+
|
|
493
|
+
Yields PipelineProgress objects as updates are received from the server.
|
|
494
|
+
Continues until the run completes, fails, or is cancelled.
|
|
495
|
+
|
|
496
|
+
Args:
|
|
497
|
+
run_id: Run identifier.
|
|
498
|
+
timeout: Maximum time to stream in seconds.
|
|
499
|
+
|
|
500
|
+
Yields:
|
|
501
|
+
PipelineProgress objects with current state.
|
|
502
|
+
|
|
503
|
+
Example:
|
|
504
|
+
>>> for progress in client.stream_progress(run_id):
|
|
505
|
+
... print(f"Status: {progress.status}, Action: {progress.current_action}")
|
|
506
|
+
"""
|
|
507
|
+
url = f'{self.base_url}/api/v1/runs/{run_id}/progress/stream'
|
|
508
|
+
|
|
509
|
+
with httpx.stream('GET', url, timeout=timeout) as response:
|
|
510
|
+
response.raise_for_status()
|
|
511
|
+
|
|
512
|
+
event_type = None
|
|
513
|
+
data_buffer = []
|
|
514
|
+
|
|
515
|
+
for line in response.iter_lines():
|
|
516
|
+
line = line.strip()
|
|
517
|
+
|
|
518
|
+
if line.startswith('event:'):
|
|
519
|
+
event_type = line[6:].strip()
|
|
520
|
+
elif line.startswith('data:'):
|
|
521
|
+
data_buffer.append(line[5:].strip())
|
|
522
|
+
elif line == '' and data_buffer:
|
|
523
|
+
# End of event - process it
|
|
524
|
+
data_str = ''.join(data_buffer)
|
|
525
|
+
data_buffer = []
|
|
526
|
+
|
|
527
|
+
try:
|
|
528
|
+
data = json.loads(data_str)
|
|
529
|
+
except json.JSONDecodeError:
|
|
530
|
+
continue
|
|
531
|
+
|
|
532
|
+
# Convert to PipelineProgress
|
|
533
|
+
progress = PipelineProgress(
|
|
534
|
+
run_id=data['run_id'],
|
|
535
|
+
pipeline_id=data.get('pipeline_id', ''),
|
|
536
|
+
status=RunStatus(data.get('status', 'pending')),
|
|
537
|
+
current_action=data.get('current_action'),
|
|
538
|
+
current_action_index=data.get('current_action_index', 0),
|
|
539
|
+
actions=[ActionProgress.from_dict(a) for a in data.get('progress', []) or []],
|
|
540
|
+
started_at=datetime.fromisoformat(data['started_at']) if data.get('started_at') else None,
|
|
541
|
+
completed_at=datetime.fromisoformat(data['completed_at']) if data.get('completed_at') else None,
|
|
542
|
+
error=data.get('error'),
|
|
543
|
+
)
|
|
544
|
+
|
|
545
|
+
yield progress
|
|
546
|
+
|
|
547
|
+
# Stop on terminal events
|
|
548
|
+
if event_type in ('completed', 'failed', 'cancelled', 'error'):
|
|
549
|
+
return
|
|
550
|
+
|
|
551
|
+
async def stream_progress_async(
|
|
552
|
+
self,
|
|
553
|
+
run_id: str,
|
|
554
|
+
timeout: float = 3600.0,
|
|
555
|
+
) -> AsyncIterator[PipelineProgress]:
|
|
556
|
+
"""Stream progress updates via SSE (async version).
|
|
557
|
+
|
|
558
|
+
Yields PipelineProgress objects as updates are received from the server.
|
|
559
|
+
Continues until the run completes, fails, or is cancelled.
|
|
560
|
+
|
|
561
|
+
Args:
|
|
562
|
+
run_id: Run identifier.
|
|
563
|
+
timeout: Maximum time to stream in seconds.
|
|
564
|
+
|
|
565
|
+
Yields:
|
|
566
|
+
PipelineProgress objects with current state.
|
|
567
|
+
|
|
568
|
+
Example:
|
|
569
|
+
>>> async for progress in client.stream_progress_async(run_id):
|
|
570
|
+
... print(f"Status: {progress.status}, Action: {progress.current_action}")
|
|
571
|
+
"""
|
|
572
|
+
url = f'{self.base_url}/api/v1/runs/{run_id}/progress/stream'
|
|
573
|
+
|
|
574
|
+
async with httpx.AsyncClient(timeout=timeout) as async_client:
|
|
575
|
+
async with async_client.stream('GET', url) as response:
|
|
576
|
+
response.raise_for_status()
|
|
577
|
+
|
|
578
|
+
event_type = None
|
|
579
|
+
data_buffer: list[str] = []
|
|
580
|
+
|
|
581
|
+
async for line in response.aiter_lines():
|
|
582
|
+
line = line.strip()
|
|
583
|
+
|
|
584
|
+
if line.startswith('event:'):
|
|
585
|
+
event_type = line[6:].strip()
|
|
586
|
+
elif line.startswith('data:'):
|
|
587
|
+
data_buffer.append(line[5:].strip())
|
|
588
|
+
elif line == '' and data_buffer:
|
|
589
|
+
# End of event - process it
|
|
590
|
+
data_str = ''.join(data_buffer)
|
|
591
|
+
data_buffer = []
|
|
592
|
+
|
|
593
|
+
try:
|
|
594
|
+
data = json.loads(data_str)
|
|
595
|
+
except json.JSONDecodeError:
|
|
596
|
+
continue
|
|
597
|
+
|
|
598
|
+
# Convert to PipelineProgress
|
|
599
|
+
started = data.get('started_at')
|
|
600
|
+
completed = data.get('completed_at')
|
|
601
|
+
progress = PipelineProgress(
|
|
602
|
+
run_id=data['run_id'],
|
|
603
|
+
pipeline_id=data.get('pipeline_id', ''),
|
|
604
|
+
status=RunStatus(data.get('status', 'pending')),
|
|
605
|
+
current_action=data.get('current_action'),
|
|
606
|
+
current_action_index=data.get('current_action_index', 0),
|
|
607
|
+
actions=[ActionProgress.from_dict(a) for a in data.get('progress', []) or []],
|
|
608
|
+
started_at=datetime.fromisoformat(started) if started else None,
|
|
609
|
+
completed_at=datetime.fromisoformat(completed) if completed else None,
|
|
610
|
+
error=data.get('error'),
|
|
611
|
+
)
|
|
612
|
+
|
|
613
|
+
yield progress
|
|
614
|
+
|
|
615
|
+
# Stop on terminal events
|
|
616
|
+
if event_type in ('completed', 'failed', 'cancelled', 'error'):
|
|
617
|
+
return
|
|
618
|
+
|
|
619
|
+
# -------------------------------------------------------------------------
|
|
620
|
+
# Health Check
|
|
621
|
+
# -------------------------------------------------------------------------
|
|
622
|
+
|
|
623
|
+
def health_check(self) -> bool:
|
|
624
|
+
"""Check if the pipeline service is healthy.
|
|
625
|
+
|
|
626
|
+
Returns:
|
|
627
|
+
True if healthy, False otherwise.
|
|
628
|
+
"""
|
|
629
|
+
try:
|
|
630
|
+
response = self.client.get('/health')
|
|
631
|
+
return response.status_code == 200
|
|
632
|
+
except Exception:
|
|
633
|
+
return False
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
__all__ = ['PipelineServiceClient']
|