spatialreal 0.2.2__tar.gz → 0.2.3__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: spatialreal
3
- Version: 0.2.2
3
+ Version: 0.2.3
4
4
  Summary: SpatialReal Python SDK — realtime avatar sessions (audio in, animation/egress out)
5
5
  Project-URL: Documentation, https://docs.spatialreal.ai
6
6
  Project-URL: Website, https://www.spatialreal.ai/
@@ -22,10 +22,10 @@ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
22
22
  Requires-Python: >=3.10.0
23
23
  Requires-Dist: aiohttp>=3.9
24
24
  Requires-Dist: nanoid>=2.0
25
- Requires-Dist: protobuf<8,>=6.31
25
+ Requires-Dist: protobuf<8,>=5.29
26
26
  Requires-Dist: websockets>=12
27
27
  Provides-Extra: dev
28
- Requires-Dist: grpcio-tools==1.75.1; extra == 'dev'
28
+ Requires-Dist: grpcio-tools==1.71.2; extra == 'dev'
29
29
  Requires-Dist: pytest; extra == 'dev'
30
30
  Requires-Dist: pytest-asyncio; extra == 'dev'
31
31
  Requires-Dist: ruff; extra == 'dev'
@@ -46,8 +46,8 @@ from spatialreal import LiveKitEgressConfig, new_avatar_session
46
46
 
47
47
  session = new_avatar_session(
48
48
  api_key="...",
49
- app_id="...",
50
49
  avatar_id="...",
50
+ # app_id is optional: the app is derived from the API key server-side
51
51
  expire_at=datetime.now(timezone.utc) + timedelta(hours=1),
52
52
  sample_rate=16000,
53
53
  livekit_egress=LiveKitEgressConfig(url=..., api_token=..., room_name=..., publisher_id=...),
@@ -102,6 +102,8 @@ implements the server's WebSocket close-code contract (40xx: don't retry,
102
102
 
103
103
  ## What's new
104
104
 
105
+ - 0.2.3: `app_id` is optional (the API key identifies the app); protobuf floor lowered
106
+ to 5.29 so the SDK installs next to packages that pin protobuf 5.x (TEN Framework agents).
105
107
  - `on_playback(PlaybackSignal)` — structured playback lifecycle; no protobuf
106
108
  parsing in caller code (`transport_frames(raw, is_last)` still exists).
107
109
  - `CloseCode` + `AvatarSDKError.retryable` — the reconnect contract as API.
@@ -13,8 +13,8 @@ from spatialreal import LiveKitEgressConfig, new_avatar_session
13
13
 
14
14
  session = new_avatar_session(
15
15
  api_key="...",
16
- app_id="...",
17
16
  avatar_id="...",
17
+ # app_id is optional: the app is derived from the API key server-side
18
18
  expire_at=datetime.now(timezone.utc) + timedelta(hours=1),
19
19
  sample_rate=16000,
20
20
  livekit_egress=LiveKitEgressConfig(url=..., api_token=..., room_name=..., publisher_id=...),
@@ -69,6 +69,8 @@ implements the server's WebSocket close-code contract (40xx: don't retry,
69
69
 
70
70
  ## What's new
71
71
 
72
+ - 0.2.3: `app_id` is optional (the API key identifies the app); protobuf floor lowered
73
+ to 5.29 so the SDK installs next to packages that pin protobuf 5.x (TEN Framework agents).
72
74
  - `on_playback(PlaybackSignal)` — structured playback lifecycle; no protobuf
73
75
  parsing in caller code (`transport_frames(raw, is_last)` still exists).
74
76
  - `CloseCode` + `AvatarSDKError.retryable` — the reconnect contract as API.
@@ -26,12 +26,12 @@ classifiers = [
26
26
  dependencies = [
27
27
  "aiohttp>=3.9",
28
28
  "websockets>=12",
29
- "protobuf>=6.31,<8",
29
+ "protobuf>=5.29,<8",
30
30
  "nanoid>=2.0",
31
31
  ]
32
32
 
33
33
  [project.optional-dependencies]
34
- dev = ["pytest", "pytest-asyncio", "grpcio-tools==1.75.1", "ruff"]
34
+ dev = ["pytest", "pytest-asyncio", "grpcio-tools==1.71.2", "ruff"]
35
35
 
36
36
  [project.urls]
37
37
  Documentation = "https://docs.spatialreal.ai"
@@ -2,7 +2,7 @@
2
2
  # Generated by the protocol buffer compiler. DO NOT EDIT!
3
3
  # NO CHECKED-IN PROTOBUF GENCODE
4
4
  # source: driveningress/v2/driveningress.proto
5
- # Protobuf Python Version: 6.31.1
5
+ # Protobuf Python Version: 5.29.0
6
6
  """Generated protocol buffer code."""
7
7
  from google.protobuf import descriptor as _descriptor
8
8
  from google.protobuf import descriptor_pool as _descriptor_pool
@@ -11,9 +11,9 @@ from google.protobuf import symbol_database as _symbol_database
11
11
  from google.protobuf.internal import builder as _builder
12
12
  _runtime_version.ValidateProtobufRuntimeVersion(
13
13
  _runtime_version.Domain.PUBLIC,
14
- 6,
15
- 31,
16
- 1,
14
+ 5,
15
+ 29,
16
+ 0,
17
17
  '',
18
18
  'driveningress/v2/driveningress.proto'
19
19
  )
@@ -2,8 +2,7 @@ from google.protobuf.internal import containers as _containers
2
2
  from google.protobuf.internal import enum_type_wrapper as _enum_type_wrapper
3
3
  from google.protobuf import descriptor as _descriptor
4
4
  from google.protobuf import message as _message
5
- from collections.abc import Iterable as _Iterable, Mapping as _Mapping
6
- from typing import ClassVar as _ClassVar, Optional as _Optional, Union as _Union
5
+ from typing import ClassVar as _ClassVar, Iterable as _Iterable, Mapping as _Mapping, Optional as _Optional, Union as _Union
7
6
 
8
7
  DESCRIPTOR: _descriptor.FileDescriptor
9
8
 
@@ -155,8 +155,6 @@ class AvatarSession:
155
155
  raise ValueError("Session not initialized (call init() first)")
156
156
  if not self._config.avatar_id:
157
157
  raise ValueError("Missing avatar ID")
158
- if not self._config.app_id:
159
- raise ValueError("Missing app ID")
160
158
  if self._config.livekit_egress is not None and self._config.agora_egress is not None:
161
159
  raise ValueError("Cannot configure both livekit_egress and agora_egress")
162
160
 
@@ -192,12 +190,17 @@ class AvatarSession:
192
190
 
193
191
  query = parse_qs(parsed.query)
194
192
  query["id"] = [self._config.avatar_id]
193
+ # The app is derived server-side from the API key; ``app_id`` is optional and only
194
+ # forwarded when set (the server ignores an absent X-App-ID / appId).
195
195
  headers: dict[str, str] = {}
196
196
  if self._config.use_query_auth:
197
- query["appId"] = [self._config.app_id]
197
+ if self._config.app_id:
198
+ query["appId"] = [self._config.app_id]
198
199
  query["sessionKey"] = [self._session_token or ""]
199
200
  else:
200
- headers = {"X-App-ID": self._config.app_id, "X-Session-Key": self._session_token or ""}
201
+ headers = {"X-Session-Key": self._session_token or ""}
202
+ if self._config.app_id:
203
+ headers["X-App-ID"] = self._config.app_id
201
204
 
202
205
  return (
203
206
  urlunparse((ws_scheme, parsed.netloc, parsed.path, parsed.params, urlencode(query, doseq=True), "")),
@@ -0,0 +1 @@
1
+ __version__ = "0.2.3"
@@ -1 +0,0 @@
1
- __version__ = "0.2.2"
File without changes
File without changes