reactor-runtime 2.3.0__tar.gz → 2.3.1__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 (130) hide show
  1. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/PKG-INFO +1 -1
  2. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/pyproject.toml +1 -1
  3. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/driver/pipeline_executor.py +11 -2
  4. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/profiler.py +15 -0
  5. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtime_api.py +0 -67
  6. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/headless/headless_runtime.py +0 -2
  7. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/http/http_runtime.py +0 -2
  8. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/PKG-INFO +1 -1
  9. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/README.md +0 -0
  10. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/setup.cfg +0 -0
  11. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/api/__init__.py +0 -0
  12. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/commands/__init__.py +0 -0
  13. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/commands/init.py +0 -0
  14. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/commands/run.py +0 -0
  15. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/commands/schema.py +0 -0
  16. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/main.py +0 -0
  17. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/utils/__init__.py +0 -0
  18. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/utils/config.py +0 -0
  19. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/utils/runtime.py +0 -0
  20. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_cli/utils/version.py +0 -0
  21. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/__init__.py +0 -0
  22. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/config.py +0 -0
  23. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/__init__.py +0 -0
  24. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/defaults.py +0 -0
  25. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/driver/__init__.py +0 -0
  26. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/driver/step_result.py +0 -0
  27. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/events/__init__.py +0 -0
  28. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/events/connected.py +0 -0
  29. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/events/event.py +0 -0
  30. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/events/messages.py +0 -0
  31. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/events/upload.py +0 -0
  32. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/internal/__init__.py +0 -0
  33. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/internal/input_buffer.py +0 -0
  34. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/internal/output_buffer.py +0 -0
  35. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/internal/reactor_core.py +0 -0
  36. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/model/__init__.py +0 -0
  37. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/model/decorators.py +0 -0
  38. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/model/handlers.py +0 -0
  39. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/model/reactor_model.py +0 -0
  40. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/pipeline/__init__.py +0 -0
  41. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/pipeline/idle.py +0 -0
  42. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/pipeline/input_state.py +0 -0
  43. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/pipeline/reactor_pipeline.py +0 -0
  44. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/tracks/__init__.py +0 -0
  45. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/tracks/descriptors.py +0 -0
  46. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/tracks/input.py +0 -0
  47. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/tracks/output.py +0 -0
  48. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/interface/upload.py +0 -0
  49. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/model_state.py +0 -0
  50. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/__init__.py +0 -0
  51. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/backends/__init__.py +0 -0
  52. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/backends/base.py +0 -0
  53. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/backends/file.py +0 -0
  54. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/backends/otlp.py +0 -0
  55. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/helpers.py +0 -0
  56. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/plotting/__init__.py +0 -0
  57. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/plotting/plot_profiling.py +0 -0
  58. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/profiling/singleton.py +0 -0
  59. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/headless/config.py +0 -0
  60. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/headless/input_feeder.py +0 -0
  61. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/http/config.py +0 -0
  62. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/runtimes/http/types.py +0 -0
  63. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/schema.py +0 -0
  64. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/schema_validator.py +0 -0
  65. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/__init__.py +0 -0
  66. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/__init__.py +0 -0
  67. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/audio_track.py +0 -0
  68. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/client.py +0 -0
  69. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/frame_conversion.py +0 -0
  70. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/ice_connection.py +0 -0
  71. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/aiortc/video_track.py +0 -0
  72. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/config.py +0 -0
  73. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/events.py +0 -0
  74. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/__init__.py +0 -0
  75. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/client.py +0 -0
  76. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/__init__.py +0 -0
  77. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/av1.py +0 -0
  78. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/base.py +0 -0
  79. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/factory.py +0 -0
  80. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/h264.py +0 -0
  81. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/h265.py +0 -0
  82. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/vp8.py +0 -0
  83. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/decoders/vp9.py +0 -0
  84. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/__init__.py +0 -0
  85. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/av1.py +0 -0
  86. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/base.py +0 -0
  87. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/factory.py +0 -0
  88. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/h264.py +0 -0
  89. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/h265.py +0 -0
  90. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/opus.py +0 -0
  91. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/vp8.py +0 -0
  92. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/encoders/vp9.py +0 -0
  93. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/gst.py +0 -0
  94. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/gst_helpers.py +0 -0
  95. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/receiver/__init__.py +0 -0
  96. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/receiver/audio.py +0 -0
  97. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/receiver/base.py +0 -0
  98. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/receiver/video.py +0 -0
  99. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sdp/__init__.py +0 -0
  100. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sdp/bundle.py +0 -0
  101. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sdp/codec.py +0 -0
  102. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sdp/extmap.py +0 -0
  103. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sdp/ice.py +0 -0
  104. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sender/__init__.py +0 -0
  105. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sender/audio.py +0 -0
  106. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sender/base.py +0 -0
  107. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/sender/video.py +0 -0
  108. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/settings.py +0 -0
  109. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/gstreamer/signals.py +0 -0
  110. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/ice_uris.py +0 -0
  111. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/interface.py +0 -0
  112. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/media.py +0 -0
  113. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/transports/types.py +0 -0
  114. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/utils/launch.py +0 -0
  115. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/utils/loader.py +0 -0
  116. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/utils/log.py +0 -0
  117. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/utils/messages.py +0 -0
  118. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime/utils/typing.py +0 -0
  119. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/SOURCES.txt +0 -0
  120. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/dependency_links.txt +0 -0
  121. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/entry_points.txt +0 -0
  122. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/requires.txt +0 -0
  123. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/reactor_runtime.egg-info/top_level.txt +0 -0
  124. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/README.md +0 -0
  125. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/__init__.py +0 -0
  126. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/config.yml +0 -0
  127. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/model.py +0 -0
  128. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/pipeline.py +0 -0
  129. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/reactor.yaml +0 -0
  130. {reactor_runtime-2.3.0 → reactor_runtime-2.3.1}/src/template/requirements.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reactor_runtime
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Reactor runtime with public model API
5
5
  Author-email: Reactor <team@reactor.inc>
6
6
  Requires-Python: >=3.9
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "reactor_runtime"
7
- version = "2.3.0"
7
+ version = "2.3.1"
8
8
  description = "Reactor runtime with public model API"
9
9
  authors = [
10
10
  { name = "Reactor", email = "team@reactor.inc" }
@@ -4,6 +4,7 @@
4
4
  from __future__ import annotations
5
5
 
6
6
  import asyncio
7
+ import dataclasses
7
8
  import inspect
8
9
  from typing import Any, Dict, Iterator, List, Optional, Type
9
10
 
@@ -144,7 +145,7 @@ class PipelineExecutor(Iterator[StepResult]):
144
145
  raise ValueError(f"Unknown event {name!r}. Available events: {available}")
145
146
 
146
147
  try:
147
- entry.event_cls(**kwargs)
148
+ event = entry.event_cls(**kwargs)
148
149
  except TypeError as exc:
149
150
  raise TypeError(f"Invalid arguments for event {name!r}: {exc}") from None
150
151
 
@@ -155,7 +156,15 @@ class PipelineExecutor(Iterator[StepResult]):
155
156
  if not ok:
156
157
  raise ValueError(f"Validation failed for event {name!r}: {reason}")
157
158
 
158
- return self._run(self._send_event(entry, **kwargs))
159
+ # Mirror production dispatch (reactor_model._invoke): splat the
160
+ # full set of event dataclass fields into the handler kwargs so
161
+ # callers that omit optional fields get the dataclass default
162
+ # (e.g. ``None``), not the raw ``FieldInfo`` sentinel that is
163
+ # still present in the handler function's ``__defaults__``.
164
+ handler_kwargs = {
165
+ f.name: getattr(event, f.name) for f in dataclasses.fields(event)
166
+ }
167
+ return self._run(self._send_event(entry, **handler_kwargs))
159
168
 
160
169
  def push_media(self, track_name: str, data: Any) -> None:
161
170
  """Push a media frame into an input buffer.
@@ -613,6 +613,18 @@ class ProfilerTimer:
613
613
  )
614
614
  self._start = None
615
615
 
616
+ def cancel(self) -> None:
617
+ """Discard the timer run without recording a measurement.
618
+
619
+ Safe to call whether or not the timer is currently running. Used to
620
+ reset state when the caller's scope is aborted before ``.stop()``
621
+ can fire (e.g. generator exit, session interruption before first
622
+ output). After ``cancel()``, the timer is idle and ``.start()``
623
+ will succeed.
624
+ """
625
+ self._start = None
626
+ self.elapsed_ms = None
627
+
616
628
 
617
629
  class _NoOpTimer:
618
630
  """No-op timer for when profiling is disabled."""
@@ -625,6 +637,9 @@ class _NoOpTimer:
625
637
  def stop(self) -> None:
626
638
  pass
627
639
 
640
+ def cancel(self) -> None:
641
+ pass
642
+
628
643
 
629
644
  class _NoOpSection:
630
645
  """No-op context manager for when profiling is disabled."""
@@ -41,7 +41,6 @@ logger = get_logger(__name__)
41
41
 
42
42
  _IDLING_INTERVAL_ENV_VAR = "IDLING_INTERVAL_SECONDS"
43
43
  _DEFAULT_IDLING_INTERVAL = 30.0
44
- _MAX_SESSION_DURATION_ENV_VAR = "MAX_SESSION_DURATION_SECONDS"
45
44
 
46
45
 
47
46
  # ---------------------------------------------------------------------------
@@ -70,10 +69,6 @@ class RuntimeConfig:
70
69
  # Priority: ENV > CLI > default. Set to None to use default.
71
70
  idling_interval: Optional[float] = None
72
71
 
73
- # Maximum session duration in seconds. If set, sessions will be automatically
74
- # stopped after this duration. Priority: ENV > CLI. Set to None to disable.
75
- max_session_duration: Optional[float] = None
76
-
77
72
  profiling_output_dir: Optional[str] = None
78
73
 
79
74
  def __post_init__(self) -> None:
@@ -102,20 +97,6 @@ class RuntimeConfig:
102
97
  if self.idling_interval is None:
103
98
  self.idling_interval = _DEFAULT_IDLING_INTERVAL
104
99
 
105
- # Resolve max_session_duration: ENV > CLI (no default - disabled if not set)
106
- max_env = os.getenv(_MAX_SESSION_DURATION_ENV_VAR)
107
- if max_env:
108
- try:
109
- self.max_session_duration = float(max_env)
110
- except ValueError:
111
- logger.warning(
112
- "Invalid max session duration env value",
113
- env_var=_MAX_SESSION_DURATION_ENV_VAR,
114
- value=max_env,
115
- )
116
- if self.max_session_duration is not None and self.max_session_duration <= 0:
117
- self.max_session_duration = None
118
-
119
100
  @staticmethod
120
101
  def parser() -> argparse.ArgumentParser:
121
102
  """Return an argument parser for runtime-specific CLI arguments.
@@ -146,12 +127,6 @@ class RuntimeConfig:
146
127
  help=f"Idling event interval ({_IDLING_INTERVAL_ENV_VAR} env overrides). "
147
128
  f"Default: {_DEFAULT_IDLING_INTERVAL}s",
148
129
  )
149
- parser.add_argument(
150
- "--max-session-duration",
151
- type=float,
152
- default=None,
153
- help=f"Max session seconds ({_MAX_SESSION_DURATION_ENV_VAR} env overrides).",
154
- )
155
130
  parser.add_argument(
156
131
  "--profiling-dir",
157
132
  type=str,
@@ -196,9 +171,6 @@ class Runtime(ModelStateMachine, ABC):
196
171
  # Idling task - sends periodic IDLING events when in READY state
197
172
  self._idling_task: Optional[asyncio.Task] = None
198
173
 
199
- # Max session duration task - stops session after configured duration
200
- self._max_session_duration_task: Optional[asyncio.Task] = None
201
-
202
174
  # Graceful shutdown state (for SIGTERM handling)
203
175
  self._shutdown_pending: bool = False
204
176
  self._shutdown_event: asyncio.Event = asyncio.Event()
@@ -334,7 +306,6 @@ class Runtime(ModelStateMachine, ABC):
334
306
  self._cancel_orphan_timeout()
335
307
 
336
308
  if previous_state == ModelState.WAITING:
337
- self._start_max_session_duration_timeout()
338
309
  if self.model is not None:
339
310
  self.model._push_event(Connected())
340
311
  logger.info("Pushed Connected event to model")
@@ -373,7 +344,6 @@ class Runtime(ModelStateMachine, ABC):
373
344
  ``@disconnected`` asynchronously on its own thread.
374
345
  """
375
346
  self._cancel_orphan_timeout()
376
- self._cancel_max_session_duration_timeout()
377
347
 
378
348
  if self.model is not None:
379
349
  self.model._push_event(Disconnected())
@@ -805,43 +775,6 @@ class Runtime(ModelStateMachine, ABC):
805
775
  self._orphan_task.cancel()
806
776
  self._orphan_task = None
807
777
 
808
- # -----------------------------------------------------------------
809
- # Max session duration
810
- # -----------------------------------------------------------------
811
-
812
- def _start_max_session_duration_timeout(self) -> None:
813
- """Start the max session duration timeout task.
814
-
815
- If max_session_duration is configured, the session will be automatically
816
- stopped when the duration expires. This provides a hard limit on session
817
- lifetime regardless of client activity.
818
- """
819
- if (
820
- self.config.max_session_duration is None
821
- or self.config.max_session_duration <= 0
822
- ):
823
- return
824
- self._cancel_max_session_duration_timeout()
825
-
826
- async def coro() -> None:
827
- try:
828
- await asyncio.sleep(self.config.max_session_duration) # type: ignore[arg-type]
829
- if self.current_state in (
830
- ModelState.STREAMING,
831
- ModelState.ORPHANED,
832
- ):
833
- self.send(ModelEvent.STOP_SESSION)
834
- except asyncio.CancelledError:
835
- pass
836
-
837
- self._max_session_duration_task = asyncio.create_task(coro())
838
-
839
- def _cancel_max_session_duration_timeout(self) -> None:
840
- """Cancel the max session duration timeout if running."""
841
- if self._max_session_duration_task is not None:
842
- self._max_session_duration_task.cancel()
843
- self._max_session_duration_task = None
844
-
845
778
  # -----------------------------------------------------------------
846
779
  # Idling
847
780
  # -----------------------------------------------------------------
@@ -397,14 +397,12 @@ async def serve(
397
397
  - output_root: Root directory for output (default: "./output")
398
398
  - no_ignore_duplicates: If True, write all frames including duplicates (default: False)
399
399
  - orphan_timeout: Seconds to wait before stopping orphaned session (default: 30.0)
400
- - max_session_duration: Maximum session duration in seconds (default: None, disabled)
401
400
  """
402
401
  config = HeadlessRuntimeConfig(
403
402
  reactor_config=reactor_config,
404
403
  output_root=kwargs.get("output_root", "./output"),
405
404
  ignore_duplicates=not kwargs.get("no_ignore_duplicates", False),
406
405
  orphan_timeout=kwargs.get("orphan_timeout", 30.0),
407
- max_session_duration=kwargs.get("max_session_duration"),
408
406
  profiling_output_dir=kwargs.get("profiling_output_dir"),
409
407
  )
410
408
 
@@ -647,7 +647,6 @@ async def serve(
647
647
  - host: Host to bind to (default: "0.0.0.0")
648
648
  - port: Port to bind to (default: 8080)
649
649
  - orphan_timeout: Seconds to wait before stopping orphaned session (default: 30.0)
650
- - max_session_duration: Maximum session duration in seconds (default: None, disabled)
651
650
  - webrtc_port_range: WebRTC ICE UDP port range as tuple (min, max) (default: None)
652
651
  - stun_servers: List of STUN server URLs (default: None, uses Google STUN)
653
652
  - turn_servers: List of TURN servers in format "username;credential;url" (default: None)
@@ -669,7 +668,6 @@ async def serve(
669
668
  host=kwargs.get("host", "0.0.0.0"),
670
669
  port=kwargs.get("port", 8080),
671
670
  orphan_timeout=kwargs.get("orphan_timeout", 30.0),
672
- max_session_duration=kwargs.get("max_session_duration"),
673
671
  webrtc_port_range=kwargs.get("webrtc_port_range"),
674
672
  stun_servers=kwargs.get("stun_servers"),
675
673
  turn_servers=kwargs.get("turn_servers"),
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: reactor_runtime
3
- Version: 2.3.0
3
+ Version: 2.3.1
4
4
  Summary: Reactor runtime with public model API
5
5
  Author-email: Reactor <team@reactor.inc>
6
6
  Requires-Python: >=3.9