sequence-base 0.4.31__tar.gz → 0.4.33__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 (127) hide show
  1. {sequence_base-0.4.31 → sequence_base-0.4.33}/PKG-INFO +1 -1
  2. {sequence_base-0.4.31 → sequence_base-0.4.33}/pyproject.toml +1 -1
  3. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/__init__.py +2 -6
  4. sequence_base-0.4.33/sequence_base/by_name.py +175 -0
  5. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/constants/version.py +2 -1
  6. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/__init__.py +1 -2
  7. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/connect.py +12 -5
  8. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/deployments.py +11 -9
  9. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/io.py +3 -4
  10. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/own_io.py +1 -1
  11. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/policy.py +10 -9
  12. sequence_base-0.4.33/sequence_base/contract/retired.py +22 -0
  13. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/wire.py +9 -9
  14. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/presets/robot_arm.py +1 -10
  15. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schema_export.py +0 -2
  16. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ActRequest.json +1 -28
  17. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ActResponse.json +1 -1
  18. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ActionChunk.json +1 -1
  19. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ActionContract.json +1 -1
  20. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ActionStep.json +1 -1
  21. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Actions.json +1 -1
  22. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/AdapterPair.json +1 -1
  23. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/AddLocal.json +1 -1
  24. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Autoscaler.json +1 -1
  25. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/BenchmarkConditionSpec.json +1 -1
  26. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/BenchmarkRegisterRequest.json +1 -1
  27. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/BenchmarkSpec.json +2 -2
  28. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/BenchmarkStatusResponse.json +1 -1
  29. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/BootstrapResponse.json +1 -1
  30. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Camera.json +1 -1
  31. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/CodeBundle.json +1 -1
  32. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Concurrency.json +1 -1
  33. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Conditions.json +1 -1
  34. sequence_base-0.4.33/sequence_base/schemas/ConnectRequest.json +16 -0
  35. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ConnectResponse.json +1 -25
  36. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/DeploymentAccepted.json +1 -1
  37. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/DeploymentPolicy.json +2 -59
  38. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/DeploymentRequest.json +2 -59
  39. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/DeploymentStatusResponse.json +1 -1
  40. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ErrorBody.json +1 -1
  41. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ErrorCodes.json +1 -1
  42. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Estimate.json +1 -1
  43. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/EvalDryRunResponse.json +1 -1
  44. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/EvalReport.json +1 -1
  45. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/EvalRequest.json +1 -1
  46. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/EvalResponse.json +1 -1
  47. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageFrame.json +1 -1
  48. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageSpec.json +1 -1
  49. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepAddLocal.json +1 -1
  50. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepApt.json +1 -1
  51. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepEnv.json +1 -1
  52. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepProject.json +1 -1
  53. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepRun.json +1 -1
  54. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepTemplateFiles.json +1 -1
  55. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ImageStepUvPip.json +1 -1
  56. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/InferParam.json +1 -1
  57. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Lease.json +1 -1
  58. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/MetricAgg.json +1 -1
  59. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Observation.json +1 -1
  60. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ObservationContract.json +1 -1
  61. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Observations.json +1 -1
  62. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ObserveRequest.json +1 -1
  63. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ObserveResponse.json +1 -1
  64. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/PolicyRegistration.json +3 -60
  65. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/PolicySpec.json +2 -59
  66. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Project.json +1 -1
  67. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Proprioception.json +1 -1
  68. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/RenderSpec.json +1 -1
  69. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/ReplaySpec.json +1 -1
  70. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Resources.json +1 -1
  71. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/RolloutResult.json +1 -1
  72. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/SecretCreateRequest.json +1 -1
  73. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/SecretInfo.json +1 -1
  74. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/SecretRef.json +1 -1
  75. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/SeqFlags.json +1 -1
  76. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Step.json +1 -1
  77. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Stream.json +1 -1
  78. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/TaskAgg.json +1 -1
  79. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/TemplateFiles.json +1 -1
  80. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Tensors.json +1 -1
  81. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Timeouts.json +1 -1
  82. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/UploadTarget.json +1 -1
  83. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/Variant.json +1 -1
  84. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeFile.json +1 -1
  85. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeInfo.json +1 -1
  86. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeMount.json +1 -1
  87. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeRef.json +1 -1
  88. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeUploadRequest.json +1 -1
  89. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/VolumeUploadResponse.json +1 -1
  90. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/schemas/WarmingError.json +1 -1
  91. sequence_base-0.4.31/sequence_base/by_name.py +0 -90
  92. sequence_base-0.4.31/sequence_base/feedback.py +0 -106
  93. sequence_base-0.4.31/sequence_base/schemas/ConnectRequest.json +0 -29
  94. sequence_base-0.4.31/sequence_base/schemas/Embodiment.json +0 -301
  95. {sequence_base-0.4.31 → sequence_base-0.4.33}/.gitignore +0 -0
  96. {sequence_base-0.4.31 → sequence_base-0.4.33}/README.md +0 -0
  97. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/auth.py +0 -0
  98. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/codec/__init__.py +0 -0
  99. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/codec/image.py +0 -0
  100. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/codec/marked.py +0 -0
  101. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/constants/__init__.py +0 -0
  102. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/constants/cards.py +0 -0
  103. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/constants/headers.py +0 -0
  104. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/constants/limits.py +0 -0
  105. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/construct.py +0 -0
  106. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/accounts.py +0 -0
  107. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/act.py +0 -0
  108. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/adapters.py +0 -0
  109. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/benchmarks.py +0 -0
  110. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/errors.py +0 -0
  111. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/eval.py +0 -0
  112. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/flags.py +0 -0
  113. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/obs_schedule.py +0 -0
  114. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/observe.py +0 -0
  115. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/templates.py +0 -0
  116. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/contract/volumes.py +0 -0
  117. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/episode.py +0 -0
  118. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/errors/__init__.py +0 -0
  119. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/errors/transport.py +0 -0
  120. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/msgpack_io.py +0 -0
  121. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/obs/__init__.py +0 -0
  122. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/obs/log.py +0 -0
  123. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/obs/rid.py +0 -0
  124. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/presets/__init__.py +0 -0
  125. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/presets/frames.py +0 -0
  126. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/telemetry/__init__.py +0 -0
  127. {sequence_base-0.4.31 → sequence_base-0.4.33}/sequence_base/telemetry/events.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: sequence-base
3
- Version: 0.4.31
3
+ Version: 0.4.33
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
  Project-URL: Changelog, https://generalsequences.com/docs/changelog/
6
6
  Requires-Python: >=3.10
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "sequence-base"
3
- version = "0.4.31"
3
+ version = "0.4.33"
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"]
@@ -24,7 +24,6 @@ from sequence_base.contract import (
24
24
  Project,
25
25
  ImageStepProject,
26
26
  Camera,
27
- Embodiment,
28
27
  ObservationContract,
29
28
  ObserveFrame,
30
29
  ObserveRequest,
@@ -130,9 +129,6 @@ from sequence_base.errors.transport import (
130
129
  from sequence_base.episode import Episode
131
130
 
132
131
 
133
- from sequence_base.feedback import Feedback
134
-
135
-
136
132
  from sequence_base import auth
137
133
 
138
134
 
@@ -148,7 +144,7 @@ __all__ = [
148
144
 
149
145
  "SeqFlags", "ImageStepUvPip", "ImageStepApt", "ImageStepEnv", "ImageStepRun", "AddLocal", "ImageStepAddLocal",
150
146
  "FROZEN_PATH", "TemplateFiles", "ImageStepTemplateFiles", "Project", "ImageStepProject", "ImageStep", "ImageSpec",
151
- "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract", "Embodiment",
147
+ "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract",
152
148
  "PolicySpec", "PolicyRegistration", "PolicyConstructor",
153
149
  "Observations", "Stream", "Actions", "Tensors",
154
150
 
@@ -177,7 +173,7 @@ __all__ = [
177
173
 
178
174
  "TransportUnavailable", "TransportWarming", "TransportRejected", "TransportOverloaded",
179
175
 
180
- "Episode", "Feedback",
176
+ "Episode",
181
177
 
182
178
  "auth",
183
179
  ]
@@ -0,0 +1,175 @@
1
+ """
2
+ Which arguments of a method a policy class names (infer=, observe=) an act's inputs fill: the inputs whole, its one
3
+ argument - or, when it takes two or more without a default, each key of the inputs to its argument of that name.
4
+
5
+ In one sentence: `takes_by_name(parameters, platform)` reads the method's arguments - less *args, **kwargs and the ones
6
+ the platform hands it itself (`platform`: INFER_PLATFORM, OBSERVE_PLATFORM) → two or more of them without a default:
7
+ it takes its inputs by name (ByName), each of its arguments a key - one without a default a key the inputs must hold,
8
+ one with a default a key they may → `ByName.call(inputs, what)` makes what it is called with, refusing inputs that are
9
+ no dict, lack a key it needs, or hold one it takes no argument for (unless it takes **kwargs), each named; fewer than
10
+ two: None, the inputs go to its first argument whole and its others with a default are inference parameters, as before.
11
+
12
+ WHY by the arguments without a default: a method that needs two or more could never be handed an act's inputs whole -
13
+ the platform refused to deploy one - so binding them by name changes nothing a class deployed today does, and a method
14
+ that takes one beside its inference parameters keeps taking its inputs whole. The SDK reads the rule when a class is
15
+ declared (seq/named.py, registry.infer_params), the worker when it calls the method (harness/handler/loader.py): one
16
+ rule on both sides.
17
+
18
+ What the platform hands a method itself is `episode` - an act function, an observe function and the method an
19
+ episode's end calls alike - and an eval's `seed`; `retired(parameters, what)` refuses a method that still takes what it
20
+ handed once (episode_id, embodiment, feedback, and a composite's plan and robot), and `ends(parameters, what)` an end
21
+ method that takes anything but the episode, each in words that say what to write instead - the SDK when a class is
22
+ declared, the worker when it loads one declared before.
23
+
24
+
25
+ A composite's planner, @seq.plan, is called on a clock with the episode alone and what it returns is kept in the
26
+ episode's state, which the act function beside it reads: `plan_refused(plan, infer_takes_episode=...)` says why a plan
27
+ method cannot be served as it is written, and `wake_on_refused(value)` why a wake_on is no list of keys - one set of
28
+ words for the SDK and the worker.
29
+ """
30
+ from __future__ import annotations
31
+
32
+ import inspect
33
+ from collections.abc import Iterable, Mapping
34
+ from dataclasses import dataclass
35
+ from typing import Any
36
+
37
+ __all__ = ["INFER_PLATFORM", "OBSERVE_PLATFORM", "RETIRED", "WAKE_ON", "ByName", "ends", "plan_refused", "retired",
38
+ "takes_by_name", "wake_on_refused"]
39
+
40
+
41
+
42
+ INFER_PLATFORM = frozenset({"seed", "episode"})
43
+ OBSERVE_PLATFORM = frozenset({"step", "episode"})
44
+
45
+
46
+ RETIRED = {"episode_id": "take episode, a seq.Episode, and read episode.id",
47
+ "embodiment": "send what the robot is with its observations, in observe(x)",
48
+ "feedback": "send what the robot was playing with its observations, in observe(x)",
49
+
50
+ "plan": ('take episode and read the newest plan as episode.state["seq.plans"][-1]["value"], what '
51
+ '@seq.plan returned (before the first, episode.state.get("seq.plans") is None)'),
52
+ "robot": ("take episode: episode.state is the robot's own dict, which @seq.plan is handed too, and "
53
+ "episode.id names it")}
54
+
55
+ WAKE_ON = ('@seq.plan(wake_on=...) is a list of the observation\'s keys whose arrival plans at once, each a string - '
56
+ 'wake_on=["say"]: an observation that holds "say" plans its episode then, its clock going on beside')
57
+
58
+ _VARIADIC = (inspect.Parameter.VAR_POSITIONAL, inspect.Parameter.VAR_KEYWORD)
59
+
60
+
61
+ @dataclass(frozen=True)
62
+ class ByName:
63
+ """A method that takes an act's inputs by name: `names`, the arguments they fill, in order; `required`, those with
64
+ no default; `positional`, those it takes by position only (before a `/`); `rest`, whether it takes **kwargs - any
65
+ other key of the inputs going there; `platform`, the names the platform hands it itself."""
66
+
67
+ names: tuple[str, ...]
68
+ required: tuple[str, ...]
69
+ positional: tuple[str, ...]
70
+ rest: bool
71
+ platform: frozenset[str]
72
+
73
+ def call(self, inputs: Any, what: str) -> tuple[list, dict]:
74
+ """(args, kwargs) the method `what` ("Model.predict") is called with for an act's `inputs`; ValueError, in its
75
+ words, for inputs that are not a dict of its arguments."""
76
+ takes = ", ".join(n if n in self.required else f"{n} (optional)" for n in self.names) or "none of them"
77
+ if not isinstance(inputs, Mapping):
78
+ raise ValueError(f"{what} takes its inputs by name ({takes}): an act's inputs are a dict of them, and "
79
+ f"these are a {type(inputs).__name__}")
80
+ missing = [n for n in self.required if n not in inputs]
81
+ extra = [k for k in inputs if k not in self.names
82
+ and not (self.rest and isinstance(k, str) and k not in self.platform)]
83
+ if missing or extra:
84
+ held = f"lack {_keys(missing)}" if missing else ""
85
+ if extra:
86
+ held += (" and " if held else "") + f"hold {_keys(extra)}, which it takes no argument for"
87
+ ours = [k for k in extra if k in self.platform]
88
+ mine = f" ({_keys(ours)}: the platform's to hand it)" if ours else ""
89
+ raise ValueError(f"{what} takes its inputs by name ({takes}), and these {held}{mine}")
90
+ args: list = []
91
+ for i, name in enumerate(self.positional):
92
+ if name not in inputs:
93
+ later = next((n for n in self.positional[i + 1:] if n in inputs), None)
94
+ if later is not None:
95
+ raise ValueError(f"{what} takes {name} and {later} by position only, in that order: these hold "
96
+ f"{later!r} and no {name!r}")
97
+ break
98
+ args.append(inputs[name])
99
+ return args, {k: v for k, v in inputs.items() if k not in self.positional}
100
+
101
+
102
+ def takes_by_name(parameters: Iterable[inspect.Parameter], platform: frozenset[str] = frozenset(), *,
103
+ always: bool = False) -> ByName | None:
104
+ """How a method of these `parameters` (self left out) takes an act's inputs: by name (ByName) when two or more of
105
+ its arguments - *args, **kwargs and `platform`'s left out - have no default, else None: whole, as one argument.
106
+ `always`: by name however many it takes - an infer= beside observe=, handed an act's arguments alone (plan3.5/92)."""
107
+ every = list(parameters)
108
+ params = [p for p in every if p.kind not in _VARIADIC and p.name not in platform]
109
+ required = tuple(p.name for p in params if p.default is inspect.Parameter.empty)
110
+ if len(required) < 2 and not always:
111
+ return None
112
+ return ByName(names=tuple(p.name for p in params), required=required,
113
+ positional=tuple(p.name for p in params if p.kind is inspect.Parameter.POSITIONAL_ONLY),
114
+ rest=any(p.kind is inspect.Parameter.VAR_KEYWORD for p in every), platform=frozenset(platform))
115
+
116
+
117
+ def retired(parameters: Iterable[inspect.Parameter], what: str) -> str | None:
118
+ """Why `what` ("Model.infer"), a method the platform calls, cannot be deployed: it takes what the platform no longer
119
+ hands it (RETIRED), said with what to write instead - or None, when it takes none of it."""
120
+ names = [p.name for p in parameters if p.name in RETIRED]
121
+ if not names:
122
+ return None
123
+ return (f"{what} takes {' and '.join(names)}, which the platform no longer hands it: "
124
+ + "; ".join(RETIRED[n] for n in names))
125
+
126
+
127
+ def ends(parameters: Iterable[inspect.Parameter], what: str) -> str | None:
128
+ """Why `what` ("Model.end"), the method an episode's end calls (@seq.on_episode), cannot be deployed: an episode's
129
+ end hands it the episode alone, so it takes `episode` or nothing - any other argument with a default, never one
130
+ the platform no longer hands (RETIRED) - or None, when it does."""
131
+ taken = [p.name for p in parameters if p.kind not in _VARIADIC
132
+ and (p.name in RETIRED or (p.name != "episode" and p.default is inspect.Parameter.empty))]
133
+ if not taken:
134
+ return None
135
+ name = what.rsplit(".", 1)[-1]
136
+ return (f"{what} takes {' and '.join(taken)}: an episode's end hands it the episode alone - write "
137
+ f"def {name}(self, episode) and read its id as episode.id, or def {name}(self)")
138
+
139
+
140
+ def _keys(names: list) -> str:
141
+ return ", ".join(repr(n) for n in names)
142
+
143
+
144
+ def plan_refused(plan: Any, *, infer_takes_episode: bool) -> str | None:
145
+ """Why `plan`, a policy's @seq.plan method, cannot be served as it is written - or None, when it can: it is called on
146
+ a clock with the episode alone, plain or async, returning (never yielding) what is kept in the episode's state for
147
+ the act function beside it, which must take the episode to read it.
148
+ """
149
+ name = getattr(plan, "__name__", "plan")
150
+ if inspect.isgeneratorfunction(plan) or inspect.isasyncgenfunction(plan):
151
+ return (f"@seq.plan {name} returns its plan rather than yielding it: return the value, which is kept in "
152
+ 'episode.state["seq.plans"] (None keeps the plans as they are)')
153
+ try:
154
+ params = inspect.signature(plan).parameters
155
+ except (TypeError, ValueError):
156
+ params = {}
157
+ others = [n for n, p in params.items()
158
+ if n not in ("self", "episode") and p.default is inspect.Parameter.empty and p.kind not in _VARIADIC]
159
+ if "episode" not in params or others:
160
+ return (f"@seq.plan is handed the episode alone: write def {name}(self, episode) - read what it needs from "
161
+ 'episode.state, and return the plan, which is kept in episode.state["seq.plans"] (None keeps the plans '
162
+ "as they are)")
163
+ if not infer_takes_episode:
164
+ return ("a policy with @seq.plan reads its plans where its act function runs: take episode in it and read "
165
+ 'episode.state["seq.plans"][-1]["value"]')
166
+ return None
167
+
168
+
169
+ def wake_on_refused(value: Any) -> str | None:
170
+ """Why `value` cannot be a @seq.plan's wake_on - the observation's top-level keys whose arrival plans an episode at
171
+ once - or None, when it can: a list (or tuple) of strings, or None for none.
172
+ """
173
+ if value is None or (isinstance(value, (list, tuple)) and all(isinstance(k, str) for k in value)):
174
+ return None
175
+ return WAKE_ON
@@ -4,7 +4,8 @@
4
4
 
5
5
 
6
6
 
7
- CONTRACT_VERSION = "0.5.28"
7
+ CONTRACT_VERSION = "0.5.29"
8
+
8
9
 
9
10
 
10
11
 
@@ -21,7 +21,6 @@ from sequence_base.contract.observe import ObserveFrame, ObserveRequest, Observe
21
21
  from sequence_base.contract.flags import SeqFlags
22
22
  from sequence_base.contract.policy import (
23
23
  Camera,
24
- Embodiment,
25
24
  ObservationContract,
26
25
  ActionContract,
27
26
  Concurrency,
@@ -129,7 +128,7 @@ __all__ = [
129
128
  "SeqFlags",
130
129
  "ImageStepUvPip", "ImageStepApt", "ImageStepEnv", "ImageStepRun", "AddLocal", "ImageStepAddLocal",
131
130
  "TemplateFiles", "ImageStepTemplateFiles", "Project", "ImageStepProject", "FROZEN_PATH", "ImageStep", "ImageSpec",
132
- "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract", "Embodiment",
131
+ "VolumeMount", "VolumeRef", "Concurrency", "ActionContract", "Camera", "ObservationContract",
133
132
  "PolicySpec", "PolicyRegistration", "PolicyConstructor",
134
133
  "Observations", "Stream", "Actions", "Tensors",
135
134
 
@@ -10,13 +10,15 @@ and the warming ETA are typed and checkable.
10
10
  from __future__ import annotations
11
11
 
12
12
  from datetime import datetime
13
+ from typing import Any
13
14
 
14
- from pydantic import BaseModel, ConfigDict, Field
15
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
15
16
 
16
17
 
17
18
  from sequence_base.contract.errors import WarmingError
18
19
  from sequence_base.contract.io import ActionContract, ObservationContract
19
20
  from sequence_base.contract.own_io import Actions, Observations
21
+ from sequence_base.contract.retired import dropped
20
22
 
21
23
  __all__ = ["Lease", "ConnectRequest", "ConnectResponse", "WarmingError"]
22
24
 
@@ -37,7 +39,11 @@ class ConnectRequest(BaseModel):
37
39
  model_config = ConfigDict(extra="forbid")
38
40
 
39
41
  model: str = Field(..., description="Deployment name to connect to")
40
- embodiment: str | None = Field(default=None, description="Which declared embodiment this session drives")
42
+
43
+ @model_validator(mode="before")
44
+ @classmethod
45
+ def _retired(cls, data: Any) -> Any:
46
+ return dropped(data, "embodiment")
41
47
 
42
48
 
43
49
  class ConnectResponse(BaseModel):
@@ -55,7 +61,6 @@ class ConnectResponse(BaseModel):
55
61
 
56
62
  action: ActionContract | None = None
57
63
  observation: ObservationContract | None = None
58
- embodiment: str | None = None
59
64
 
60
65
  io: str | None = None
61
66
 
@@ -63,5 +68,7 @@ class ConnectResponse(BaseModel):
63
68
  observations: Observations | None = None
64
69
  actions: Actions | None = None
65
70
 
66
-
67
- feedback: bool | None = None
71
+ @model_validator(mode="before")
72
+ @classmethod
73
+ def _retired(cls, data: Any) -> Any:
74
+ return dropped(data, "embodiment", "feedback")
@@ -16,13 +16,14 @@ import binascii
16
16
  import hashlib
17
17
  import re
18
18
  from enum import Enum
19
- from typing import Literal
19
+ from typing import Any, Literal
20
20
 
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.io import Embodiment, ObservationContract
24
+ from sequence_base.contract.io import ObservationContract
25
25
  from sequence_base.contract.own_io import Actions, Observations, Tensors, check_own_io
26
+ from sequence_base.contract.retired import dropped
26
27
  from sequence_base.contract.policy import (
27
28
  KIND_NAME,
28
29
  ActionContract,
@@ -165,8 +166,9 @@ def describe(param: "InferParam") -> str:
165
166
 
166
167
  class DeploymentPolicy(BaseModel):
167
168
  """The policy block of the deployments body. Only `handler_ref` is required. The robot-arm preset's contracts
168
- (`action`, `observation`, `embodiments`) are optional since contract 0.4.14: a deployment that declares none is held
169
- to nothing and its inputs / outputs pass through the worker untouched.
169
+ (`action`, `observation`) are optional since contract 0.4.14: a deployment that declares none is held to nothing and
170
+ its inputs / outputs pass through the worker untouched. One stored from before contract 0.5.29 reads with its
171
+ `embodiments` and `feedback` dropped (contract.retired).
170
172
 
171
173
  `secrets` carries the policy's declared secret BUNDLES BY NAME ONLY (list[SecretRef]) — the gateway
172
174
  validates each name exists and belongs to the deployer at submit time, and the
@@ -176,6 +178,11 @@ class DeploymentPolicy(BaseModel):
176
178
 
177
179
  model_config = ConfigDict(extra="forbid")
178
180
 
181
+ @model_validator(mode="before")
182
+ @classmethod
183
+ def _retired(cls, data: Any) -> Any:
184
+ return dropped(data, "embodiments", "feedback")
185
+
179
186
  handler_ref: str
180
187
  action: ActionContract | None = None
181
188
 
@@ -184,14 +191,9 @@ class DeploymentPolicy(BaseModel):
184
191
 
185
192
 
186
193
  streaming: bool = Field(default=False, exclude=True)
187
-
188
-
189
- feedback: bool | None = None
190
194
  secrets: list[SecretRef] = Field(default_factory=list)
191
195
 
192
-
193
196
  observation: ObservationContract | None = None
194
- embodiments: dict[str, Embodiment] | None = None
195
197
 
196
198
 
197
199
 
@@ -1,5 +1,5 @@
1
1
  """
2
- The robot-arm I/O contracts (`action=`, `observation=`, `embodiments=`), re-exported from
2
+ The robot-arm I/O contracts (`action=`, `observation=`), re-exported from
3
3
  `sequence_base.presets.robot_arm`.
4
4
 
5
5
  Declaring one is optional since contract 0.4.14: a deployment that declares none is held to nothing, and its
@@ -11,11 +11,10 @@ from sequence_base.presets.robot_arm import (
11
11
  PROPRIO_FIELDS,
12
12
  ActionContract,
13
13
  Camera,
14
- Embodiment,
15
14
  ObservationContract,
16
15
  fit_hint,
17
16
  frame_size_problem,
18
17
  )
19
18
 
20
- __all__ = ["ActionContract", "PROPRIO_FIELDS", "Camera", "ObservationContract", "Embodiment", "frame_size_problem",
21
- "fit_hint", "PAYLOAD_HINT"]
19
+ __all__ = ["ActionContract", "PROPRIO_FIELDS", "Camera", "ObservationContract", "frame_size_problem", "fit_hint",
20
+ "PAYLOAD_HINT"]
@@ -235,7 +235,7 @@ def check_own_io(spec: Any) -> None:
235
235
  new = [name for name in ("observations", "actions", "tensors") if getattr(spec, name) is not None]
236
236
  if not new:
237
237
  return
238
- if spec.action or spec.observation or spec.embodiments:
238
+ if spec.action or spec.observation:
239
239
  raise ValueError(f"{', '.join(new)} {'is' if len(new) == 1 else 'are'} for a policy of its own inputs and "
240
240
  "outputs; this one declares the robot-arm contract, where observation history and the action "
241
241
  "chunk say it")
@@ -20,11 +20,11 @@ from sequence_base.contract.io import (
20
20
  PROPRIO_FIELDS,
21
21
  ActionContract,
22
22
  Camera,
23
- Embodiment,
24
23
  ObservationContract,
25
24
  )
26
25
  from sequence_base.contract.flags import SeqFlags
27
26
  from sequence_base.contract.own_io import Actions, Observations, Tensors, check_own_io
27
+ from sequence_base.contract.retired import dropped
28
28
 
29
29
  __all__ = [
30
30
  "Episodes",
@@ -347,12 +347,18 @@ Episodes = Literal["shared", "own"]
347
347
 
348
348
 
349
349
  class PolicySpec(BaseModel):
350
- """What `@seq.policy(...)` accrues — a policy's complete infra declaration, losslessly. `action` /
351
- `observation` / `embodiments` are optional (contract 0.4.14): a policy that declares none defines its I/O in its own
352
- code, and the platform passes it through."""
350
+ """What `@seq.policy(...)` accrues — a policy's complete infra declaration, losslessly. `action` / `observation`
351
+ are optional (contract 0.4.14): a policy that declares none defines its I/O in its own code, and the platform passes
352
+ it through. A spec from before contract 0.5.29 reads
353
+ with its `embodiments` and `feedback` dropped (contract.retired)."""
353
354
 
354
355
  model_config = ConfigDict(extra="forbid")
355
356
 
357
+ @model_validator(mode="before")
358
+ @classmethod
359
+ def _retired(cls, data: Any) -> Any:
360
+ return dropped(data, "embodiments", "feedback")
361
+
356
362
  name: str
357
363
 
358
364
 
@@ -377,14 +383,9 @@ class PolicySpec(BaseModel):
377
383
 
378
384
  streaming: bool = Field(default=False, exclude=True)
379
385
 
380
-
381
-
382
- feedback: bool | None = None
383
-
384
386
  action: ActionContract | None = None
385
387
 
386
388
  observation: ObservationContract | None = None
387
- embodiments: dict[str, Embodiment] | None = None
388
389
 
389
390
 
390
391
 
@@ -0,0 +1,22 @@
1
+ """
2
+ Fields the wire carried once and carries no more (contract 0.5.29): what a robot is (`embodiment`, `embodiments`) and
3
+ what it was playing (`feedback`). A body from before - a spec stored when its policy was deployed, an act or a connect
4
+ an older gateway queued or an older SDK sends - still reads under extra="forbid", each of them dropped as it is read.
5
+
6
+ WHY dropped rather than kept unread: nothing reads them - an act function is handed its episode alone, and a robot sends
7
+ what it is, and what it played, with its observations - so a model that kept them would only carry them on.
8
+
9
+
10
+ """
11
+ from __future__ import annotations
12
+
13
+ from typing import Any
14
+
15
+ __all__ = ["dropped"]
16
+
17
+
18
+ def dropped(data: Any, *names: str) -> Any:
19
+ """`data` without `names`: a dict that holds any of them, a copy without them; anything else as it is."""
20
+ if isinstance(data, dict) and any(n in data for n in names):
21
+ return {k: v for k, v in data.items() if k not in names}
22
+ return data
@@ -7,8 +7,8 @@ posts them to the worker's /act unchanged → the worker hands them to the polic
7
7
  of the user's own code, never by the platform.
8
8
 
9
9
  Alongside the payload the envelope carries only what the platform itself acts on: a seed (determinism), the episode
10
- (per-episode state and `/act/episode_end`), the declared inference parameters, and — for a robot-arm preset policy with
11
- several bodies — the embodiment chosen at connect.
10
+ (per-episode state and `/act/episode_end`) and the declared inference parameters. An act from before contract 0.5.29
11
+ reads with its `embodiment` and `feedback` dropped (contract.retired).
12
12
 
13
13
  Compatibility: a worker also accepts the version-1 body (`observation` instead of `inputs`), and a policy written
14
14
  against the robot-arm preset (`infer(self, obs: Observation) -> ActionChunk`) also answers `action_chunk`, so older SDKs
@@ -18,7 +18,9 @@ from __future__ import annotations
18
18
 
19
19
  from typing import Any
20
20
 
21
- from pydantic import BaseModel, ConfigDict, Field
21
+ from pydantic import BaseModel, ConfigDict, Field, model_validator
22
+
23
+ from sequence_base.contract.retired import dropped
22
24
 
23
25
  __all__ = ["ActRequest", "ActResponse"]
24
26
 
@@ -33,8 +35,6 @@ class ActRequest(BaseModel):
33
35
  episode_id: str | None = Field(default=None, description="The episode this call belongs to (per-episode state)")
34
36
  params: dict[str, Any] | None = Field(default=None,
35
37
  description="Values for the inference parameters the policy declares")
36
- embodiment: str | None = Field(default=None,
37
- description="Robot-arm preset only: which declared embodiment this session drives")
38
38
 
39
39
 
40
40
  plan: dict[str, Any] | None = Field(default=None,
@@ -45,10 +45,10 @@ class ActRequest(BaseModel):
45
45
  seq: int | None = Field(default=None, ge=0,
46
46
  description="The newest observation's number in its episode's stream (POST /observe)")
47
47
 
48
-
49
-
50
- feedback: dict[str, Any] | None = Field(default=None,
51
- description="What the robot was playing: left, delay, played, last")
48
+ @model_validator(mode="before")
49
+ @classmethod
50
+ def _retired(cls, data: Any) -> Any:
51
+ return dropped(data, "embodiment", "feedback")
52
52
 
53
53
 
54
54
  class ActResponse(BaseModel):
@@ -5,7 +5,7 @@ Optional, not the platform's wire. Under custom-io the worker hands a policy's `
5
5
  returns whatever it answers; this module is the shape OUR templates and benchmarks agree on, kept so they keep
6
6
  working. A policy uses it by annotating `infer(self, obs: Observation, ...) -> ActionChunk` (the worker then parses
7
7
  `inputs` into an Observation and serializes the chunk) and, if it wants them enforced, by declaring `action=` /
8
- `observation=` / `embodiments=` contracts.
8
+ `observation=` contracts.
9
9
 
10
10
  `sequence_base.contract.act` and `sequence_base.contract.io` re-export everything here, so existing imports keep
11
11
  resolving to these same classes.
@@ -277,12 +277,3 @@ class ObservationContract(BaseModel):
277
277
  return v
278
278
 
279
279
 
280
- class Embodiment(BaseModel):
281
- """One robot body a multi-embodiment policy serves: its action contract, its observation contract, and
282
- free-form metadata the policy reads (e.g. which normalisation statistics). Chosen per session at connect."""
283
-
284
- model_config = ConfigDict(extra="forbid")
285
-
286
- action: ActionContract
287
- observation: ObservationContract | None = None
288
- meta: dict[str, Any] = Field(default_factory=dict)
@@ -80,7 +80,6 @@ from sequence_base.contract.eval import (
80
80
  from sequence_base.contract.flags import seqflags_json_schema
81
81
  from sequence_base.contract.policy import (
82
82
  Camera,
83
- Embodiment,
84
83
  ObservationContract,
85
84
  ActionContract,
86
85
  Concurrency,
@@ -136,7 +135,6 @@ WIRE_MODELS: dict[str, type[BaseModel]] = {
136
135
  "ActionContract": ActionContract,
137
136
  "Camera": Camera,
138
137
  "ObservationContract": ObservationContract,
139
- "Embodiment": Embodiment,
140
138
  "PolicySpec": PolicySpec,
141
139
  "PolicyRegistration": PolicyRegistration,
142
140
 
@@ -2,19 +2,6 @@
2
2
  "additionalProperties": false,
3
3
  "description": "POST /act, version 2. `inputs` is any JSON value; the worker does not inspect it.",
4
4
  "properties": {
5
- "embodiment": {
6
- "anyOf": [
7
- {
8
- "type": "string"
9
- },
10
- {
11
- "type": "null"
12
- }
13
- ],
14
- "default": null,
15
- "description": "Robot-arm preset only: which declared embodiment this session drives",
16
- "title": "Embodiment"
17
- },
18
5
  "episode_id": {
19
6
  "anyOf": [
20
7
  {
@@ -28,20 +15,6 @@
28
15
  "description": "The episode this call belongs to (per-episode state)",
29
16
  "title": "Episode Id"
30
17
  },
31
- "feedback": {
32
- "anyOf": [
33
- {
34
- "additionalProperties": true,
35
- "type": "object"
36
- },
37
- {
38
- "type": "null"
39
- }
40
- ],
41
- "default": null,
42
- "description": "What the robot was playing: left, delay, played, last",
43
- "title": "Feedback"
44
- },
45
18
  "inputs": {
46
19
  "description": "Whatever the policy's infer() takes, exactly as the robot's code built it",
47
20
  "title": "Inputs"
@@ -107,5 +80,5 @@
107
80
  ],
108
81
  "title": "ActRequest",
109
82
  "type": "object",
110
- "x-contract-version": "0.5.28"
83
+ "x-contract-version": "0.5.29"
111
84
  }
@@ -89,5 +89,5 @@
89
89
  ],
90
90
  "title": "ActResponse",
91
91
  "type": "object",
92
- "x-contract-version": "0.5.28"
92
+ "x-contract-version": "0.5.29"
93
93
  }
@@ -99,5 +99,5 @@
99
99
  ],
100
100
  "title": "ActionChunk",
101
101
  "type": "object",
102
- "x-contract-version": "0.5.28"
102
+ "x-contract-version": "0.5.29"
103
103
  }
@@ -96,5 +96,5 @@
96
96
  ],
97
97
  "title": "ActionContract",
98
98
  "type": "object",
99
- "x-contract-version": "0.5.28"
99
+ "x-contract-version": "0.5.29"
100
100
  }
@@ -19,5 +19,5 @@
19
19
  ],
20
20
  "title": "ActionStep",
21
21
  "type": "object",
22
- "x-contract-version": "0.5.28"
22
+ "x-contract-version": "0.5.29"
23
23
  }
@@ -59,5 +59,5 @@
59
59
  },
60
60
  "title": "Actions",
61
61
  "type": "object",
62
- "x-contract-version": "0.5.28"
62
+ "x-contract-version": "0.5.29"
63
63
  }
@@ -17,5 +17,5 @@
17
17
  ],
18
18
  "title": "AdapterPair",
19
19
  "type": "object",
20
- "x-contract-version": "0.5.28"
20
+ "x-contract-version": "0.5.29"
21
21
  }