phystack-hub-client 6.18.2__tar.gz → 6.20.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) hide show
  1. phystack_hub_client-6.20.0/CLAUDE.md +41 -0
  2. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/PKG-INFO +31 -5
  3. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/README.md +26 -0
  4. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/examples/browser_test_backend.py +19 -10
  5. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/pyproject.toml +13 -8
  6. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/scripts/python-node-test.sh +3 -3
  7. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/scripts/webrtc-test.sh +5 -5
  8. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/__init__.py +67 -61
  9. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/client.py +72 -91
  10. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/cloud_twins.py +1 -3
  11. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/instances/base_instance.py +12 -14
  12. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/instances/edge_instance.py +8 -23
  13. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/instances/peripheral_instance.py +13 -27
  14. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/cloud_app_connection.py +2 -6
  15. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/cloud_app_token.py +2 -6
  16. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/phyhub_connection.py +5 -15
  17. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/signals.py +58 -45
  18. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/data_channel.py +22 -16
  19. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/data_responder.py +3 -9
  20. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/media_responder.py +2 -6
  21. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/media_stream.py +26 -26
  22. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/twin_messaging.py +13 -11
  23. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/twin_registry.py +4 -10
  24. phystack_hub_client-6.18.2/tests/test_communication.py → phystack_hub_client-6.20.0/tests/communication_harness.py +52 -22
  25. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_client_integration.py +1 -3
  26. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_cloud_app_token.py +2 -6
  27. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_data_channel.py +7 -21
  28. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_instance_listeners.py +1 -3
  29. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_media_resilience.py +3 -9
  30. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_media_responder.py +2 -6
  31. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_peripheral_lifecycle.py +6 -20
  32. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_signals_rollover.py +3 -4
  33. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/.gitignore +0 -0
  34. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/CHANGELOG.md +0 -0
  35. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/advisory_validation.py +0 -0
  36. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/instances/__init__.py +0 -0
  37. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/scoped_hardware_id.py +0 -0
  38. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/__init__.py +0 -0
  39. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/web_session_code.py +0 -0
  40. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/__init__.py +0 -0
  41. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/services/webrtc/media_source.py +0 -0
  42. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/types/__init__.py +1 -1
  43. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/src/phystack/hub_client/types/twin_types.py +0 -0
  44. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_advisory_validation.py +0 -0
  45. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_cloud_twins.py +0 -0
  46. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_media_kinds.py +0 -0
  47. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_media_source.py +0 -0
  48. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_no_google_stun.py +0 -0
  49. {phystack_hub_client-6.18.2 → phystack_hub_client-6.20.0}/tests/test_web_session_code.py +0 -0
@@ -0,0 +1,41 @@
1
+ # hub-client-py (Python)
2
+
3
+ Python port of `packages/hub-client` (Node). Published to PyPI as
4
+ `phystack-hub-client`, import path `phystack.hub_client`. Build backend:
5
+ hatchling. Not part of the Bun workspace (no package.json — deliberate).
6
+
7
+ Imported from the archived `phystack/phystack-pypi` repo; its full commit
8
+ history lives on the `imported/phystack-pypi-main` branch of this repo.
9
+
10
+ ## Commands
11
+
12
+ - `uv venv && uv pip install -e '.[dev]'` — set up (requires uv)
13
+ - `uv run --no-sync pytest` — offline test suite (exactly what the
14
+ hub-client-py PR job runs)
15
+ - `uv run --no-sync ruff check .` and `uv run --no-sync black .` — lint/format
16
+ (CI-gated, pinned versions in pyproject)
17
+ - `tests/communication_harness.py` — LIVE two-device interop harness
18
+ (ROLE/PEER_TWIN_ID env vars); deliberately not named `test_*.py` so pytest
19
+ never collects it. Never runs in CI.
20
+ - `scripts/python-node-test.sh` / `scripts/webrtc-test.sh` — live Node↔Python
21
+ interop; need `.env.interop-test` / `.env.webrtc-test` credentials.
22
+
23
+ ## Parity with the Node client
24
+
25
+ `packages/hub-client` is the reference implementation. **Before finishing any
26
+ change here, evaluate the Node client** — port behavior changes both ways, or
27
+ record in the PR why the other client is unaffected. Wire formats and protocol
28
+ constants MUST stay byte-identical.
29
+
30
+ ## Releasing
31
+
32
+ **Python-only changes still need a changeset.** Both clients are in the same
33
+ changesets fixed group: `bunx changeset`, select `@phystack/hub-client` — the
34
+ Python version follows the Node bump automatically at publish. No changeset =
35
+ no release. Never hand-edit `version` in `pyproject.toml`
36
+ (`scripts/sync-py-version.ts` owns it).
37
+
38
+ ## Typing
39
+
40
+ `[tool.mypy] strict = true` is configured but not CI-gated yet (dependencies
41
+ lack stubs). Keep new code annotated; don't regress it.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: phystack-hub-client
3
- Version: 6.18.2
3
+ Version: 6.20.0
4
4
  Summary: Python client for PhyHub - events, actions, DataChannel, and MediaStream
5
- Project-URL: Homepage, https://github.com/phystack/phystack-pypi
5
+ Project-URL: Homepage, https://github.com/phystack/ps-platform
6
6
  Project-URL: Documentation, https://docs.phystack.com
7
- Project-URL: Repository, https://github.com/phystack/phystack-pypi
7
+ Project-URL: Repository, https://github.com/phystack/ps-platform/tree/master/packages/hub-client-py
8
8
  Author-email: Phystack <dev@phystack.com>
9
9
  License-Expression: MIT
10
10
  Classifier: Development Status :: 3 - Alpha
@@ -22,11 +22,11 @@ Requires-Dist: opencv-python<5.0.0,>=4.8.0
22
22
  Requires-Dist: python-engineio<4.12.0,>=4.9.0
23
23
  Requires-Dist: python-socketio[asyncio-client]<5.12.0,>=5.11.0
24
24
  Provides-Extra: dev
25
- Requires-Dist: black>=23.0.0; extra == 'dev'
25
+ Requires-Dist: black<26,>=25; extra == 'dev'
26
26
  Requires-Dist: mypy>=1.5.0; extra == 'dev'
27
27
  Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
28
28
  Requires-Dist: pytest>=7.4.0; extra == 'dev'
29
- Requires-Dist: ruff>=0.1.0; extra == 'dev'
29
+ Requires-Dist: ruff<0.17,>=0.16; extra == 'dev'
30
30
  Description-Content-Type: text/markdown
31
31
 
32
32
  # Phystack Hub Client (Python)
@@ -36,6 +36,32 @@ Python client for PhyHub that provides:
36
36
  - WebRTC DataChannel for P2P data
37
37
  - WebRTC MediaStream for P2P video/audio (with webcam support)
38
38
 
39
+ Python port of the Node client at `packages/hub-client` (`@phystack/hub-client`);
40
+ both release under the same version.
41
+
42
+ ## Architecture
43
+
44
+ ```mermaid
45
+ graph LR
46
+ App[Python App] --> HubClient[phystack-hub-client]
47
+ HubClient -->|Socket.IO| PhyHub[PhyHub Server]
48
+ HubClient -->|WebRTC| Peer[Peer Twin / Browser]
49
+ PhyHub --> TwinRegistry[Twin Registry]
50
+ PhyHub --> TwinMessaging[Twin Messaging]
51
+ ```
52
+
53
+ ## Tech Stack
54
+
55
+ | Layer | Technology |
56
+ |-------|------------|
57
+ | Language | Python 3.10+ |
58
+ | Build system | Hatch / hatchling |
59
+ | WebSocket | python-socketio (async) |
60
+ | WebRTC | aiortc |
61
+ | Video capture | OpenCV |
62
+ | Linting | Black, Ruff, mypy |
63
+ | Testing | pytest, pytest-asyncio |
64
+
39
65
  ## Installation
40
66
 
41
67
  ```bash
@@ -5,6 +5,32 @@ Python client for PhyHub that provides:
5
5
  - WebRTC DataChannel for P2P data
6
6
  - WebRTC MediaStream for P2P video/audio (with webcam support)
7
7
 
8
+ Python port of the Node client at `packages/hub-client` (`@phystack/hub-client`);
9
+ both release under the same version.
10
+
11
+ ## Architecture
12
+
13
+ ```mermaid
14
+ graph LR
15
+ App[Python App] --> HubClient[phystack-hub-client]
16
+ HubClient -->|Socket.IO| PhyHub[PhyHub Server]
17
+ HubClient -->|WebRTC| Peer[Peer Twin / Browser]
18
+ PhyHub --> TwinRegistry[Twin Registry]
19
+ PhyHub --> TwinMessaging[Twin Messaging]
20
+ ```
21
+
22
+ ## Tech Stack
23
+
24
+ | Layer | Technology |
25
+ |-------|------------|
26
+ | Language | Python 3.10+ |
27
+ | Build system | Hatch / hatchling |
28
+ | WebSocket | python-socketio (async) |
29
+ | WebRTC | aiortc |
30
+ | Video capture | OpenCV |
31
+ | Linting | Black, Ruff, mypy |
32
+ | Testing | pytest, pytest-asyncio |
33
+
8
34
  ## Installation
9
35
 
10
36
  ```bash
@@ -24,7 +24,7 @@ from typing import Any, Optional
24
24
  # Add src to path for local development
25
25
  sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
26
26
 
27
- from phystack.hub_client import PhyHubClient, TwinMessageResult, TwinMessageResultStatus
27
+ from phystack.hub_client import PhyHubClient, TwinMessageResult
28
28
 
29
29
 
30
30
  # ANSI colors
@@ -123,10 +123,13 @@ class BrowserTestRunner:
123
123
 
124
124
  # Send events
125
125
  for i in range(1, expected_count + 1):
126
- instance.to(self.peer_twin_id).emit("test-event", {
127
- "count": i,
128
- "timestamp": int(time.time() * 1000),
129
- })
126
+ instance.to(self.peer_twin_id).emit(
127
+ "test-event",
128
+ {
129
+ "count": i,
130
+ "timestamp": int(time.time() * 1000),
131
+ },
132
+ )
130
133
  log_info(f" Sent event {i}")
131
134
  await asyncio.sleep(0.2)
132
135
 
@@ -302,7 +305,7 @@ async def run_interactive() -> None:
302
305
 
303
306
  try:
304
307
  async with PhyHubClient.from_env() as client:
305
- log_success(f"Connected to PhyHub")
308
+ log_success("Connected to PhyHub")
306
309
 
307
310
  instance = await client.get_instance()
308
311
  if instance:
@@ -317,6 +320,7 @@ async def run_interactive() -> None:
317
320
  except Exception as e:
318
321
  log_error(f"Error: {e}")
319
322
  import traceback
323
+
320
324
  traceback.print_exc()
321
325
  sys.exit(1)
322
326
 
@@ -366,15 +370,20 @@ async def run_continuous() -> None:
366
370
  break
367
371
  elif cmd == "e":
368
372
  if instance:
369
- instance.to(peer_twin_id).emit("test-event", {
370
- "count": 1,
371
- "timestamp": int(time.time() * 1000),
372
- })
373
+ instance.to(peer_twin_id).emit(
374
+ "test-event",
375
+ {
376
+ "count": 1,
377
+ "timestamp": int(time.time() * 1000),
378
+ },
379
+ )
373
380
  log_info("Sent event")
374
381
  elif cmd == "a":
375
382
  if instance:
383
+
376
384
  def cb(r: TwinMessageResult) -> None:
377
385
  log_info(f"Response: {r.status.value} - {r.message}")
386
+
378
387
  instance.to(peer_twin_id).emit("test-action", {"count": 1}, callback=cb)
379
388
  log_info("Sent action")
380
389
  elif cmd == "d":
@@ -4,10 +4,11 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "phystack-hub-client"
7
- # Fixed version group with the Node hub-client (@phystack/hub-client in
8
- # phystack/ps-platform): both clients implement the same twin/WebRTC contract
9
- # and are released together under the same version.
10
- version = "6.18.2"
7
+ # Fixed version group with the Node hub-client (@phystack/hub-client): both
8
+ # clients implement the same twin/WebRTC contract and release under the same
9
+ # version. Managed by scripts/sync-py-version.ts during ci:version - do not
10
+ # edit by hand.
11
+ version = "6.20.0"
11
12
  description = "Python client for PhyHub - events, actions, DataChannel, and MediaStream"
12
13
  readme = "README.md"
13
14
  license = "MIT"
@@ -47,15 +48,17 @@ dependencies = [
47
48
  dev = [
48
49
  "pytest>=7.4.0",
49
50
  "pytest-asyncio>=0.21.0",
50
- "black>=23.0.0",
51
- "ruff>=0.1.0",
51
+ # black/ruff are CI formatting gates; pinned to a minor so a new linter
52
+ # release cannot redden master.
53
+ "black>=25,<26",
54
+ "ruff>=0.16,<0.17",
52
55
  "mypy>=1.5.0",
53
56
  ]
54
57
 
55
58
  [project.urls]
56
- Homepage = "https://github.com/phystack/phystack-pypi"
59
+ Homepage = "https://github.com/phystack/ps-platform"
57
60
  Documentation = "https://docs.phystack.com"
58
- Repository = "https://github.com/phystack/phystack-pypi"
61
+ Repository = "https://github.com/phystack/ps-platform/tree/master/packages/hub-client-py"
59
62
 
60
63
  [tool.hatch.build.targets.wheel]
61
64
  packages = ["src/phystack"]
@@ -66,6 +69,8 @@ target-version = ["py310"]
66
69
 
67
70
  [tool.ruff]
68
71
  line-length = 100
72
+
73
+ [tool.ruff.lint]
69
74
  select = ["E", "F", "I", "W"]
70
75
 
71
76
  [tool.mypy]
@@ -198,7 +198,7 @@ run_python_initiator() {
198
198
  PEER_TWIN_ID="$DEVICE_B_TWIN_ID" \
199
199
  PHYHUB_REGION="$PHYHUB_REGION" \
200
200
  ROLE=initiator \
201
- python tests/test_communication.py 2>&1 | tee "$LOCAL_LOG"
201
+ python tests/communication_harness.py 2>&1 | tee "$LOCAL_LOG"
202
202
  }
203
203
 
204
204
  # Start Python responder
@@ -213,7 +213,7 @@ start_python_responder() {
213
213
  PEER_TWIN_ID="$DEVICE_B_TWIN_ID" \
214
214
  PHYHUB_REGION="$PHYHUB_REGION" \
215
215
  ROLE=responder \
216
- python tests/test_communication.py > "$LOCAL_LOG" 2>&1 &
216
+ python tests/communication_harness.py > "$LOCAL_LOG" 2>&1 &
217
217
 
218
218
  log_info "Waiting for Python responder to be ready..."
219
219
  sleep 5
@@ -259,7 +259,7 @@ collect_results() {
259
259
  cleanup() {
260
260
  log_info "Cleaning up..."
261
261
  pkill -f 'communication-comprehensive-test' 2>/dev/null || true
262
- pkill -f 'test_communication.py' 2>/dev/null || true
262
+ pkill -f 'communication_harness.py' 2>/dev/null || true
263
263
  rm -f "$REMOTE_LOG" "$LOCAL_LOG" 2>/dev/null || true
264
264
  log_success "Cleanup complete"
265
265
  }
@@ -184,7 +184,7 @@ start_remote_responder() {
184
184
  log_info "Starting Python responder on remote host..."
185
185
 
186
186
  # Kill any existing responder process
187
- ssh "$REMOTE_HOST" "pkill -f 'test_communication.py' 2>/dev/null || true"
187
+ ssh "$REMOTE_HOST" "pkill -f 'communication_harness.py' 2>/dev/null || true"
188
188
  sleep 1
189
189
 
190
190
  # Copy env file to remote
@@ -202,7 +202,7 @@ export ACCESS_KEY="\$DEVICE_B_KEY"
202
202
  export PEER_TWIN_ID="\$DEVICE_A_TWIN_ID"
203
203
  export PHYHUB_REGION="\$PHYHUB_REGION"
204
204
  export ROLE=responder
205
- ./venv/bin/python tests/test_communication.py
205
+ ./venv/bin/python tests/communication_harness.py
206
206
  EOF
207
207
  scp -q "$tmp_script" "$REMOTE_HOST:$REMOTE_PATH/run-responder.sh"
208
208
  rm -f "$tmp_script"
@@ -241,7 +241,7 @@ run_local_initiator() {
241
241
  PEER_TWIN_ID="$DEVICE_B_TWIN_ID" \
242
242
  PHYHUB_REGION="$PHYHUB_REGION" \
243
243
  ROLE=initiator \
244
- python tests/test_communication.py 2>&1 | tee "$LOCAL_LOG"
244
+ python tests/communication_harness.py 2>&1 | tee "$LOCAL_LOG"
245
245
  }
246
246
 
247
247
  # Collect and display results
@@ -264,7 +264,7 @@ cleanup() {
264
264
  log_info "Cleaning up..."
265
265
 
266
266
  # Kill remote responder
267
- ssh "$REMOTE_HOST" "pkill -f 'test_communication.py' 2>/dev/null || true"
267
+ ssh "$REMOTE_HOST" "pkill -f 'communication_harness.py' 2>/dev/null || true"
268
268
 
269
269
  # Clean remote logs
270
270
  ssh "$REMOTE_HOST" "rm -f $REMOTE_LOG 2>/dev/null || true"
@@ -281,7 +281,7 @@ cmd_clean() {
281
281
 
282
282
  log_info "Cleaning up remote host..."
283
283
 
284
- ssh "$REMOTE_HOST" "pkill -f 'test_communication.py' 2>/dev/null || true"
284
+ ssh "$REMOTE_HOST" "pkill -f 'communication_harness.py' 2>/dev/null || true"
285
285
  ssh "$REMOTE_HOST" "rm -rf $REMOTE_PATH 2>/dev/null || true"
286
286
  ssh "$REMOTE_HOST" "rm -f $REMOTE_LOG 2>/dev/null || true"
287
287
 
@@ -44,44 +44,61 @@ Or with context manager:
44
44
  stream = await instance.get_media_stream(peer_twin_id)
45
45
  """
46
46
 
47
+ from importlib.metadata import PackageNotFoundError, version
48
+
49
+ from phystack.hub_client.advisory_validation import (
50
+ CompiledValidator,
51
+ DescriptorValidator,
52
+ validate_emitted_facet,
53
+ )
47
54
  from phystack.hub_client.client import PhyHubClient, connect_phy_client
48
- from phystack.hub_client.types.twin_types import (
49
- PeripheralCreateResult,
50
- PeripheralHandover,
51
- PeripheralOwnershipLoss,
52
- TwinMessageResult,
53
- TwinMessageResultStatus,
54
- TwinProperties,
55
- TwinTypeEnum,
56
- TwinStatusEnum,
55
+ from phystack.hub_client.cloud_twins import CloudTwinStore
56
+ from phystack.hub_client.instances import (
57
+ BaseInstance,
58
+ EdgeInstance,
59
+ PeripheralInstance,
57
60
  )
58
61
  from phystack.hub_client.scoped_hardware_id import (
59
62
  HARDWARE_ID_SCOPES,
60
63
  HARDWARE_ID_USER_PART_MAX_LENGTH,
61
64
  format_scoped_hardware_id,
62
65
  )
63
- from phystack.hub_client.instances import (
64
- BaseInstance,
65
- EdgeInstance,
66
- PeripheralInstance,
66
+ from phystack.hub_client.services.cloud_app_connection import (
67
+ CloudAppConnection,
68
+ CloudAppConnectionParams,
69
+ CloudAppConnectResult,
70
+ )
71
+ from phystack.hub_client.services.cloud_app_token import (
72
+ CloudAppToken,
73
+ CloudAppTokenExchangeError,
74
+ exchange_cloud_app_token,
75
+ )
76
+ from phystack.hub_client.services.signals import (
77
+ CheckoutProduct,
78
+ CheckoutProps,
79
+ DataRequestTypeEnum,
80
+ DataResidencyEnum,
81
+ EventTypeEnum,
82
+ InitSignalPayload,
83
+ PurchaseProps,
84
+ SignalsService,
85
+ )
86
+ from phystack.hub_client.services.web_session_code import (
87
+ WebSessionCode,
88
+ WebSessionCodeConfigError,
89
+ WebSessionCodeIssuer,
90
+ WebSessionCodeListener,
91
+ WebSessionCodeState,
67
92
  )
68
- from phystack.hub_client.twin_registry import TwinRegistry
69
93
  from phystack.hub_client.services.webrtc.data_channel import (
70
94
  DataChannelHandler,
71
95
  DataChannelOptions,
72
96
  PhygridDataChannel,
73
97
  )
74
- from phystack.hub_client.services.webrtc.media_stream import (
75
- MediaStreamHandler,
76
- MediaStreamOptions,
77
- MediaTrackKind,
78
- MissingMediaTrackError,
79
- PhygridMediaStream,
80
- WebcamVideoTrack,
81
- )
82
- from phystack.hub_client.services.webrtc.media_source import (
83
- FrameSourceTrack,
84
- VideoFrameSource,
98
+ from phystack.hub_client.services.webrtc.data_responder import (
99
+ DataChannelResponder,
100
+ DataChannelResponderOptions,
101
+ ResponderChannel,
85
102
  )
86
103
  from phystack.hub_client.services.webrtc.media_responder import (
87
104
  MediaStreamResponder,
@@ -89,48 +106,37 @@ from phystack.hub_client.services.webrtc.media_responder import (
89
106
  PeerCapReachedError,
90
107
  ResponderPeer,
91
108
  )
92
- from phystack.hub_client.services.webrtc.data_responder import (
93
- DataChannelResponder,
94
- DataChannelResponderOptions,
95
- ResponderChannel,
96
- )
97
- from phystack.hub_client.advisory_validation import (
98
- CompiledValidator,
99
- DescriptorValidator,
100
- validate_emitted_facet,
101
- )
102
- from phystack.hub_client.services.cloud_app_token import (
103
- CloudAppToken,
104
- CloudAppTokenExchangeError,
105
- exchange_cloud_app_token,
106
- )
107
- from phystack.hub_client.services.cloud_app_connection import (
108
- CloudAppConnection,
109
- CloudAppConnectionParams,
110
- CloudAppConnectResult,
109
+ from phystack.hub_client.services.webrtc.media_source import (
110
+ FrameSourceTrack,
111
+ VideoFrameSource,
111
112
  )
112
- from phystack.hub_client.cloud_twins import CloudTwinStore
113
- from phystack.hub_client.services.web_session_code import (
114
- WebSessionCode,
115
- WebSessionCodeConfigError,
116
- WebSessionCodeIssuer,
117
- WebSessionCodeListener,
118
- WebSessionCodeState,
113
+ from phystack.hub_client.services.webrtc.media_stream import (
114
+ MediaStreamHandler,
115
+ MediaStreamOptions,
116
+ MediaTrackKind,
117
+ MissingMediaTrackError,
118
+ PhygridMediaStream,
119
+ WebcamVideoTrack,
119
120
  )
120
- from phystack.hub_client.services.signals import (
121
- SignalsService,
122
- InitSignalPayload,
123
- DataRequestTypeEnum,
124
- DataResidencyEnum,
125
- EventTypeEnum,
126
- CheckoutProps,
127
- CheckoutProduct,
128
- PurchaseProps,
121
+ from phystack.hub_client.twin_registry import TwinRegistry
122
+ from phystack.hub_client.types.twin_types import (
123
+ PeripheralCreateResult,
124
+ PeripheralHandover,
125
+ PeripheralOwnershipLoss,
126
+ TwinMessageResult,
127
+ TwinMessageResultStatus,
128
+ TwinProperties,
129
+ TwinStatusEnum,
130
+ TwinTypeEnum,
129
131
  )
130
132
 
131
133
  # Kept in a fixed version group with @phystack/hub-client (npm) — same
132
134
  # contract, same release version.
133
- __version__ = "6.16.0"
135
+ try:
136
+ __version__ = version("phystack-hub-client")
137
+ except PackageNotFoundError:
138
+ # Running from an uninstalled source tree (no dist metadata).
139
+ __version__ = "0.0.0"
134
140
  __all__ = [
135
141
  # Client
136
142
  "PhyHubClient",