simulo-interfaces 0.2.0__tar.gz → 0.3.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.2.0/src/simulo_interfaces.egg-info → simulo_interfaces-0.3.0}/PKG-INFO +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/pyproject.toml +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/__init__.py +4 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/runs.py +81 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/submit.py +5 -4
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0/src/simulo_interfaces.egg-info}/PKG-INFO +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/MANIFEST.in +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/PYPI.md +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/setup.cfg +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/__init__.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/exceptions.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/ids.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/app.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/asset.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/callbacks.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/debug.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/domain.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/enums.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/runtime.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/volume.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/py.typed +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/__init__.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/anomaly.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/components.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/env.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/player.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/policy.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/scenario.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/task.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/tensors.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/trainer.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/SOURCES.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/dependency_links.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/requires.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/top_level.txt +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "simulo-interfaces"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.3.0"
|
|
8
8
|
description = "Type contracts for the Simulo SDK. Installed automatically as a dependency of the simulo package."
|
|
9
9
|
readme = "PYPI.md"
|
|
10
10
|
requires-python = ">=3.11"
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/__init__.py
RENAMED
|
@@ -14,12 +14,14 @@ from simulo.interfaces.platform.debug import DebugSessionProtocol, ReplaySession
|
|
|
14
14
|
from simulo.interfaces.platform.domain import Checkpoint, Job, Package, Project, Resource, Tag, TrainedModel
|
|
15
15
|
from simulo.interfaces.platform.enums import ArtifactKind, JobStatus, ResourceKind, ResumePolicy
|
|
16
16
|
from simulo.interfaces.platform.runs import (
|
|
17
|
+
JOB_CANCEL_ROUTE_TEMPLATE,
|
|
17
18
|
JOB_LOGS_ROUTE_TEMPLATE,
|
|
18
19
|
JOB_RESULT_ROUTE_TEMPLATE,
|
|
19
20
|
JOB_ROUTE_TEMPLATE,
|
|
20
21
|
JOBS_API_DEFAULT_PORT,
|
|
21
22
|
JOBS_ROUTE,
|
|
22
23
|
LOG_CHUNK_MAX_BYTES,
|
|
24
|
+
LOG_TAIL_MAX_BYTES,
|
|
23
25
|
TERMINAL_JOB_STATUSES,
|
|
24
26
|
JobRecord,
|
|
25
27
|
)
|
|
@@ -75,9 +77,11 @@ __all__ = [
|
|
|
75
77
|
"JOBS_API_DEFAULT_PORT",
|
|
76
78
|
"JOBS_ROUTE",
|
|
77
79
|
"JOB_ROUTE_TEMPLATE",
|
|
80
|
+
"JOB_CANCEL_ROUTE_TEMPLATE",
|
|
78
81
|
"JOB_LOGS_ROUTE_TEMPLATE",
|
|
79
82
|
"JOB_RESULT_ROUTE_TEMPLATE",
|
|
80
83
|
"LOG_CHUNK_MAX_BYTES",
|
|
84
|
+
"LOG_TAIL_MAX_BYTES",
|
|
81
85
|
# submit / worker / recordings wire contract (PR-0)
|
|
82
86
|
"PACKAGES_ROUTE",
|
|
83
87
|
"PACKAGE_ARCHIVE_ROUTE_TEMPLATE",
|
|
@@ -37,8 +37,50 @@ HTTP API shape (all responses JSON; all timestamps ISO 8601 UTC, e.g.
|
|
|
37
37
|
``next_offset == offset``; the accompanying ``status`` tells the client
|
|
38
38
|
whether more output may still arrive (poll while the status is
|
|
39
39
|
non-terminal, stop once it is in :data:`TERMINAL_JOB_STATUSES`).
|
|
40
|
+
|
|
41
|
+
**Tail semantics (optional, additive):** ``?tail_bytes=K`` (``0 <= K <=``
|
|
42
|
+
:data:`LOG_TAIL_MAX_BYTES`; ``offset`` must be omitted or 0, otherwise the
|
|
43
|
+
request is ambiguous and answers 422 — the control plane's code is
|
|
44
|
+
``tail_bytes_conflicts_with_offset``; clients need only the status)
|
|
45
|
+
asks the server to start the read near the END of the stream instead of at
|
|
46
|
+
``offset``: the server computes ``start = max(0, total_len - K)`` and
|
|
47
|
+
returns the chunk from there, adding ``"start_offset": start`` to the
|
|
48
|
+
response. ``start_offset`` is present ONLY when tail was honored — its
|
|
49
|
+
absence tells a tail-requesting client it is talking to an older server
|
|
50
|
+
that ignored the (undeclared) parameter and answered from offset 0, so the
|
|
51
|
+
client can degrade to full history instead of mis-trimming. ``tail_bytes=0``
|
|
52
|
+
is the "seek to end-of-log" primitive: an empty ``chunk`` with
|
|
53
|
+
``next_offset == start_offset == total_len``. After one tail response the
|
|
54
|
+
client resumes normal offset paging from ``next_offset`` (never sending
|
|
55
|
+
``tail_bytes`` again), so a tail-following client never drains the full
|
|
56
|
+
history. ``start`` is a byte position and may land mid-line or mid-UTF-8
|
|
57
|
+
sequence; a line-oriented client trims its first partial line client-side
|
|
58
|
+
(``simulo logs --follow`` requests a generous byte window for its line
|
|
59
|
+
count and does exactly that).
|
|
40
60
|
* ``GET /v1/jobs/{job_id}/result`` — the job's result JSON object. 404 (code
|
|
41
61
|
``result_not_available``) until the job has completed successfully.
|
|
62
|
+
* ``POST /v1/jobs/{job_id}/cancel`` — request cancellation of a queued or
|
|
63
|
+
running job (no request body). Semantics by current status:
|
|
64
|
+
|
|
65
|
+
- ``queued`` → the job transitions to terminal ``cancelled`` immediately
|
|
66
|
+
(it can never be claimed afterwards). 200::
|
|
67
|
+
|
|
68
|
+
{"job_id": "...", "status": "cancelled"}
|
|
69
|
+
|
|
70
|
+
- ``running`` → cancellation is REQUESTED; the executor observes it on its
|
|
71
|
+
next heartbeat, stops the job, and reports terminal ``cancelled``
|
|
72
|
+
(existing ``best.pt``/``latest.pt`` checkpoints are uploaded first —
|
|
73
|
+
cancel never vaporizes training progress; partial recordings are
|
|
74
|
+
dropped). Idempotent: repeat requests return the same 202::
|
|
75
|
+
|
|
76
|
+
{"job_id": "...", "status": "running", "cancel_requested": true}
|
|
77
|
+
|
|
78
|
+
A ``running`` job whose executor is provably gone (expired lease, no
|
|
79
|
+
active claim) transitions directly to ``cancelled`` → 200 as above.
|
|
80
|
+
- terminal (``completed``/``failed``/``cancelled``) → 409, code
|
|
81
|
+
``job_not_running``, with the job's actual status in the human message.
|
|
82
|
+
- unknown/cross-tenant/malformed id → 404 ``job_not_found`` (never 403 —
|
|
83
|
+
anti-enumeration, same as every other per-job route).
|
|
42
84
|
|
|
43
85
|
**Scoping (evolves toward the cloud):** every route above is UNSCOPED locally
|
|
44
86
|
— there is no project/org filter because the local stand-in has exactly one
|
|
@@ -77,10 +119,48 @@ JOB_ROUTE_TEMPLATE = "/v1/jobs/{job_id}"
|
|
|
77
119
|
JOB_LOGS_ROUTE_TEMPLATE = "/v1/jobs/{job_id}/logs"
|
|
78
120
|
#: ``GET`` — the result JSON of a successfully completed job. ``.format(job_id=...)``.
|
|
79
121
|
JOB_RESULT_ROUTE_TEMPLATE = "/v1/jobs/{job_id}/result"
|
|
122
|
+
#: ``POST`` — cancel a queued/running job (no body). ``.format(job_id=...)``.
|
|
123
|
+
#: 200 terminal ``cancelled`` (queued, or running with a provably-dead
|
|
124
|
+
#: executor); 202 ``{"cancel_requested": true}`` (running — the executor
|
|
125
|
+
#: stops it within one heartbeat interval); 409 ``job_not_running``
|
|
126
|
+
#: (already terminal); 404 ``job_not_found``. Full semantics in the module
|
|
127
|
+
#: docstring above.
|
|
128
|
+
JOB_CANCEL_ROUTE_TEMPLATE = "/v1/jobs/{job_id}/cancel"
|
|
80
129
|
|
|
81
130
|
#: Upper bound on the log bytes a single ``/logs`` response carries. The server
|
|
82
131
|
#: may return fewer bytes (never more); clients keep reading from ``next_offset``.
|
|
83
|
-
|
|
132
|
+
#: This is a server-side response-size POLICY value, not a structural wire
|
|
133
|
+
#: shape — clients are not expected to depend on the exact number (they
|
|
134
|
+
#: read ``chunk``/``next_offset`` generically and loop until caught up), so
|
|
135
|
+
#: it is safe to raise without breaking already-published clients reading
|
|
136
|
+
#: OFFSET responses. **Rollout order caveat (added with tail semantics):**
|
|
137
|
+
#: :data:`LOG_TAIL_MAX_BYTES` is DERIVED from this constant (``4x``), so
|
|
138
|
+
#: raising this ALSO raises what a new client may send as ``?tail_bytes=``.
|
|
139
|
+
#: A server that has not yet picked up the raised bound still enforces its
|
|
140
|
+
#: OLD, smaller ``le=`` cap on that query param and answers 422 — a hard
|
|
141
|
+
#: rejection the client's tail-degradation path does not cover (that path
|
|
142
|
+
#: handles an old server IGNORING the unknown param, not one REJECTING an
|
|
143
|
+
#: in-range-for-the-client-but-out-of-range-for-the-server value). Deploy
|
|
144
|
+
#: every server before shipping a `simulo-interfaces` release that raises
|
|
145
|
+
#: this constant. Bumped
|
|
146
|
+
#: 64 KiB -> 256 KiB (simulo-control-plane PR6, 2026-07-11): a poll-cadence
|
|
147
|
+
#: rate limit sized against the OLD 64 KiB cap could still 429 mid-drain on
|
|
148
|
+
#: a large/fast-growing log because a no-sleep catch-up loop bursts through
|
|
149
|
+
#: it; see that PR's `jobs/routes.py::_LOGS_POLL_RATE` docstring for the
|
|
150
|
+
#: exact math. No PyPI republish accompanies this source change — no
|
|
151
|
+
#: published thin-client version reads this constant at runtime; it takes
|
|
152
|
+
#: effect for whichever `simulo-interfaces` version ships next.
|
|
153
|
+
LOG_CHUNK_MAX_BYTES = 256 * 1024
|
|
154
|
+
|
|
155
|
+
#: Upper bound on ``?tail_bytes=`` (the "start this many bytes before the end"
|
|
156
|
+
#: request parameter — see the module docstring's tail semantics). A tail
|
|
157
|
+
#: window is a REQUEST-side positioning value, not a response-size promise:
|
|
158
|
+
#: the response is still capped at :data:`LOG_CHUNK_MAX_BYTES`, and a window
|
|
159
|
+
#: larger than one response chunk arrives across normal offset pages. 4x the
|
|
160
|
+
#: response cap comfortably covers the CLI's default (50 lines x ~200
|
|
161
|
+
#: bytes/line ≈ 10 KiB) and any plausible ``--tail N`` while keeping the
|
|
162
|
+
#: server's tail scan bounded. Values above this cap answer 422.
|
|
163
|
+
LOG_TAIL_MAX_BYTES = 4 * LOG_CHUNK_MAX_BYTES
|
|
84
164
|
|
|
85
165
|
#: Statuses after which a job's log stream and record no longer change. A log
|
|
86
166
|
#: follower drains the remaining bytes and stops once the status is terminal.
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/submit.py
RENAMED
|
@@ -344,10 +344,11 @@ MAX_PACKAGE_BYTES = 64 * 1024 * 1024 # 64 MiB
|
|
|
344
344
|
#: (``POST`` :data:`WORKER_JOB_LOGS_ROUTE_TEMPLATE` body) — the write-side cap, 1 MiB.
|
|
345
345
|
#:
|
|
346
346
|
#: **Not the same constant as** ``simulo.interfaces.platform.runs.LOG_CHUNK_MAX_BYTES``
|
|
347
|
-
#: (
|
|
348
|
-
#: ``GET .../logs?offset=N``
|
|
349
|
-
#:
|
|
350
|
-
#:
|
|
347
|
+
#: (256 KiB as of 2026-07-11 — see that constant's docstring) — that is the
|
|
348
|
+
#: pre-existing **client** read-side cap on a single ``GET .../logs?offset=N``
|
|
349
|
+
#: response (``runs.py``). Both are now re-exported from
|
|
350
|
+
#: ``simulo.interfaces.platform``, so importing the wrong one silently
|
|
351
|
+
#: changes behavior by 4x: a worker that POSTs up to ``runs.LOG_CHUNK_MAX_BYTES``
|
|
351
352
|
#: per call under-uses its allowance; a client GET that budgeted for this
|
|
352
353
|
#: (larger) constant would be surprised the server never returns that much.
|
|
353
354
|
MAX_LOG_CHUNK_BYTES = 1 * 1024 * 1024 # 1 MiB
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/domain.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/runtime.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/platform/volume.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/__init__.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/anomaly.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/components.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/scenario.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/tensors.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo/interfaces/runtime/trainer.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/requires.txt
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.3.0}/src/simulo_interfaces.egg-info/top_level.txt
RENAMED
|
File without changes
|