simulo-interfaces 0.2.0__tar.gz → 0.4.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.4.0}/PKG-INFO +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/pyproject.toml +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/__init__.py +13 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/runs.py +81 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/submit.py +101 -4
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0/src/simulo_interfaces.egg-info}/PKG-INFO +1 -1
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/MANIFEST.in +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/PYPI.md +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/setup.cfg +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/__init__.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/exceptions.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/ids.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/app.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/asset.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/callbacks.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/debug.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/domain.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/enums.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/runtime.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/volume.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/py.typed +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/__init__.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/anomaly.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/components.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/env.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/player.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/policy.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/scenario.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/task.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/tensors.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/trainer.py +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/SOURCES.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/dependency_links.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/requires.txt +0 -0
- {simulo_interfaces-0.2.0 → simulo_interfaces-0.4.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.4.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.4.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
|
)
|
|
@@ -36,11 +38,15 @@ from simulo.interfaces.platform.submit import (
|
|
|
36
38
|
MAX_LOG_TOTAL_BYTES,
|
|
37
39
|
MAX_PACKAGE_BYTES,
|
|
38
40
|
MAX_RESULT_BYTES,
|
|
41
|
+
MAX_SEED_REF_CHARS,
|
|
39
42
|
MODEL_KINDS,
|
|
40
43
|
PACKAGE_ARCHIVE_ROUTE_TEMPLATE,
|
|
41
44
|
PACKAGES_ROUTE,
|
|
42
45
|
RESERVED_RUNTIME_ENV_KEYS,
|
|
43
46
|
RESERVED_RUNTIME_ENV_PREFIXES,
|
|
47
|
+
SEED_JOB_REF_GRAMMAR,
|
|
48
|
+
SEED_SOURCE_CONFLICT_CODE,
|
|
49
|
+
SEED_SOURCE_FIELDS,
|
|
44
50
|
WORKER_CLAIM_ROUTE,
|
|
45
51
|
WORKER_JOB_COMPLETE_ROUTE_TEMPLATE,
|
|
46
52
|
WORKER_JOB_HEARTBEAT_ROUTE_TEMPLATE,
|
|
@@ -75,9 +81,11 @@ __all__ = [
|
|
|
75
81
|
"JOBS_API_DEFAULT_PORT",
|
|
76
82
|
"JOBS_ROUTE",
|
|
77
83
|
"JOB_ROUTE_TEMPLATE",
|
|
84
|
+
"JOB_CANCEL_ROUTE_TEMPLATE",
|
|
78
85
|
"JOB_LOGS_ROUTE_TEMPLATE",
|
|
79
86
|
"JOB_RESULT_ROUTE_TEMPLATE",
|
|
80
87
|
"LOG_CHUNK_MAX_BYTES",
|
|
88
|
+
"LOG_TAIL_MAX_BYTES",
|
|
81
89
|
# submit / worker / recordings wire contract (PR-0)
|
|
82
90
|
"PACKAGES_ROUTE",
|
|
83
91
|
"PACKAGE_ARCHIVE_ROUTE_TEMPLATE",
|
|
@@ -106,6 +114,11 @@ __all__ = [
|
|
|
106
114
|
"RecordingRecord",
|
|
107
115
|
"RESERVED_RUNTIME_ENV_KEYS",
|
|
108
116
|
"RESERVED_RUNTIME_ENV_PREFIXES",
|
|
117
|
+
# explicit-run-intent plan: submit-time seed source (additive)
|
|
118
|
+
"SEED_SOURCE_FIELDS",
|
|
119
|
+
"SEED_SOURCE_CONFLICT_CODE",
|
|
120
|
+
"SEED_JOB_REF_GRAMMAR",
|
|
121
|
+
"MAX_SEED_REF_CHARS",
|
|
109
122
|
# protocols
|
|
110
123
|
"RuntimeProtocol",
|
|
111
124
|
"AssetProtocol",
|
|
@@ -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.4.0}/src/simulo/interfaces/platform/submit.py
RENAMED
|
@@ -83,6 +83,49 @@ platform-standard shape: ``{"error": {"code": ..., "message": ..., "request_id":
|
|
|
83
83
|
with the *existing* record rather than creating a second job — a client
|
|
84
84
|
retry (e.g. after a dropped response) must not double-submit.
|
|
85
85
|
|
|
86
|
+
**Seed source (explicit-run-intent plan, additive):** the request body
|
|
87
|
+
optionally carries one of two further top-level fields, both **siblings of
|
|
88
|
+
``args`` — never nested inside it, and never written into the package
|
|
89
|
+
manifest**::
|
|
90
|
+
|
|
91
|
+
{"package_id": "...", "job_name": "train_cartpole", "args": {...},
|
|
92
|
+
"seed_from_job_id": "<job-id>[:latest]"}
|
|
93
|
+
|
|
94
|
+
This placement is load-bearing, not stylistic: ``args``' canonical JSON is
|
|
95
|
+
what the client hashes (together with the source digest and job name) to
|
|
96
|
+
derive ``package_id`` (``_client/manifest.py``), so a seed reference living
|
|
97
|
+
inside ``args`` would make re-running the exact same package bytes with a
|
|
98
|
+
*different* seed register as a *different* package — collapsing package
|
|
99
|
+
identity (content-addressed, immutable) into job identity (per-submit,
|
|
100
|
+
mutable). ``viewstream`` (the worker's ``_child_env``) already follows this
|
|
101
|
+
same package-≠-job placement rule; these two fields are the same shape.
|
|
102
|
+
Consumers of this contract MUST build the seed fields onto the request
|
|
103
|
+
exactly the way ``create_job`` builds ``viewstream`` today — as extra keys
|
|
104
|
+
set directly on the top-level body dict — and MUST NOT fold them into the
|
|
105
|
+
``args`` mapping that gets hashed.
|
|
106
|
+
|
|
107
|
+
:data:`SEED_SOURCE_FIELDS` pins the two field names:
|
|
108
|
+
|
|
109
|
+
- ``seed_from_job_id`` (``str``) — continue training from another job's
|
|
110
|
+
checkpoint. A bare job id selects that job's ``best.pt``; suffixing
|
|
111
|
+
``:latest`` (``"<job-id>:latest"``) selects ``latest.pt`` instead — the
|
|
112
|
+
suffix lives inside this one string; there is no separate "kind" field.
|
|
113
|
+
- ``seed_from_model_id`` (``str``) — continue from one exact
|
|
114
|
+
:class:`ModelRecord` artifact, pinned by id.
|
|
115
|
+
|
|
116
|
+
Both default to (and an old client that predates this field pair always
|
|
117
|
+
sends) absent/``None`` — a **fresh run**, the new default with no
|
|
118
|
+
exceptions: an un-upgraded client that omits both fields degrades to
|
|
119
|
+
exactly the semantics this plan wants, with zero change to the bytes it
|
|
120
|
+
already sends. The two are **mutually exclusive**: a request setting both
|
|
121
|
+
is rejected whole, ``422`` :data:`SEED_SOURCE_CONFLICT_CODE`
|
|
122
|
+
(``"seed_source_conflict"``) — the server never silently prefers one over
|
|
123
|
+
the other. Further validation of the referenced job/model (org membership,
|
|
124
|
+
terminal status, artifact kind) is server-side business logic layered on
|
|
125
|
+
top of this wire shape, not defined by this module — see the
|
|
126
|
+
explicit-run-intent plan's "Server validation" section
|
|
127
|
+
(``context/implementation-plans/explicit-run-intent-plan.md``).
|
|
128
|
+
|
|
86
129
|
## Client-facing: recordings
|
|
87
130
|
|
|
88
131
|
* :data:`JOB_RECORDINGS_ROUTE_TEMPLATE` (``GET``) — paginated envelope of
|
|
@@ -298,6 +341,59 @@ JOB_MODEL_DOWNLOAD_ROUTE_TEMPLATE = "/v1/jobs/{job_id}/models/{model_id}/downloa
|
|
|
298
341
|
#: There is deliberately no separate ``*_SUBMIT_ROUTE`` constant here — see
|
|
299
342
|
#: the module docstring's "Client-facing: package submit + job create" section.
|
|
300
343
|
|
|
344
|
+
#: The two mutually-exclusive, optional ``POST /v1/jobs`` body fields — both
|
|
345
|
+
#: **siblings of ``args``**, never nested inside it — that seed a fresh job's
|
|
346
|
+
#: starting checkpoint from another job's or model's already-uploaded
|
|
347
|
+
#: artifact (explicit-run-intent plan). Neither set = a fresh run, the
|
|
348
|
+
#: default and the only behavior an old client (unaware of this pair) can
|
|
349
|
+
#: produce. Setting both in the same request is rejected whole as
|
|
350
|
+
#: :data:`SEED_SOURCE_CONFLICT_CODE`. Full field-by-field semantics live in
|
|
351
|
+
#: the module docstring's "Client-facing: package submit + job create"
|
|
352
|
+
#: section, above — this tuple exists so PRs building against this contract
|
|
353
|
+
#: (control plane request validation, the thin client's ``--from`` flag —
|
|
354
|
+
#: which resolves a job-ref + artifact name to a concrete ``model_id``, so no
|
|
355
|
+
#: UUID ever reaches a human) import one pinned pair of literal names instead
|
|
356
|
+
#: of re-typing them. There is deliberately no ``--from-model`` CLI flag.
|
|
357
|
+
SEED_SOURCE_FIELDS = ("seed_from_job_id", "seed_from_model_id")
|
|
358
|
+
|
|
359
|
+
#: Grammar of the ``seed_from_job_id`` value (the ``seed_from_model_id`` value
|
|
360
|
+
#: is a bare model id, no suffix). Pinned here because BOTH sides parse it and
|
|
361
|
+
#: a divergence is silent: the client would accept a value the server rejects
|
|
362
|
+
#: (a wasted package build + archive upload for a typo), or reject one the
|
|
363
|
+
#: server accepts.
|
|
364
|
+
#:
|
|
365
|
+
#: ``<job-ref>[:<kind>]`` — ``job-ref`` is a full job UUID or an unambiguous
|
|
366
|
+
#: id prefix; ``kind`` is one of :data:`MODEL_KINDS`, compared **lowercased
|
|
367
|
+
#: after stripping surrounding whitespace**. Rules, in the order both sides
|
|
368
|
+
#: apply them:
|
|
369
|
+
#:
|
|
370
|
+
#: * ``":" not in value`` → the whole value is the ref; ``kind`` defaults to
|
|
371
|
+
#: ``MODEL_KINDS[0]`` (``"best"``). ``":"`` is not in the UUID/prefix
|
|
372
|
+
#: alphabet, so its presence is an unambiguous suffix signal.
|
|
373
|
+
#: * otherwise split on the LAST ``":"`` (``rpartition``) and reject — never
|
|
374
|
+
#: silently fall back — when EITHER side is empty (``":latest"`` is not a
|
|
375
|
+
#: ref named ``latest``; ``"8b52:"`` is not an implicit ``:best``) or when
|
|
376
|
+
#: ``kind`` is outside :data:`MODEL_KINDS`.
|
|
377
|
+
#:
|
|
378
|
+
#: A value violating this grammar is ``422`` ``seed_artifact_invalid``.
|
|
379
|
+
SEED_JOB_REF_GRAMMAR = "<job-ref>[:best|:latest]"
|
|
380
|
+
|
|
381
|
+
#: Server-pinned max length of either :data:`SEED_SOURCE_FIELDS` value on the
|
|
382
|
+
#: wire (the control plane's Pydantic ``max_length``). A client MUST check
|
|
383
|
+
#: this before packaging: a longer value is otherwise packaged and uploaded
|
|
384
|
+
#: only to be rejected by generic schema validation, whose envelope carries
|
|
385
|
+
#: none of the seed error codes a client maps to friendly copy.
|
|
386
|
+
MAX_SEED_REF_CHARS = 80
|
|
387
|
+
|
|
388
|
+
#: Error code (``POST /v1/jobs``, ``422``) when a request sets BOTH
|
|
389
|
+
#: :data:`SEED_SOURCE_FIELDS` in the same body. Pinned as a constant — unlike
|
|
390
|
+
#: this module's other wire error codes (e.g. ``lease_lost``,
|
|
391
|
+
#: ``log_offset_gap``), which are documented as literal strings only —
|
|
392
|
+
#: because both the control plane raising it and the thin client's seed-source
|
|
393
|
+
#: mutual-exclusion check need to switch on this exact string; a bare literal
|
|
394
|
+
#: risks silent drift between the two.
|
|
395
|
+
SEED_SOURCE_CONFLICT_CODE = "seed_source_conflict"
|
|
396
|
+
|
|
301
397
|
# --------------------------------------------------------------------------
|
|
302
398
|
# Worker-facing routes (bearer = static WORKER_TOKEN, constant-time compare;
|
|
303
399
|
# empty server-side config disables every route below, fail-closed)
|
|
@@ -344,10 +440,11 @@ MAX_PACKAGE_BYTES = 64 * 1024 * 1024 # 64 MiB
|
|
|
344
440
|
#: (``POST`` :data:`WORKER_JOB_LOGS_ROUTE_TEMPLATE` body) — the write-side cap, 1 MiB.
|
|
345
441
|
#:
|
|
346
442
|
#: **Not the same constant as** ``simulo.interfaces.platform.runs.LOG_CHUNK_MAX_BYTES``
|
|
347
|
-
#: (
|
|
348
|
-
#: ``GET .../logs?offset=N``
|
|
349
|
-
#:
|
|
350
|
-
#:
|
|
443
|
+
#: (256 KiB as of 2026-07-11 — see that constant's docstring) — that is the
|
|
444
|
+
#: pre-existing **client** read-side cap on a single ``GET .../logs?offset=N``
|
|
445
|
+
#: response (``runs.py``). Both are now re-exported from
|
|
446
|
+
#: ``simulo.interfaces.platform``, so importing the wrong one silently
|
|
447
|
+
#: changes behavior by 4x: a worker that POSTs up to ``runs.LOG_CHUNK_MAX_BYTES``
|
|
351
448
|
#: per call under-uses its allowance; a client GET that budgeted for this
|
|
352
449
|
#: (larger) constant would be surprised the server never returns that much.
|
|
353
450
|
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.4.0}/src/simulo/interfaces/platform/callbacks.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/domain.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/runtime.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/platform/volume.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/__init__.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/anomaly.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.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.4.0}/src/simulo/interfaces/runtime/scenario.py
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/tensors.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo/interfaces/runtime/trainer.py
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/SOURCES.txt
RENAMED
|
File without changes
|
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/requires.txt
RENAMED
|
File without changes
|
{simulo_interfaces-0.2.0 → simulo_interfaces-0.4.0}/src/simulo_interfaces.egg-info/top_level.txt
RENAMED
|
File without changes
|