simulo-interfaces 0.1.0__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.
- simulo_interfaces-0.1.0/PKG-INFO +166 -0
- simulo_interfaces-0.1.0/README.md +135 -0
- simulo_interfaces-0.1.0/pyproject.toml +94 -0
- simulo_interfaces-0.1.0/setup.cfg +4 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/__init__.py +65 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/exceptions.py +31 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/ids.py +21 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/__init__.py +120 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/app.py +47 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/asset.py +15 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/callbacks.py +17 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/debug.py +31 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/domain.py +118 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/enums.py +49 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/runs.py +112 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/runtime.py +19 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/submit.py +538 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/platform/volume.py +13 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/py.typed +0 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/__init__.py +50 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/anomaly.py +195 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/components.py +35 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/env.py +27 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/player.py +19 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/policy.py +16 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/scenario.py +13 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/task.py +21 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/tensors.py +12 -0
- simulo_interfaces-0.1.0/src/simulo/interfaces/runtime/trainer.py +37 -0
- simulo_interfaces-0.1.0/src/simulo_interfaces.egg-info/PKG-INFO +166 -0
- simulo_interfaces-0.1.0/src/simulo_interfaces.egg-info/SOURCES.txt +42 -0
- simulo_interfaces-0.1.0/src/simulo_interfaces.egg-info/dependency_links.txt +1 -0
- simulo_interfaces-0.1.0/src/simulo_interfaces.egg-info/requires.txt +14 -0
- simulo_interfaces-0.1.0/src/simulo_interfaces.egg-info/top_level.txt +1 -0
- simulo_interfaces-0.1.0/tests/test_anomaly_contract.py +164 -0
- simulo_interfaces-0.1.0/tests/test_domain_dataclasses.py +34 -0
- simulo_interfaces-0.1.0/tests/test_enums.py +30 -0
- simulo_interfaces-0.1.0/tests/test_ids.py +13 -0
- simulo_interfaces-0.1.0/tests/test_import_without_torch.py +21 -0
- simulo_interfaces-0.1.0/tests/test_no_heavy_deps.py +19 -0
- simulo_interfaces-0.1.0/tests/test_platform_protocols.py +80 -0
- simulo_interfaces-0.1.0/tests/test_runs_contract.py +95 -0
- simulo_interfaces-0.1.0/tests/test_runtime_protocols.py +124 -0
- simulo_interfaces-0.1.0/tests/test_submit_contract.py +269 -0
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: simulo-interfaces
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Implementation-free contract layer for the Simulo platform — torch-free runtime/sim Protocols and platform/workspace domain contracts. Importable with no torch/numpy/gymnasium/Isaac installed.
|
|
5
|
+
Author-email: Simulo Team <team@simulo.ai>
|
|
6
|
+
License: BSD-3-Clause
|
|
7
|
+
Project-URL: Homepage, https://simulo.ai
|
|
8
|
+
Project-URL: Source, https://github.com/simulo-org/simulo-platform
|
|
9
|
+
Keywords: robotics,contracts,protocols,interfaces,simulo
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
13
|
+
Classifier: Operating System :: OS Independent
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Typing :: Typed
|
|
17
|
+
Requires-Python: >=3.11
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
Provides-Extra: dev
|
|
20
|
+
Requires-Dist: black>=24.0; extra == "dev"
|
|
21
|
+
Requires-Dist: isort>=5.13; extra == "dev"
|
|
22
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
23
|
+
Requires-Dist: mypy>=1.10; extra == "dev"
|
|
24
|
+
Requires-Dist: pytest>=8.2; extra == "dev"
|
|
25
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
26
|
+
Requires-Dist: twine>=5.1; extra == "dev"
|
|
27
|
+
Provides-Extra: release
|
|
28
|
+
Requires-Dist: commitizen>=3.27; extra == "release"
|
|
29
|
+
Requires-Dist: build>=1.2; extra == "release"
|
|
30
|
+
Requires-Dist: twine>=5.1; extra == "release"
|
|
31
|
+
|
|
32
|
+
# simulo-interfaces
|
|
33
|
+
|
|
34
|
+
The **implementation-free contract layer** for the Simulo platform. A single,
|
|
35
|
+
stable, torch-free, **zero-runtime-dependency** package that both Simulo SDK
|
|
36
|
+
distributions depend on:
|
|
37
|
+
|
|
38
|
+
- `simulo-backend` — the cloud GPU SDK (torch + IsaacLab + Isaac Sim).
|
|
39
|
+
- `simulo` — the future thin local client (no heavy deps).
|
|
40
|
+
|
|
41
|
+
Because both distributions share these contracts, `simulo-interfaces` is the one
|
|
42
|
+
place the runtime Protocols and the platform/workspace domain model are defined.
|
|
43
|
+
|
|
44
|
+
## What it is
|
|
45
|
+
|
|
46
|
+
A pure-stdlib set of `typing.Protocol` contracts, frozen dataclasses, enums,
|
|
47
|
+
`NewType` identifiers, and an exception hierarchy. Nothing here does any work —
|
|
48
|
+
it only describes shapes.
|
|
49
|
+
|
|
50
|
+
## What it is NOT
|
|
51
|
+
|
|
52
|
+
It imports **none** of: `torch`, `numpy`, `gymnasium`, IsaacLab / Isaac Sim, AWS
|
|
53
|
+
SDKs, HTTP clients, or database drivers. It performs **no** I/O, persistence, or
|
|
54
|
+
computation. It is **not** a dumping ground (Contract Rule #12) — only contracts
|
|
55
|
+
shared by more than one distribution belong here.
|
|
56
|
+
|
|
57
|
+
The central invariant (Contract Rule #11): this package must import on a laptop
|
|
58
|
+
with no torch/numpy/gymnasium/Isaac installed. Two tests enforce it:
|
|
59
|
+
`tests/test_import_without_torch.py` (no heavy module enters `sys.modules`) and
|
|
60
|
+
`tests/test_no_heavy_deps.py` (zero unconditional `Requires-Dist`).
|
|
61
|
+
|
|
62
|
+
## Two parts
|
|
63
|
+
|
|
64
|
+
### Part A — `simulo.interfaces.runtime`
|
|
65
|
+
|
|
66
|
+
Tensor-library-agnostic structural mirrors of the `simulo.core` runtime surface.
|
|
67
|
+
Tensors are typed as `TensorLike` (an alias for `Any`) so the contracts never
|
|
68
|
+
bind to a concrete tensor library.
|
|
69
|
+
|
|
70
|
+
- `TaskProtocol`, `PolicyProtocol`, `TrainerProtocol`, `PlayerProtocol`
|
|
71
|
+
- `LearningEnvProtocol`, `ScenarioProtocol`
|
|
72
|
+
- `ObservationComponentProtocol`, `RewardComponentProtocol`,
|
|
73
|
+
`TerminationConditionProtocol`
|
|
74
|
+
- `PolicyExporterProtocol` — the narrow *optional* export capability
|
|
75
|
+
(`export_policy(path) -> str`). Deliberately not a `TrainerProtocol` member:
|
|
76
|
+
a Protocol binds all implementations, and only some trainers (today
|
|
77
|
+
`simulo.core.trainer.RLTrainer`) can deliver a deterministic standalone
|
|
78
|
+
policy export. Consumers feature-detect with `isinstance(trainer,
|
|
79
|
+
PolicyExporterProtocol)`.
|
|
80
|
+
|
|
81
|
+
### Part B — `simulo.interfaces.platform`
|
|
82
|
+
|
|
83
|
+
The platform/workspace domain contracts:
|
|
84
|
+
|
|
85
|
+
- **Enums** — `JobStatus`, `ResumePolicy`, `ResourceKind`, `ArtifactKind`.
|
|
86
|
+
- **Domain dataclasses** (frozen, slotted, keyword-only) — `Tag`, `Project`,
|
|
87
|
+
`Package`, `Resource`, `Job`, `Checkpoint`, `TrainedModel`.
|
|
88
|
+
- **Cloud-execution Protocols** — `AppProtocol`, `JobFunctionProtocol`,
|
|
89
|
+
`RuntimeProtocol`, `AssetProtocol`, `VolumeProtocol`, `JobCallbackProtocol`,
|
|
90
|
+
`DebugSessionProtocol`, `ReplaySessionProtocol`, `VisualizationSessionProtocol`.
|
|
91
|
+
|
|
92
|
+
## Public import surface
|
|
93
|
+
|
|
94
|
+
```python
|
|
95
|
+
import simulo.interfaces as si
|
|
96
|
+
|
|
97
|
+
# exceptions + ids re-exported at the top level
|
|
98
|
+
si.SimuloError, si.ContractViolationError, si.JobFailedError
|
|
99
|
+
si.ProjectId, si.JobId, si.ResourceUri, si.Digest
|
|
100
|
+
|
|
101
|
+
# Part A
|
|
102
|
+
from simulo.interfaces.runtime import TaskProtocol, PolicyProtocol, LearningEnvProtocol
|
|
103
|
+
|
|
104
|
+
# Part B
|
|
105
|
+
from simulo.interfaces.platform import (
|
|
106
|
+
JobStatus, ResumePolicy, ResourceKind, ArtifactKind,
|
|
107
|
+
Project, Package, Job, Resource, Checkpoint, TrainedModel, Tag,
|
|
108
|
+
AppProtocol, RuntimeProtocol, AssetProtocol, VolumeProtocol,
|
|
109
|
+
)
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Conformance model
|
|
113
|
+
|
|
114
|
+
The contracts are `typing.Protocol`s — implementers conform **structurally**, no
|
|
115
|
+
inheritance required.
|
|
116
|
+
|
|
117
|
+
- **Static** — implementers (e.g. `simulo-backend`) are type-checked against
|
|
118
|
+
these Protocols by mypy. That static assertion is the primary conformance
|
|
119
|
+
gate and lives in the **implementer** package, not here.
|
|
120
|
+
- **Runtime** — every Protocol is `@runtime_checkable`, so `isinstance(obj,
|
|
121
|
+
SomeProtocol)` provides a lightweight smoke check (presence of members only —
|
|
122
|
+
not signatures). This package's tests use that smoke form.
|
|
123
|
+
- **Nominal (optional, opt-in per implementer)** — `simulo-backend`'s
|
|
124
|
+
`simulo.core` classes additionally *declare* the Part A Protocols as base
|
|
125
|
+
classes, so mypy drift-checks each implementation against its mirror at the
|
|
126
|
+
class-definition site. Nominal declaration never replaces the structural
|
|
127
|
+
contract — a third-party implementation that merely matches the signatures
|
|
128
|
+
still conforms.
|
|
129
|
+
|
|
130
|
+
## Domain-model invariants
|
|
131
|
+
|
|
132
|
+
- **Package ≠ Job** (Rule #5) — a `Package` is an immutable, content-addressed
|
|
133
|
+
source archive; a `Job` is one execution of a package and references it by id.
|
|
134
|
+
- **Resource ≠ Package** (Rule #6) — a `Resource` is a read-only, versioned,
|
|
135
|
+
registry-resolved mount (robot / environment / dataset / …).
|
|
136
|
+
- **Checkpoint ≠ TrainedModel** (Rule #8) — an intermediate training artifact is
|
|
137
|
+
a distinct type from the final, deployable model. Never collapse them.
|
|
138
|
+
- **Project is the anchor** (Rule #7) — every other domain object hangs off a
|
|
139
|
+
`Project`.
|
|
140
|
+
- **No packaged-skill type** (Rule #11) — there is deliberately no `Skill` /
|
|
141
|
+
`PackagedSkill` type here.
|
|
142
|
+
|
|
143
|
+
## Stability policy
|
|
144
|
+
|
|
145
|
+
- Enum **values** are a stable wire ABI: append-only, never renumber or rename.
|
|
146
|
+
- Dataclass fields and Protocol method signatures follow the same
|
|
147
|
+
breaking-change discipline as the rest of the contract layer.
|
|
148
|
+
- The package follows SemVer; additive changes (new optional field, new
|
|
149
|
+
Protocol, new enum member at the end) are minor/patch, removals/renames major.
|
|
150
|
+
|
|
151
|
+
## Requirements
|
|
152
|
+
|
|
153
|
+
- Python **>= 3.11** (uses `enum.StrEnum`). Tested on 3.11 and 3.12.
|
|
154
|
+
- Standard library only — **zero** runtime dependencies.
|
|
155
|
+
|
|
156
|
+
## Development
|
|
157
|
+
|
|
158
|
+
```bash
|
|
159
|
+
pip install -e ".[dev]"
|
|
160
|
+
ruff check src
|
|
161
|
+
black --check src tests
|
|
162
|
+
isort --check-only src tests
|
|
163
|
+
mypy src # strict
|
|
164
|
+
python -m build && twine check dist/*
|
|
165
|
+
pytest
|
|
166
|
+
```
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
# simulo-interfaces
|
|
2
|
+
|
|
3
|
+
The **implementation-free contract layer** for the Simulo platform. A single,
|
|
4
|
+
stable, torch-free, **zero-runtime-dependency** package that both Simulo SDK
|
|
5
|
+
distributions depend on:
|
|
6
|
+
|
|
7
|
+
- `simulo-backend` — the cloud GPU SDK (torch + IsaacLab + Isaac Sim).
|
|
8
|
+
- `simulo` — the future thin local client (no heavy deps).
|
|
9
|
+
|
|
10
|
+
Because both distributions share these contracts, `simulo-interfaces` is the one
|
|
11
|
+
place the runtime Protocols and the platform/workspace domain model are defined.
|
|
12
|
+
|
|
13
|
+
## What it is
|
|
14
|
+
|
|
15
|
+
A pure-stdlib set of `typing.Protocol` contracts, frozen dataclasses, enums,
|
|
16
|
+
`NewType` identifiers, and an exception hierarchy. Nothing here does any work —
|
|
17
|
+
it only describes shapes.
|
|
18
|
+
|
|
19
|
+
## What it is NOT
|
|
20
|
+
|
|
21
|
+
It imports **none** of: `torch`, `numpy`, `gymnasium`, IsaacLab / Isaac Sim, AWS
|
|
22
|
+
SDKs, HTTP clients, or database drivers. It performs **no** I/O, persistence, or
|
|
23
|
+
computation. It is **not** a dumping ground (Contract Rule #12) — only contracts
|
|
24
|
+
shared by more than one distribution belong here.
|
|
25
|
+
|
|
26
|
+
The central invariant (Contract Rule #11): this package must import on a laptop
|
|
27
|
+
with no torch/numpy/gymnasium/Isaac installed. Two tests enforce it:
|
|
28
|
+
`tests/test_import_without_torch.py` (no heavy module enters `sys.modules`) and
|
|
29
|
+
`tests/test_no_heavy_deps.py` (zero unconditional `Requires-Dist`).
|
|
30
|
+
|
|
31
|
+
## Two parts
|
|
32
|
+
|
|
33
|
+
### Part A — `simulo.interfaces.runtime`
|
|
34
|
+
|
|
35
|
+
Tensor-library-agnostic structural mirrors of the `simulo.core` runtime surface.
|
|
36
|
+
Tensors are typed as `TensorLike` (an alias for `Any`) so the contracts never
|
|
37
|
+
bind to a concrete tensor library.
|
|
38
|
+
|
|
39
|
+
- `TaskProtocol`, `PolicyProtocol`, `TrainerProtocol`, `PlayerProtocol`
|
|
40
|
+
- `LearningEnvProtocol`, `ScenarioProtocol`
|
|
41
|
+
- `ObservationComponentProtocol`, `RewardComponentProtocol`,
|
|
42
|
+
`TerminationConditionProtocol`
|
|
43
|
+
- `PolicyExporterProtocol` — the narrow *optional* export capability
|
|
44
|
+
(`export_policy(path) -> str`). Deliberately not a `TrainerProtocol` member:
|
|
45
|
+
a Protocol binds all implementations, and only some trainers (today
|
|
46
|
+
`simulo.core.trainer.RLTrainer`) can deliver a deterministic standalone
|
|
47
|
+
policy export. Consumers feature-detect with `isinstance(trainer,
|
|
48
|
+
PolicyExporterProtocol)`.
|
|
49
|
+
|
|
50
|
+
### Part B — `simulo.interfaces.platform`
|
|
51
|
+
|
|
52
|
+
The platform/workspace domain contracts:
|
|
53
|
+
|
|
54
|
+
- **Enums** — `JobStatus`, `ResumePolicy`, `ResourceKind`, `ArtifactKind`.
|
|
55
|
+
- **Domain dataclasses** (frozen, slotted, keyword-only) — `Tag`, `Project`,
|
|
56
|
+
`Package`, `Resource`, `Job`, `Checkpoint`, `TrainedModel`.
|
|
57
|
+
- **Cloud-execution Protocols** — `AppProtocol`, `JobFunctionProtocol`,
|
|
58
|
+
`RuntimeProtocol`, `AssetProtocol`, `VolumeProtocol`, `JobCallbackProtocol`,
|
|
59
|
+
`DebugSessionProtocol`, `ReplaySessionProtocol`, `VisualizationSessionProtocol`.
|
|
60
|
+
|
|
61
|
+
## Public import surface
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
import simulo.interfaces as si
|
|
65
|
+
|
|
66
|
+
# exceptions + ids re-exported at the top level
|
|
67
|
+
si.SimuloError, si.ContractViolationError, si.JobFailedError
|
|
68
|
+
si.ProjectId, si.JobId, si.ResourceUri, si.Digest
|
|
69
|
+
|
|
70
|
+
# Part A
|
|
71
|
+
from simulo.interfaces.runtime import TaskProtocol, PolicyProtocol, LearningEnvProtocol
|
|
72
|
+
|
|
73
|
+
# Part B
|
|
74
|
+
from simulo.interfaces.platform import (
|
|
75
|
+
JobStatus, ResumePolicy, ResourceKind, ArtifactKind,
|
|
76
|
+
Project, Package, Job, Resource, Checkpoint, TrainedModel, Tag,
|
|
77
|
+
AppProtocol, RuntimeProtocol, AssetProtocol, VolumeProtocol,
|
|
78
|
+
)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
## Conformance model
|
|
82
|
+
|
|
83
|
+
The contracts are `typing.Protocol`s — implementers conform **structurally**, no
|
|
84
|
+
inheritance required.
|
|
85
|
+
|
|
86
|
+
- **Static** — implementers (e.g. `simulo-backend`) are type-checked against
|
|
87
|
+
these Protocols by mypy. That static assertion is the primary conformance
|
|
88
|
+
gate and lives in the **implementer** package, not here.
|
|
89
|
+
- **Runtime** — every Protocol is `@runtime_checkable`, so `isinstance(obj,
|
|
90
|
+
SomeProtocol)` provides a lightweight smoke check (presence of members only —
|
|
91
|
+
not signatures). This package's tests use that smoke form.
|
|
92
|
+
- **Nominal (optional, opt-in per implementer)** — `simulo-backend`'s
|
|
93
|
+
`simulo.core` classes additionally *declare* the Part A Protocols as base
|
|
94
|
+
classes, so mypy drift-checks each implementation against its mirror at the
|
|
95
|
+
class-definition site. Nominal declaration never replaces the structural
|
|
96
|
+
contract — a third-party implementation that merely matches the signatures
|
|
97
|
+
still conforms.
|
|
98
|
+
|
|
99
|
+
## Domain-model invariants
|
|
100
|
+
|
|
101
|
+
- **Package ≠ Job** (Rule #5) — a `Package` is an immutable, content-addressed
|
|
102
|
+
source archive; a `Job` is one execution of a package and references it by id.
|
|
103
|
+
- **Resource ≠ Package** (Rule #6) — a `Resource` is a read-only, versioned,
|
|
104
|
+
registry-resolved mount (robot / environment / dataset / …).
|
|
105
|
+
- **Checkpoint ≠ TrainedModel** (Rule #8) — an intermediate training artifact is
|
|
106
|
+
a distinct type from the final, deployable model. Never collapse them.
|
|
107
|
+
- **Project is the anchor** (Rule #7) — every other domain object hangs off a
|
|
108
|
+
`Project`.
|
|
109
|
+
- **No packaged-skill type** (Rule #11) — there is deliberately no `Skill` /
|
|
110
|
+
`PackagedSkill` type here.
|
|
111
|
+
|
|
112
|
+
## Stability policy
|
|
113
|
+
|
|
114
|
+
- Enum **values** are a stable wire ABI: append-only, never renumber or rename.
|
|
115
|
+
- Dataclass fields and Protocol method signatures follow the same
|
|
116
|
+
breaking-change discipline as the rest of the contract layer.
|
|
117
|
+
- The package follows SemVer; additive changes (new optional field, new
|
|
118
|
+
Protocol, new enum member at the end) are minor/patch, removals/renames major.
|
|
119
|
+
|
|
120
|
+
## Requirements
|
|
121
|
+
|
|
122
|
+
- Python **>= 3.11** (uses `enum.StrEnum`). Tested on 3.11 and 3.12.
|
|
123
|
+
- Standard library only — **zero** runtime dependencies.
|
|
124
|
+
|
|
125
|
+
## Development
|
|
126
|
+
|
|
127
|
+
```bash
|
|
128
|
+
pip install -e ".[dev]"
|
|
129
|
+
ruff check src
|
|
130
|
+
black --check src tests
|
|
131
|
+
isort --check-only src tests
|
|
132
|
+
mypy src # strict
|
|
133
|
+
python -m build && twine check dist/*
|
|
134
|
+
pytest
|
|
135
|
+
```
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "simulo-interfaces"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Implementation-free contract layer for the Simulo platform — torch-free runtime/sim Protocols and platform/workspace domain contracts. Importable with no torch/numpy/gymnasium/Isaac installed."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.11"
|
|
11
|
+
license = { text = "BSD-3-Clause" }
|
|
12
|
+
authors = [{ name = "Simulo Team", email = "team@simulo.ai" }]
|
|
13
|
+
keywords = ["robotics", "contracts", "protocols", "interfaces", "simulo"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: BSD License",
|
|
18
|
+
"Operating System :: OS Independent",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Typing :: Typed",
|
|
22
|
+
]
|
|
23
|
+
# ZERO runtime dependencies. Hard invariant (Rule #11): the thin client must
|
|
24
|
+
# import this with no torch/numpy/gymnasium/Isaac/AWS/HTTP present. Enforced by
|
|
25
|
+
# tests/test_no_heavy_deps.py + tests/test_import_without_torch.py.
|
|
26
|
+
dependencies = []
|
|
27
|
+
|
|
28
|
+
[project.optional-dependencies]
|
|
29
|
+
dev = ["black>=24.0", "isort>=5.13", "ruff>=0.5", "mypy>=1.10", "pytest>=8.2", "build>=1.2", "twine>=5.1"]
|
|
30
|
+
# Mirrors simulo-backend's [release] extra. `dev` above carries build/twine
|
|
31
|
+
# but deliberately NOT commitizen — the release skill (.claude/skills/release/
|
|
32
|
+
# SKILL.md) installs THIS extra specifically so `cz` is available without
|
|
33
|
+
# also pulling in a second copy of build/twine.
|
|
34
|
+
release = ["commitizen>=3.27", "build>=1.2", "twine>=5.1"]
|
|
35
|
+
|
|
36
|
+
[project.urls]
|
|
37
|
+
Homepage = "https://simulo.ai"
|
|
38
|
+
Source = "https://github.com/simulo-org/simulo-platform"
|
|
39
|
+
|
|
40
|
+
# PEP 420 namespace package: NO src/simulo/__init__.py. `namespaces = true`
|
|
41
|
+
# makes setuptools pick up simulo.interfaces.* while leaving `simulo` a shared
|
|
42
|
+
# namespace simulo-backend also contributes to. Mirrors simulo-backend exactly.
|
|
43
|
+
[tool.setuptools.packages.find]
|
|
44
|
+
where = ["src"]
|
|
45
|
+
namespaces = true
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.package-data]
|
|
48
|
+
"simulo.interfaces" = ["py.typed"]
|
|
49
|
+
|
|
50
|
+
[tool.mypy]
|
|
51
|
+
python_version = "3.11"
|
|
52
|
+
mypy_path = ["src"]
|
|
53
|
+
namespace_packages = true
|
|
54
|
+
explicit_package_bases = true
|
|
55
|
+
strict = true
|
|
56
|
+
|
|
57
|
+
[tool.pytest.ini_options]
|
|
58
|
+
testpaths = ["tests"]
|
|
59
|
+
addopts = "--import-mode=importlib"
|
|
60
|
+
|
|
61
|
+
[tool.isort]
|
|
62
|
+
profile = "black"
|
|
63
|
+
line_length = 120
|
|
64
|
+
known_first_party = ["simulo"]
|
|
65
|
+
|
|
66
|
+
[tool.ruff]
|
|
67
|
+
line-length = 120
|
|
68
|
+
src = ["src"]
|
|
69
|
+
|
|
70
|
+
[tool.black]
|
|
71
|
+
line-length = 120
|
|
72
|
+
target-version = ["py311"]
|
|
73
|
+
|
|
74
|
+
# --- Commitizen ------------------------------------------------------------
|
|
75
|
+
# Path B release flow (see `.claude/skills/release/SKILL.md`): `cz bump` here
|
|
76
|
+
# creates the bump commit + tag locally; `.github/workflows/release.yml`
|
|
77
|
+
# publishes to PyPI on tag push. version_provider = "pep621" reads/writes
|
|
78
|
+
# [project].version directly; there is no in-tree __version__ mirror to keep
|
|
79
|
+
# in sync (version_files = []).
|
|
80
|
+
#
|
|
81
|
+
# The FIRST release is a hand-written bump commit per the release skill's
|
|
82
|
+
# First-release appendix, NOT a `cz bump` — this package's version is
|
|
83
|
+
# already 0.1.0 with no releasable commits since repo history began, so a
|
|
84
|
+
# real `cz bump --dry-run` would report "no increment"; the first tag simply
|
|
85
|
+
# publishes the current 0.1.0 as-is.
|
|
86
|
+
[tool.commitizen]
|
|
87
|
+
name = "cz_conventional_commits"
|
|
88
|
+
version_provider = "pep621"
|
|
89
|
+
version_files = []
|
|
90
|
+
tag_format = "simulo-interfaces-v$version"
|
|
91
|
+
update_changelog_on_bump = true
|
|
92
|
+
changelog_incremental = true
|
|
93
|
+
major_version_zero = true
|
|
94
|
+
bump_message = "chore(release): bump simulo-interfaces to v$new_version"
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"""Simulo Interfaces — implementation-free contract layer for the Simulo platform.
|
|
2
|
+
|
|
3
|
+
Torch-free, zero-runtime-dependency (Rule #11). Importable on a laptop with no
|
|
4
|
+
torch / numpy / gymnasium / Isaac / AWS / HTTP / DB installed. Two parts:
|
|
5
|
+
|
|
6
|
+
* **Part A — ``simulo.interfaces.runtime``**: tensor-library-agnostic structural
|
|
7
|
+
Protocols mirroring the ``simulo.core`` runtime surface (Task, Policy,
|
|
8
|
+
Trainer, Player, LearningEnv, Scenario, and the observation/reward/termination
|
|
9
|
+
components).
|
|
10
|
+
* **Part B — ``simulo.interfaces.platform``**: platform/workspace domain
|
|
11
|
+
contracts — wire-stable enums, frozen domain dataclasses (Project, Package,
|
|
12
|
+
Job, Resource, Checkpoint, TrainedModel, Tag), and the cloud-execution
|
|
13
|
+
Protocols (App, Runtime, Asset, Volume, callbacks, and
|
|
14
|
+
debug/replay/visualization sessions).
|
|
15
|
+
|
|
16
|
+
This package contributes ``simulo.interfaces.*`` to the shared ``simulo`` PEP 420
|
|
17
|
+
namespace that ``simulo-backend`` also contributes to; it ships NO
|
|
18
|
+
``src/simulo/__init__.py``.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
from simulo.interfaces import platform, runtime
|
|
22
|
+
from simulo.interfaces.exceptions import (
|
|
23
|
+
ContractViolationError,
|
|
24
|
+
ImportResolutionError,
|
|
25
|
+
JobFailedError,
|
|
26
|
+
ResourceNotFoundError,
|
|
27
|
+
ResumeIncompatibleError,
|
|
28
|
+
SimuloError,
|
|
29
|
+
)
|
|
30
|
+
from simulo.interfaces.ids import (
|
|
31
|
+
CheckpointId,
|
|
32
|
+
Digest,
|
|
33
|
+
JobId,
|
|
34
|
+
OrganizationId,
|
|
35
|
+
PackageId,
|
|
36
|
+
ProjectId,
|
|
37
|
+
ResourceId,
|
|
38
|
+
ResourceUri,
|
|
39
|
+
TagId,
|
|
40
|
+
TrainedModelId,
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
__all__ = [
|
|
44
|
+
# subpackages
|
|
45
|
+
"platform",
|
|
46
|
+
"runtime",
|
|
47
|
+
# exception hierarchy
|
|
48
|
+
"SimuloError",
|
|
49
|
+
"ContractViolationError",
|
|
50
|
+
"ImportResolutionError",
|
|
51
|
+
"ResourceNotFoundError",
|
|
52
|
+
"ResumeIncompatibleError",
|
|
53
|
+
"JobFailedError",
|
|
54
|
+
# identifiers
|
|
55
|
+
"OrganizationId",
|
|
56
|
+
"ProjectId",
|
|
57
|
+
"PackageId",
|
|
58
|
+
"JobId",
|
|
59
|
+
"ResourceId",
|
|
60
|
+
"CheckpointId",
|
|
61
|
+
"TrainedModelId",
|
|
62
|
+
"TagId",
|
|
63
|
+
"ResourceUri",
|
|
64
|
+
"Digest",
|
|
65
|
+
]
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"""Shared Simulo contract exception hierarchy.
|
|
2
|
+
|
|
3
|
+
Implementation-free (Rule #11): no I/O, no heavy deps. These types are the
|
|
4
|
+
common error vocabulary the thin ``simulo`` client and the ``simulo-backend``
|
|
5
|
+
GPU SDK both raise/catch when a contract is violated.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class SimuloError(Exception):
|
|
10
|
+
"""Root of the shared Simulo contract exception hierarchy."""
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class ContractViolationError(SimuloError):
|
|
14
|
+
"""An object failed to satisfy a Simulo contract/Protocol."""
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class ImportResolutionError(SimuloError):
|
|
18
|
+
"""A deferred ``runtime.imports()`` symbol was used in local discovery mode
|
|
19
|
+
without a resolved cloud import (Rule #3)."""
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ResourceNotFoundError(SimuloError):
|
|
23
|
+
"""``from_registry()``/``from_name()`` could not resolve a resource/volume (Rule #6)."""
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class ResumeIncompatibleError(SimuloError):
|
|
27
|
+
"""A discovered checkpoint is incompatible with the current job (Rule #9)."""
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
class JobFailedError(SimuloError):
|
|
31
|
+
"""A submitted job terminated in ``JobStatus.FAILED``."""
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""Strongly-typed string identifiers for the platform domain model (Part B).
|
|
2
|
+
|
|
3
|
+
``NewType`` aliases — zero runtime cost (each is the underlying ``str`` at
|
|
4
|
+
runtime) but distinct to the type checker, so a ``ProjectId`` can never be
|
|
5
|
+
passed where a ``JobId`` is expected.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
from typing import NewType
|
|
9
|
+
|
|
10
|
+
OrganizationId = NewType("OrganizationId", str)
|
|
11
|
+
ProjectId = NewType("ProjectId", str)
|
|
12
|
+
PackageId = NewType("PackageId", str)
|
|
13
|
+
JobId = NewType("JobId", str)
|
|
14
|
+
ResourceId = NewType("ResourceId", str)
|
|
15
|
+
CheckpointId = NewType("CheckpointId", str)
|
|
16
|
+
TrainedModelId = NewType("TrainedModelId", str)
|
|
17
|
+
TagId = NewType("TagId", str)
|
|
18
|
+
ResourceUri = NewType("ResourceUri", str) # e.g. "robot/so-arm-100:v3"
|
|
19
|
+
Digest = NewType("Digest", str) # content-addressed package source digest
|
|
20
|
+
RecordingId = NewType("RecordingId", str) # a job-produced MCAP recording (PR-0 wire contract)
|
|
21
|
+
WorkerId = NewType("WorkerId", str) # a claiming worker process (PR-0 wire contract)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Part B — platform/workspace domain contracts.
|
|
2
|
+
|
|
3
|
+
Wire-stable enums, frozen domain dataclasses (Project, Package, Job, Resource,
|
|
4
|
+
Checkpoint, TrainedModel, Tag), and the cloud-execution Protocols (App, Runtime,
|
|
5
|
+
Asset, Volume, job callbacks, and debug/replay/visualization sessions). All
|
|
6
|
+
implementation-free (Rule #11) — concrete behaviour lives in the future
|
|
7
|
+
``simulo`` client and the ``simulo-backend`` SDK.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from simulo.interfaces.platform.app import AppProtocol, JobFunctionProtocol, Mount
|
|
11
|
+
from simulo.interfaces.platform.asset import AssetProtocol
|
|
12
|
+
from simulo.interfaces.platform.callbacks import JobCallbackProtocol
|
|
13
|
+
from simulo.interfaces.platform.debug import DebugSessionProtocol, ReplaySessionProtocol, VisualizationSessionProtocol
|
|
14
|
+
from simulo.interfaces.platform.domain import Checkpoint, Job, Package, Project, Resource, Tag, TrainedModel
|
|
15
|
+
from simulo.interfaces.platform.enums import ArtifactKind, JobStatus, ResourceKind, ResumePolicy
|
|
16
|
+
from simulo.interfaces.platform.runs import (
|
|
17
|
+
JOB_LOGS_ROUTE_TEMPLATE,
|
|
18
|
+
JOB_RESULT_ROUTE_TEMPLATE,
|
|
19
|
+
JOB_ROUTE_TEMPLATE,
|
|
20
|
+
JOBS_API_DEFAULT_PORT,
|
|
21
|
+
JOBS_ROUTE,
|
|
22
|
+
LOG_CHUNK_MAX_BYTES,
|
|
23
|
+
TERMINAL_JOB_STATUSES,
|
|
24
|
+
JobRecord,
|
|
25
|
+
)
|
|
26
|
+
from simulo.interfaces.platform.runtime import RuntimeProtocol
|
|
27
|
+
from simulo.interfaces.platform.submit import (
|
|
28
|
+
JOB_MODEL_DOWNLOAD_ROUTE_TEMPLATE,
|
|
29
|
+
JOB_MODEL_ROUTE_TEMPLATE,
|
|
30
|
+
JOB_MODELS_ROUTE_TEMPLATE,
|
|
31
|
+
JOB_RECORDING_DOWNLOAD_ROUTE_TEMPLATE,
|
|
32
|
+
JOB_RECORDINGS_ROUTE_TEMPLATE,
|
|
33
|
+
MAX_COMPLETE_MESSAGE_CHARS,
|
|
34
|
+
MAX_COMPLETE_REASON_CODE_CHARS,
|
|
35
|
+
MAX_LOG_CHUNK_BYTES,
|
|
36
|
+
MAX_LOG_TOTAL_BYTES,
|
|
37
|
+
MAX_PACKAGE_BYTES,
|
|
38
|
+
MAX_RESULT_BYTES,
|
|
39
|
+
MODEL_KINDS,
|
|
40
|
+
PACKAGE_ARCHIVE_ROUTE_TEMPLATE,
|
|
41
|
+
PACKAGES_ROUTE,
|
|
42
|
+
RESERVED_RUNTIME_ENV_KEYS,
|
|
43
|
+
RESERVED_RUNTIME_ENV_PREFIXES,
|
|
44
|
+
WORKER_CLAIM_ROUTE,
|
|
45
|
+
WORKER_JOB_COMPLETE_ROUTE_TEMPLATE,
|
|
46
|
+
WORKER_JOB_HEARTBEAT_ROUTE_TEMPLATE,
|
|
47
|
+
WORKER_JOB_LOGS_ROUTE_TEMPLATE,
|
|
48
|
+
WORKER_JOB_MODELS_PRESIGN_ROUTE_TEMPLATE,
|
|
49
|
+
WORKER_JOB_MODELS_ROUTE_TEMPLATE,
|
|
50
|
+
WORKER_JOB_RECORDINGS_PRESIGN_ROUTE_TEMPLATE,
|
|
51
|
+
WORKER_JOB_RECORDINGS_ROUTE_TEMPLATE,
|
|
52
|
+
WORKER_LEASE_HEADER,
|
|
53
|
+
ModelRecord,
|
|
54
|
+
RecordingRecord,
|
|
55
|
+
)
|
|
56
|
+
from simulo.interfaces.platform.volume import VolumeProtocol
|
|
57
|
+
|
|
58
|
+
__all__ = [
|
|
59
|
+
# enums
|
|
60
|
+
"JobStatus",
|
|
61
|
+
"ResumePolicy",
|
|
62
|
+
"ResourceKind",
|
|
63
|
+
"ArtifactKind",
|
|
64
|
+
# domain dataclasses
|
|
65
|
+
"Tag",
|
|
66
|
+
"Project",
|
|
67
|
+
"Package",
|
|
68
|
+
"Resource",
|
|
69
|
+
"Job",
|
|
70
|
+
"Checkpoint",
|
|
71
|
+
"TrainedModel",
|
|
72
|
+
# job-run contract (run record schema + jobs HTTP API shape)
|
|
73
|
+
"JobRecord",
|
|
74
|
+
"TERMINAL_JOB_STATUSES",
|
|
75
|
+
"JOBS_API_DEFAULT_PORT",
|
|
76
|
+
"JOBS_ROUTE",
|
|
77
|
+
"JOB_ROUTE_TEMPLATE",
|
|
78
|
+
"JOB_LOGS_ROUTE_TEMPLATE",
|
|
79
|
+
"JOB_RESULT_ROUTE_TEMPLATE",
|
|
80
|
+
"LOG_CHUNK_MAX_BYTES",
|
|
81
|
+
# submit / worker / recordings wire contract (PR-0)
|
|
82
|
+
"PACKAGES_ROUTE",
|
|
83
|
+
"PACKAGE_ARCHIVE_ROUTE_TEMPLATE",
|
|
84
|
+
"JOB_RECORDINGS_ROUTE_TEMPLATE",
|
|
85
|
+
"JOB_RECORDING_DOWNLOAD_ROUTE_TEMPLATE",
|
|
86
|
+
"JOB_MODELS_ROUTE_TEMPLATE",
|
|
87
|
+
"JOB_MODEL_ROUTE_TEMPLATE",
|
|
88
|
+
"JOB_MODEL_DOWNLOAD_ROUTE_TEMPLATE",
|
|
89
|
+
"WORKER_CLAIM_ROUTE",
|
|
90
|
+
"WORKER_JOB_LOGS_ROUTE_TEMPLATE",
|
|
91
|
+
"WORKER_JOB_HEARTBEAT_ROUTE_TEMPLATE",
|
|
92
|
+
"WORKER_JOB_COMPLETE_ROUTE_TEMPLATE",
|
|
93
|
+
"WORKER_JOB_RECORDINGS_PRESIGN_ROUTE_TEMPLATE",
|
|
94
|
+
"WORKER_JOB_RECORDINGS_ROUTE_TEMPLATE",
|
|
95
|
+
"WORKER_JOB_MODELS_PRESIGN_ROUTE_TEMPLATE",
|
|
96
|
+
"WORKER_JOB_MODELS_ROUTE_TEMPLATE",
|
|
97
|
+
"WORKER_LEASE_HEADER",
|
|
98
|
+
"MAX_PACKAGE_BYTES",
|
|
99
|
+
"MAX_LOG_CHUNK_BYTES",
|
|
100
|
+
"MAX_LOG_TOTAL_BYTES",
|
|
101
|
+
"MAX_RESULT_BYTES",
|
|
102
|
+
"MAX_COMPLETE_MESSAGE_CHARS",
|
|
103
|
+
"MAX_COMPLETE_REASON_CODE_CHARS",
|
|
104
|
+
"MODEL_KINDS",
|
|
105
|
+
"ModelRecord",
|
|
106
|
+
"RecordingRecord",
|
|
107
|
+
"RESERVED_RUNTIME_ENV_KEYS",
|
|
108
|
+
"RESERVED_RUNTIME_ENV_PREFIXES",
|
|
109
|
+
# protocols
|
|
110
|
+
"RuntimeProtocol",
|
|
111
|
+
"AssetProtocol",
|
|
112
|
+
"VolumeProtocol",
|
|
113
|
+
"JobCallbackProtocol",
|
|
114
|
+
"JobFunctionProtocol",
|
|
115
|
+
"AppProtocol",
|
|
116
|
+
"Mount",
|
|
117
|
+
"DebugSessionProtocol",
|
|
118
|
+
"ReplaySessionProtocol",
|
|
119
|
+
"VisualizationSessionProtocol",
|
|
120
|
+
]
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
"""User-facing job-container Protocols (Part B) — ``App`` / ``@app.job`` surface."""
|
|
2
|
+
|
|
3
|
+
from typing import Callable, Mapping, Optional, Protocol, Sequence, TypeVar, Union, overload, runtime_checkable
|
|
4
|
+
|
|
5
|
+
from simulo.interfaces.ids import JobId
|
|
6
|
+
from simulo.interfaces.platform.asset import AssetProtocol
|
|
7
|
+
from simulo.interfaces.platform.callbacks import JobCallbackProtocol
|
|
8
|
+
from simulo.interfaces.platform.enums import ResumePolicy
|
|
9
|
+
from simulo.interfaces.platform.runtime import RuntimeProtocol
|
|
10
|
+
from simulo.interfaces.platform.volume import VolumeProtocol
|
|
11
|
+
|
|
12
|
+
F = TypeVar("F", bound=Callable[..., object])
|
|
13
|
+
Mount = Union[AssetProtocol, VolumeProtocol]
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
@runtime_checkable
|
|
17
|
+
class JobFunctionProtocol(Protocol):
|
|
18
|
+
"""What ``@app.job`` returns: the user's original function, wrapped (Rule #1 — source-preserving). FORWARD."""
|
|
19
|
+
|
|
20
|
+
def __call__(self, *args: object, **kwargs: object) -> object: ...
|
|
21
|
+
def submit(self, *args: object, **kwargs: object) -> JobId: ...
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@runtime_checkable
|
|
25
|
+
class AppProtocol(Protocol):
|
|
26
|
+
"""User-facing job container: ``app = simulo.App(name, runtime=, mounts={...})``. FORWARD."""
|
|
27
|
+
|
|
28
|
+
@property
|
|
29
|
+
def name(self) -> str: ...
|
|
30
|
+
@property
|
|
31
|
+
def runtime(self) -> RuntimeProtocol: ...
|
|
32
|
+
@property
|
|
33
|
+
def mounts(self) -> Mapping[str, Mount]: ...
|
|
34
|
+
@overload
|
|
35
|
+
def job(self, fn: F) -> JobFunctionProtocol: ...
|
|
36
|
+
@overload
|
|
37
|
+
def job(
|
|
38
|
+
self, *, callbacks: Sequence[JobCallbackProtocol] = ..., resume: ResumePolicy = ...
|
|
39
|
+
) -> Callable[[F], JobFunctionProtocol]: ...
|
|
40
|
+
def job(
|
|
41
|
+
self,
|
|
42
|
+
fn: Optional[F] = None,
|
|
43
|
+
*,
|
|
44
|
+
callbacks: Sequence[JobCallbackProtocol] = (),
|
|
45
|
+
resume: ResumePolicy = ResumePolicy.AUTO,
|
|
46
|
+
) -> Union[JobFunctionProtocol, Callable[[F], JobFunctionProtocol]]: ...
|
|
47
|
+
def local_entrypoint(self, fn: F) -> F: ...
|