sequence-base 0.3.28__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.
Files changed (107) hide show
  1. {sequence_base-0.3.28 → sequence_base-0.4.0}/PKG-INFO +1 -1
  2. {sequence_base-0.3.28 → sequence_base-0.4.0}/README.md +4 -5
  3. {sequence_base-0.3.28 → sequence_base-0.4.0}/pyproject.toml +1 -1
  4. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/__init__.py +24 -2
  5. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/codec/image.py +16 -1
  6. sequence_base-0.4.0/sequence_base/constants/version.py +30 -0
  7. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/__init__.py +21 -3
  8. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/accounts.py +11 -17
  9. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/benchmarks.py +32 -0
  10. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/connect.py +3 -2
  11. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/deployments.py +48 -19
  12. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/errors.py +6 -7
  13. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/eval.py +32 -1
  14. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/flags.py +16 -2
  15. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/policy.py +51 -6
  16. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/templates.py +2 -0
  17. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/volumes.py +5 -0
  18. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/wire.py +2 -0
  19. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/errors/transport.py +2 -4
  20. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/obs/rid.py +2 -3
  21. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/presets/robot_arm.py +28 -0
  22. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schema_export.py +13 -3
  23. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ActRequest.json +1 -1
  24. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ActResponse.json +1 -1
  25. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ActionChunk.json +1 -1
  26. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ActionContract.json +1 -1
  27. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ActionStep.json +1 -1
  28. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/AdapterTransform.json +1 -1
  29. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/AddLocal.json +1 -1
  30. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Autoscaler.json +1 -1
  31. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/BenchmarkConditionSpec.json +1 -1
  32. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/BenchmarkRegisterRequest.json +2 -2
  33. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/BenchmarkSpec.json +3 -3
  34. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/BenchmarkStatusResponse.json +1 -1
  35. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/BootstrapResponse.json +1 -1
  36. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Camera.json +1 -1
  37. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ClampInfo.json +1 -1
  38. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/CodeBundle.json +1 -1
  39. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Concurrency.json +1 -1
  40. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Conditions.json +1 -1
  41. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ConnectRequest.json +1 -1
  42. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ConnectResponse.json +1 -20
  43. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/DeploymentAccepted.json +1 -1
  44. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/DeploymentPolicy.json +2 -2
  45. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/DeploymentRequest.json +3 -3
  46. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/DeploymentStatusResponse.json +1 -1
  47. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Embodiment.json +1 -1
  48. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ErrorBody.json +1 -1
  49. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ErrorCodes.json +1 -1
  50. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Estimate.json +1 -1
  51. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/EvalDryRunResponse.json +1 -1
  52. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/EvalReport.json +1 -1
  53. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/EvalRequest.json +1 -1
  54. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/EvalResponse.json +1 -1
  55. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageFrame.json +1 -1
  56. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageSpec.json +2 -2
  57. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageStepAddLocal.json +1 -1
  58. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageStepApt.json +1 -1
  59. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageStepEnv.json +1 -1
  60. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageStepRun.json +1 -1
  61. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ImageStepUvPip.json +1 -1
  62. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/InferParam.json +1 -1
  63. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Lease.json +1 -1
  64. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/LossyTransform.json +1 -1
  65. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/MetricAgg.json +1 -1
  66. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Observation.json +1 -1
  67. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/ObservationContract.json +1 -1
  68. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/PolicyRegistration.json +3 -3
  69. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/PolicySpec.json +2 -2
  70. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Proprioception.json +1 -1
  71. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/RenderSpec.json +1 -1
  72. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Resources.json +1 -1
  73. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/RolloutResult.json +2 -2
  74. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/SecretCreateRequest.json +1 -1
  75. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/SecretInfo.json +1 -1
  76. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/SecretRef.json +1 -1
  77. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/SeqFlags.json +1 -1
  78. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Step.json +1 -1
  79. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/SuiteAgg.json +1 -1
  80. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/TaskAgg.json +1 -1
  81. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Timeouts.json +1 -1
  82. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/UploadTarget.json +1 -1
  83. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/Variant.json +1 -1
  84. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeAttach.json +1 -1
  85. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeFile.json +1 -1
  86. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeInfo.json +1 -1
  87. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeMount.json +1 -1
  88. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeRef.json +1 -1
  89. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeUploadRequest.json +1 -1
  90. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/VolumeUploadResponse.json +1 -1
  91. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/schemas/WarmingError.json +1 -1
  92. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/telemetry/events.py +7 -4
  93. sequence_base-0.3.28/sequence_base/constants/env.py +0 -7
  94. sequence_base-0.3.28/sequence_base/constants/version.py +0 -3
  95. sequence_base-0.3.28/sequence_base/schemas/UsageReport.json +0 -38
  96. {sequence_base-0.3.28 → sequence_base-0.4.0}/.gitignore +0 -0
  97. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/auth.py +0 -0
  98. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/codec/__init__.py +0 -0
  99. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/constants/__init__.py +0 -0
  100. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/constants/headers.py +0 -0
  101. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/act.py +0 -0
  102. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/contract/io.py +0 -0
  103. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/errors/__init__.py +0 -0
  104. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/obs/__init__.py +0 -0
  105. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/obs/log.py +0 -0
  106. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/presets/__init__.py +0 -0
  107. {sequence_base-0.3.28 → sequence_base-0.4.0}/sequence_base/telemetry/__init__.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sequence-base
3
- Version: 0.3.28
3
+ Version: 0.4.0
4
4
  Summary: Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness.
5
5
  Requires-Python: >=3.10
6
6
  Requires-Dist: pydantic>=2.0
@@ -14,13 +14,12 @@ from sequence_base import TransportWarming, TransportOverloaded # error taxonom
14
14
  ```
15
15
  sequence_base/
16
16
  contract/ act.py — Observation / ActionChunk / ImageFrame / Proprioception / ActionSpace / ActionStep
17
- (grows: chat.py, perceive.py) · sdk + gateway + container
17
+ · sdk + gateway + container
18
18
  obs/ rid.py (HEADER, new_rid, clean) · log.py (log, Timer) · sdk + gateway + container
19
19
  errors/ transport.py (Warming / Rejected / Overloaded / Unavailable) · gateway + container
20
- (grows: client.py)
21
- constants/ headers.py · env.py · version.py · all three
22
- codec/ [P1] image.py (encode/decode) · resize.py — sdk encodes, container decodes; MUST match
23
- telemetry/ [P1] events.py — container→gateway event shapes
20
+ constants/ headers.py · version.py · all three
21
+ codec/ [P1] image.py (encode/decode) — sdk encodes, container decodes; MUST match
22
+ telemetry/ [P1] events.py — the cold-start Stage vocabulary a worker logs
24
23
  ```
25
24
 
26
25
  ## The one rule for what goes in here
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sequence-base"
3
- version = "0.3.28"
3
+ version = "0.4.0"
4
4
  description = "Shared foundation for the Sequences platform — wire contract, correlation, error taxonomy, constants. Used by the robot SDK, gateway, and container harness."
5
5
  requires-python = ">=3.10"
6
6
  dependencies = ["pydantic>=2.0"]
@@ -11,6 +11,8 @@ defined once so they cannot drift. Import from here; never redefine.
11
11
  Only shared-by-≥2-and-drifts-if-duplicated things live here. Model-specific, provider-specific, and
12
12
  catalogue values stay in container / gateway / spec.py.
13
13
  """
14
+
15
+
14
16
  from sequence_base.contract import (
15
17
  ActRequest,
16
18
  ActResponse,
@@ -87,7 +89,6 @@ from sequence_base.contract import (
87
89
  SuiteAgg,
88
90
  TaskAgg,
89
91
  Timeouts,
90
- UsageReport,
91
92
  Variant,
92
93
  VolumeAttach,
93
94
  VolumeMount,
@@ -96,11 +97,14 @@ from sequence_base.contract import (
96
97
  code_for_status,
97
98
  )
98
99
 
100
+
99
101
  from sequence_base.constants.version import CONTRACT_VERSION
100
102
 
103
+
101
104
  from sequence_base.obs.log import Timer, enabled, log
102
105
  from sequence_base.obs.rid import HEADER, clean, new_rid
103
106
 
107
+
104
108
  from sequence_base.errors.transport import (
105
109
  TransportOverloaded,
106
110
  TransportRejected,
@@ -108,35 +112,53 @@ from sequence_base.errors.transport import (
108
112
  TransportWarming,
109
113
  )
110
114
 
115
+
111
116
  from sequence_base import auth
112
117
 
113
118
 
114
119
 
120
+
121
+
122
+
115
123
  __all__ = [
124
+
116
125
  "ImageFrame", "Proprioception", "Observation", "ActionSpace", "ActionStep", "ActionChunk",
117
126
  "ActRequest", "ActResponse",
127
+
118
128
  "SeqFlags", "ImageStepUvPip", "ImageStepApt", "ImageStepEnv", "ImageStepRun", "AddLocal", "ImageStepAddLocal",
119
129
  "ImageStep", "ImageSpec",
120
130
  "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract", "Embodiment",
121
131
  "PolicySpec", "PolicyRegistration",
132
+
122
133
  "MAX_CODE_BUNDLE_BYTES", "CodeBundle",
123
134
  "Resources", "Autoscaler", "Timeouts", "VolumeAttach", "DeploymentPolicy", "InferParam", "DeploymentRequest",
124
135
  "DeploymentAccepted", "DeploymentState", "DeploymentStatusResponse",
136
+
125
137
  "Lease", "ConnectRequest", "ConnectResponse",
138
+
126
139
  "Variant", "Conditions", "RenderSpec", "Step", "BenchmarkSpec", "BenchmarkConditionSpec", "BenchmarkRegisterRequest", "BenchmarkStatusResponse",
127
140
  "EvalRequest", "ClampInfo", "Estimate", "EvalResponse", "EvalDryRunResponse", "RolloutResult",
128
141
  "EvalStatus", "SuiteAgg", "TaskAgg", "MetricAgg", "LossyTransform", "EvalReport",
129
142
  "AdapterKind", "AdapterTransform",
130
- "SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse", "UsageReport",
143
+
144
+ "SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse",
145
+
131
146
  "VolumeFile", "VolumeUploadRequest", "UploadTarget", "VolumeUploadResponse", "VolumeInfo", "parse_vol",
147
+
132
148
  "TEMPLATE_SCHEME", "parse_template",
149
+
133
150
  "ErrorCode", "ErrorBody", "WarmingError", "ERRORS", "ErrorSpec", "code_for_status", "CONTRACT_VERSION",
151
+
134
152
  "HEADER", "new_rid", "clean", "log", "Timer", "enabled",
153
+
135
154
  "TransportUnavailable", "TransportWarming", "TransportRejected", "TransportOverloaded",
155
+
136
156
  "auth",
137
157
  ]
138
158
 
139
159
  try:
160
+
161
+
140
162
  from importlib.metadata import PackageNotFoundError, version as _version
141
163
 
142
164
  __version__ = _version("sequence-base")
@@ -16,8 +16,19 @@ import io
16
16
  from typing import Any
17
17
 
18
18
 
19
+
20
+
21
+
22
+
23
+
24
+
19
25
  DEFAULT_JPEG_QUALITY = 95
20
26
 
27
+
28
+
29
+
30
+
31
+
21
32
  MAX_UPLOAD_EDGE = 640
22
33
 
23
34
 
@@ -48,6 +59,8 @@ def encode(frame: Any, *, quality: int = DEFAULT_JPEG_QUALITY) -> str:
48
59
  img = img.convert("RGB")
49
60
  if max(img.size) > MAX_UPLOAD_EDGE:
50
61
  scale = MAX_UPLOAD_EDGE / max(img.size)
62
+
63
+
51
64
  img = img.resize((max(1, round(img.width * scale)),
52
65
  max(1, round(img.height * scale))), Image.LANCZOS)
53
66
 
@@ -72,6 +85,7 @@ def decode(data: str) -> "Any":
72
85
  return np.asarray(Image.open(io.BytesIO(raw)).convert("RGB"), dtype=np.uint8)
73
86
 
74
87
 
88
+
75
89
  _DEPTH_UNITS = {"m": 1000.0, "mm": 1.0}
76
90
 
77
91
 
@@ -79,7 +93,8 @@ def encode_depth(depth: Any, *, unit: str = "m") -> str:
79
93
  """A depth map -> the base64 16-bit PNG a depth frame (ImageFrame kind="depth") carries: millimetres as uint16, 0
80
94
  where there is no reading (NaN, inf, <= 0), clipped at 65.535 m. `unit` is what the array holds: "m" (float metres,
81
95
  the default) or "mm". Lossless, unlike the JPEG colour frames take — a depth error is a geometry error.
82
- """
96
+
97
+ """
83
98
  import numpy as np
84
99
  from PIL import Image
85
100
 
@@ -0,0 +1,30 @@
1
+ """The shared wire contract's version."""
2
+
3
+
4
+
5
+
6
+
7
+ CONTRACT_VERSION = "0.5.0"
8
+
9
+
10
+
11
+
12
+
13
+
14
+
15
+
16
+
17
+
18
+
19
+
20
+
21
+
22
+
23
+
24
+
25
+
26
+
27
+
28
+
29
+
30
+
@@ -1,7 +1,8 @@
1
1
  """
2
2
  The shared wire contract — one definition per shape, imported (never redeclared) by the SDK, gateway,
3
- and container harness. Grouped by the contract number in docs/platform/contracts.md.
3
+ and container harness. Grouped by contract number.
4
4
  """
5
+
5
6
  from sequence_base.contract.act import (
6
7
  ActionChunk,
7
8
  ActionSpace,
@@ -11,8 +12,10 @@ from sequence_base.contract.act import (
11
12
  Proprioception,
12
13
  )
13
14
 
15
+
14
16
  from sequence_base.contract.wire import ActRequest, ActResponse
15
17
 
18
+
16
19
  from sequence_base.contract.flags import SeqFlags
17
20
  from sequence_base.contract.policy import (
18
21
  Camera,
@@ -34,6 +37,7 @@ from sequence_base.contract.policy import (
34
37
  VolumeRef,
35
38
  )
36
39
 
40
+
37
41
  from sequence_base.contract.deployments import (
38
42
  MAX_CODE_BUNDLE_BYTES,
39
43
  Autoscaler,
@@ -49,8 +53,10 @@ from sequence_base.contract.deployments import (
49
53
  VolumeAttach,
50
54
  )
51
55
 
56
+
52
57
  from sequence_base.contract.connect import ConnectRequest, ConnectResponse, Lease
53
58
 
59
+
54
60
  from sequence_base.contract.benchmarks import (
55
61
  BenchmarkConditionSpec,
56
62
  BenchmarkRegisterRequest,
@@ -78,16 +84,18 @@ from sequence_base.contract.eval import (
78
84
  TaskAgg,
79
85
  )
80
86
 
87
+
81
88
  from sequence_base.contract.accounts import (
82
89
  BootstrapResponse,
83
90
  SecretCreateRequest,
84
91
  SecretInfo,
85
92
  SecretRef,
86
- UsageReport,
87
93
  )
88
94
 
95
+
89
96
  from sequence_base.contract.templates import TEMPLATE_SCHEME, parse_template
90
97
 
98
+
91
99
  from sequence_base.contract.volumes import (
92
100
  MAX_FILES,
93
101
  MAX_UPLOAD_BYTES,
@@ -100,27 +108,37 @@ from sequence_base.contract.volumes import (
100
108
  parse_vol,
101
109
  )
102
110
 
111
+
103
112
  from sequence_base.contract.errors import ERRORS, ErrorBody, ErrorCode, ErrorSpec, WarmingError, code_for_status
104
113
 
105
114
  __all__ = [
115
+
106
116
  "ImageFrame", "Proprioception", "Observation", "ActionSpace", "ActionStep", "ActionChunk",
107
117
  "ActRequest", "ActResponse",
118
+
108
119
  "SeqFlags",
109
120
  "ImageStepUvPip", "ImageStepApt", "ImageStepEnv", "ImageStepRun", "AddLocal", "ImageStepAddLocal", "ImageStep",
110
121
  "ImageSpec",
111
122
  "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract", "Embodiment",
112
123
  "PolicySpec", "PolicyRegistration",
124
+
113
125
  "MAX_CODE_BUNDLE_BYTES", "CodeBundle",
114
126
  "Resources", "Autoscaler", "Timeouts", "VolumeAttach", "DeploymentPolicy", "InferParam", "DeploymentRequest",
115
127
  "DeploymentAccepted", "DeploymentState", "DeploymentStatusResponse",
128
+
116
129
  "Lease", "ConnectRequest", "ConnectResponse",
130
+
117
131
  "Variant", "Conditions", "RenderSpec", "Step", "BenchmarkSpec", "BenchmarkConditionSpec", "BenchmarkRegisterRequest", "BenchmarkStatusResponse",
118
132
  "EvalRequest", "ClampInfo", "Estimate", "EvalResponse", "EvalDryRunResponse", "RolloutResult",
119
133
  "EvalStatus", "SuiteAgg", "TaskAgg", "MetricAgg", "LossyTransform", "EvalReport",
120
134
  "AdapterKind", "AdapterTransform",
121
- "SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse", "UsageReport",
135
+
136
+ "SecretRef", "SecretCreateRequest", "SecretInfo", "BootstrapResponse",
137
+
122
138
  "MAX_FILES", "MAX_UPLOAD_BYTES", "VolumeFile", "VolumeUploadRequest", "UploadTarget", "VolumeUploadResponse",
123
139
  "VolumeInfo", "check_volume_name", "parse_vol",
140
+
124
141
  "TEMPLATE_SCHEME", "parse_template",
142
+
125
143
  "ErrorCode", "ErrorBody", "WarmingError", "ERRORS", "ErrorSpec", "code_for_status",
126
144
  ]
@@ -1,5 +1,5 @@
1
1
  """
2
- Contract 6 — accounts / secret / billing wire types (full picture in docs/platform/accounts.md).
2
+ Contract 6 — accounts / secret / billing wire types.
3
3
 
4
4
  Secret-leak rule, mechanically checkable (goal 15). Two kinds of secret:
5
5
  (a) platform-minted — `direct_secret`, TLS private key. May appear in the DOWN direction only:
@@ -7,8 +7,7 @@ Secret-leak rule, mechanically checkable (goal 15). Two kinds of secret:
7
7
  (b) user Secret-Manager values. May appear in the WRITE direction only:
8
8
  SecretCreateRequest.env, BootstrapResponse.env (injected into the worker subprocess).
9
9
  These four fields are the entire allow-list for carrying a plaintext secret value. Everything returned
10
- to a client, reported asynchronously, or written to a report/log (SecretRef, SecretInfo, UsageReport,
11
- eval report, /act response) exposes only names / env_keys — never a value-bearing field.
10
+ to a client or written to a report/log (SecretRef, SecretInfo, eval report, /act response) exposes only names / env_keys — never a value-bearing field.
12
11
  """
13
12
  from __future__ import annotations
14
13
 
@@ -23,7 +22,6 @@ __all__ = [
23
22
  "SecretCreateRequest",
24
23
  "SecretInfo",
25
24
  "BootstrapResponse",
26
- "UsageReport",
27
25
  ]
28
26
 
29
27
 
@@ -40,6 +38,8 @@ class SecretCreateRequest(BaseModel):
40
38
  """POST /v1/secrets — one name = one group of env values (e.g. planner = {PLANNER_API_KEY}).
41
39
  `env` carries plaintext values; this is the WRITE-direction allow-list field (goal 15)."""
42
40
 
41
+
42
+
43
43
  model_config = ConfigDict(extra="forbid", hide_input_in_errors=True)
44
44
 
45
45
  name: str
@@ -49,6 +49,10 @@ class SecretCreateRequest(BaseModel):
49
49
  class SecretInfo(BaseModel):
50
50
  """GET /v1/secrets element — metadata only, NO values. Exposes `env_keys`, not `env`."""
51
51
 
52
+
53
+
54
+
55
+
52
56
  model_config = ConfigDict(extra="forbid", hide_input_in_errors=True)
53
57
 
54
58
  name: str
@@ -61,24 +65,14 @@ class BootstrapResponse(BaseModel):
61
65
  """What a worker receives when it starts — everything it needs to serve direct TLS `/act`. `direct_secret` + `tls_key` are DOWN-direction platform secrets; `env` is the
62
66
  WRITE-direction injection of the policy's declared user secrets into its subprocess (goal 15)."""
63
67
 
68
+
69
+
64
70
  model_config = ConfigDict(extra="forbid", hide_input_in_errors=True)
65
71
 
66
72
  direct_secret: str = Field(..., description="Platform-minted bearer the worker's guard checks")
67
73
  tls_key: str = Field(..., description="Self-signed TLS private key (down-direction platform secret)")
68
74
  tls_cert: str = Field(..., description="Self-signed TLS certificate (public)")
69
75
  env: dict[str, str] = Field(..., description="Policy's user secrets, expanded ENV_KEY → value")
76
+
70
77
  weights_uri: str | None = None
71
78
  lease: Lease
72
-
73
-
74
- class UsageReport(BaseModel):
75
- """A worker's metering report, sent as it serves. Carries counts only, no secrets.
76
- This usage shape is defined here (sequence-base) once, so gateway and worker cannot drift."""
77
-
78
- model_config = ConfigDict(extra="forbid")
79
-
80
- deployment_id: str
81
- window_start: datetime
82
- window_end: datetime
83
- requests: int
84
- controlled_seconds: float
@@ -60,6 +60,10 @@ class RenderSpec(BaseModel):
60
60
 
61
61
  camera: str = Field(..., description="Which camera to pull frames from, e.g. 'wrist' / 'agentview'")
62
62
  fps: int = 30
63
+
64
+
65
+
66
+
63
67
  flip: Literal["vertical", "horizontal", "both"] | None = Field(
64
68
  None, description="'vertical': rows reversed (upside down); 'horizontal': mirrored; 'both': turned 180°; "
65
69
  "None: as drawn")
@@ -99,16 +103,20 @@ class BenchmarkSpec(BaseModel):
99
103
  handler_ref: str
100
104
  bindings: dict[SeqFlags, str] = Field(..., description="SETUP / RESET / CHECK / SCORE (+ OBSERVE / STEP) → method name")
101
105
  gpu: str | list[str] | None = None
106
+
102
107
  envs: int | None = Field(default=None, ge=1, le=65536)
103
108
  assets: list[VolumeRef] = Field(default_factory=list)
104
109
  render: RenderSpec | None = None
105
110
  cpu: int | None = None
106
111
  memory_gb: int | None = None
107
112
  secrets: list[SecretRef] = Field(default_factory=list)
113
+
108
114
  engine: str | None = Field(default=None, pattern=KIND_NAME)
109
115
 
110
116
  @model_validator(mode="after")
111
117
  def _bindings_only_benchmark_hooks(self) -> "BenchmarkSpec":
118
+
119
+
112
120
  bad = set(self.bindings) - set(BENCHMARK_BINDABLE)
113
121
  if bad:
114
122
  names = ", ".join(sorted(f.name or str(f.value) for f in bad))
@@ -152,19 +160,43 @@ class BenchmarkRegisterRequest(BaseModel):
152
160
  render: RenderSpec | None = None
153
161
  cpu: int | None = None
154
162
  memory_gb: int | None = None
163
+
164
+
155
165
  code: CodeBundle | None = None
166
+
167
+
156
168
  suite_of: dict[str, str] = Field(default_factory=dict)
169
+
170
+
157
171
  action_contract: ActionContract | None = None
172
+
173
+
158
174
  secrets: list[SecretRef] = Field(default_factory=list)
175
+
176
+
159
177
  score: bool = False
178
+
179
+
160
180
  condition_list: list[BenchmarkConditionSpec] | None = Field(default=None, max_length=5000)
181
+
161
182
  timeout_s: float | None = Field(default=None, gt=0)
183
+
162
184
  default_adapter_ref: str | None = None
185
+
186
+
163
187
  gpu: str | None = Field(default=None, max_length=32)
188
+
164
189
  envs: int | None = Field(default=None, ge=1, le=65536)
190
+
191
+
192
+
165
193
  params: dict[str, InferParam] | None = Field(default=None, max_length=32)
194
+
166
195
  batched: bool = False
196
+
167
197
  image_context: CodeBundle | None = None
198
+
199
+
168
200
  engine: str | None = Field(default=None, pattern=KIND_NAME)
169
201
 
170
202
  @model_validator(mode="after")
@@ -13,6 +13,7 @@ from datetime import datetime
13
13
 
14
14
  from pydantic import BaseModel, ConfigDict, Field
15
15
 
16
+
16
17
  from sequence_base.contract.errors import WarmingError
17
18
  from sequence_base.contract.io import ActionContract, ObservationContract
18
19
 
@@ -50,9 +51,9 @@ class ConnectResponse(BaseModel):
50
51
  cert_fingerprint: str = Field(..., description="Self-signed cert fingerprint the SDK pins")
51
52
  direct_secret: str = Field(..., description="Bearer for the worker /act; valid within the lease")
52
53
  lease: Lease
53
- warming: bool = Field(default=False, description="True → worker still warming; see warming_eta_s")
54
- warming_eta_s: int | None = Field(default=None, description="Seconds until warm, when warming")
54
+
55
55
  action: ActionContract | None = None
56
56
  observation: ObservationContract | None = None
57
57
  embodiment: str | None = None
58
+
58
59
  io: str | None = None
@@ -21,8 +21,6 @@ from typing import Literal
21
21
  from pydantic import BaseModel, ConfigDict, Field, field_validator, model_validator
22
22
 
23
23
  from sequence_base.contract.accounts import SecretRef
24
- from sequence_base.contract.templates import TEMPLATE_SCHEME, parse_template
25
- from sequence_base.contract.volumes import VOL_SCHEME, parse_vol
26
24
  from sequence_base.contract.io import Embodiment, ObservationContract
27
25
  from sequence_base.contract.policy import (
28
26
  KIND_NAME,
@@ -53,10 +51,15 @@ class Resources(BaseModel):
53
51
  model_config = ConfigDict(extra="forbid")
54
52
 
55
53
  gpu: list[str]
54
+
55
+
56
+
56
57
  cpu: float | None = Field(default=None, ge=0.125, le=64)
57
58
  cpu_limit: float | None = Field(default=None, ge=0.125, le=128)
58
59
  memory_gb: float | None = Field(default=None, ge=0.125, le=1024)
59
60
  memory_limit_gb: float | None = Field(default=None, ge=0.125, le=1024)
61
+
62
+
60
63
  region: str | None = Field(default=None, max_length=32)
61
64
 
62
65
  @model_validator(mode="after")
@@ -73,10 +76,16 @@ class Autoscaler(BaseModel):
73
76
  model_config = ConfigDict(extra="forbid")
74
77
 
75
78
  min_containers: int = 0
79
+
80
+
76
81
  max_containers: int | None = None
82
+
83
+
77
84
  max_gpus: int | None = Field(default=None, ge=1, le=256)
78
85
  buffer_containers: int | None = None
79
86
  scaledown_window: int = 600
87
+
88
+
80
89
  on_full: Literal["queue", "reject"] = "queue"
81
90
  queue_timeout_s: int = Field(default=120, ge=5, le=3600)
82
91
 
@@ -160,9 +169,9 @@ class DeploymentPolicy(BaseModel):
160
169
  to nothing and its inputs / outputs pass through the worker untouched.
161
170
 
162
171
  `secrets` carries the policy's declared secret BUNDLES BY NAME ONLY (list[SecretRef]) — the gateway
163
- validates each name exists and belongs to the deployer at submit time (accounts ⑦ / S3 goal 14), and the
172
+ validates each name exists and belongs to the deployer at submit time, and the
164
173
  worker bootstrap fetches the matching env group by name. A secret VALUE never travels here: SecretRef is
165
- name-only, so this field cannot carry one (S3 goal 15). Defaults to `[]` so a policy with no secrets is
174
+ name-only, so this field cannot carry one. Defaults to `[]` so a policy with no secrets is
166
175
  unaffected."""
167
176
 
168
177
  model_config = ConfigDict(extra="forbid")
@@ -172,12 +181,28 @@ class DeploymentPolicy(BaseModel):
172
181
  streaming: bool = False
173
182
  frames_per_chunk: int | None = None
174
183
  secrets: list[SecretRef] = Field(default_factory=list)
184
+
185
+
175
186
  observation: ObservationContract | None = None
176
187
  embodiments: dict[str, Embodiment] | None = None
188
+
189
+
190
+
191
+
177
192
  action_declared: bool | None = None
193
+
194
+
178
195
  io: str | None = Field(default=None, max_length=4000)
196
+
197
+
179
198
  family: str | None = Field(default=None, pattern=KIND_NAME)
199
+
200
+
180
201
  params: dict[str, InferParam] | None = Field(default=None, max_length=32)
202
+
203
+
204
+
205
+
181
206
  models: list[str] | None = Field(default=None, max_length=16)
182
207
 
183
208
  @model_validator(mode="after")
@@ -185,6 +210,7 @@ class DeploymentPolicy(BaseModel):
185
210
  for name in self.params or {}:
186
211
  if not name.isidentifier() or name.startswith("_"):
187
212
  raise ValueError(f"inference parameter {name!r} is not a public Python identifier")
213
+
188
214
  for model in self.models or []:
189
215
  if not model or model != model.strip() or "/" not in model:
190
216
  raise ValueError(f"policy model {model!r} is not a catalogue id (accounts/sequences/models/<name>)")
@@ -240,15 +266,26 @@ class DeploymentRequest(BaseModel):
240
266
 
241
267
  name: str
242
268
  image: ImageSpec
269
+
243
270
  weights: VolumeMount | None = None
244
271
  resources: Resources
245
272
  policy: DeploymentPolicy
273
+
274
+
246
275
  code: CodeBundle | None = None
276
+
277
+
247
278
  image_context: CodeBundle | None = None
279
+
280
+
248
281
  volumes: list[VolumeAttach] = Field(default_factory=list)
249
282
  autoscaler: Autoscaler = Field(default_factory=Autoscaler)
283
+
250
284
  concurrency: Concurrency = Field(default_factory=Concurrency)
251
285
  timeouts: Timeouts | None = None
286
+
287
+
288
+
252
289
  weights_name: str | None = None
253
290
  extra_weights: dict[str, VolumeMount] | None = None
254
291
 
@@ -265,9 +302,10 @@ class DeploymentRequest(BaseModel):
265
302
 
266
303
  @model_validator(mode="after")
267
304
  def _weights_have_an_origin(self) -> "DeploymentRequest":
268
- """The checkpoint the build provisions: an official template://, an hf:// repo or an uploaded vol:// volume —
269
- and, until they are removed, a gs:// or s3:// prefix or an https:// file — never empty. PolicySpec already enforces this for SDK-authored deploys; this holds it for any POSTed body."""
270
- from sequence_base.contract.policy import check_weights_parts
305
+ """The checkpoint the build provisions, when there is one: an official template://, an hf:// repo or an
306
+ uploaded vol:// volume, never empty. PolicySpec already enforces this for SDK-authored deploys; this holds it
307
+ for any POSTed body."""
308
+ from sequence_base.contract.policy import check_weights_parts, check_weights_uri
271
309
 
272
310
  if self.weights is None:
273
311
  if self.weights_name or self.extra_weights:
@@ -276,22 +314,12 @@ class DeploymentRequest(BaseModel):
276
314
  check_weights_parts(self.weights_name, dict(self.extra_weights or {}))
277
315
  for what, ref in [("weights.uri", self.weights)] + [(f"extra_weights[{n!r}].uri", r)
278
316
  for n, r in (self.extra_weights or {}).items()]:
279
- uri = ref.uri.strip()
280
- if uri.startswith(TEMPLATE_SCHEME):
281
- parse_template(uri)
282
- continue
283
- if uri.startswith(VOL_SCHEME):
284
- parse_vol(uri)
285
- continue
286
- if not any(uri.startswith(s) and len(uri) > len(s) for s in _WEIGHTS_SCHEMES):
287
- raise ValueError(f"{what} must be a template://<name> official template, an hf://org/model repo or "
288
- "a vol://<name> volume (gs://, s3:// and https:// are still accepted until they "
289
- "are removed)")
317
+ check_weights_uri(ref.uri.strip(), what)
290
318
  return self
291
319
 
292
320
 
321
+
293
322
  _NAME = re.compile(r"[A-Za-z0-9][A-Za-z0-9._-]{0,63}")
294
- _WEIGHTS_SCHEMES = ("gs://", "hf://", "s3://", "https://")
295
323
 
296
324
 
297
325
  class DeploymentAccepted(BaseModel):
@@ -320,4 +348,5 @@ class DeploymentStatusResponse(BaseModel):
320
348
  status: DeploymentState
321
349
  model: str
322
350
  error: str | None = Field(default=None, description="Build-failure reason; set only when FAILED")
351
+
323
352
  reason: Literal["gpu_out_of_memory", "host_out_of_memory", "crashed"] | None = None
@@ -7,6 +7,7 @@ the `seq` CLI exit code. The gateway and the worker harness import it; the SDK,
7
7
  this package on a robot, carries a generated copy that a test compares against `ErrorCodes.json`.
8
8
  That is what makes the same situation surface the same way at every entry point.
9
9
 
10
+
10
11
  Distinct from `sequence_base.errors.transport`, which is the internal exception taxonomy the gateway
11
12
  and harness raise before a response is built.
12
13
  """
@@ -48,6 +49,8 @@ class ErrorSpec(NamedTuple):
48
49
  exit_code: int
49
50
 
50
51
 
52
+
53
+
51
54
  ERRORS: dict[ErrorCode, ErrorSpec] = {
52
55
  ErrorCode.INVALID_REQUEST: ErrorSpec(400, False, "InvalidRequest", 2),
53
56
  ErrorCode.PAYLOAD_TOO_LARGE: ErrorSpec(413, False, "InvalidRequest", 2),
@@ -68,6 +71,7 @@ ERRORS: dict[ErrorCode, ErrorSpec] = {
68
71
  ErrorCode.DEPENDENCY_MISSING: ErrorSpec(424, False, "InternalError", 1),
69
72
  }
70
73
 
74
+
71
75
  _CODE_FOR_STATUS: dict[int, ErrorCode] = {
72
76
  400: ErrorCode.INVALID_REQUEST, 401: ErrorCode.UNAUTHENTICATED, 402: ErrorCode.INSUFFICIENT_CREDIT,
73
77
  403: ErrorCode.FORBIDDEN, 404: ErrorCode.NOT_FOUND, 405: ErrorCode.INVALID_REQUEST,
@@ -103,15 +107,10 @@ class ErrorBody(BaseModel):
103
107
  @model_validator(mode="before")
104
108
  @classmethod
105
109
  def _retryable_from_table(cls, data: Any) -> Any:
110
+
111
+
106
112
  if not isinstance(data, dict):
107
113
  return data
108
- if "message" in data and "detail" not in data:
109
- data = {k: v for k, v in data.items() if k != "message"} | {"detail": data["message"]}
110
- if "eta_s" in data:
111
- eta = data["eta_s"]
112
- data = {k: v for k, v in data.items() if k != "eta_s"}
113
- if eta is not None:
114
- data["details"] = {**data.get("details", {}), "eta_s": eta}
115
114
  code = data.get("code")
116
115
  if code is None:
117
116
  default = cls.model_fields["code"].default