agentenv-framework-protocol 0.1.456__tar.gz → 0.1.458__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 (126) hide show
  1. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/PKG-INFO +1 -1
  2. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/pyproject.toml +1 -1
  3. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/recording.py +23 -3
  4. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_recording.py +21 -0
  5. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/.gitignore +0 -0
  6. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/LICENSE +0 -0
  7. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/NOTICE +0 -0
  8. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/README.md +0 -0
  9. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/THIRD_PARTY_NOTICES.md +0 -0
  10. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/__init__.py +0 -0
  11. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/advanced_agent.py +0 -0
  12. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/basic_agent.py +0 -0
  13. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/custom_extensions_agent.py +0 -0
  14. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/multimodal_agent.py +0 -0
  15. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/reference_model.py +0 -0
  16. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/examples/streaming_agent.py +0 -0
  17. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/__init__.py +0 -0
  18. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/__init__.py +0 -0
  19. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/_trajectory_log.py +0 -0
  20. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/_triggers.py +0 -0
  21. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/extensions.py +0 -0
  22. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/framework.py +0 -0
  23. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/peer_agents.py +0 -0
  24. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/proxy.py +0 -0
  25. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/registry.py +0 -0
  26. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/staging.py +0 -0
  27. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/tasks/__init__.py +0 -0
  28. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/a2a_agent/tasks/v1.py +0 -0
  29. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/agent_env_environment.py +0 -0
  30. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/browser_cdp.py +0 -0
  31. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/client.py +0 -0
  32. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/__init__.py +0 -0
  33. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/_declare.py +0 -0
  34. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/_linux.py +0 -0
  35. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/_load.py +0 -0
  36. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/_with_fds.py +0 -0
  37. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/app.py +0 -0
  38. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/app_data.py +0 -0
  39. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/app_runtime.py +0 -0
  40. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/apps.py +0 -0
  41. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/card.py +0 -0
  42. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/checks.py +0 -0
  43. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/__init__.py +0 -0
  44. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/__main__.py +0 -0
  45. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/checks.py +0 -0
  46. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/client.py +0 -0
  47. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/fixture.py +0 -0
  48. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/mp4.py +0 -0
  49. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/page_fixture.py +0 -0
  50. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/conformance/report.py +0 -0
  51. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/dataplane.py +0 -0
  52. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/driver.py +0 -0
  53. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/errors.py +0 -0
  54. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/extensions.py +0 -0
  55. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/frames.py +0 -0
  56. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/keys.py +0 -0
  57. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/launch.py +0 -0
  58. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/manifest.py +0 -0
  59. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/operations.py +0 -0
  60. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/platform.py +0 -0
  61. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/queue.py +0 -0
  62. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/results.py +0 -0
  63. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/run_install_step.py +0 -0
  64. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/runtime.py +0 -0
  65. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/seed.py +0 -0
  66. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/serve.py +0 -0
  67. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/serve_app.py +0 -0
  68. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/session.py +0 -0
  69. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/settings.py +0 -0
  70. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/skill.py +0 -0
  71. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/spaces.py +0 -0
  72. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/svc.py +0 -0
  73. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/computer/tools.py +0 -0
  74. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/errors.py +0 -0
  75. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/manifest.py +0 -0
  76. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/preflight.py +0 -0
  77. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/tool_access.py +0 -0
  78. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/tool_client.py +0 -0
  79. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/tool_context.py +0 -0
  80. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/transfers.py +0 -0
  81. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/types.py +0 -0
  82. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/src/agentenv_protocol/website_browser.py +0 -0
  83. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/computer_fake.py +0 -0
  84. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/probe_fake.py +0 -0
  85. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_agent.py +0 -0
  86. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_agent_examples.py +0 -0
  87. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_cdp_config.py +0 -0
  88. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_object_transfers.py +0 -0
  89. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_peer_agents.py +0 -0
  90. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_proxy.py +0 -0
  91. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_staging.py +0 -0
  92. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_a2a_trajectory_log.py +0 -0
  93. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_agent_env_environment.py +0 -0
  94. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_browser_cdp.py +0 -0
  95. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_client.py +0 -0
  96. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_app_data.py +0 -0
  97. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_app_server.py +0 -0
  98. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_conformance.py +0 -0
  99. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_conformance_checks.py +0 -0
  100. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_conformance_page.py +0 -0
  101. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_conformance_recording.py +0 -0
  102. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_dataplane.py +0 -0
  103. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_declare.py +0 -0
  104. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_driver.py +0 -0
  105. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_extensions.py +0 -0
  106. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_frames.py +0 -0
  107. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_page.py +0 -0
  108. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_queue.py +0 -0
  109. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_seed.py +0 -0
  110. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_serve.py +0 -0
  111. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_spaces.py +0 -0
  112. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_computer_svc_forward.py +0 -0
  113. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_control_token.py +0 -0
  114. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_data_objects.py +0 -0
  115. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_errors.py +0 -0
  116. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_extension_methods.py +0 -0
  117. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_intake.py +0 -0
  118. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_manifest.py +0 -0
  119. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_preflight.py +0 -0
  120. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_access.py +0 -0
  121. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_annotations.py +0 -0
  122. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_client.py +0 -0
  123. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_context.py +0 -0
  124. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_context_fastmcp.py +0 -0
  125. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_tool_context_injection.py +0 -0
  126. {agentenv_framework_protocol-0.1.456 → agentenv_framework_protocol-0.1.458}/tests/test_website_browser.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: agentenv-framework-protocol
3
- Version: 0.1.456
3
+ Version: 0.1.458
4
4
  Summary: Open data-plane protocol and server SDK for agent environments.
5
5
  Project-URL: Homepage, https://www.agentenvframework.com
6
6
  Project-URL: Documentation, https://www.agentenvframework.com/docs
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "agentenv-framework-protocol"
3
- version = "0.1.456"
3
+ version = "0.1.458"
4
4
  description = "Open data-plane protocol and server SDK for agent environments."
5
5
  readme = "README.md"
6
6
  license = "Apache-2.0"
@@ -52,6 +52,8 @@ FAILING_S = 60.0
52
52
  GAP_S = 2.0
53
53
  #: How long a stream that stopped or failed waits before it is started again.
54
54
  RETRY_S = 1.0
55
+ #: How long a recording's start waits for its first frame, so a recording a start answered for is recording.
56
+ FIRST_FRAME_S = 5.0
55
57
  #: How often free disk is checked while frames arrive.
56
58
  DISK_CHECK_S = 5.0
57
59
  KEEP_ENDED = 64
@@ -127,8 +129,9 @@ def recording_params(recording: Recording, streams: bool) -> dict:
127
129
 
128
130
 
129
131
  class Recordings:
130
- """The recordings of one driver: started by request id, open ones counted against ``max_concurrent``, ended
131
- ones kept with their manifests so a repeated ``end`` answers the same."""
132
+ """The recordings of one driver: started by request id, each start answering once its recording is recording, open
133
+ ones counted against ``max_concurrent``, ended ones kept with their manifests so a repeated ``end`` answers the
134
+ same."""
132
135
 
133
136
  def __init__(self, runtime: ComputerRuntime) -> None:
134
137
  self.runtime = runtime
@@ -144,7 +147,9 @@ class Recordings:
144
147
  raise InvalidArgument("request_id is a non-empty string")
145
148
  async with self._lock:
146
149
  if request_id in self.started:
147
- return self.started[request_id]
150
+ answer = self.started[request_id]
151
+ await self._live(self.running.get(answer["recording_id"]))
152
+ return answer
148
153
  hints, grant = self._hints(features, scope, window, fps, max_edge, cursor, upload)
149
154
  stopped = [rid for rid, r in self.running.items() if r.done]
150
155
  for rid in stopped[:max(0, len(stopped) - KEEP_ENDED)]: # stopped by itself and never ended
@@ -164,8 +169,16 @@ class Recordings:
164
169
  self.started[request_id] = answer
165
170
  while len(self.started) > KEEP_STARTED:
166
171
  self.started.popitem(last=False)
172
+ await self._live(recording)
167
173
  return answer
168
174
 
175
+ @staticmethod
176
+ async def _live(recording: Optional[_Recording]) -> None:
177
+ """Wait up to FIRST_FRAME_S for ``recording``, one still running, to have its first frame."""
178
+ if recording is not None:
179
+ with contextlib.suppress(TimeoutError):
180
+ await asyncio.wait_for(recording.live.wait(), FIRST_FRAME_S)
181
+
169
182
  async def end(self, recording_id: str, upload: Optional[dict], reason: str) -> dict:
170
183
  if reason not in REASONS:
171
184
  raise InvalidArgument(f"reason is one of {list(REASONS)}, got {reason!r}")
@@ -219,6 +232,7 @@ class _Recording:
219
232
  self.ended_by: Optional[str] = None
220
233
  self.error: Optional[str] = None
221
234
  self.done = False
235
+ self.live = asyncio.Event()
222
236
  self.task: Optional[asyncio.Task] = None
223
237
  self.timer: Optional[asyncio.TimerHandle] = None
224
238
  self.released: Optional[asyncio.Future] = None
@@ -228,7 +242,11 @@ class _Recording:
228
242
  self._last_disk_check = 0.0
229
243
 
230
244
  async def run(self) -> None:
245
+ """Frames or segments from the source, recorded until the recording ends; ``live`` once it's recording: a
246
+ stream from its start, the fallback's polling from its first frame, which a busy computer is slow to take."""
231
247
  failing_since: Optional[float] = None
248
+ if self.streams:
249
+ self.live.set()
232
250
  try:
233
251
  while True:
234
252
  try:
@@ -255,6 +273,7 @@ class _Recording:
255
273
  await self._close()
256
274
  finally:
257
275
  self.done = True
276
+ self.live.set()
258
277
  self.released = asyncio.ensure_future(self._release())
259
278
 
260
279
  def expire(self) -> None:
@@ -315,6 +334,7 @@ class _Recording:
315
334
  path = self.hints.directory / f"{len(self.segments):04d}.mp4"
316
335
  self.encoder = await self._in_thread(_Encoder, path, frame.width, frame.height, self.hints.fps, at)
317
336
  await self._in_thread(self.encoder.add, frame, at)
337
+ self.live.set()
318
338
  self._check_disk()
319
339
 
320
340
  async def _add_segment(self, item: RecordedSegment) -> None:
@@ -176,6 +176,27 @@ async def test_the_fallback_polls_capture_and_draws_the_pointer(home):
176
176
  assert _at(manifest["started_at"]) <= _at(manifest["ended_at"])
177
177
 
178
178
 
179
+ @pytest.mark.asyncio
180
+ async def test_a_start_answers_once_its_recording_has_its_first_frame_however_slow_the_capture(home):
181
+ driver = Recorded()
182
+ driver.slow["capture"] = 0.5
183
+ async with http_client(driver) as http:
184
+ began = time.monotonic()
185
+ started = (await http.post(START, json={"request_id": "r", "fps": 10})).json()
186
+ took = time.monotonic() - began
187
+ recording = driver._computer.recordings.running[started["recording_id"]]
188
+ assert took >= 0.5 and recording.encoder is not None and recording.encoder.frames >= 1
189
+ await http.post(END, json={"recording_id": started["recording_id"]})
190
+
191
+ recordings = driver._computer.recordings
192
+ with pytest.raises(TimeoutError):
193
+ await asyncio.wait_for(recordings.start("cancelled", "display", None, 10, None, True, None), 0.1)
194
+ retried = await recordings.start("cancelled", "display", None, 10, None, True, None)
195
+ running = [r for r in recordings.running.values() if not r.done]
196
+ assert [r.id for r in running] == [retried["recording_id"]] and running[0].encoder.frames >= 1
197
+ await http.post(END, json={"recording_id": retried["recording_id"]})
198
+
199
+
179
200
  @pytest.mark.asyncio
180
201
  async def test_a_driver_without_the_pointer_group_records_without_a_cursor(home):
181
202
  _, manifest = await _record(MinimalDriver(), 0.4)