rxon 1.0b0__tar.gz

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.
rxon-1.0b0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Dmitrii Gagarin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
rxon-1.0b0/PKG-INFO ADDED
@@ -0,0 +1,118 @@
1
+ Metadata-Version: 2.4
2
+ Name: rxon
3
+ Version: 1.0b0
4
+ Summary: RXON (Reverse Axon) - Lightweight Inter-node Reverse Communication Protocol.
5
+ Author-email: Dmitrii Gagarin <madgagarin@gmail.com>
6
+ Maintainer-email: Dmitrii Gagarin <madgagarin@gmail.com>
7
+ Project-URL: Homepage, https://github.com/madgagarin/rxon
8
+ Project-URL: Repository, https://github.com/madgagarin/rxon
9
+ Project-URL: Bug Tracker, https://github.com/madgagarin/rxon/issues
10
+ Keywords: rxon,hln,protocol,distributed-systems,holarchy,holon
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Intended Audience :: System Administrators
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: License :: OSI Approved :: MIT License
18
+ Classifier: Operating System :: OS Independent
19
+ Classifier: Typing :: Typed
20
+ Requires-Python: >=3.11
21
+ Description-Content-Type: text/markdown
22
+ License-File: LICENSE
23
+ Requires-Dist: aiohttp>=3.12
24
+ Requires-Dist: orjson>=3.10
25
+ Dynamic: license-file
26
+
27
+ # RXON (Reverse Axon) Protocol
28
+
29
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
30
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/release/python-3110/)
31
+ [![Typing: Typed](https://img.shields.io/badge/Typing-Typed-brightgreen.svg)](https://peps.python.org/pep-0561/)
32
+
33
+ > **[RU](https://github.com/madgagarin/rxon/blob/main/README_RU.md)**
34
+
35
+ **RXON** (Reverse Axon) is a lightweight reverse-connection inter-service communication protocol designed for the **[HLN (Hierarchical Logic Network)](https://github.com/avtomatika-ai/hln)** architecture.
36
+
37
+ It serves as the "nervous system" for distributed multi-agent systems, connecting autonomous nodes (Holons) into a single hierarchical network.
38
+
39
+ ## 🧬 The Biological Metaphor
40
+
41
+ The name **RXON** is derived from the biological term *Axon* (the nerve fiber). In classic networks, commands typically flow "top-down" (Push model). In RXON, the connection initiative always comes from the subordinate node (Worker/Shell) to the superior node (Orchestrator/Ghost). This is a "Reverse Axon" that grows from the bottom up, creating a channel through which commands subsequently descend.
42
+
43
+ ## ✨ Key Features
44
+
45
+ - **Pluggable Transports**: Full abstraction from the network layer. The same code can run over HTTP, WebSocket, gRPC, or Tor.
46
+ - **Zero Dependency Core**: The protocol core has no external dependencies (standard transports use `aiohttp` and `orjson`).
47
+ - **Strictly Typed**: All messages (tasks, results, heartbeats) are defined via strictly typed models for maximum performance and correctness.
48
+ - **Blob Storage Native**: Built-in support for offloading heavy data via S3-compatible storage (`rxon.blob`).
49
+
50
+ ## 🏗 Architecture
51
+
52
+ The protocol is divided into two main interfaces:
53
+
54
+ 1. **Transport (Worker side)**: Interface for initiating connections, retrieving tasks, and sending results.
55
+ 2. **Listener (Orchestrator side)**: Interface for accepting incoming connections and routing messages to the orchestration engine.
56
+
57
+ ### Usage Example (Worker side)
58
+
59
+ ```python
60
+ from rxon import create_transport, WorkerRegistration
61
+
62
+ # 1. Create transport (automatically selects HttpTransport based on URL scheme)
63
+ transport = create_transport(
64
+ url="https://orchestrator.local",
65
+ worker_id="gpu-01",
66
+ token="secret-token"
67
+ )
68
+
69
+ await transport.connect()
70
+
71
+ # 2. Register
72
+ await transport.register(reg_payload)
73
+
74
+ # 3. Poll for tasks
75
+ task = await transport.poll_task(timeout=30)
76
+ ```
77
+
78
+ ### Usage Example (Orchestrator side)
79
+
80
+ ```python
81
+ from rxon import HttpListener, TaskPayload
82
+
83
+ async def my_handler(message_type, payload, context):
84
+ if message_type == "poll":
85
+ # Task dispatch logic
86
+ return TaskPayload(...)
87
+ return True
88
+
89
+ # Listener attaches to a web application or starts its own server
90
+ listener = HttpListener(app)
91
+ await listener.start(handler=my_handler)
92
+ ```
93
+
94
+ ## 📦 Package Structure
95
+
96
+ - **`rxon.models`**: DTOs for registrations, tasks, heartbeats, and results.
97
+ - **`rxon.constants`**: Standardized error codes (TIMEOUT, RESOURCE_EXHAUSTED, etc.) and API endpoints.
98
+ - **`rxon.transports`**: Abstract base classes and implementations (HTTP, WebSocket).
99
+ - **`rxon.blob`**: Unified interface for blob storage operations (S3 URI parsing, hashing).
100
+ - **`rxon.security`**: Helpers for mTLS and access tokens.
101
+
102
+ ## 🚀 Installation
103
+
104
+ ```bash
105
+ pip install rxon
106
+ ```
107
+
108
+ For developers (local):
109
+ ```bash
110
+ pip install -e packages/rxon
111
+ ```
112
+
113
+ ## 📜 License
114
+
115
+ The project is distributed under the MIT License.
116
+
117
+ ---
118
+ *Mantra: "The RXON is the medium for the Ghost."*
rxon-1.0b0/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # RXON (Reverse Axon) Protocol
2
+
3
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
4
+ [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/release/python-3110/)
5
+ [![Typing: Typed](https://img.shields.io/badge/Typing-Typed-brightgreen.svg)](https://peps.python.org/pep-0561/)
6
+
7
+ > **[RU](https://github.com/madgagarin/rxon/blob/main/README_RU.md)**
8
+
9
+ **RXON** (Reverse Axon) is a lightweight reverse-connection inter-service communication protocol designed for the **[HLN (Hierarchical Logic Network)](https://github.com/avtomatika-ai/hln)** architecture.
10
+
11
+ It serves as the "nervous system" for distributed multi-agent systems, connecting autonomous nodes (Holons) into a single hierarchical network.
12
+
13
+ ## 🧬 The Biological Metaphor
14
+
15
+ The name **RXON** is derived from the biological term *Axon* (the nerve fiber). In classic networks, commands typically flow "top-down" (Push model). In RXON, the connection initiative always comes from the subordinate node (Worker/Shell) to the superior node (Orchestrator/Ghost). This is a "Reverse Axon" that grows from the bottom up, creating a channel through which commands subsequently descend.
16
+
17
+ ## ✨ Key Features
18
+
19
+ - **Pluggable Transports**: Full abstraction from the network layer. The same code can run over HTTP, WebSocket, gRPC, or Tor.
20
+ - **Zero Dependency Core**: The protocol core has no external dependencies (standard transports use `aiohttp` and `orjson`).
21
+ - **Strictly Typed**: All messages (tasks, results, heartbeats) are defined via strictly typed models for maximum performance and correctness.
22
+ - **Blob Storage Native**: Built-in support for offloading heavy data via S3-compatible storage (`rxon.blob`).
23
+
24
+ ## 🏗 Architecture
25
+
26
+ The protocol is divided into two main interfaces:
27
+
28
+ 1. **Transport (Worker side)**: Interface for initiating connections, retrieving tasks, and sending results.
29
+ 2. **Listener (Orchestrator side)**: Interface for accepting incoming connections and routing messages to the orchestration engine.
30
+
31
+ ### Usage Example (Worker side)
32
+
33
+ ```python
34
+ from rxon import create_transport, WorkerRegistration
35
+
36
+ # 1. Create transport (automatically selects HttpTransport based on URL scheme)
37
+ transport = create_transport(
38
+ url="https://orchestrator.local",
39
+ worker_id="gpu-01",
40
+ token="secret-token"
41
+ )
42
+
43
+ await transport.connect()
44
+
45
+ # 2. Register
46
+ await transport.register(reg_payload)
47
+
48
+ # 3. Poll for tasks
49
+ task = await transport.poll_task(timeout=30)
50
+ ```
51
+
52
+ ### Usage Example (Orchestrator side)
53
+
54
+ ```python
55
+ from rxon import HttpListener, TaskPayload
56
+
57
+ async def my_handler(message_type, payload, context):
58
+ if message_type == "poll":
59
+ # Task dispatch logic
60
+ return TaskPayload(...)
61
+ return True
62
+
63
+ # Listener attaches to a web application or starts its own server
64
+ listener = HttpListener(app)
65
+ await listener.start(handler=my_handler)
66
+ ```
67
+
68
+ ## 📦 Package Structure
69
+
70
+ - **`rxon.models`**: DTOs for registrations, tasks, heartbeats, and results.
71
+ - **`rxon.constants`**: Standardized error codes (TIMEOUT, RESOURCE_EXHAUSTED, etc.) and API endpoints.
72
+ - **`rxon.transports`**: Abstract base classes and implementations (HTTP, WebSocket).
73
+ - **`rxon.blob`**: Unified interface for blob storage operations (S3 URI parsing, hashing).
74
+ - **`rxon.security`**: Helpers for mTLS and access tokens.
75
+
76
+ ## 🚀 Installation
77
+
78
+ ```bash
79
+ pip install rxon
80
+ ```
81
+
82
+ For developers (local):
83
+ ```bash
84
+ pip install -e packages/rxon
85
+ ```
86
+
87
+ ## 📜 License
88
+
89
+ The project is distributed under the MIT License.
90
+
91
+ ---
92
+ *Mantra: "The RXON is the medium for the Ghost."*
@@ -0,0 +1,66 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61.0"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "rxon"
7
+ version = "1.0b0"
8
+ description = "RXON (Reverse Axon) - Lightweight Inter-node Reverse Communication Protocol."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11"
11
+ authors = [
12
+ {name = "Dmitrii Gagarin", email = "madgagarin@gmail.com"},
13
+ ]
14
+ maintainers = [
15
+ {name = "Dmitrii Gagarin", email = "madgagarin@gmail.com"},
16
+ ]
17
+ keywords = ["rxon", "hln", "protocol", "distributed-systems", "holarchy", "holon"]
18
+ classifiers = [
19
+ "Development Status :: 4 - Beta",
20
+ "Intended Audience :: Developers",
21
+ "Intended Audience :: System Administrators",
22
+ "Programming Language :: Python :: 3",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "License :: OSI Approved :: MIT License",
26
+ "Operating System :: OS Independent",
27
+ "Typing :: Typed",
28
+ ]
29
+ dependencies = [
30
+ "aiohttp>=3.12",
31
+ "orjson>=3.10",
32
+ ]
33
+
34
+ [project.urls]
35
+ "Homepage" = "https://github.com/madgagarin/rxon"
36
+ "Repository" = "https://github.com/madgagarin/rxon"
37
+ "Bug Tracker" = "https://github.com/madgagarin/rxon/issues"
38
+
39
+ [tool.setuptools.packages.find]
40
+ where = ["src"]
41
+
42
+ [tool.setuptools.package-data]
43
+ rxon = ["py.typed"]
44
+
45
+ [tool.ruff]
46
+ src = ["src"]
47
+ target-version = "py311"
48
+ line-length = 120
49
+
50
+ [tool.ruff.lint]
51
+ select = ["E", "W", "F", "I", "B", "A", "SIM", "C4"]
52
+
53
+ [tool.ruff.format]
54
+ quote-style = "double"
55
+
56
+ [tool.pytest.ini_options]
57
+ asyncio_mode = "auto"
58
+ asyncio_default_fixture_loop_scope = "function"
59
+
60
+ [dependency-groups]
61
+ dev = [
62
+ "mypy>=1.19.1",
63
+ "pytest>=9.0.2",
64
+ "pytest-asyncio>=1.3.0",
65
+ "pytest-cov>=7.0.0",
66
+ ]
rxon-1.0b0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,152 @@
1
+ from importlib.metadata import PackageNotFoundError, version
2
+
3
+ from .blob import RXON_BLOB_SCHEME, calculate_config_hash, parse_uri
4
+ from .constants import (
5
+ AUTH_HEADER_CLIENT,
6
+ AUTH_HEADER_WORKER,
7
+ COMMAND_CANCEL_TASK,
8
+ ENDPOINT_TASK_NEXT,
9
+ ENDPOINT_TASK_RESULT,
10
+ ENDPOINT_WORKER_HEARTBEAT,
11
+ ENDPOINT_WORKER_REGISTER,
12
+ ERROR_CODE_DEPENDENCY,
13
+ ERROR_CODE_INTEGRITY_MISMATCH,
14
+ ERROR_CODE_INTERNAL,
15
+ ERROR_CODE_INVALID_INPUT,
16
+ ERROR_CODE_PERMANENT,
17
+ ERROR_CODE_RESOURCE_EXHAUSTED,
18
+ ERROR_CODE_SECURITY,
19
+ ERROR_CODE_TIMEOUT,
20
+ ERROR_CODE_TRANSIENT,
21
+ JOB_STATUS_CANCELLED,
22
+ JOB_STATUS_ERROR,
23
+ JOB_STATUS_FAILED,
24
+ JOB_STATUS_FINISHED,
25
+ JOB_STATUS_PENDING,
26
+ JOB_STATUS_QUARANTINED,
27
+ JOB_STATUS_RUNNING,
28
+ JOB_STATUS_WAITING_FOR_HUMAN,
29
+ JOB_STATUS_WAITING_FOR_PARALLEL,
30
+ JOB_STATUS_WAITING_FOR_WORKER,
31
+ MSG_TYPE_PROGRESS,
32
+ PROTOCOL_VERSION,
33
+ STS_TOKEN_ENDPOINT,
34
+ TASK_STATUS_CANCELLED,
35
+ TASK_STATUS_FAILURE,
36
+ TASK_STATUS_SUCCESS,
37
+ WORKER_API_PREFIX,
38
+ WS_ENDPOINT,
39
+ )
40
+ from .exceptions import (
41
+ IntegrityError,
42
+ ParamValidationError,
43
+ RXONProtocolError,
44
+ S3ConfigMismatchError,
45
+ )
46
+ from .models import (
47
+ FileMetadata,
48
+ GPUInfo,
49
+ Heartbeat,
50
+ InstalledModel,
51
+ ProgressUpdatePayload,
52
+ Resources,
53
+ TaskError,
54
+ TaskPayload,
55
+ TaskResult,
56
+ TokenResponse,
57
+ WorkerCapabilities,
58
+ WorkerCommand,
59
+ WorkerRegistration,
60
+ )
61
+ from .security import (
62
+ create_client_ssl_context,
63
+ create_server_ssl_context,
64
+ extract_cert_identity,
65
+ )
66
+ from .transports.base import Listener, Transport
67
+ from .transports.factory import create_transport
68
+ from .transports.http import HttpTransport
69
+ from .transports.http_server import HttpListener
70
+ from .utils import to_dict
71
+ from .validators import is_valid_identifier, validate_identifier
72
+
73
+ __all__ = [
74
+ # Blob
75
+ "RXON_BLOB_SCHEME",
76
+ "calculate_config_hash",
77
+ "parse_uri",
78
+ # Constants
79
+ "AUTH_HEADER_CLIENT",
80
+ "AUTH_HEADER_WORKER",
81
+ "COMMAND_CANCEL_TASK",
82
+ "ENDPOINT_TASK_NEXT",
83
+ "ENDPOINT_TASK_RESULT",
84
+ "ENDPOINT_WORKER_HEARTBEAT",
85
+ "ENDPOINT_WORKER_REGISTER",
86
+ "ERROR_CODE_DEPENDENCY",
87
+ "ERROR_CODE_INTEGRITY_MISMATCH",
88
+ "ERROR_CODE_INTERNAL",
89
+ "ERROR_CODE_INVALID_INPUT",
90
+ "ERROR_CODE_PERMANENT",
91
+ "ERROR_CODE_RESOURCE_EXHAUSTED",
92
+ "ERROR_CODE_SECURITY",
93
+ "ERROR_CODE_TIMEOUT",
94
+ "ERROR_CODE_TRANSIENT",
95
+ "JOB_STATUS_CANCELLED",
96
+ "JOB_STATUS_ERROR",
97
+ "JOB_STATUS_FAILED",
98
+ "JOB_STATUS_FINISHED",
99
+ "JOB_STATUS_PENDING",
100
+ "JOB_STATUS_QUARANTINED",
101
+ "JOB_STATUS_RUNNING",
102
+ "JOB_STATUS_WAITING_FOR_HUMAN",
103
+ "JOB_STATUS_WAITING_FOR_PARALLEL",
104
+ "JOB_STATUS_WAITING_FOR_WORKER",
105
+ "MSG_TYPE_PROGRESS",
106
+ "PROTOCOL_VERSION",
107
+ "STS_TOKEN_ENDPOINT",
108
+ "TASK_STATUS_CANCELLED",
109
+ "TASK_STATUS_FAILURE",
110
+ "TASK_STATUS_SUCCESS",
111
+ "WORKER_API_PREFIX",
112
+ "WS_ENDPOINT",
113
+ # Exceptions
114
+ "IntegrityError",
115
+ "ParamValidationError",
116
+ "RXONProtocolError",
117
+ "S3ConfigMismatchError",
118
+ # Models
119
+ "FileMetadata",
120
+ "GPUInfo",
121
+ "Heartbeat",
122
+ "InstalledModel",
123
+ "ProgressUpdatePayload",
124
+ "Resources",
125
+ "TaskError",
126
+ "TaskPayload",
127
+ "TaskResult",
128
+ "TokenResponse",
129
+ "WorkerCapabilities",
130
+ "WorkerCommand",
131
+ "WorkerRegistration",
132
+ # Security
133
+ "create_client_ssl_context",
134
+ "create_server_ssl_context",
135
+ "extract_cert_identity",
136
+ # Transports
137
+ "Listener",
138
+ "Transport",
139
+ "create_transport",
140
+ "HttpTransport",
141
+ "HttpListener",
142
+ # Utils
143
+ "to_dict",
144
+ # Validators
145
+ "is_valid_identifier",
146
+ "validate_identifier",
147
+ ]
148
+
149
+ try:
150
+ __version__ = version("rxon")
151
+ except PackageNotFoundError:
152
+ __version__ = "unknown"
@@ -0,0 +1,51 @@
1
+ from hashlib import sha256
2
+ from typing import Tuple
3
+ from urllib.parse import urlparse
4
+
5
+ __all__ = [
6
+ "RXON_BLOB_SCHEME",
7
+ "calculate_config_hash",
8
+ "parse_uri",
9
+ ]
10
+
11
+ RXON_BLOB_SCHEME = "s3"
12
+
13
+
14
+ def calculate_config_hash(endpoint: str | None, access_key: str | None, bucket: str | None) -> str | None:
15
+ """
16
+ Calculates a consistent hash of the Blob/S3 configuration.
17
+ Used to ensure Workers and Orchestrators are talking to the same storage.
18
+ Uses '|' as separator.
19
+ """
20
+ if not endpoint or not access_key or not bucket:
21
+ return None
22
+
23
+ config_str = f"{endpoint}|{access_key}|{bucket}"
24
+ return sha256(config_str.encode()).hexdigest()[:16]
25
+
26
+
27
+ def parse_uri(uri: str, default_bucket: str | None = None, prefix: str = "") -> Tuple[str, str, bool]:
28
+ """
29
+ Parses a Blob/S3 URI or relative path into (bucket, key, is_directory).
30
+ Protocol: s3://bucket/key
31
+
32
+ :param uri: Full URI (s3://bucket/key) or relative path (key)
33
+ :param default_bucket: Bucket to use if URI is relative
34
+ :param prefix: Optional prefix to prepend to relative paths
35
+ :return: (bucket, key, is_directory)
36
+ :raises ValueError: If URI format is invalid or bucket is missing
37
+ """
38
+ is_dir = uri.endswith("/")
39
+
40
+ if uri.startswith(f"{RXON_BLOB_SCHEME}://"):
41
+ parsed = urlparse(uri)
42
+ bucket = parsed.netloc
43
+ key = parsed.path.lstrip("/")
44
+ return bucket, key, is_dir
45
+ else:
46
+ if not default_bucket:
47
+ raise ValueError(f"Cannot parse relative path '{uri}' without a default bucket.")
48
+
49
+ clean_path = uri.lstrip("/")
50
+ key = f"{prefix}{clean_path}" if prefix else clean_path
51
+ return default_bucket, key, is_dir
@@ -0,0 +1,94 @@
1
+ """
2
+ Centralized constants for the RXON protocol.
3
+ Shared between Orchestrator and Worker SDK.
4
+ """
5
+
6
+ __all__ = [
7
+ "AUTH_HEADER_CLIENT",
8
+ "AUTH_HEADER_WORKER",
9
+ "ERROR_CODE_TRANSIENT",
10
+ "ERROR_CODE_PERMANENT",
11
+ "ERROR_CODE_INVALID_INPUT",
12
+ "ERROR_CODE_INTEGRITY_MISMATCH",
13
+ "ERROR_CODE_TIMEOUT",
14
+ "ERROR_CODE_RESOURCE_EXHAUSTED",
15
+ "ERROR_CODE_DEPENDENCY",
16
+ "ERROR_CODE_SECURITY",
17
+ "ERROR_CODE_INTERNAL",
18
+ "TASK_STATUS_SUCCESS",
19
+ "TASK_STATUS_FAILURE",
20
+ "TASK_STATUS_CANCELLED",
21
+ "COMMAND_CANCEL_TASK",
22
+ "MSG_TYPE_PROGRESS",
23
+ "STS_TOKEN_ENDPOINT",
24
+ "WS_ENDPOINT",
25
+ "ENDPOINT_WORKER_REGISTER",
26
+ "ENDPOINT_TASK_NEXT",
27
+ "ENDPOINT_TASK_RESULT",
28
+ "ENDPOINT_WORKER_HEARTBEAT",
29
+ "JOB_STATUS_PENDING",
30
+ "JOB_STATUS_WAITING_FOR_WORKER",
31
+ "JOB_STATUS_RUNNING",
32
+ "JOB_STATUS_FINISHED",
33
+ "JOB_STATUS_FAILED",
34
+ "JOB_STATUS_ERROR",
35
+ "JOB_STATUS_QUARANTINED",
36
+ "JOB_STATUS_CANCELLED",
37
+ "JOB_STATUS_WAITING_FOR_HUMAN",
38
+ "JOB_STATUS_WAITING_FOR_PARALLEL",
39
+ "WORKER_API_PREFIX",
40
+ "PROTOCOL_VERSION",
41
+ ]
42
+
43
+ # --- Protocol Metadata ---
44
+ PROTOCOL_VERSION = "1.0"
45
+
46
+ # --- Auth Headers ---
47
+ AUTH_HEADER_CLIENT = "X-Client-Token"
48
+ AUTH_HEADER_WORKER = "X-Worker-Token"
49
+
50
+ # --- Error Codes ---
51
+ # Error codes returned by workers in the result payload
52
+ ERROR_CODE_TRANSIENT = "TRANSIENT_ERROR"
53
+ ERROR_CODE_PERMANENT = "PERMANENT_ERROR"
54
+ ERROR_CODE_INVALID_INPUT = "INVALID_INPUT_ERROR"
55
+ ERROR_CODE_INTEGRITY_MISMATCH = "INTEGRITY_MISMATCH_ERROR"
56
+ ERROR_CODE_TIMEOUT = "TIMEOUT_ERROR"
57
+ ERROR_CODE_RESOURCE_EXHAUSTED = "RESOURCE_EXHAUSTED_ERROR"
58
+ ERROR_CODE_DEPENDENCY = "DEPENDENCY_ERROR"
59
+ ERROR_CODE_SECURITY = "SECURITY_ERROR"
60
+ ERROR_CODE_INTERNAL = "INTERNAL_ERROR"
61
+
62
+ # --- Task Statuses ---
63
+ # Standard statuses for task results
64
+ TASK_STATUS_SUCCESS = "success"
65
+ TASK_STATUS_FAILURE = "failure"
66
+ TASK_STATUS_CANCELLED = "cancelled"
67
+
68
+ # --- Commands (WebSocket) ---
69
+ COMMAND_CANCEL_TASK = "cancel_task"
70
+ MSG_TYPE_PROGRESS = "progress_update"
71
+
72
+ # --- Endpoints ---
73
+ WORKER_API_PREFIX = "/_worker"
74
+
75
+ STS_TOKEN_ENDPOINT = f"{WORKER_API_PREFIX}/auth/token"
76
+ WS_ENDPOINT = f"{WORKER_API_PREFIX}/ws"
77
+
78
+ # Routes for REST API interaction
79
+ ENDPOINT_WORKER_REGISTER = f"{WORKER_API_PREFIX}/workers/register"
80
+ ENDPOINT_TASK_NEXT = f"{WORKER_API_PREFIX}/workers/{{worker_id}}/tasks/next"
81
+ ENDPOINT_TASK_RESULT = f"{WORKER_API_PREFIX}/tasks/result"
82
+ ENDPOINT_WORKER_HEARTBEAT = f"{WORKER_API_PREFIX}/workers/{{worker_id}}"
83
+
84
+ # --- Job Statuses ---
85
+ JOB_STATUS_PENDING = "pending"
86
+ JOB_STATUS_WAITING_FOR_WORKER = "waiting_for_worker"
87
+ JOB_STATUS_RUNNING = "running"
88
+ JOB_STATUS_FINISHED = "finished"
89
+ JOB_STATUS_FAILED = "failed"
90
+ JOB_STATUS_ERROR = "error"
91
+ JOB_STATUS_QUARANTINED = "quarantined"
92
+ JOB_STATUS_CANCELLED = "cancelled"
93
+ JOB_STATUS_WAITING_FOR_HUMAN = "waiting_for_human"
94
+ JOB_STATUS_WAITING_FOR_PARALLEL = "waiting_for_parallel_tasks"
@@ -0,0 +1,30 @@
1
+ __all__ = [
2
+ "RXONProtocolError",
3
+ "S3ConfigMismatchError",
4
+ "IntegrityError",
5
+ "ParamValidationError",
6
+ ]
7
+
8
+
9
+ class RXONProtocolError(Exception):
10
+ """Base exception for all protocol-related errors."""
11
+
12
+ pass
13
+
14
+
15
+ class S3ConfigMismatchError(RXONProtocolError):
16
+ """Raised when Worker and Orchestrator S3 configurations do not match."""
17
+
18
+ pass
19
+
20
+
21
+ class IntegrityError(RXONProtocolError):
22
+ """Raised when file integrity check (size/hash) fails."""
23
+
24
+ pass
25
+
26
+
27
+ class ParamValidationError(RXONProtocolError):
28
+ """Raised when task parameters fail validation."""
29
+
30
+ pass