zrt 0.0.1b1__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.
- zrt-0.0.1b1/LICENSE +54 -0
- zrt-0.0.1b1/MANIFEST.in +5 -0
- zrt-0.0.1b1/PKG-INFO +234 -0
- zrt-0.0.1b1/README.md +195 -0
- zrt-0.0.1b1/pyproject.toml +83 -0
- zrt-0.0.1b1/setup.cfg +4 -0
- zrt-0.0.1b1/tests/test_grpc_headers.py +66 -0
- zrt-0.0.1b1/tests/test_imports.py +23 -0
- zrt-0.0.1b1/tests/test_surface.py +59 -0
- zrt-0.0.1b1/zrt/__init__.py +41 -0
- zrt-0.0.1b1/zrt/agents/__init__.py +312 -0
- zrt-0.0.1b1/zrt/agents/_agent_registry.py +878 -0
- zrt-0.0.1b1/zrt/agents/_client_meta.py +97 -0
- zrt-0.0.1b1/zrt/agents/_config_builders.py +484 -0
- zrt-0.0.1b1/zrt/agents/_grpc_bridge.py +953 -0
- zrt-0.0.1b1/zrt/agents/_legacy_register.py +382 -0
- zrt-0.0.1b1/zrt/agents/_zrt_auth.py +37 -0
- zrt-0.0.1b1/zrt/agents/a2a.py +18 -0
- zrt-0.0.1b1/zrt/agents/agent.py +113 -0
- zrt-0.0.1b1/zrt/agents/agent_runtime_pb2.py +418 -0
- zrt-0.0.1b1/zrt/agents/agent_runtime_pb2_grpc.py +664 -0
- zrt-0.0.1b1/zrt/agents/audio_track.py +70 -0
- zrt-0.0.1b1/zrt/agents/background_audio.py +16 -0
- zrt-0.0.1b1/zrt/agents/chat.py +78 -0
- zrt-0.0.1b1/zrt/agents/config.py +91 -0
- zrt-0.0.1b1/zrt/agents/debug/__init__.py +3 -0
- zrt-0.0.1b1/zrt/agents/debug/http_server.py +215 -0
- zrt-0.0.1b1/zrt/agents/debug/tracing.py +90 -0
- zrt-0.0.1b1/zrt/agents/denoise.py +27 -0
- zrt-0.0.1b1/zrt/agents/dtmf_handler.py +49 -0
- zrt-0.0.1b1/zrt/agents/enums.py +112 -0
- zrt-0.0.1b1/zrt/agents/event_emitter.py +81 -0
- zrt-0.0.1b1/zrt/agents/execution/__init__.py +3 -0
- zrt-0.0.1b1/zrt/agents/execution/types.py +3 -0
- zrt-0.0.1b1/zrt/agents/fallback.py +57 -0
- zrt-0.0.1b1/zrt/agents/handoff.py +14 -0
- zrt-0.0.1b1/zrt/agents/images.py +60 -0
- zrt-0.0.1b1/zrt/agents/inference/__init__.py +9 -0
- zrt-0.0.1b1/zrt/agents/inference/denoise.py +10 -0
- zrt-0.0.1b1/zrt/agents/inference/llm.py +51 -0
- zrt-0.0.1b1/zrt/agents/inference/realtime.py +43 -0
- zrt-0.0.1b1/zrt/agents/inference/stt.py +89 -0
- zrt-0.0.1b1/zrt/agents/inference/tts.py +95 -0
- zrt-0.0.1b1/zrt/agents/inference/turn.py +87 -0
- zrt-0.0.1b1/zrt/agents/job.py +524 -0
- zrt-0.0.1b1/zrt/agents/knowledge_base.py +53 -0
- zrt-0.0.1b1/zrt/agents/mcp.py +18 -0
- zrt-0.0.1b1/zrt/agents/metrics.py +3 -0
- zrt-0.0.1b1/zrt/agents/pipeline.py +528 -0
- zrt-0.0.1b1/zrt/agents/providers.py +228 -0
- zrt-0.0.1b1/zrt/agents/session.py +1119 -0
- zrt-0.0.1b1/zrt/agents/tools.py +130 -0
- zrt-0.0.1b1/zrt/agents/utils.py +22 -0
- zrt-0.0.1b1/zrt/agents/utterance.py +70 -0
- zrt-0.0.1b1/zrt/agents/voice_mail_detector.py +40 -0
- zrt-0.0.1b1/zrt/plugins/__init__.py +1 -0
- zrt-0.0.1b1/zrt/plugins/anthropic/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/anthropic/llm.py +30 -0
- zrt-0.0.1b1/zrt/plugins/assemblyai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/assemblyai/stt.py +19 -0
- zrt-0.0.1b1/zrt/plugins/aws/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/aws/tts.py +18 -0
- zrt-0.0.1b1/zrt/plugins/azure/__init__.py +4 -0
- zrt-0.0.1b1/zrt/plugins/azure/stt.py +18 -0
- zrt-0.0.1b1/zrt/plugins/azure/tts.py +17 -0
- zrt-0.0.1b1/zrt/plugins/azure/voice_live.py +76 -0
- zrt-0.0.1b1/zrt/plugins/cambai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/cambai/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/cartesia/__init__.py +7 -0
- zrt-0.0.1b1/zrt/plugins/cartesia/tts.py +80 -0
- zrt-0.0.1b1/zrt/plugins/cerebras/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/cerebras/llm.py +16 -0
- zrt-0.0.1b1/zrt/plugins/cometapi/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/cometapi/llm.py +16 -0
- zrt-0.0.1b1/zrt/plugins/deepgram/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/deepgram/stt.py +45 -0
- zrt-0.0.1b1/zrt/plugins/elevenlabs/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/elevenlabs/tts.py +46 -0
- zrt-0.0.1b1/zrt/plugins/gemini_realtime/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/gemini_realtime/realtime.py +84 -0
- zrt-0.0.1b1/zrt/plugins/gladia/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/gladia/stt.py +17 -0
- zrt-0.0.1b1/zrt/plugins/google/__init__.py +4 -0
- zrt-0.0.1b1/zrt/plugins/google/llm.py +71 -0
- zrt-0.0.1b1/zrt/plugins/google/stt.py +19 -0
- zrt-0.0.1b1/zrt/plugins/google/tts.py +68 -0
- zrt-0.0.1b1/zrt/plugins/groq/__init__.py +3 -0
- zrt-0.0.1b1/zrt/plugins/groq/llm.py +16 -0
- zrt-0.0.1b1/zrt/plugins/groq/tts.py +17 -0
- zrt-0.0.1b1/zrt/plugins/humeai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/humeai/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/inworldai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/inworldai/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/lmnt/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/lmnt/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/murfai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/murfai/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/navana/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/navana/turn_detector.py +12 -0
- zrt-0.0.1b1/zrt/plugins/neuphonic/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/neuphonic/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/nvidia/__init__.py +3 -0
- zrt-0.0.1b1/zrt/plugins/nvidia/stt.py +16 -0
- zrt-0.0.1b1/zrt/plugins/nvidia/tts.py +15 -0
- zrt-0.0.1b1/zrt/plugins/openai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/openai/llm.py +42 -0
- zrt-0.0.1b1/zrt/plugins/openai_realtime/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/openai_realtime/realtime.py +69 -0
- zrt-0.0.1b1/zrt/plugins/papla/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/papla/tts.py +15 -0
- zrt-0.0.1b1/zrt/plugins/resemble/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/resemble/tts.py +15 -0
- zrt-0.0.1b1/zrt/plugins/rime/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/rime/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/rnnoise/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/rnnoise/denoise.py +8 -0
- zrt-0.0.1b1/zrt/plugins/sarvamai/__init__.py +4 -0
- zrt-0.0.1b1/zrt/plugins/sarvamai/llm.py +17 -0
- zrt-0.0.1b1/zrt/plugins/sarvamai/stt.py +34 -0
- zrt-0.0.1b1/zrt/plugins/sarvamai/tts.py +35 -0
- zrt-0.0.1b1/zrt/plugins/silero/__init__.py +5 -0
- zrt-0.0.1b1/zrt/plugins/silero/vad.py +37 -0
- zrt-0.0.1b1/zrt/plugins/smallestai/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/smallestai/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/speechify/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/speechify/tts.py +16 -0
- zrt-0.0.1b1/zrt/plugins/turn_detector/__init__.py +23 -0
- zrt-0.0.1b1/zrt/plugins/turn_detector/detector.py +13 -0
- zrt-0.0.1b1/zrt/plugins/turn_detector/detector_v2.py +13 -0
- zrt-0.0.1b1/zrt/plugins/turn_detector/namo_v2.py +20 -0
- zrt-0.0.1b1/zrt/plugins/ultravox/__init__.py +2 -0
- zrt-0.0.1b1/zrt/plugins/ultravox/realtime.py +67 -0
- zrt-0.0.1b1/zrt/plugins/xai/__init__.py +3 -0
- zrt-0.0.1b1/zrt/plugins/xai/llm.py +16 -0
- zrt-0.0.1b1/zrt/plugins/xai/realtime.py +72 -0
- zrt-0.0.1b1/zrt/py.typed +0 -0
- zrt-0.0.1b1/zrt.egg-info/PKG-INFO +234 -0
- zrt-0.0.1b1/zrt.egg-info/SOURCES.txt +139 -0
- zrt-0.0.1b1/zrt.egg-info/dependency_links.txt +1 -0
- zrt-0.0.1b1/zrt.egg-info/requires.txt +14 -0
- zrt-0.0.1b1/zrt.egg-info/top_level.txt +1 -0
zrt-0.0.1b1/LICENSE
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
ZRT Python SDK — Proprietary License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Zujo Tech Pvt Ltd. All rights reserved.
|
|
4
|
+
|
|
5
|
+
This software, including its source code, object code, and accompanying
|
|
6
|
+
documentation (collectively, the "Software"), is the proprietary and
|
|
7
|
+
confidential property of Zujo Tech Pvt Ltd ("Licensor"). The Software is
|
|
8
|
+
licensed, not sold. No ownership rights are transferred to you. "Zero Runtime"
|
|
9
|
+
and "ZRT" are products and services of Zujo Tech Pvt Ltd.
|
|
10
|
+
|
|
11
|
+
1. License Grant. Subject to your continued compliance with this License (and
|
|
12
|
+
with any separate written agreement you have entered into with Licensor),
|
|
13
|
+
Licensor grants you a limited, non-exclusive, non-transferable, non-
|
|
14
|
+
sublicensable, revocable license to install and use the Software solely to
|
|
15
|
+
develop and operate applications that connect to and interoperate with the
|
|
16
|
+
Zero Runtime service.
|
|
17
|
+
|
|
18
|
+
2. Restrictions. Except to the extent expressly permitted in Section 1, by a
|
|
19
|
+
separate written agreement with Licensor, or by applicable law that cannot
|
|
20
|
+
be contractually waived, you may NOT:
|
|
21
|
+
(a) copy, modify, adapt, translate, or create derivative works of the
|
|
22
|
+
Software;
|
|
23
|
+
(b) distribute, publish, sublicense, sell, rent, lease, lend, or
|
|
24
|
+
otherwise make the Software available to any third party;
|
|
25
|
+
(c) reverse engineer, decompile, or disassemble the Software, or attempt
|
|
26
|
+
to derive its source code where not provided;
|
|
27
|
+
(d) use the Software to build or operate a product or service that
|
|
28
|
+
competes with the Zero Runtime service; or
|
|
29
|
+
(e) remove, obscure, or alter any proprietary notices, labels, or marks
|
|
30
|
+
on or in the Software.
|
|
31
|
+
|
|
32
|
+
3. Ownership. The Software is protected by copyright and other intellectual
|
|
33
|
+
property laws and treaties. Licensor and its licensors retain all right,
|
|
34
|
+
title, and interest in and to the Software, including all intellectual
|
|
35
|
+
property rights therein.
|
|
36
|
+
|
|
37
|
+
4. Termination. This License is effective until terminated. It terminates
|
|
38
|
+
automatically, without notice, if you breach any of its terms. Upon
|
|
39
|
+
termination you must cease all use of the Software and destroy all copies
|
|
40
|
+
in your possession or control.
|
|
41
|
+
|
|
42
|
+
5. No Warranty. THE SOFTWARE IS PROVIDED "AS IS" AND "AS AVAILABLE", WITHOUT
|
|
43
|
+
WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
|
|
44
|
+
WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, TITLE, AND
|
|
45
|
+
NONINFRINGEMENT.
|
|
46
|
+
|
|
47
|
+
6. Limitation of Liability. TO THE MAXIMUM EXTENT PERMITTED BY LAW, IN NO EVENT
|
|
48
|
+
SHALL LICENSOR BE LIABLE FOR ANY INDIRECT, INCIDENTAL, SPECIAL,
|
|
49
|
+
CONSEQUENTIAL, OR PUNITIVE DAMAGES, OR ANY LOSS OF PROFITS, DATA, OR USE,
|
|
50
|
+
ARISING OUT OF OR RELATED TO THIS LICENSE OR THE SOFTWARE, WHETHER IN
|
|
51
|
+
CONTRACT, TORT, OR OTHERWISE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
|
52
|
+
DAMAGES.
|
|
53
|
+
|
|
54
|
+
For licensing inquiries, contact: support@videosdk.live
|
zrt-0.0.1b1/MANIFEST.in
ADDED
zrt-0.0.1b1/PKG-INFO
ADDED
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: zrt
|
|
3
|
+
Version: 0.0.1b1
|
|
4
|
+
Summary: Build real-time AI voice agents in Python. Zero Runtime runs the speech-to-speech pipeline (STT, LLM, TTS) for you.
|
|
5
|
+
Author-email: Zujo Tech Pvt Ltd <support@videosdk.live>
|
|
6
|
+
License-Expression: LicenseRef-Proprietary
|
|
7
|
+
Project-URL: Homepage, https://zeroruntime.ai/
|
|
8
|
+
Project-URL: Examples, https://github.com/ZeroRuntimeAI/zrt-python-sdk-examples
|
|
9
|
+
Keywords: voice-agents,voice-ai,ai-voice-agent,conversational-ai,voice-assistant,speech-to-speech,realtime-voice,voicebot,llm,stt,tts,speech-to-text,text-to-speech,telephony,sip,webrtc,zero-runtime
|
|
10
|
+
Classifier: Development Status :: 4 - Beta
|
|
11
|
+
Classifier: Intended Audience :: Developers
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Multimedia :: Sound/Audio :: Speech
|
|
20
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
21
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
22
|
+
Classifier: Typing :: Typed
|
|
23
|
+
Requires-Python: >=3.10
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
License-File: LICENSE
|
|
26
|
+
Requires-Dist: grpcio>=1.81.0
|
|
27
|
+
Requires-Dist: protobuf>=6.31.0
|
|
28
|
+
Requires-Dist: aiohttp>=3.9.0
|
|
29
|
+
Provides-Extra: vision
|
|
30
|
+
Requires-Dist: Pillow>=10.0; extra == "vision"
|
|
31
|
+
Provides-Extra: dev
|
|
32
|
+
Requires-Dist: pytest>=8.4; extra == "dev"
|
|
33
|
+
Requires-Dist: pytest-asyncio>=0.24; extra == "dev"
|
|
34
|
+
Requires-Dist: grpcio-tools>=1.81.0; extra == "dev"
|
|
35
|
+
Requires-Dist: build>=1.2; extra == "dev"
|
|
36
|
+
Requires-Dist: twine>=6.0; extra == "dev"
|
|
37
|
+
Requires-Dist: ruff>=0.6; extra == "dev"
|
|
38
|
+
Dynamic: license-file
|
|
39
|
+
|
|
40
|
+
# ZRT — Zero Runtime Python SDK
|
|
41
|
+
|
|
42
|
+
**Build real-time AI voice agents in Python — without running the infrastructure.**
|
|
43
|
+
You write the agent (instructions, tools, logic); **Zero Runtime** runs the live
|
|
44
|
+
speech-to-speech pipeline — speech-to-text → LLM → text-to-speech, with turn
|
|
45
|
+
detection, denoising, and interruptions — at low latency in the cloud.
|
|
46
|
+
|
|
47
|
+
> **Write the agent. We run the runtime.**
|
|
48
|
+
|
|
49
|
+
## A different kind of voice SDK
|
|
50
|
+
|
|
51
|
+
Most voice frameworks make you run the hard part — media servers, GPUs, turn-taking,
|
|
52
|
+
autoscaling. No-code platforms hide all that but lock you into a dashboard.
|
|
53
|
+
**Zero Runtime is the middle:** real Python and your own providers, with none of the
|
|
54
|
+
real-time infrastructure to operate.
|
|
55
|
+
|
|
56
|
+
| | Self-hosted frameworks | No-code platforms | **Zero Runtime** |
|
|
57
|
+
|---|:---:|:---:|:---:|
|
|
58
|
+
| Write real Python + custom tools | ✅ | ❌ (dashboard) | ✅ |
|
|
59
|
+
| Run media servers / GPUs / scaling | ❌ *you run it* | ✅ managed | ✅ managed |
|
|
60
|
+
| Swap any STT / LLM / TTS provider | ✅ | limited | ✅ |
|
|
61
|
+
| Low-latency speech-to-speech | you tune it | managed | managed |
|
|
62
|
+
|
|
63
|
+
## Requirements
|
|
64
|
+
|
|
65
|
+
- Python **3.11+**
|
|
66
|
+
- A ZRT runtime endpoint + auth token (from your Zero Runtime account)
|
|
67
|
+
- API key(s) for the providers you use (e.g. Deepgram, Google, Cartesia)
|
|
68
|
+
|
|
69
|
+
## Install
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install --pre zrt
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
> Public beta — `--pre` is required until the stable release.
|
|
76
|
+
|
|
77
|
+
## Quickstart
|
|
78
|
+
|
|
79
|
+
**1. Set your environment**
|
|
80
|
+
|
|
81
|
+
```bash
|
|
82
|
+
export ZRT_RUNTIME_ADDRESS=us1.rt.zeroruntime.ai:443 # your ZRT runtime
|
|
83
|
+
export ZRT_AUTH_TOKEN=<your-token>
|
|
84
|
+
|
|
85
|
+
export DEEPGRAM_API_KEY=<key> # speech-to-text
|
|
86
|
+
export GOOGLE_API_KEY=<key> # the LLM (Gemini)
|
|
87
|
+
export CARTESIA_API_KEY=<key> # text-to-speech
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**2. Write your agent** — `agent.py`
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
from zrt.agents import (
|
|
94
|
+
Agent, AgentSession, Pipeline, WorkerJob, JobContext, RoomOptions,
|
|
95
|
+
EOUConfig, InterruptConfig,
|
|
96
|
+
)
|
|
97
|
+
from zrt.plugins.deepgram import DeepgramSTT
|
|
98
|
+
from zrt.plugins.google import GoogleLLM
|
|
99
|
+
from zrt.plugins.cartesia import CartesiaTTS
|
|
100
|
+
from zrt.plugins.silero import SileroVAD
|
|
101
|
+
from zrt.plugins.turn_detector import NamoTurnDetectorV1
|
|
102
|
+
from zrt.plugins.rnnoise import RNNoise
|
|
103
|
+
|
|
104
|
+
IGNORE_PATTERNS = [r"\b(uh+|um+)\b"] # filler words to drop from transcripts
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Assistant(Agent):
|
|
108
|
+
def __init__(self):
|
|
109
|
+
super().__init__(instructions="You are a friendly voice assistant. Keep replies short.")
|
|
110
|
+
|
|
111
|
+
async def on_enter(self):
|
|
112
|
+
await self.session.say("Hi! How can I help?")
|
|
113
|
+
|
|
114
|
+
async def on_exit(self):
|
|
115
|
+
pass
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
async def entrypoint(ctx: JobContext):
|
|
119
|
+
session = AgentSession(
|
|
120
|
+
agent=Assistant(),
|
|
121
|
+
pipeline=Pipeline(
|
|
122
|
+
stt=DeepgramSTT(),
|
|
123
|
+
llm=GoogleLLM(
|
|
124
|
+
model="gemini-2.5-flash",
|
|
125
|
+
thinking_budget=0,
|
|
126
|
+
include_thoughts=False,
|
|
127
|
+
max_output_tokens=8192,
|
|
128
|
+
),
|
|
129
|
+
tts=CartesiaTTS(),
|
|
130
|
+
vad=SileroVAD(threshold=0.4),
|
|
131
|
+
turn_detector=NamoTurnDetectorV1(language="en", threshold=0.8),
|
|
132
|
+
denoise=RNNoise(),
|
|
133
|
+
eou_config=EOUConfig(mode="ADAPTIVE", min_max_speech_wait_timeout=[0.1, 0.3]),
|
|
134
|
+
interrupt_config=InterruptConfig(
|
|
135
|
+
interrupt_min_duration=0.5,
|
|
136
|
+
interrupt_min_words=2,
|
|
137
|
+
resume_on_false_interrupt=True,
|
|
138
|
+
),
|
|
139
|
+
stt_filter_patterns=IGNORE_PATTERNS,
|
|
140
|
+
stt_word_substitutions={"recording": "", "recorded": ""},
|
|
141
|
+
),
|
|
142
|
+
)
|
|
143
|
+
await session.start(wait_for_participant=True, run_until_shutdown=True)
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
if __name__ == "__main__":
|
|
147
|
+
WorkerJob(
|
|
148
|
+
entrypoint=entrypoint,
|
|
149
|
+
jobctx=lambda: JobContext(room_options=RoomOptions(name="Assistant")),
|
|
150
|
+
).start()
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
**3. Run it**
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
python agent.py
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
That's it — speech in → your agent → speech out, in real time.
|
|
160
|
+
|
|
161
|
+
## How it works
|
|
162
|
+
|
|
163
|
+
| Piece | What it is |
|
|
164
|
+
|---|---|
|
|
165
|
+
| **`Agent`** | Your behavior — instructions, tools, what it says on enter/exit. |
|
|
166
|
+
| **`Pipeline`** | The voice stack: STT (hear) → LLM (think) → TTS (speak), plus VAD, turn detection, and denoising. |
|
|
167
|
+
| **`WorkerJob`** | Runs your agent and connects it to Zero Runtime. |
|
|
168
|
+
|
|
169
|
+
## Give your agent tools
|
|
170
|
+
|
|
171
|
+
Let the LLM call your Python functions — just decorate them:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
from zrt.agents import function_tool
|
|
175
|
+
|
|
176
|
+
@function_tool
|
|
177
|
+
async def get_weather(city: str) -> dict:
|
|
178
|
+
"""Get the weather for a city.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
city: City name
|
|
182
|
+
"""
|
|
183
|
+
return {"city": city, "temp_c": 22}
|
|
184
|
+
|
|
185
|
+
# then pass them to your agent:
|
|
186
|
+
# super().__init__(instructions="...", tools=[get_weather])
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Your tool runs in your worker; the runtime calls it when the LLM decides to.
|
|
190
|
+
|
|
191
|
+
## Providers
|
|
192
|
+
|
|
193
|
+
Mix and match — bring the best model for each stage, swap any one in a line:
|
|
194
|
+
|
|
195
|
+
- **Speech-to-text (STT):** Deepgram, AssemblyAI, Google, Azure, Gladia, NVIDIA, Sarvam
|
|
196
|
+
- **LLM:** OpenAI, Google Gemini, Anthropic Claude, Groq, Cerebras, xAI Grok, Sarvam
|
|
197
|
+
- **Text-to-speech (TTS):** Cartesia, ElevenLabs, Google, AWS Polly, Azure, Deepgram, Rime, LMNT, Neuphonic, Hume AI, Inworld, Murf, Resemble, Smallest, Speechify, CambAI, NVIDIA
|
|
198
|
+
- **Realtime speech-to-speech:** OpenAI Realtime, Gemini Live, Ultravox, Azure Voice Live
|
|
199
|
+
- **Turn detection:** Namo · **VAD:** Silero · **Denoise:** RNNoise
|
|
200
|
+
|
|
201
|
+
```python
|
|
202
|
+
from zrt.plugins.elevenlabs import ElevenLabsTTS # different TTS
|
|
203
|
+
from zrt.plugins.anthropic import AnthropicLLM # different LLM
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## Use cases
|
|
207
|
+
|
|
208
|
+
Phone & telephony agents, IVR replacement, customer-support voice bots, voice
|
|
209
|
+
assistants, outbound/inbound call automation, and any real-time conversational AI.
|
|
210
|
+
|
|
211
|
+
## FAQ
|
|
212
|
+
|
|
213
|
+
**How is this different from a voice-agent framework?**
|
|
214
|
+
* Frameworks make you host and scale the real-time runtime (media, GPUs, turn-taking).
|
|
215
|
+
ZRT runs that for you — you only write and deploy the agent.
|
|
216
|
+
|
|
217
|
+
**How is it different from a no-code voice platform?**
|
|
218
|
+
* You write real Python with your own tools, logic, and providers — not a dashboard
|
|
219
|
+
configuration. Full code control, zero infrastructure.
|
|
220
|
+
|
|
221
|
+
**Can I use my own STT / LLM / TTS providers?**
|
|
222
|
+
* Yes — mix any supported providers, and bring your own API keys.
|
|
223
|
+
|
|
224
|
+
**What do I need to run it?**
|
|
225
|
+
* A ZRT runtime endpoint + token and the provider keys for the stages you use.
|
|
226
|
+
|
|
227
|
+
## Examples
|
|
228
|
+
|
|
229
|
+
More complete examples: https://github.com/ZeroRuntimeAI/zrt-python-sdk-examples
|
|
230
|
+
|
|
231
|
+
## Contact
|
|
232
|
+
support@videosdk.live
|
|
233
|
+
|
|
234
|
+
Copyright © 2026 Zujo Tech Pvt Ltd. All rights reserved.
|
zrt-0.0.1b1/README.md
ADDED
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
# ZRT — Zero Runtime Python SDK
|
|
2
|
+
|
|
3
|
+
**Build real-time AI voice agents in Python — without running the infrastructure.**
|
|
4
|
+
You write the agent (instructions, tools, logic); **Zero Runtime** runs the live
|
|
5
|
+
speech-to-speech pipeline — speech-to-text → LLM → text-to-speech, with turn
|
|
6
|
+
detection, denoising, and interruptions — at low latency in the cloud.
|
|
7
|
+
|
|
8
|
+
> **Write the agent. We run the runtime.**
|
|
9
|
+
|
|
10
|
+
## A different kind of voice SDK
|
|
11
|
+
|
|
12
|
+
Most voice frameworks make you run the hard part — media servers, GPUs, turn-taking,
|
|
13
|
+
autoscaling. No-code platforms hide all that but lock you into a dashboard.
|
|
14
|
+
**Zero Runtime is the middle:** real Python and your own providers, with none of the
|
|
15
|
+
real-time infrastructure to operate.
|
|
16
|
+
|
|
17
|
+
| | Self-hosted frameworks | No-code platforms | **Zero Runtime** |
|
|
18
|
+
|---|:---:|:---:|:---:|
|
|
19
|
+
| Write real Python + custom tools | ✅ | ❌ (dashboard) | ✅ |
|
|
20
|
+
| Run media servers / GPUs / scaling | ❌ *you run it* | ✅ managed | ✅ managed |
|
|
21
|
+
| Swap any STT / LLM / TTS provider | ✅ | limited | ✅ |
|
|
22
|
+
| Low-latency speech-to-speech | you tune it | managed | managed |
|
|
23
|
+
|
|
24
|
+
## Requirements
|
|
25
|
+
|
|
26
|
+
- Python **3.11+**
|
|
27
|
+
- A ZRT runtime endpoint + auth token (from your Zero Runtime account)
|
|
28
|
+
- API key(s) for the providers you use (e.g. Deepgram, Google, Cartesia)
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pip install --pre zrt
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
> Public beta — `--pre` is required until the stable release.
|
|
37
|
+
|
|
38
|
+
## Quickstart
|
|
39
|
+
|
|
40
|
+
**1. Set your environment**
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
export ZRT_RUNTIME_ADDRESS=us1.rt.zeroruntime.ai:443 # your ZRT runtime
|
|
44
|
+
export ZRT_AUTH_TOKEN=<your-token>
|
|
45
|
+
|
|
46
|
+
export DEEPGRAM_API_KEY=<key> # speech-to-text
|
|
47
|
+
export GOOGLE_API_KEY=<key> # the LLM (Gemini)
|
|
48
|
+
export CARTESIA_API_KEY=<key> # text-to-speech
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**2. Write your agent** — `agent.py`
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
from zrt.agents import (
|
|
55
|
+
Agent, AgentSession, Pipeline, WorkerJob, JobContext, RoomOptions,
|
|
56
|
+
EOUConfig, InterruptConfig,
|
|
57
|
+
)
|
|
58
|
+
from zrt.plugins.deepgram import DeepgramSTT
|
|
59
|
+
from zrt.plugins.google import GoogleLLM
|
|
60
|
+
from zrt.plugins.cartesia import CartesiaTTS
|
|
61
|
+
from zrt.plugins.silero import SileroVAD
|
|
62
|
+
from zrt.plugins.turn_detector import NamoTurnDetectorV1
|
|
63
|
+
from zrt.plugins.rnnoise import RNNoise
|
|
64
|
+
|
|
65
|
+
IGNORE_PATTERNS = [r"\b(uh+|um+)\b"] # filler words to drop from transcripts
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class Assistant(Agent):
|
|
69
|
+
def __init__(self):
|
|
70
|
+
super().__init__(instructions="You are a friendly voice assistant. Keep replies short.")
|
|
71
|
+
|
|
72
|
+
async def on_enter(self):
|
|
73
|
+
await self.session.say("Hi! How can I help?")
|
|
74
|
+
|
|
75
|
+
async def on_exit(self):
|
|
76
|
+
pass
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
async def entrypoint(ctx: JobContext):
|
|
80
|
+
session = AgentSession(
|
|
81
|
+
agent=Assistant(),
|
|
82
|
+
pipeline=Pipeline(
|
|
83
|
+
stt=DeepgramSTT(),
|
|
84
|
+
llm=GoogleLLM(
|
|
85
|
+
model="gemini-2.5-flash",
|
|
86
|
+
thinking_budget=0,
|
|
87
|
+
include_thoughts=False,
|
|
88
|
+
max_output_tokens=8192,
|
|
89
|
+
),
|
|
90
|
+
tts=CartesiaTTS(),
|
|
91
|
+
vad=SileroVAD(threshold=0.4),
|
|
92
|
+
turn_detector=NamoTurnDetectorV1(language="en", threshold=0.8),
|
|
93
|
+
denoise=RNNoise(),
|
|
94
|
+
eou_config=EOUConfig(mode="ADAPTIVE", min_max_speech_wait_timeout=[0.1, 0.3]),
|
|
95
|
+
interrupt_config=InterruptConfig(
|
|
96
|
+
interrupt_min_duration=0.5,
|
|
97
|
+
interrupt_min_words=2,
|
|
98
|
+
resume_on_false_interrupt=True,
|
|
99
|
+
),
|
|
100
|
+
stt_filter_patterns=IGNORE_PATTERNS,
|
|
101
|
+
stt_word_substitutions={"recording": "", "recorded": ""},
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
await session.start(wait_for_participant=True, run_until_shutdown=True)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
if __name__ == "__main__":
|
|
108
|
+
WorkerJob(
|
|
109
|
+
entrypoint=entrypoint,
|
|
110
|
+
jobctx=lambda: JobContext(room_options=RoomOptions(name="Assistant")),
|
|
111
|
+
).start()
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
**3. Run it**
|
|
115
|
+
|
|
116
|
+
```bash
|
|
117
|
+
python agent.py
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
That's it — speech in → your agent → speech out, in real time.
|
|
121
|
+
|
|
122
|
+
## How it works
|
|
123
|
+
|
|
124
|
+
| Piece | What it is |
|
|
125
|
+
|---|---|
|
|
126
|
+
| **`Agent`** | Your behavior — instructions, tools, what it says on enter/exit. |
|
|
127
|
+
| **`Pipeline`** | The voice stack: STT (hear) → LLM (think) → TTS (speak), plus VAD, turn detection, and denoising. |
|
|
128
|
+
| **`WorkerJob`** | Runs your agent and connects it to Zero Runtime. |
|
|
129
|
+
|
|
130
|
+
## Give your agent tools
|
|
131
|
+
|
|
132
|
+
Let the LLM call your Python functions — just decorate them:
|
|
133
|
+
|
|
134
|
+
```python
|
|
135
|
+
from zrt.agents import function_tool
|
|
136
|
+
|
|
137
|
+
@function_tool
|
|
138
|
+
async def get_weather(city: str) -> dict:
|
|
139
|
+
"""Get the weather for a city.
|
|
140
|
+
|
|
141
|
+
Args:
|
|
142
|
+
city: City name
|
|
143
|
+
"""
|
|
144
|
+
return {"city": city, "temp_c": 22}
|
|
145
|
+
|
|
146
|
+
# then pass them to your agent:
|
|
147
|
+
# super().__init__(instructions="...", tools=[get_weather])
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Your tool runs in your worker; the runtime calls it when the LLM decides to.
|
|
151
|
+
|
|
152
|
+
## Providers
|
|
153
|
+
|
|
154
|
+
Mix and match — bring the best model for each stage, swap any one in a line:
|
|
155
|
+
|
|
156
|
+
- **Speech-to-text (STT):** Deepgram, AssemblyAI, Google, Azure, Gladia, NVIDIA, Sarvam
|
|
157
|
+
- **LLM:** OpenAI, Google Gemini, Anthropic Claude, Groq, Cerebras, xAI Grok, Sarvam
|
|
158
|
+
- **Text-to-speech (TTS):** Cartesia, ElevenLabs, Google, AWS Polly, Azure, Deepgram, Rime, LMNT, Neuphonic, Hume AI, Inworld, Murf, Resemble, Smallest, Speechify, CambAI, NVIDIA
|
|
159
|
+
- **Realtime speech-to-speech:** OpenAI Realtime, Gemini Live, Ultravox, Azure Voice Live
|
|
160
|
+
- **Turn detection:** Namo · **VAD:** Silero · **Denoise:** RNNoise
|
|
161
|
+
|
|
162
|
+
```python
|
|
163
|
+
from zrt.plugins.elevenlabs import ElevenLabsTTS # different TTS
|
|
164
|
+
from zrt.plugins.anthropic import AnthropicLLM # different LLM
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Use cases
|
|
168
|
+
|
|
169
|
+
Phone & telephony agents, IVR replacement, customer-support voice bots, voice
|
|
170
|
+
assistants, outbound/inbound call automation, and any real-time conversational AI.
|
|
171
|
+
|
|
172
|
+
## FAQ
|
|
173
|
+
|
|
174
|
+
**How is this different from a voice-agent framework?**
|
|
175
|
+
* Frameworks make you host and scale the real-time runtime (media, GPUs, turn-taking).
|
|
176
|
+
ZRT runs that for you — you only write and deploy the agent.
|
|
177
|
+
|
|
178
|
+
**How is it different from a no-code voice platform?**
|
|
179
|
+
* You write real Python with your own tools, logic, and providers — not a dashboard
|
|
180
|
+
configuration. Full code control, zero infrastructure.
|
|
181
|
+
|
|
182
|
+
**Can I use my own STT / LLM / TTS providers?**
|
|
183
|
+
* Yes — mix any supported providers, and bring your own API keys.
|
|
184
|
+
|
|
185
|
+
**What do I need to run it?**
|
|
186
|
+
* A ZRT runtime endpoint + token and the provider keys for the stages you use.
|
|
187
|
+
|
|
188
|
+
## Examples
|
|
189
|
+
|
|
190
|
+
More complete examples: https://github.com/ZeroRuntimeAI/zrt-python-sdk-examples
|
|
191
|
+
|
|
192
|
+
## Contact
|
|
193
|
+
support@videosdk.live
|
|
194
|
+
|
|
195
|
+
Copyright © 2026 Zujo Tech Pvt Ltd. All rights reserved.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "zrt"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Build real-time AI voice agents in Python. Zero Runtime runs the speech-to-speech pipeline (STT, LLM, TTS) for you."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = "LicenseRef-Proprietary"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [{ name = "Zujo Tech Pvt Ltd", email = "support@videosdk.live" }]
|
|
14
|
+
keywords = [
|
|
15
|
+
"voice-agents", "voice-ai", "ai-voice-agent", "conversational-ai",
|
|
16
|
+
"voice-assistant", "speech-to-speech", "realtime-voice", "voicebot",
|
|
17
|
+
"llm", "stt", "tts", "speech-to-text", "text-to-speech",
|
|
18
|
+
"telephony", "sip", "webrtc", "zero-runtime",
|
|
19
|
+
]
|
|
20
|
+
classifiers = [
|
|
21
|
+
"Development Status :: 4 - Beta",
|
|
22
|
+
"Intended Audience :: Developers",
|
|
23
|
+
"Operating System :: OS Independent",
|
|
24
|
+
"Programming Language :: Python :: 3",
|
|
25
|
+
"Programming Language :: Python :: 3.10",
|
|
26
|
+
"Programming Language :: Python :: 3.11",
|
|
27
|
+
"Programming Language :: Python :: 3.12",
|
|
28
|
+
"Programming Language :: Python :: 3.13",
|
|
29
|
+
"Programming Language :: Python :: 3.14",
|
|
30
|
+
"Topic :: Multimedia :: Sound/Audio :: Speech",
|
|
31
|
+
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
|
32
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
33
|
+
"Typing :: Typed",
|
|
34
|
+
]
|
|
35
|
+
dependencies = [
|
|
36
|
+
# gRPC transport to the runtime + async HTTP for auth/init. Floors have 3.14 wheels.
|
|
37
|
+
"grpcio>=1.81.0",
|
|
38
|
+
"protobuf>=6.31.0",
|
|
39
|
+
"aiohttp>=3.9.0",
|
|
40
|
+
]
|
|
41
|
+
|
|
42
|
+
[project.optional-dependencies]
|
|
43
|
+
# Vision helper — only when passing frame objects (PIL.Image / numpy / av) to
|
|
44
|
+
# session.send_image() / send_message_with_frames(). Pre-encoded bytes never need it.
|
|
45
|
+
vision = ["Pillow>=10.0"]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=8.4",
|
|
48
|
+
"pytest-asyncio>=0.24",
|
|
49
|
+
"grpcio-tools>=1.81.0",
|
|
50
|
+
"build>=1.2",
|
|
51
|
+
"twine>=6.0",
|
|
52
|
+
"ruff>=0.6",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[project.urls]
|
|
56
|
+
Homepage = "https://zeroruntime.ai/"
|
|
57
|
+
Examples = "https://github.com/ZeroRuntimeAI/zrt-python-sdk-examples"
|
|
58
|
+
|
|
59
|
+
[tool.setuptools.packages.find]
|
|
60
|
+
include = ["zrt*"]
|
|
61
|
+
|
|
62
|
+
[tool.setuptools.package-data]
|
|
63
|
+
zrt = ["py.typed"]
|
|
64
|
+
|
|
65
|
+
[tool.setuptools.dynamic]
|
|
66
|
+
version = { attr = "zrt.__version__" }
|
|
67
|
+
|
|
68
|
+
[tool.pytest.ini_options]
|
|
69
|
+
asyncio_mode = "auto"
|
|
70
|
+
testpaths = ["tests"]
|
|
71
|
+
|
|
72
|
+
[tool.ruff]
|
|
73
|
+
line-length = 100
|
|
74
|
+
target-version = "py310"
|
|
75
|
+
# Generated protobuf stubs + the vendored runtime SDK package are not linted.
|
|
76
|
+
extend-exclude = ["*_pb2.py", "*_pb2_grpc.py", "zrt/agents", "zrt/plugins"]
|
|
77
|
+
|
|
78
|
+
[tool.ruff.lint.per-file-ignores]
|
|
79
|
+
# Aggregator packages re-export names and import after a setup function.
|
|
80
|
+
"__init__.py" = ["E402", "F401"]
|
|
81
|
+
# importorskip() must run before importing modules that need the optional dep.
|
|
82
|
+
"tests/test_grpc_loopback.py" = ["E402"]
|
|
83
|
+
"tests/test_grpc_headers.py" = ["E402"]
|
zrt-0.0.1b1/setup.cfg
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"""The SDK must attach the minimal identity headers to every gRPC call."""
|
|
2
|
+
import pytest
|
|
3
|
+
|
|
4
|
+
grpc = pytest.importorskip("grpc")
|
|
5
|
+
pytest.importorskip("zrt.agents.agent_runtime_pb2")
|
|
6
|
+
|
|
7
|
+
from zrt.agents import agent_runtime_pb2 as pb
|
|
8
|
+
from zrt.agents import agent_runtime_pb2_grpc as pbg
|
|
9
|
+
from zrt.agents._grpc_bridge import _open_grpc_channel
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
class _Servicer(pbg.AgentRuntimeServicer):
|
|
13
|
+
def __init__(self):
|
|
14
|
+
self.metadata = {}
|
|
15
|
+
|
|
16
|
+
async def CreateSession(self, request, context):
|
|
17
|
+
self.metadata = dict(context.invocation_metadata())
|
|
18
|
+
return pb.CreateSessionResponse(
|
|
19
|
+
session=pb.SessionInfo(session_id="s1", runtime_version="rt/1"))
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
async def test_minimal_headers_sent(monkeypatch):
|
|
23
|
+
monkeypatch.setenv("ZRT_RUNTIME_INSECURE", "1")
|
|
24
|
+
|
|
25
|
+
servicer = _Servicer()
|
|
26
|
+
server = grpc.aio.server()
|
|
27
|
+
pbg.add_AgentRuntimeServicer_to_server(servicer, server)
|
|
28
|
+
port = server.add_insecure_port("127.0.0.1:0")
|
|
29
|
+
await server.start()
|
|
30
|
+
try:
|
|
31
|
+
ch = _open_grpc_channel(f"127.0.0.1:{port}", auth_token="room-jwt-xyz")
|
|
32
|
+
stub = pbg.AgentRuntimeStub(ch)
|
|
33
|
+
await stub.CreateSession(pb.SessionConfig(session_id="s1"))
|
|
34
|
+
await ch.close()
|
|
35
|
+
finally:
|
|
36
|
+
await server.stop(0)
|
|
37
|
+
|
|
38
|
+
md = servicer.metadata
|
|
39
|
+
assert md["x-zrt-sdk"] == "zrt-python"
|
|
40
|
+
assert md["x-zrt-sdk-version"]
|
|
41
|
+
assert md["x-zrt-proto-version"] == "1"
|
|
42
|
+
assert md["x-zrt-device-os"]
|
|
43
|
+
assert md["x-zrt-device-arch"]
|
|
44
|
+
assert md["x-zrt-host"]
|
|
45
|
+
assert md["authorization"] == "Bearer room-jwt-xyz"
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
async def test_auth_header_omitted_without_token(monkeypatch):
|
|
49
|
+
monkeypatch.setenv("ZRT_RUNTIME_INSECURE", "1")
|
|
50
|
+
monkeypatch.delenv("ZRT_AUTH_TOKEN", raising=False)
|
|
51
|
+
|
|
52
|
+
servicer = _Servicer()
|
|
53
|
+
server = grpc.aio.server()
|
|
54
|
+
pbg.add_AgentRuntimeServicer_to_server(servicer, server)
|
|
55
|
+
port = server.add_insecure_port("127.0.0.1:0")
|
|
56
|
+
await server.start()
|
|
57
|
+
try:
|
|
58
|
+
ch = _open_grpc_channel(f"127.0.0.1:{port}") # no token
|
|
59
|
+
stub = pbg.AgentRuntimeStub(ch)
|
|
60
|
+
await stub.CreateSession(pb.SessionConfig(session_id="s1"))
|
|
61
|
+
await ch.close()
|
|
62
|
+
finally:
|
|
63
|
+
await server.stop(0)
|
|
64
|
+
|
|
65
|
+
assert "authorization" not in servicer.metadata
|
|
66
|
+
assert servicer.metadata["x-zrt-sdk"] == "zrt-python"
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"""Every submodule (agents core + all provider plugins) must import cleanly."""
|
|
2
|
+
import importlib
|
|
3
|
+
import pkgutil
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_all_submodules_import():
|
|
7
|
+
import zrt.agents
|
|
8
|
+
import zrt.plugins
|
|
9
|
+
|
|
10
|
+
failures = []
|
|
11
|
+
for pkg in (zrt.agents, zrt.plugins):
|
|
12
|
+
for mod in pkgutil.walk_packages(pkg.__path__, pkg.__name__ + "."):
|
|
13
|
+
try:
|
|
14
|
+
importlib.import_module(mod.name)
|
|
15
|
+
except Exception as exc: # noqa: BLE001
|
|
16
|
+
failures.append(f"{mod.name}: {type(exc).__name__}: {exc}")
|
|
17
|
+
assert not failures, "import failures:\n" + "\n".join(failures)
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def test_version():
|
|
21
|
+
import zrt
|
|
22
|
+
|
|
23
|
+
assert isinstance(zrt.__version__, str) and zrt.__version__.count(".") >= 1
|