vision-agents 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.
Files changed (73) hide show
  1. vision_agents-0.2.3/.gitignore +90 -0
  2. vision_agents-0.2.3/PKG-INFO +91 -0
  3. vision_agents-0.2.3/README.md +13 -0
  4. vision_agents-0.2.3/pyproject.toml +91 -0
  5. vision_agents-0.2.3/vision_agents/PROTOBUF_GENERATION.md +286 -0
  6. vision_agents-0.2.3/vision_agents/_generate_sfu_events.py +590 -0
  7. vision_agents-0.2.3/vision_agents/core/__init__.py +8 -0
  8. vision_agents-0.2.3/vision_agents/core/agents/__init__.py +15 -0
  9. vision_agents-0.2.3/vision_agents/core/agents/agent_launcher.py +131 -0
  10. vision_agents-0.2.3/vision_agents/core/agents/agent_session.py +89 -0
  11. vision_agents-0.2.3/vision_agents/core/agents/agent_types.py +56 -0
  12. vision_agents-0.2.3/vision_agents/core/agents/agents.py +1357 -0
  13. vision_agents-0.2.3/vision_agents/core/agents/conversation.py +237 -0
  14. vision_agents-0.2.3/vision_agents/core/agents/events.py +66 -0
  15. vision_agents-0.2.3/vision_agents/core/agents/transcript_buffer.py +89 -0
  16. vision_agents-0.2.3/vision_agents/core/cli/__init__.py +0 -0
  17. vision_agents-0.2.3/vision_agents/core/cli/cli_runner.py +140 -0
  18. vision_agents-0.2.3/vision_agents/core/cli.py +92 -0
  19. vision_agents-0.2.3/vision_agents/core/edge/__init__.py +9 -0
  20. vision_agents-0.2.3/vision_agents/core/edge/edge_transport.py +61 -0
  21. vision_agents-0.2.3/vision_agents/core/edge/events.py +43 -0
  22. vision_agents-0.2.3/vision_agents/core/edge/sfu_events.py +2360 -0
  23. vision_agents-0.2.3/vision_agents/core/edge/types.py +49 -0
  24. vision_agents-0.2.3/vision_agents/core/events/__init__.py +131 -0
  25. vision_agents-0.2.3/vision_agents/core/events/base.py +139 -0
  26. vision_agents-0.2.3/vision_agents/core/events/manager.py +561 -0
  27. vision_agents-0.2.3/vision_agents/core/instructions.py +115 -0
  28. vision_agents-0.2.3/vision_agents/core/llm/__init__.py +13 -0
  29. vision_agents-0.2.3/vision_agents/core/llm/events.py +153 -0
  30. vision_agents-0.2.3/vision_agents/core/llm/function_registry.py +282 -0
  31. vision_agents-0.2.3/vision_agents/core/llm/llm.py +455 -0
  32. vision_agents-0.2.3/vision_agents/core/llm/llm_test.py +21 -0
  33. vision_agents-0.2.3/vision_agents/core/llm/llm_types.py +166 -0
  34. vision_agents-0.2.3/vision_agents/core/llm/realtime.py +188 -0
  35. vision_agents-0.2.3/vision_agents/core/llm/wrap_function.py +51 -0
  36. vision_agents-0.2.3/vision_agents/core/llm/wrap_method.py +60 -0
  37. vision_agents-0.2.3/vision_agents/core/mcp/__init__.py +15 -0
  38. vision_agents-0.2.3/vision_agents/core/mcp/mcp_base.py +189 -0
  39. vision_agents-0.2.3/vision_agents/core/mcp/mcp_manager.py +158 -0
  40. vision_agents-0.2.3/vision_agents/core/mcp/mcp_server_local.py +146 -0
  41. vision_agents-0.2.3/vision_agents/core/mcp/mcp_server_remote.py +153 -0
  42. vision_agents-0.2.3/vision_agents/core/mcp/tool_converter.py +101 -0
  43. vision_agents-0.2.3/vision_agents/core/observability/__init__.py +31 -0
  44. vision_agents-0.2.3/vision_agents/core/observability/metrics.py +77 -0
  45. vision_agents-0.2.3/vision_agents/core/processors/__init__.py +34 -0
  46. vision_agents-0.2.3/vision_agents/core/processors/base_processor.py +207 -0
  47. vision_agents-0.2.3/vision_agents/core/profiling/__init__.py +3 -0
  48. vision_agents-0.2.3/vision_agents/core/profiling/base.py +49 -0
  49. vision_agents-0.2.3/vision_agents/core/stt/__init__.py +4 -0
  50. vision_agents-0.2.3/vision_agents/core/stt/events.py +104 -0
  51. vision_agents-0.2.3/vision_agents/core/stt/stt.py +175 -0
  52. vision_agents-0.2.3/vision_agents/core/tts/__init__.py +3 -0
  53. vision_agents-0.2.3/vision_agents/core/tts/events.py +72 -0
  54. vision_agents-0.2.3/vision_agents/core/tts/manual_test.py +135 -0
  55. vision_agents-0.2.3/vision_agents/core/tts/testing.py +129 -0
  56. vision_agents-0.2.3/vision_agents/core/tts/tts.py +314 -0
  57. vision_agents-0.2.3/vision_agents/core/turn_detection/README.md +113 -0
  58. vision_agents-0.2.3/vision_agents/core/turn_detection/__init__.py +18 -0
  59. vision_agents-0.2.3/vision_agents/core/turn_detection/events.py +49 -0
  60. vision_agents-0.2.3/vision_agents/core/turn_detection/turn_detection.py +92 -0
  61. vision_agents-0.2.3/vision_agents/core/utils/__init__.py +13 -0
  62. vision_agents-0.2.3/vision_agents/core/utils/audio_forwarder.py +67 -0
  63. vision_agents-0.2.3/vision_agents/core/utils/audio_queue.py +275 -0
  64. vision_agents-0.2.3/vision_agents/core/utils/audio_track.py +11 -0
  65. vision_agents-0.2.3/vision_agents/core/utils/examples.py +42 -0
  66. vision_agents-0.2.3/vision_agents/core/utils/logging.py +108 -0
  67. vision_agents-0.2.3/vision_agents/core/utils/utils.py +83 -0
  68. vision_agents-0.2.3/vision_agents/core/utils/video_forwarder.py +185 -0
  69. vision_agents-0.2.3/vision_agents/core/utils/video_queue.py +30 -0
  70. vision_agents-0.2.3/vision_agents/core/utils/video_track.py +90 -0
  71. vision_agents-0.2.3/vision_agents/core/utils/video_utils.py +127 -0
  72. vision_agents-0.2.3/vision_agents/core/vad/__init__.py +0 -0
  73. vision_agents-0.2.3/vision_agents/core/vad/silero.py +96 -0
@@ -0,0 +1,90 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .cursor/*
7
+ # Distribution / packaging
8
+ .Python
9
+ build/
10
+ dist/
11
+ downloads/
12
+ develop-eggs/
13
+ eggs/
14
+ .eggs/
15
+ lib64/
16
+ parts/
17
+ sdist/
18
+ var/
19
+ wheels/
20
+ share/python-wheels/
21
+ pip-wheel-metadata/
22
+ MANIFEST
23
+ *.egg-info/
24
+ *.egg
25
+
26
+ # Installer logs
27
+ pip-log.txt
28
+ pip-delete-this-directory.txt
29
+
30
+ # Unit test / coverage reports
31
+ htmlcov/
32
+ .tox/
33
+ .nox/
34
+ .coverage
35
+ .coverage.*
36
+ .cache
37
+ coverage.xml
38
+ nosetests.xml
39
+ *.cover
40
+ *.py,cover
41
+ .hypothesis/
42
+ .pytest_cache/
43
+
44
+ # Type checker / lint caches
45
+ .mypy_cache/
46
+ .dmypy.json
47
+ dmypy.json
48
+ .pytype/
49
+ .pyre/
50
+ .ruff_cache/
51
+
52
+ # Environments
53
+ .venv
54
+ env/
55
+ venv/
56
+ ENV/
57
+ env.bak/
58
+ venv.bak/
59
+ .env
60
+ .env.local
61
+ .env.*.local
62
+ .env.bak
63
+ pyvenv.cfg
64
+ .python-version
65
+
66
+ # Editors / IDEs
67
+ .vscode/
68
+ .idea/
69
+
70
+ # Jupyter Notebook
71
+ .ipynb_checkpoints/
72
+
73
+ # OS / Misc
74
+ .DS_Store
75
+ *.log
76
+
77
+ # Tooling & repo-specific
78
+ pyrightconfig.json
79
+ shell.nix
80
+ bin/*
81
+ lib/*
82
+ stream-py/
83
+
84
+ # Artifacts / assets
85
+ *.pt
86
+ *.kef
87
+ *.onnx
88
+ profile.html
89
+
90
+ /opencode.json
@@ -0,0 +1,91 @@
1
+ Metadata-Version: 2.4
2
+ Name: vision-agents
3
+ Version: 0.2.3
4
+ Summary: Open video agents. Build low latency video and voice agents on any realtime edge network.
5
+ Project-URL: Documentation, https://visionagents.ai/
6
+ Project-URL: Website, https://visionagents.ai/
7
+ Project-URL: Source, https://github.com/GetStream/Vision-Agents
8
+ Keywords: AI,agents,video AI,video agents,voice AI,voice agents
9
+ Classifier: Operating System :: OS Independent
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.10
12
+ Classifier: Programming Language :: Python :: 3.11
13
+ Classifier: Programming Language :: Python :: 3.12
14
+ Classifier: Programming Language :: Python :: 3.13
15
+ Classifier: Programming Language :: Python :: Implementation :: CPython
16
+ Requires-Python: >=3.10
17
+ Requires-Dist: colorlog>=6.10.1
18
+ Requires-Dist: getstream[telemetry,webrtc]>=2.5.16
19
+ Requires-Dist: mcp>=1.16.0
20
+ Requires-Dist: numpy>=1.24.0
21
+ Requires-Dist: pillow>=10.4.0
22
+ Requires-Dist: python-dotenv>=1.1.1
23
+ Provides-Extra: all-plugins
24
+ Requires-Dist: vision-agents-plugins-anthropic; extra == 'all-plugins'
25
+ Requires-Dist: vision-agents-plugins-cartesia; extra == 'all-plugins'
26
+ Requires-Dist: vision-agents-plugins-deepgram; extra == 'all-plugins'
27
+ Requires-Dist: vision-agents-plugins-elevenlabs; extra == 'all-plugins'
28
+ Requires-Dist: vision-agents-plugins-gemini; extra == 'all-plugins'
29
+ Requires-Dist: vision-agents-plugins-getstream; extra == 'all-plugins'
30
+ Requires-Dist: vision-agents-plugins-heygen; extra == 'all-plugins'
31
+ Requires-Dist: vision-agents-plugins-inworld; extra == 'all-plugins'
32
+ Requires-Dist: vision-agents-plugins-kokoro; extra == 'all-plugins'
33
+ Requires-Dist: vision-agents-plugins-moonshine; extra == 'all-plugins'
34
+ Requires-Dist: vision-agents-plugins-openai; extra == 'all-plugins'
35
+ Requires-Dist: vision-agents-plugins-roboflow; extra == 'all-plugins'
36
+ Requires-Dist: vision-agents-plugins-smart-turn; extra == 'all-plugins'
37
+ Requires-Dist: vision-agents-plugins-ultralytics; extra == 'all-plugins'
38
+ Requires-Dist: vision-agents-plugins-wizper; extra == 'all-plugins'
39
+ Requires-Dist: vision-agents-plugins-xai; extra == 'all-plugins'
40
+ Provides-Extra: anthropic
41
+ Requires-Dist: vision-agents-plugins-anthropic; extra == 'anthropic'
42
+ Provides-Extra: cartesia
43
+ Requires-Dist: vision-agents-plugins-cartesia; extra == 'cartesia'
44
+ Provides-Extra: deepgram
45
+ Requires-Dist: vision-agents-plugins-deepgram; extra == 'deepgram'
46
+ Provides-Extra: dev
47
+ Requires-Dist: click; extra == 'dev'
48
+ Requires-Dist: mypy; extra == 'dev'
49
+ Requires-Dist: pytest; extra == 'dev'
50
+ Requires-Dist: ruff; extra == 'dev'
51
+ Provides-Extra: elevenlabs
52
+ Requires-Dist: vision-agents-plugins-elevenlabs; extra == 'elevenlabs'
53
+ Provides-Extra: gemini
54
+ Requires-Dist: vision-agents-plugins-gemini; extra == 'gemini'
55
+ Provides-Extra: getstream
56
+ Requires-Dist: vision-agents-plugins-getstream; extra == 'getstream'
57
+ Provides-Extra: heygen
58
+ Requires-Dist: vision-agents-plugins-heygen; extra == 'heygen'
59
+ Provides-Extra: inworld
60
+ Requires-Dist: vision-agents-plugins-inworld; extra == 'inworld'
61
+ Provides-Extra: kokoro
62
+ Requires-Dist: vision-agents-plugins-kokoro; extra == 'kokoro'
63
+ Provides-Extra: moonshine
64
+ Requires-Dist: vision-agents-plugins-moonshine; extra == 'moonshine'
65
+ Provides-Extra: openai
66
+ Requires-Dist: vision-agents-plugins-openai; extra == 'openai'
67
+ Provides-Extra: roboflow
68
+ Requires-Dist: vision-agents-plugins-roboflow; extra == 'roboflow'
69
+ Provides-Extra: smart-turn
70
+ Requires-Dist: vision-agents-plugins-smart-turn; extra == 'smart-turn'
71
+ Provides-Extra: ultralytics
72
+ Requires-Dist: vision-agents-plugins-ultralytics; extra == 'ultralytics'
73
+ Provides-Extra: wizper
74
+ Requires-Dist: vision-agents-plugins-wizper; extra == 'wizper'
75
+ Provides-Extra: xai
76
+ Requires-Dist: vision-agents-plugins-xai; extra == 'xai'
77
+ Description-Content-Type: text/markdown
78
+
79
+ # Open Vision Agents by Stream
80
+
81
+ Build Vision Agents quickly with any model or video provider.
82
+
83
+ - **Video AI**: Built for real-time video AI. Combine Yolo, Roboflow and others with gemini/openai realtime
84
+ - **Low Latency**: Join quickly (500ms) and low audio/video latency (30ms)
85
+ - **Open**: Built by Stream, but use any video edge network that you like
86
+ - **Native APIs**: Native SDK methods from OpenAI (create response), Gemini (generate) and Claude (create message). So you're never behind on the latest features
87
+ - **SDKs**: SDKs for React, Android, iOS, Flutter, React, React Native and Unity.
88
+
89
+ Created by Stream, uses [Stream's edge network](https://getstream.io/video/) for ultra-low latency.
90
+
91
+ See [Github](https://github.com/GetStream/Vision-Agents).
@@ -0,0 +1,13 @@
1
+ # Open Vision Agents by Stream
2
+
3
+ Build Vision Agents quickly with any model or video provider.
4
+
5
+ - **Video AI**: Built for real-time video AI. Combine Yolo, Roboflow and others with gemini/openai realtime
6
+ - **Low Latency**: Join quickly (500ms) and low audio/video latency (30ms)
7
+ - **Open**: Built by Stream, but use any video edge network that you like
8
+ - **Native APIs**: Native SDK methods from OpenAI (create response), Gemini (generate) and Claude (create message). So you're never behind on the latest features
9
+ - **SDKs**: SDKs for React, Android, iOS, Flutter, React, React Native and Unity.
10
+
11
+ Created by Stream, uses [Stream's edge network](https://getstream.io/video/) for ultra-low latency.
12
+
13
+ See [Github](https://github.com/GetStream/Vision-Agents).
@@ -0,0 +1,91 @@
1
+ [build-system]
2
+ requires = ["hatchling", "hatch-vcs", "setuptools-scm"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "vision-agents"
7
+ description = "Open video agents. Build low latency video and voice agents on any realtime edge network."
8
+ readme = "README.md"
9
+ keywords = ["video AI", "AI", "voice AI", "video agents", "voice agents", "agents", "AI"]
10
+ dynamic = ["version"]
11
+
12
+ classifiers = [
13
+ "Programming Language :: Python :: 3",
14
+ "Programming Language :: Python :: 3.10",
15
+ "Programming Language :: Python :: 3.11",
16
+ "Programming Language :: Python :: 3.12",
17
+ "Programming Language :: Python :: 3.13",
18
+ "Programming Language :: Python :: Implementation :: CPython",
19
+ "Operating System :: OS Independent",
20
+ ]
21
+
22
+ requires-python = ">=3.10"
23
+ dependencies = [
24
+ "getstream[webrtc,telemetry]>=2.5.16",
25
+ "python-dotenv>=1.1.1",
26
+ "pillow>=10.4.0", # Compatible with moondream SDK (<11.0.0)
27
+ "numpy>=1.24.0",
28
+ "mcp>=1.16.0",
29
+ "colorlog>=6.10.1",
30
+ ]
31
+
32
+ [project.urls]
33
+ Documentation = "https://visionagents.ai/"
34
+ Website = "https://visionagents.ai/"
35
+ Source = "https://github.com/GetStream/Vision-Agents"
36
+
37
+ [project.optional-dependencies]
38
+ dev = ["pytest", "mypy", "ruff", "click"]
39
+ anthropic = ["vision-agents-plugins-anthropic"]
40
+ cartesia = ["vision-agents-plugins-cartesia"]
41
+ deepgram = ["vision-agents-plugins-deepgram"]
42
+ elevenlabs = ["vision-agents-plugins-elevenlabs"]
43
+ gemini = ["vision-agents-plugins-gemini"]
44
+ getstream = ["vision-agents-plugins-getstream"]
45
+ heygen = ["vision-agents-plugins-heygen"]
46
+ inworld = ["vision-agents-plugins-inworld"]
47
+ kokoro = ["vision-agents-plugins-kokoro"]
48
+ moonshine = ["vision-agents-plugins-moonshine"]
49
+ openai = ["vision-agents-plugins-openai"]
50
+ roboflow = ["vision-agents-plugins-roboflow"]
51
+ smart_turn = ["vision-agents-plugins-smart-turn"]
52
+ ultralytics = ["vision-agents-plugins-ultralytics"]
53
+ wizper = ["vision-agents-plugins-wizper"]
54
+ xai = ["vision-agents-plugins-xai"]
55
+ all-plugins = [
56
+ "vision-agents-plugins-anthropic",
57
+ "vision-agents-plugins-cartesia",
58
+ "vision-agents-plugins-deepgram",
59
+ "vision-agents-plugins-elevenlabs",
60
+ "vision-agents-plugins-gemini",
61
+ "vision-agents-plugins-getstream",
62
+ "vision-agents-plugins-heygen",
63
+ "vision-agents-plugins-inworld",
64
+ "vision-agents-plugins-kokoro",
65
+ "vision-agents-plugins-moonshine",
66
+ "vision-agents-plugins-roboflow",
67
+ "vision-agents-plugins-openai",
68
+ "vision-agents-plugins-smart-turn",
69
+ "vision-agents-plugins-ultralytics",
70
+ "vision-agents-plugins-wizper",
71
+ "vision-agents-plugins-xai",
72
+ ]
73
+
74
+ [tool.hatch.metadata]
75
+ allow-direct-references = true
76
+
77
+ [tool.hatch.version]
78
+ source = "vcs"
79
+ raw-options = { root = "..", search_parent_directories = true, fallback_version = "0.0.0" }
80
+
81
+ [tool.hatch.build.targets.wheel]
82
+ packages = ["vision_agents"]
83
+
84
+ [tool.hatch.build.targets.sdist]
85
+ include = ["vision_agents"]
86
+
87
+ #[tool.uv.sources]
88
+ # getstream = { git = "https://github.com/GetStream/stream-py.git", branch = "audio-more" }
89
+ # for local development
90
+ # getstream = { path = "../../stream-py/", editable = true }
91
+ # aiortc = { path = "../stream-py/", editable = true }
@@ -0,0 +1,286 @@
1
+ # Protobuf Event Generation
2
+
3
+ ## Overview
4
+
5
+ The `_generate_sfu_events.py` script automatically generates Python dataclass wrappers for protobuf messages from the SFU (Selective Forwarding Unit) event system. These generated classes inherit from `BaseEvent` and provide type-safe access to protobuf fields with all fields being optional.
6
+
7
+ ## Location
8
+
9
+ - **Generator Script**: `agents-core/vision_agents/_generate_sfu_events.py`
10
+ - **Generated Output**: `agents-core/vision_agents/core/edge/sfu_events.py`
11
+
12
+ ## Key Features
13
+
14
+ ### 1. BaseEvent Inheritance
15
+
16
+ All generated classes inherit from `BaseEvent`, providing:
17
+ - `type`: Event type identifier (auto-set from protobuf full name)
18
+ - `event_id`: Unique identifier (auto-generated UUID)
19
+ - `timestamp`: Event creation time (auto-generated)
20
+ - `session_id`: Optional session identifier
21
+ - `user_metadata`: Optional user metadata
22
+
23
+ ### 2. Optional Fields
24
+
25
+ All fields are optional, allowing event creation without a payload:
26
+
27
+ ```python
28
+ event = AudioLevelEvent() # All fields are optional
29
+ ```
30
+
31
+ ### 3. Advanced Type Mapping
32
+
33
+ The generator uses `_get_python_type_from_protobuf_field()` to map protobuf types to Python types with **full nested message type resolution**:
34
+
35
+ - Protobuf scalar types → Python primitives (int, float, str, bool, bytes)
36
+ - Protobuf repeated fields → `Optional[List[T]]`
37
+ - **Protobuf message types → Proper typed dataclass wrappers** (e.g., `Optional[Participant]`)
38
+ - Protobuf enum types → `Optional[int]`
39
+
40
+ All types are wrapped in `Optional` for flexibility.
41
+
42
+ #### Message Type Wrappers
43
+
44
+ The generator automatically creates dataclass wrappers for all protobuf message types used in events. These wrappers:
45
+ - Are placed at the top of the generated file
46
+ - Include all fields with proper Python types
47
+ - Support nested message types recursively
48
+ - Provide `from_proto()` class method for conversion
49
+ - Are fully typed for IDE autocomplete and type checking
50
+
51
+ Example:
52
+ ```python
53
+ @dataclass
54
+ class Participant(DataClassJsonMixin):
55
+ """Wrapper for stream.video.sfu.models.Participant."""
56
+ user_id: Optional[str] = None
57
+ session_id: Optional[str] = None
58
+ name: Optional[str] = None
59
+ is_speaking: Optional[bool] = None
60
+ audio_level: Optional[float] = None
61
+ # ... all other fields
62
+
63
+ @classmethod
64
+ def from_proto(cls, proto_obj) -> 'Participant':
65
+ """Create from protobuf Participant."""
66
+ # ... conversion logic
67
+ ```
68
+
69
+ ### 4. Property-Based Access
70
+
71
+ Protobuf fields are exposed as properties with proper type hints:
72
+
73
+ ```python
74
+ @property
75
+ def user_id(self) -> Optional[str]:
76
+ """Access user_id field from the protobuf payload."""
77
+ if self.payload is None:
78
+ return None
79
+ return getattr(self.payload, 'user_id', None)
80
+ ```
81
+
82
+ ### 5. Protobuf Integration
83
+
84
+ Each generated class provides:
85
+ - `from_proto(proto_obj)`: Create event from protobuf message
86
+ - `as_dict()`: Convert protobuf payload to dictionary
87
+ - `__getattr__()`: Delegate attribute access to protobuf payload
88
+
89
+ ## Usage
90
+
91
+ ### Regenerating Events
92
+
93
+ ```bash
94
+ cd agents-core
95
+ uv run python vision_agents/_generate_sfu_events.py
96
+ ```
97
+
98
+ ### Verification
99
+
100
+ Verify type mappings and generated classes:
101
+
102
+ ```bash
103
+ # Show type mappings
104
+ uv run python vision_agents/_generate_sfu_events.py --verify-types
105
+
106
+ # Verify generated classes
107
+ uv run python vision_agents/_generate_sfu_events.py --verify
108
+
109
+ # Both
110
+ uv run python vision_agents/_generate_sfu_events.py --verify-types --verify
111
+ ```
112
+
113
+ ### Example Usage
114
+
115
+ ```python
116
+ from vision_agents.core.edge.sfu_events import (
117
+ AudioLevelEvent,
118
+ TrackUnpublishedEvent,
119
+ Participant # Now properly typed!
120
+ )
121
+ from getstream.video.rtc.pb.stream.video.sfu.event import events_pb2
122
+ from getstream.video.rtc.pb.stream.video.sfu.models import models_pb2
123
+
124
+ # Example 1: Simple event without payload
125
+ event1 = AudioLevelEvent()
126
+ print(event1.user_id) # None
127
+
128
+ # Example 2: Event from protobuf
129
+ proto = events_pb2.AudioLevel(user_id='user123', level=0.85, is_speaking=True)
130
+ event2 = AudioLevelEvent.from_proto(proto)
131
+ print(event2.user_id) # 'user123'
132
+ print(event2.level) # 0.85
133
+ print(event2.is_speaking) # True
134
+ print(event2.as_dict()) # {'user_id': 'user123', 'level': 0.85, 'is_speaking': True}
135
+
136
+ # Example 3: Event with nested message type (Participant)
137
+ proto_participant = models_pb2.Participant(
138
+ user_id='user456',
139
+ name='John Doe',
140
+ is_speaking=True,
141
+ audio_level=0.92
142
+ )
143
+ proto_track = events_pb2.TrackUnpublished(
144
+ user_id='user456',
145
+ participant=proto_participant
146
+ )
147
+ event3 = TrackUnpublishedEvent.from_proto(proto_track)
148
+
149
+ # Participant is properly typed as Participant dataclass!
150
+ participant: Participant = event3.participant # Type-safe!
151
+ print(participant.user_id) # 'user456'
152
+ print(participant.name) # 'John Doe'
153
+ print(participant.is_speaking) # True
154
+ print(participant.audio_level) # 0.92
155
+
156
+ # IDE autocomplete works perfectly for all Participant fields!
157
+ ```
158
+
159
+ ## Verification Functions
160
+
161
+ ### `_get_python_type_from_protobuf_field(field_descriptor)`
162
+
163
+ Determines the appropriate Python type annotation from a protobuf field descriptor. Maps protobuf types to Python types with proper handling of:
164
+ - Scalar types (int, float, str, bool, bytes)
165
+ - Repeated fields (lists)
166
+ - Message types (nested protobuf messages)
167
+ - Enum types
168
+
169
+ ### `verify_field_types()`
170
+
171
+ Displays a comprehensive report of all field type mappings for verification:
172
+ ```
173
+ AudioLevelEvent (AudioLevel):
174
+ Protobuf type: stream.video.sfu.event.AudioLevel
175
+ - user_id: type=9 (required) → Optional[str]
176
+ - level: type=2 (required) → Optional[float]
177
+ - is_speaking: type=8 (required) → Optional[bool]
178
+ ```
179
+
180
+ ### `verify_generated_classes()`
181
+
182
+ Verifies that generated classes match protobuf definitions by checking:
183
+ - Class exists in generated module
184
+ - All protobuf fields are accessible as properties
185
+ - Properties have correct types
186
+ - No missing or incorrect field mappings
187
+
188
+ ## Generated Class Structure
189
+
190
+ Each generated class follows this pattern:
191
+
192
+ ```python
193
+ @dataclass
194
+ class AudioLevelEvent(BaseEvent):
195
+ """Dataclass event for video.sfu.event.events_pb2.AudioLevel."""
196
+ type: str = field(default="stream.video.sfu.event.AudioLevel", init=False)
197
+ payload: Optional[events_pb2.AudioLevel] = field(default=None, repr=False)
198
+
199
+ @property
200
+ def user_id(self) -> Optional[str]:
201
+ """Access user_id field from the protobuf payload."""
202
+ if self.payload is None:
203
+ return None
204
+ return getattr(self.payload, 'user_id', None)
205
+
206
+ # ... more properties ...
207
+
208
+ @classmethod
209
+ def from_proto(cls, proto_obj: events_pb2.AudioLevel, **extra):
210
+ """Create event instance from protobuf message."""
211
+ return cls(payload=proto_obj, **extra)
212
+
213
+ def as_dict(self) -> Dict[str, Any]:
214
+ """Convert protobuf payload to dictionary."""
215
+ if self.payload is None:
216
+ return {}
217
+ return _to_dict(self.payload)
218
+
219
+ def __getattr__(self, item: str):
220
+ """Delegate attribute access to protobuf payload."""
221
+ if self.payload is not None:
222
+ return getattr(self.payload, item)
223
+ raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{item}'")
224
+ ```
225
+
226
+ ## Import Strategy
227
+
228
+ The edge module uses absolute imports instead of relative imports to avoid naming conflicts with standard library modules (specifically avoiding conflicts with Python's `types` module).
229
+
230
+ ```python
231
+ # In edge/__init__.py
232
+ from vision_agents.core.edge.edge_transport import EdgeTransport
233
+ from vision_agents.core.edge import sfu_events
234
+ ```
235
+
236
+ ## Event Manager Integration
237
+
238
+ The EventManager has been updated to seamlessly handle the new protobuf events:
239
+
240
+ ### How It Works
241
+
242
+ 1. **Register protobuf event classes** like any other event:
243
+ ```python
244
+ from vision_agents.core.events.manager import EventManager
245
+ from vision_agents.core.edge.sfu_events import AudioLevelEvent
246
+
247
+ manager = EventManager()
248
+ manager.register(AudioLevelEvent)
249
+ ```
250
+
251
+ 2. **Send events** in three ways:
252
+ - Send wrapped events (already BaseEvent):
253
+ ```python
254
+ proto = events_pb2.AudioLevel(user_id='user123', level=0.85)
255
+ event = AudioLevelEvent.from_proto(proto, session_id='session123')
256
+ manager.send(event) # BaseEvent fields preserved
257
+ ```
258
+
259
+ - Send raw protobuf messages (auto-wrapped):
260
+ ```python
261
+ proto = events_pb2.AudioLevel(user_id='user456', level=0.95)
262
+ manager.send(proto) # Automatically wrapped in AudioLevelEvent
263
+ ```
264
+
265
+ - Create events without payload (all fields optional):
266
+ ```python
267
+ event = AudioLevelEvent() # No protobuf payload needed
268
+ manager.send(event)
269
+ ```
270
+
271
+ 3. **Subscribe to protobuf events** like any other event:
272
+ ```python
273
+ @manager.subscribe
274
+ async def handle_audio(event: AudioLevelEvent):
275
+ print(f"User: {event.user_id}, Level: {event.level}")
276
+ print(f"Session: {event.session_id}, ID: {event.event_id}")
277
+ ```
278
+
279
+ ### Key Improvements
280
+
281
+ - **No double-wrapping**: Already-wrapped BaseEvent subclasses are not re-wrapped
282
+ - **BaseEvent fields preserved**: session_id, event_id, timestamp all work correctly
283
+ - **Simplified logic**: Single check distinguishes raw protobuf from wrapped events
284
+ - **Type safety**: All generated events properly inherit from BaseEvent
285
+ - **Flexible usage**: Use raw protobuf or wrapped events interchangeably
286
+