harness-sdk-python 0.31.1__tar.gz → 0.31.2__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 (44) hide show
  1. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/PKG-INFO +2 -2
  2. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/pyproject.toml +2 -2
  3. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/voice.py +4 -3
  4. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_voice.py +13 -1
  5. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/.gitignore +0 -0
  6. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/README.md +0 -0
  7. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/examples/__init__.py +0 -0
  8. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/examples/runs_app.py +0 -0
  9. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/__init__.py +0 -0
  10. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/checkpoints.py +0 -0
  11. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/deepagents.py +0 -0
  12. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/fenced_postgres.py +0 -0
  13. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/linear_thread.py +0 -0
  14. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/src/harness_sdk/run_manager.py +0 -0
  15. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/run_helpers.py +0 -0
  16. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_admit_steer.py +0 -0
  17. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_applied_visibility.py +0 -0
  18. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_batches.py +0 -0
  19. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_branch_anchor.py +0 -0
  20. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_checkpoints.py +0 -0
  21. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_deepagents_messages.py +0 -0
  22. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_dispatching.py +0 -0
  23. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_durability.py +0 -0
  24. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_edit_dispatched.py +0 -0
  25. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_edit_reload.py +0 -0
  26. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_enqueue.py +0 -0
  27. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_fenced_postgres.py +0 -0
  28. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_input_required.py +0 -0
  29. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_linear_thread.py +0 -0
  30. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_meta.py +0 -0
  31. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_mint_concurrency.py +0 -0
  32. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_outcomes.py +0 -0
  33. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_placement.py +0 -0
  34. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_prepare_hooks.py +0 -0
  35. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_restore.py +0 -0
  36. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_rewind_during_run.py +0 -0
  37. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_run_crash_sweep.py +0 -0
  38. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_settle.py +0 -0
  39. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_steer.py +0 -0
  40. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_stop_continue.py +0 -0
  41. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_stopping_window.py +0 -0
  42. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_voice_delegation.py +0 -0
  43. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/test_voice_frontend_tools.py +0 -0
  44. {harness_sdk_python-0.31.1 → harness_sdk_python-0.31.2}/tests/voice_helpers.py +0 -0
@@ -1,11 +1,11 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: harness-sdk-python
3
- Version: 0.31.1
3
+ Version: 0.31.2
4
4
  Summary: RunManager: the harness-sdk runs subsystem for Python Statewire hosts
5
5
  Project-URL: Repository, https://github.com/assistant-ui/harness-sdk
6
6
  License-Expression: MIT
7
7
  Requires-Python: <4.0,>=3.12
8
- Requires-Dist: pinned<0.15,>=0.14.0
8
+ Requires-Dist: pinned<0.15,>=0.14.6
9
9
  Requires-Dist: statewire<0.13,>=0.12.3
10
10
  Provides-Extra: deepagents
11
11
  Requires-Dist: deepagents>=0.6.12; extra == 'deepagents'
@@ -1,11 +1,11 @@
1
1
  [project]
2
2
  name = "harness-sdk-python"
3
- version = "0.31.1"
3
+ version = "0.31.2"
4
4
  description = "RunManager: the harness-sdk runs subsystem for Python Statewire hosts"
5
5
  readme = "README.md"
6
6
  license = "MIT"
7
7
  requires-python = ">=3.12,<4.0"
8
- dependencies = ["statewire>=0.12.3,<0.13", "pinned>=0.14.0,<0.15"]
8
+ dependencies = ["statewire>=0.12.3,<0.13", "pinned>=0.14.6,<0.15"]
9
9
 
10
10
  [project.optional-dependencies]
11
11
  postgres = ["langgraph-checkpoint-postgres>=2.0.0"]
@@ -672,11 +672,11 @@ def voice_manager() -> Callable[[Callable[..., Any]], VoiceManagerDescriptor]:
672
672
  return decorate
673
673
 
674
674
 
675
- def _voice_of(host: Any) -> VoiceManagerNamespace | None:
675
+ def _voice_of(host: Any, *, create: bool = True) -> VoiceManagerNamespace | None:
676
676
  for cls in type(host).__mro__:
677
677
  for name, member in vars(cls).items():
678
678
  if isinstance(member, VoiceManagerDescriptor):
679
- return getattr(host, name)
679
+ return getattr(host, name) if create else member.peek(host)
680
680
  return None
681
681
 
682
682
 
@@ -698,7 +698,8 @@ async def end_voice(host: Any, *, ctx: Any) -> None:
698
698
 
699
699
  def voice_client_departed(host: Any, client_id: str) -> None:
700
700
  """The Statewire ``client_departed`` hook body: routes to the host's declared voice manager."""
701
- namespace = _voice_of(host)
701
+ # peek: instantiating here would stamp voice state after the attach snapshot
702
+ namespace = _voice_of(host, create=False)
702
703
  if namespace is not None:
703
704
  namespace.client_departed(client_id)
704
705
 
@@ -4,7 +4,7 @@
4
4
  import asyncio
5
5
 
6
6
  from run_helpers import _statement, assert_rejected
7
- from statewire_helpers import post_frame, stream_of
7
+ from statewire_helpers import apply_ops, post_frame, stream_of
8
8
  from voice_helpers import (
9
9
  ANSWER,
10
10
  OFFER,
@@ -316,6 +316,18 @@ async def test_reattach_within_grace_keeps_the_session(monkeypatch):
316
316
  assert not bench.provider.closed
317
317
 
318
318
 
319
+ async def test_departure_before_any_voice_command_leaves_state_untouched():
320
+ bench = Bench()
321
+ async with voice_host(bench) as (drv, app):
322
+ async with stream_of(app, client_id="c2") as stream:
323
+ await stream.next_event()
324
+ await asyncio.sleep(0.05)
325
+ assert "voice" not in drv.replica
326
+ async with stream_of(app, client_id="c3") as stream:
327
+ snapshot = apply_ops({}, await stream.next_event())
328
+ assert "voice" not in snapshot
329
+
330
+
319
331
  async def test_start_over_a_detached_owner_replaces_the_session():
320
332
  bench = Bench()
321
333
  async with voice_host(bench) as (drv, app):