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
synapse_sdk/loggers.py
CHANGED
|
@@ -1,116 +1,497 @@
|
|
|
1
|
-
import
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import logging
|
|
2
4
|
import time
|
|
5
|
+
import warnings
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
7
|
+
from collections.abc import Mapping
|
|
8
|
+
from dataclasses import dataclass, field
|
|
9
|
+
from enum import Enum
|
|
10
|
+
from typing import TYPE_CHECKING, Any, Protocol
|
|
11
|
+
|
|
12
|
+
if TYPE_CHECKING:
|
|
13
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
14
|
+
|
|
15
|
+
# Module-level logger for SDK output
|
|
16
|
+
_logger = logging.getLogger('synapse_sdk.loggers')
|
|
17
|
+
|
|
18
|
+
# LogLevel string value → Python logging level mapping
|
|
19
|
+
_LOG_LEVEL_MAP: dict[str, int] = {
|
|
20
|
+
'debug': logging.DEBUG,
|
|
21
|
+
'info': logging.INFO,
|
|
22
|
+
'warning': logging.WARNING,
|
|
23
|
+
'error': logging.ERROR,
|
|
24
|
+
'critical': logging.CRITICAL,
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class LoggerBackend(Protocol):
|
|
29
|
+
"""Protocol for logger backends that handle data synchronization."""
|
|
30
|
+
|
|
31
|
+
def publish_progress(self, job_id: str, progress: 'ProgressData') -> None: ...
|
|
32
|
+
def publish_metrics(self, job_id: str, metrics: dict[str, Any]) -> None: ...
|
|
33
|
+
def publish_log(self, job_id: str, log_entry: 'LogEntry') -> None: ...
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@dataclass
|
|
37
|
+
class ProgressData:
|
|
38
|
+
"""Immutable progress data snapshot."""
|
|
39
|
+
|
|
40
|
+
percent: float
|
|
41
|
+
time_remaining: float | None = None
|
|
42
|
+
elapsed_time: float | None = None
|
|
43
|
+
status: str = 'running'
|
|
44
|
+
|
|
45
|
+
|
|
46
|
+
@dataclass
|
|
47
|
+
class LogEntry:
|
|
48
|
+
"""Single log entry."""
|
|
49
|
+
|
|
50
|
+
event: str
|
|
51
|
+
data: dict[str, Any]
|
|
52
|
+
timestamp: float = field(default_factory=time.time)
|
|
53
|
+
file: str | None = None
|
|
54
|
+
step: str | None = None # 신규: 로그가 발생한 step
|
|
55
|
+
level: Any = None # 신규: 로그 레벨 (LogLevel enum, 순환 import 방지를 위해 Any)
|
|
56
|
+
|
|
57
|
+
def to_dict(self) -> dict[str, Any]:
|
|
58
|
+
"""Convert to dictionary for API serialization."""
|
|
59
|
+
return {
|
|
60
|
+
'event': self.event,
|
|
61
|
+
'data': self.data,
|
|
62
|
+
'timestamp': self.timestamp,
|
|
63
|
+
'file': self.file,
|
|
64
|
+
'step': self.step,
|
|
65
|
+
'level': self.level.value if self.level else None,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
class BaseLogger(ABC):
|
|
70
|
+
"""Base class for logging progress, metrics, and events.
|
|
71
|
+
|
|
72
|
+
All state is instance-level to prevent cross-instance contamination.
|
|
73
|
+
Uses composition over inheritance for backend communication.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
_start_time: float
|
|
77
|
+
_progress: dict[str, ProgressData]
|
|
78
|
+
_metrics: dict[str, dict[str, Any]]
|
|
79
|
+
_category_start_times: dict[str, float]
|
|
80
|
+
_current_step: str | None
|
|
81
|
+
_is_finished: bool
|
|
82
|
+
|
|
83
|
+
def __init__(self) -> None:
|
|
84
|
+
self._start_time = time.monotonic()
|
|
85
|
+
self._progress = {}
|
|
86
|
+
self._metrics = {}
|
|
87
|
+
self._category_start_times = {}
|
|
88
|
+
self._current_step = None
|
|
89
|
+
self._is_finished = False
|
|
90
|
+
|
|
91
|
+
def set_step(self, step: str | None) -> None:
|
|
92
|
+
"""Set the current step for logging context.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
step: The step name, or None to clear.
|
|
96
|
+
"""
|
|
97
|
+
self._current_step = step
|
|
98
|
+
|
|
99
|
+
def get_step(self) -> str | None:
|
|
100
|
+
"""Get the current step.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
The current step name, or None if not set.
|
|
104
|
+
"""
|
|
105
|
+
return self._current_step
|
|
106
|
+
|
|
107
|
+
def _raise_if_finished(self) -> None:
|
|
108
|
+
if self._is_finished:
|
|
109
|
+
raise RuntimeError('Cannot log to a finished logger')
|
|
110
|
+
|
|
111
|
+
def log(
|
|
112
|
+
self,
|
|
113
|
+
level: LogLevel,
|
|
114
|
+
event: str,
|
|
115
|
+
data: dict[str, Any],
|
|
116
|
+
file: str | None = None,
|
|
117
|
+
step: str | None = None,
|
|
118
|
+
) -> None:
|
|
119
|
+
"""Log an event with data.
|
|
120
|
+
|
|
121
|
+
Args:
|
|
122
|
+
level: Log level (LogLevel enum).
|
|
123
|
+
event: Event name/type.
|
|
124
|
+
data: Dictionary of event data.
|
|
125
|
+
file: Optional file path associated with the event.
|
|
126
|
+
step: Optional step name. Uses current step if not specified.
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
TypeError: If level is not a LogLevel enum or data is not a dictionary.
|
|
130
|
+
RuntimeError: If logger is already finished.
|
|
131
|
+
"""
|
|
132
|
+
self._raise_if_finished()
|
|
133
|
+
|
|
134
|
+
# Validate level is a LogLevel enum (duck typing check to avoid circular import)
|
|
135
|
+
if not (isinstance(level, Enum) and hasattr(level, 'value') and level.value in _LOG_LEVEL_MAP):
|
|
136
|
+
raise TypeError(f'level must be a LogLevel enum, got {type(level).__name__}')
|
|
137
|
+
|
|
138
|
+
if not isinstance(data, Mapping):
|
|
139
|
+
raise TypeError(f'data must be a dict, got {type(data).__name__}')
|
|
140
|
+
|
|
141
|
+
data = dict(data) # Copy to avoid mutating input
|
|
142
|
+
# Use explicit step or fall back to current step
|
|
143
|
+
effective_step = step if step is not None else self._current_step
|
|
144
|
+
self._log_impl(event, data, file, effective_step, level)
|
|
145
|
+
|
|
146
|
+
def info(self, message: str) -> None:
|
|
147
|
+
"""Log an info message."""
|
|
148
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
149
|
+
|
|
150
|
+
self.log(LogLevel.INFO, 'info', {'message': message})
|
|
151
|
+
|
|
152
|
+
def debug(self, message: str) -> None:
|
|
153
|
+
"""Log a debug message."""
|
|
154
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
155
|
+
|
|
156
|
+
self.log(LogLevel.DEBUG, 'debug', {'message': message})
|
|
157
|
+
|
|
158
|
+
def warning(self, message: str) -> None:
|
|
159
|
+
"""Log a warning message."""
|
|
160
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
161
|
+
|
|
162
|
+
self.log(LogLevel.WARNING, 'warning', {'message': message})
|
|
163
|
+
|
|
164
|
+
def error(self, message: str) -> None:
|
|
165
|
+
"""Log an error message."""
|
|
166
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
167
|
+
|
|
168
|
+
self.log(LogLevel.ERROR, 'error', {'message': message})
|
|
169
|
+
|
|
170
|
+
def critical(self, message: str) -> None:
|
|
171
|
+
"""Log a critical message."""
|
|
172
|
+
from synapse_sdk.plugins.models.logger import LogLevel
|
|
173
|
+
|
|
174
|
+
self.log(LogLevel.CRITICAL, 'critical', {'message': message})
|
|
175
|
+
|
|
176
|
+
def set_progress(
|
|
177
|
+
self,
|
|
178
|
+
current: int,
|
|
179
|
+
total: int,
|
|
180
|
+
step: str | None = None,
|
|
181
|
+
category: str | None = None,
|
|
182
|
+
) -> None:
|
|
183
|
+
"""Set progress for the current operation.
|
|
184
|
+
|
|
185
|
+
Args:
|
|
186
|
+
current: Current progress value (0 to total).
|
|
187
|
+
total: Total progress value.
|
|
188
|
+
step: Optional step name. Uses current step if not specified.
|
|
189
|
+
category: Deprecated. Use step instead.
|
|
3
190
|
|
|
4
|
-
|
|
191
|
+
Raises:
|
|
192
|
+
ValueError: If current/total values are invalid.
|
|
193
|
+
RuntimeError: If logger is already finished.
|
|
194
|
+
"""
|
|
195
|
+
self._raise_if_finished()
|
|
5
196
|
|
|
197
|
+
if total <= 0:
|
|
198
|
+
raise ValueError(f'total must be > 0, got {total}')
|
|
199
|
+
if not 0 <= current <= total:
|
|
200
|
+
raise ValueError(f'current must be between 0 and {total}, got {current}')
|
|
6
201
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
202
|
+
# Priority: explicit step > current step > category (deprecated)
|
|
203
|
+
effective_key: str | None = None
|
|
204
|
+
if step is not None:
|
|
205
|
+
effective_key = step
|
|
206
|
+
if category is not None:
|
|
207
|
+
warnings.warn(
|
|
208
|
+
"The 'category' parameter is deprecated. Use 'step' instead. "
|
|
209
|
+
"'step' takes precedence when both are provided.",
|
|
210
|
+
DeprecationWarning,
|
|
211
|
+
stacklevel=2,
|
|
212
|
+
)
|
|
213
|
+
elif self._current_step is not None:
|
|
214
|
+
# Use current step if available
|
|
215
|
+
effective_key = self._current_step
|
|
216
|
+
if category is not None:
|
|
217
|
+
warnings.warn(
|
|
218
|
+
"The 'category' parameter is deprecated. Use 'step' instead. "
|
|
219
|
+
'Current step takes precedence over category.',
|
|
220
|
+
DeprecationWarning,
|
|
221
|
+
stacklevel=2,
|
|
222
|
+
)
|
|
223
|
+
elif category is not None:
|
|
224
|
+
warnings.warn(
|
|
225
|
+
"The 'category' parameter is deprecated. Use 'step' instead.",
|
|
226
|
+
DeprecationWarning,
|
|
227
|
+
stacklevel=2,
|
|
228
|
+
)
|
|
229
|
+
effective_key = category
|
|
12
230
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if progress_categories:
|
|
16
|
-
self.progress_record['categories'] = progress_categories
|
|
231
|
+
key = effective_key or '__default__'
|
|
232
|
+
now = time.monotonic()
|
|
17
233
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
234
|
+
# Initialize start time on first call for this category
|
|
235
|
+
if key not in self._category_start_times or current == 0:
|
|
236
|
+
self._category_start_times[key] = now
|
|
21
237
|
|
|
22
|
-
|
|
23
|
-
percent = round(
|
|
24
|
-
# TODO current 0 으로 시작하지 않아도 작동되도록 수정
|
|
25
|
-
if current == 0:
|
|
26
|
-
self.time_begin_per_category[category] = time.time()
|
|
27
|
-
time_remaining = None
|
|
28
|
-
else:
|
|
29
|
-
seconds_per_item = (time.time() - self.time_begin_per_category[category]) / current
|
|
30
|
-
time_remaining = round(seconds_per_item * (total - current), 2)
|
|
238
|
+
elapsed = now - self._category_start_times[key]
|
|
239
|
+
percent = round((current / total) * 100, 2)
|
|
31
240
|
|
|
32
|
-
|
|
241
|
+
# Calculate time remaining
|
|
242
|
+
time_remaining = None
|
|
243
|
+
if current > 0:
|
|
244
|
+
rate = elapsed / current
|
|
245
|
+
time_remaining = round(rate * (total - current), 2)
|
|
33
246
|
|
|
247
|
+
progress = ProgressData(
|
|
248
|
+
percent=percent,
|
|
249
|
+
time_remaining=time_remaining,
|
|
250
|
+
elapsed_time=round(elapsed, 2),
|
|
251
|
+
)
|
|
252
|
+
|
|
253
|
+
self._progress[key] = progress
|
|
254
|
+
self._on_progress(progress, effective_key)
|
|
255
|
+
|
|
256
|
+
def set_progress_failed(self, category: str | None = None) -> None:
|
|
257
|
+
"""Mark progress as failed.
|
|
258
|
+
|
|
259
|
+
Args:
|
|
260
|
+
category: Optional category name.
|
|
261
|
+
|
|
262
|
+
Raises:
|
|
263
|
+
RuntimeError: If logger is already finished.
|
|
264
|
+
"""
|
|
265
|
+
self._raise_if_finished()
|
|
266
|
+
|
|
267
|
+
key = category or '__default__'
|
|
268
|
+
elapsed = None
|
|
269
|
+
|
|
270
|
+
if key in self._category_start_times:
|
|
271
|
+
elapsed = round(time.monotonic() - self._category_start_times[key], 2)
|
|
272
|
+
|
|
273
|
+
progress = ProgressData(
|
|
274
|
+
percent=0.0,
|
|
275
|
+
time_remaining=None,
|
|
276
|
+
elapsed_time=elapsed,
|
|
277
|
+
status='failed',
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
self._progress[key] = progress
|
|
281
|
+
self._on_progress(progress, category)
|
|
282
|
+
|
|
283
|
+
def set_metrics(
|
|
284
|
+
self,
|
|
285
|
+
value: dict[str, Any],
|
|
286
|
+
step: str | None = None,
|
|
287
|
+
category: str | None = None,
|
|
288
|
+
) -> None:
|
|
289
|
+
"""Set metrics for a step.
|
|
290
|
+
|
|
291
|
+
Args:
|
|
292
|
+
value: Dictionary of metric values.
|
|
293
|
+
step: Optional step name. Uses current step if not specified.
|
|
294
|
+
category: Deprecated. Use step instead.
|
|
295
|
+
|
|
296
|
+
Raises:
|
|
297
|
+
ValueError: If no step/category is available.
|
|
298
|
+
TypeError: If value is not a dictionary.
|
|
299
|
+
RuntimeError: If logger is already finished.
|
|
300
|
+
"""
|
|
301
|
+
self._raise_if_finished()
|
|
302
|
+
|
|
303
|
+
if not isinstance(value, Mapping):
|
|
304
|
+
raise TypeError(f'value must be a dict, got {type(value).__name__}')
|
|
305
|
+
|
|
306
|
+
# Priority: explicit step > current step > category (deprecated)
|
|
307
|
+
effective_key: str | None = None
|
|
308
|
+
if step is not None:
|
|
309
|
+
effective_key = step
|
|
310
|
+
if category is not None:
|
|
311
|
+
warnings.warn(
|
|
312
|
+
"The 'category' parameter is deprecated. Use 'step' instead. "
|
|
313
|
+
"'step' takes precedence when both are provided.",
|
|
314
|
+
DeprecationWarning,
|
|
315
|
+
stacklevel=2,
|
|
316
|
+
)
|
|
317
|
+
elif self._current_step is not None:
|
|
318
|
+
# Use current step if available
|
|
319
|
+
effective_key = self._current_step
|
|
320
|
+
if category is not None:
|
|
321
|
+
warnings.warn(
|
|
322
|
+
"The 'category' parameter is deprecated. Use 'step' instead. "
|
|
323
|
+
'Current step takes precedence over category.',
|
|
324
|
+
DeprecationWarning,
|
|
325
|
+
stacklevel=2,
|
|
326
|
+
)
|
|
327
|
+
elif category is not None:
|
|
328
|
+
warnings.warn(
|
|
329
|
+
"The 'category' parameter is deprecated. Use 'step' instead.",
|
|
330
|
+
DeprecationWarning,
|
|
331
|
+
stacklevel=2,
|
|
332
|
+
)
|
|
333
|
+
effective_key = category
|
|
334
|
+
|
|
335
|
+
if not effective_key:
|
|
336
|
+
raise ValueError('step must be specified or set via set_step()')
|
|
337
|
+
|
|
338
|
+
data = dict(value) # Copy
|
|
339
|
+
|
|
340
|
+
if effective_key not in self._metrics:
|
|
341
|
+
self._metrics[effective_key] = {}
|
|
342
|
+
self._metrics[effective_key].update(data)
|
|
343
|
+
|
|
344
|
+
self._on_metrics(effective_key, self._metrics[effective_key])
|
|
345
|
+
|
|
346
|
+
def get_progress(self, category: str | None = None) -> ProgressData | None:
|
|
347
|
+
"""Get progress for a category."""
|
|
348
|
+
key = category or '__default__'
|
|
349
|
+
return self._progress.get(key)
|
|
350
|
+
|
|
351
|
+
def get_metrics(self, category: str | None = None) -> dict[str, Any]:
|
|
352
|
+
"""Get metrics, optionally filtered by category."""
|
|
34
353
|
if category:
|
|
35
|
-
self.
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
'time_remaining': self.progress_record.get('time_remaining'),
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return progress
|
|
354
|
+
return dict(self._metrics.get(category, {}))
|
|
355
|
+
return {k: dict(v) for k, v in self._metrics.items()}
|
|
356
|
+
|
|
357
|
+
def finish(self) -> None:
|
|
358
|
+
"""Mark the logger as finished. No further logging is allowed."""
|
|
359
|
+
self._is_finished = True
|
|
360
|
+
self._on_finish()
|
|
361
|
+
|
|
362
|
+
@abstractmethod
|
|
363
|
+
def _log_impl(
|
|
364
|
+
self,
|
|
365
|
+
event: str,
|
|
366
|
+
data: dict[str, Any],
|
|
367
|
+
file: str | None,
|
|
368
|
+
step: str | None,
|
|
369
|
+
level: LogLevel | None = None,
|
|
370
|
+
) -> None:
|
|
371
|
+
"""Implementation-specific log handling."""
|
|
372
|
+
...
|
|
373
|
+
|
|
374
|
+
def _on_progress(self, progress: ProgressData, category: str | None) -> None:
|
|
375
|
+
"""Hook called when progress is updated. Override in subclasses."""
|
|
376
|
+
pass
|
|
377
|
+
|
|
378
|
+
def _on_metrics(self, category: str, metrics: dict[str, Any]) -> None:
|
|
379
|
+
"""Hook called when metrics are updated. Override in subclasses."""
|
|
380
|
+
pass
|
|
381
|
+
|
|
382
|
+
def _on_finish(self) -> None:
|
|
383
|
+
"""Hook called when logger is finished. Override in subclasses."""
|
|
384
|
+
pass
|
|
70
385
|
|
|
71
386
|
|
|
72
387
|
class ConsoleLogger(BaseLogger):
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
388
|
+
"""Logger that prints to console using Python logging module."""
|
|
389
|
+
|
|
390
|
+
def _log_impl(
|
|
391
|
+
self,
|
|
392
|
+
event: str,
|
|
393
|
+
data: dict[str, Any],
|
|
394
|
+
file: str | None,
|
|
395
|
+
step: str | None,
|
|
396
|
+
level: LogLevel | None = None,
|
|
397
|
+
) -> None:
|
|
398
|
+
prefix = f'[{step}] ' if step else ''
|
|
399
|
+
level_str = level.value.upper() if level else 'INFO'
|
|
400
|
+
message = f'{level_str}: {prefix}{event} {data}'
|
|
76
401
|
|
|
77
|
-
|
|
78
|
-
|
|
402
|
+
# Use print with flush=True for immediate output
|
|
403
|
+
# This ensures logs are visible in Ray remote workers
|
|
404
|
+
print(message, flush=True)
|
|
405
|
+
|
|
406
|
+
def _on_progress(self, progress: ProgressData, category: str | None) -> None:
|
|
407
|
+
prefix = f'[{category}] ' if category else ''
|
|
408
|
+
print(f'INFO: {prefix}Progress: {progress.percent}% | ETA: {progress.time_remaining}s', flush=True)
|
|
409
|
+
|
|
410
|
+
def _on_metrics(self, category: str, metrics: dict[str, Any]) -> None:
|
|
411
|
+
print(f'INFO: [{category}] Metrics: {metrics}', flush=True)
|
|
79
412
|
|
|
80
413
|
|
|
81
414
|
class BackendLogger(BaseLogger):
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
415
|
+
"""Logger that syncs with a remote backend.
|
|
416
|
+
|
|
417
|
+
Uses a backend interface for decoupled communication.
|
|
418
|
+
"""
|
|
85
419
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
420
|
+
_backend: LoggerBackend | None
|
|
421
|
+
_job_id: str
|
|
422
|
+
_log_queue: list[LogEntry]
|
|
423
|
+
|
|
424
|
+
def __init__(self, backend: LoggerBackend | None, job_id: str) -> None:
|
|
425
|
+
super().__init__()
|
|
426
|
+
self._backend = backend
|
|
427
|
+
self._job_id = job_id
|
|
428
|
+
self._log_queue = []
|
|
429
|
+
|
|
430
|
+
def _log_impl(
|
|
431
|
+
self,
|
|
432
|
+
event: str,
|
|
433
|
+
data: dict[str, Any],
|
|
434
|
+
file: str | None,
|
|
435
|
+
step: str | None,
|
|
436
|
+
level: LogLevel | None = None,
|
|
437
|
+
) -> None:
|
|
438
|
+
entry = LogEntry(event=event, data=data, file=file, step=step, level=level)
|
|
439
|
+
self._log_queue.append(entry)
|
|
440
|
+
self._flush_logs()
|
|
441
|
+
|
|
442
|
+
def _on_progress(self, progress: ProgressData, category: str | None) -> None:
|
|
443
|
+
if self._backend is None:
|
|
444
|
+
return
|
|
90
445
|
|
|
91
|
-
def set_progress(self, current, total, category=None):
|
|
92
|
-
super().set_progress(current, total, category=category)
|
|
93
446
|
try:
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
def log(self, event, data):
|
|
103
|
-
print(event, data)
|
|
104
|
-
|
|
105
|
-
log = {
|
|
106
|
-
'event': event,
|
|
107
|
-
'data': data,
|
|
108
|
-
'datetime': datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S.%f'),
|
|
109
|
-
'job': self.job_id,
|
|
110
|
-
}
|
|
111
|
-
self.logs_queue.append(log)
|
|
447
|
+
self._backend.publish_progress(self._job_id, progress)
|
|
448
|
+
except Exception as e:
|
|
449
|
+
_logger.error(f'Failed to publish progress: {e}')
|
|
450
|
+
|
|
451
|
+
def _on_metrics(self, category: str, metrics: dict[str, Any]) -> None:
|
|
452
|
+
if self._backend is None:
|
|
453
|
+
return
|
|
454
|
+
|
|
112
455
|
try:
|
|
113
|
-
self.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
456
|
+
self._backend.publish_metrics(self._job_id, {category: metrics})
|
|
457
|
+
except Exception as e:
|
|
458
|
+
_logger.error(f'Failed to publish metrics: {e}')
|
|
459
|
+
|
|
460
|
+
def _flush_logs(self) -> None:
|
|
461
|
+
if self._backend is None or not self._log_queue:
|
|
462
|
+
return
|
|
463
|
+
|
|
464
|
+
try:
|
|
465
|
+
for entry in self._log_queue:
|
|
466
|
+
self._backend.publish_log(self._job_id, entry)
|
|
467
|
+
self._log_queue.clear()
|
|
468
|
+
except Exception as e:
|
|
469
|
+
_logger.error(f'Failed to flush logs: {e}')
|
|
470
|
+
|
|
471
|
+
def _on_finish(self) -> None:
|
|
472
|
+
self._flush_logs()
|
|
473
|
+
|
|
474
|
+
|
|
475
|
+
class NoOpLogger(BaseLogger):
|
|
476
|
+
"""Logger that does nothing. Useful for testing or disabled logging."""
|
|
477
|
+
|
|
478
|
+
def _log_impl(
|
|
479
|
+
self,
|
|
480
|
+
event: str,
|
|
481
|
+
data: dict[str, Any],
|
|
482
|
+
file: str | None,
|
|
483
|
+
step: str | None,
|
|
484
|
+
level: LogLevel | None = None,
|
|
485
|
+
) -> None:
|
|
486
|
+
pass
|
|
487
|
+
|
|
488
|
+
|
|
489
|
+
__all__ = [
|
|
490
|
+
'BaseLogger',
|
|
491
|
+
'BackendLogger',
|
|
492
|
+
'ConsoleLogger',
|
|
493
|
+
'LogEntry',
|
|
494
|
+
'LoggerBackend',
|
|
495
|
+
'NoOpLogger',
|
|
496
|
+
'ProgressData',
|
|
497
|
+
]
|
synapse_sdk/mcp/MCP.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# Synapse MCP Server
|
|
2
|
+
|
|
3
|
+
MCP server for AI assistants to interact with Synapse infrastructure.
|
|
4
|
+
|
|
5
|
+
## Quick Start
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
# Initialize config
|
|
9
|
+
uvx --from 'synapse-sdk[mcp]' synapse mcp init
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Setup via AI assistant
|
|
13
|
+
|
|
14
|
+
```
|
|
15
|
+
1. add_environment(name="prod", backend_url="...", access_token="...")
|
|
16
|
+
2. list_agents()
|
|
17
|
+
3. select_agent(123) # Required for job operations
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Configuration
|
|
21
|
+
|
|
22
|
+
`~/.synapse/config.yaml`:
|
|
23
|
+
|
|
24
|
+
## Cursor Setup
|
|
25
|
+
|
|
26
|
+
`~/.cursor/mcp.json`:
|
|
27
|
+
```json
|
|
28
|
+
{
|
|
29
|
+
"mcpServers": {
|
|
30
|
+
"synapse": {
|
|
31
|
+
"command": "uvx",
|
|
32
|
+
"args": ["--from", "synapse-sdk[mcp]", "synapse", "mcp", "serve"]
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Claude Code Setup
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
claude mcp add synapse -- uvx --from 'synapse-sdk[mcp]' synapse mcp serve
|
|
42
|
+
|
|
43
|
+
# Local development:
|
|
44
|
+
claude mcp add synapse -- uv run --directory <path-to-sdk> synapse mcp serve
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Tools
|
|
48
|
+
|
|
49
|
+
| Category | Tools |
|
|
50
|
+
|----------|-------|
|
|
51
|
+
| Environment | `switch_environment`, `list_environments`, `get_current_environment`, `add_environment` |
|
|
52
|
+
| Agents | `list_agents`, `select_agent`, `clear_agent` |
|
|
53
|
+
| Plugins | `list_plugin_releases`, `get_plugin_release`, `discover_local_plugin`, `get_action_config`, `validate_plugin_config`, `publish_plugin` |
|
|
54
|
+
| Execution | `run_plugin`, `run_debug_plugin`, `run_local_plugin` |
|
|
55
|
+
| Jobs | `list_jobs`, `get_job`, `get_job_logs`, `stop_job` |
|
|
56
|
+
| Deployments | `list_serve_applications`, `get_serve_application`, `delete_serve_application` |
|
|
57
|
+
| Models | `list_models`, `get_model` |
|
|
58
|
+
|
|
59
|
+
## Resources
|
|
60
|
+
|
|
61
|
+
- `synapse://config` - Current configuration
|
|
62
|
+
- `synapse://environments` - List of environments
|
|
63
|
+
- `synapse://plugin/{path}/config` - Plugin config.yaml
|
|
64
|
+
- `synapse://plugin/{path}/actions` - Plugin actions
|
|
65
|
+
- `synapse://plugin/{path}/action/{name}/schema` - Action schema
|
|
66
|
+
|
|
67
|
+
## Prompts
|
|
68
|
+
|
|
69
|
+
`debug_plugin`, `publish_plugin_workflow`, `diagnose_job`, `setup_environment`
|