hypha-rpc 0.20.91__py3-none-any.whl → 0.20.93__py3-none-any.whl
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.
- hypha_rpc/VERSION +1 -1
- hypha_rpc/__init__.py +7 -2
- hypha_rpc/http_client.py +23 -7
- hypha_rpc/websocket_client.py +112 -4
- {hypha_rpc-0.20.91.dist-info → hypha_rpc-0.20.93.dist-info}/METADATA +1 -1
- {hypha_rpc-0.20.91.dist-info → hypha_rpc-0.20.93.dist-info}/RECORD +8 -9
- hypha_rpc/client.py +0 -123
- {hypha_rpc-0.20.91.dist-info → hypha_rpc-0.20.93.dist-info}/WHEEL +0 -0
- {hypha_rpc-0.20.91.dist-info → hypha_rpc-0.20.93.dist-info}/top_level.txt +0 -0
hypha_rpc/VERSION
CHANGED
hypha_rpc/__init__.py
CHANGED
|
@@ -15,8 +15,13 @@ from .sync import login as login_sync
|
|
|
15
15
|
from .sync import logout as logout_sync
|
|
16
16
|
from .sync import register_rtc_service as register_rtc_service_sync
|
|
17
17
|
from .webrtc_client import get_rtc_service, register_rtc_service
|
|
18
|
-
from .
|
|
19
|
-
|
|
18
|
+
from .websocket_client import (
|
|
19
|
+
connect_to_server,
|
|
20
|
+
get_remote_service,
|
|
21
|
+
login,
|
|
22
|
+
logout,
|
|
23
|
+
setup_local_client,
|
|
24
|
+
)
|
|
20
25
|
from .http_client import HTTPStreamingRPCConnection
|
|
21
26
|
|
|
22
27
|
# read the version from the VERSION file; but get the path from the __file__
|
hypha_rpc/http_client.py
CHANGED
|
@@ -174,15 +174,26 @@ class HTTPStreamingRPCConnection:
|
|
|
174
174
|
elif self._ssl is not None:
|
|
175
175
|
verify = self._ssl
|
|
176
176
|
|
|
177
|
+
# Try to enable HTTP/2 if h2 is available
|
|
178
|
+
try:
|
|
179
|
+
import h2 # noqa
|
|
180
|
+
http2_enabled = True
|
|
181
|
+
logger.info("HTTP/2 enabled for improved performance")
|
|
182
|
+
except ImportError:
|
|
183
|
+
http2_enabled = False
|
|
184
|
+
logger.debug("HTTP/2 not available (install httpx[http2] for better performance)")
|
|
185
|
+
|
|
177
186
|
return httpx.AsyncClient(
|
|
178
187
|
timeout=httpx.Timeout(self._timeout, connect=30.0),
|
|
179
188
|
verify=verify,
|
|
180
|
-
#
|
|
189
|
+
# Optimized connection pooling for high-performance RPC
|
|
181
190
|
limits=httpx.Limits(
|
|
182
|
-
max_connections=
|
|
183
|
-
max_keepalive_connections=
|
|
184
|
-
keepalive_expiry=
|
|
191
|
+
max_connections=200, # Max total connections (increased for parallel requests)
|
|
192
|
+
max_keepalive_connections=50, # More reusable connections (up from 20)
|
|
193
|
+
keepalive_expiry=300.0, # Keep connections alive longer (5 minutes)
|
|
185
194
|
),
|
|
195
|
+
# Enable HTTP/2 for better multiplexing if available
|
|
196
|
+
http2=http2_enabled,
|
|
186
197
|
)
|
|
187
198
|
|
|
188
199
|
async def open(self):
|
|
@@ -418,7 +429,11 @@ class HTTPStreamingRPCConnection:
|
|
|
418
429
|
self._handle_message(data)
|
|
419
430
|
|
|
420
431
|
async def emit_message(self, data: bytes):
|
|
421
|
-
"""Send a message to the server via HTTP POST.
|
|
432
|
+
"""Send a message to the server via HTTP POST.
|
|
433
|
+
|
|
434
|
+
Uses optimized connection pooling with keep-alive for better performance.
|
|
435
|
+
HTTP client automatically handles efficient transfer for all payload sizes.
|
|
436
|
+
"""
|
|
422
437
|
if self._closed:
|
|
423
438
|
raise ConnectionError("Connection is closed")
|
|
424
439
|
|
|
@@ -430,6 +445,7 @@ class HTTPStreamingRPCConnection:
|
|
|
430
445
|
params = {"client_id": self._client_id}
|
|
431
446
|
|
|
432
447
|
try:
|
|
448
|
+
# httpx handles large payloads efficiently with connection pooling
|
|
433
449
|
response = await self._http_client.post(
|
|
434
450
|
url,
|
|
435
451
|
content=data,
|
|
@@ -511,7 +527,7 @@ def connect_to_server_http(config=None, **kwargs):
|
|
|
511
527
|
Returns:
|
|
512
528
|
ServerContextManager that can be used as async context manager
|
|
513
529
|
"""
|
|
514
|
-
from .
|
|
530
|
+
from .websocket_client import connect_to_server
|
|
515
531
|
config = config or {}
|
|
516
532
|
config.update(kwargs)
|
|
517
533
|
config["transport"] = "http"
|
|
@@ -625,7 +641,7 @@ def get_remote_service_http(service_uri: str, config=None, **kwargs):
|
|
|
625
641
|
This is a convenience function that sets transport="http" automatically.
|
|
626
642
|
For a unified interface, use get_remote_service with transport="http" instead.
|
|
627
643
|
"""
|
|
628
|
-
from .
|
|
644
|
+
from .websocket_client import get_remote_service
|
|
629
645
|
config = config or {}
|
|
630
646
|
config.update(kwargs)
|
|
631
647
|
config["transport"] = "http"
|
hypha_rpc/websocket_client.py
CHANGED
|
@@ -738,10 +738,6 @@ async def logout(config):
|
|
|
738
738
|
await server.disconnect()
|
|
739
739
|
|
|
740
740
|
|
|
741
|
-
# Re-export from client.py for backwards compatibility
|
|
742
|
-
from .client import ServerContextManager, connect_to_server, get_remote_service
|
|
743
|
-
|
|
744
|
-
|
|
745
741
|
async def webrtc_get_service(wm, rtc_service_id, query, config=None, **kwargs):
|
|
746
742
|
config = config or {}
|
|
747
743
|
config.update(kwargs)
|
|
@@ -1151,6 +1147,118 @@ async def _connect_to_server(config):
|
|
|
1151
1147
|
return wm
|
|
1152
1148
|
|
|
1153
1149
|
|
|
1150
|
+
class ServerContextManager:
|
|
1151
|
+
"""Server context manager.
|
|
1152
|
+
|
|
1153
|
+
Supports multiple transport types:
|
|
1154
|
+
- "websocket" (default): Traditional WebSocket connection
|
|
1155
|
+
- "http": HTTP streaming connection (more resilient to network issues)
|
|
1156
|
+
"""
|
|
1157
|
+
|
|
1158
|
+
def __init__(self, config=None, service_id=None, **kwargs):
|
|
1159
|
+
self.config = config or {}
|
|
1160
|
+
self.config.update(kwargs)
|
|
1161
|
+
|
|
1162
|
+
if not self.config:
|
|
1163
|
+
# try to load from env
|
|
1164
|
+
if not os.environ.get("HYPHA_SERVER_URL"):
|
|
1165
|
+
try:
|
|
1166
|
+
from dotenv import load_dotenv, find_dotenv
|
|
1167
|
+
load_dotenv(dotenv_path=find_dotenv(usecwd=True))
|
|
1168
|
+
# use info from .env file
|
|
1169
|
+
print("✅ Loaded connection configuration from .env file.")
|
|
1170
|
+
except ImportError:
|
|
1171
|
+
pass
|
|
1172
|
+
self.config = {
|
|
1173
|
+
"server_url": os.getenv("HYPHA_SERVER_URL"),
|
|
1174
|
+
"token": os.getenv("HYPHA_TOKEN"),
|
|
1175
|
+
"client_id": os.getenv("HYPHA_CLIENT_ID"),
|
|
1176
|
+
"workspace": os.getenv("HYPHA_WORKSPACE"),
|
|
1177
|
+
}
|
|
1178
|
+
if not self.config["server_url"]:
|
|
1179
|
+
raise ValueError(
|
|
1180
|
+
"Please set the HYPHA_SERVER_URL, HYPHA_TOKEN, "
|
|
1181
|
+
"HYPHA_CLIENT_ID, and HYPHA_WORKSPACE environment variables"
|
|
1182
|
+
)
|
|
1183
|
+
self._service_id = service_id
|
|
1184
|
+
self._transport = self.config.pop("transport", "websocket")
|
|
1185
|
+
self.wm = None
|
|
1186
|
+
|
|
1187
|
+
async def __aenter__(self):
|
|
1188
|
+
if self._transport == "http":
|
|
1189
|
+
from .http_client import _connect_to_server_http
|
|
1190
|
+
self.wm = await _connect_to_server_http(self.config)
|
|
1191
|
+
else:
|
|
1192
|
+
self.wm = await _connect_to_server(self.config)
|
|
1193
|
+
if self._service_id:
|
|
1194
|
+
return await self.wm.get_service(
|
|
1195
|
+
self._service_id,
|
|
1196
|
+
{"case_conversion": self.config.get("case_conversion")},
|
|
1197
|
+
)
|
|
1198
|
+
return self.wm
|
|
1199
|
+
|
|
1200
|
+
async def __aexit__(self, exc_type, exc, tb):
|
|
1201
|
+
await self.wm.disconnect()
|
|
1202
|
+
|
|
1203
|
+
def __await__(self):
|
|
1204
|
+
return self.__aenter__().__await__()
|
|
1205
|
+
|
|
1206
|
+
|
|
1207
|
+
def connect_to_server(config=None, **kwargs):
|
|
1208
|
+
"""Connect to a Hypha server.
|
|
1209
|
+
|
|
1210
|
+
Args:
|
|
1211
|
+
config: Configuration dict with connection options
|
|
1212
|
+
**kwargs: Additional configuration options
|
|
1213
|
+
|
|
1214
|
+
Configuration options:
|
|
1215
|
+
server_url: The server URL (required)
|
|
1216
|
+
workspace: Target workspace (optional)
|
|
1217
|
+
token: Authentication token (optional)
|
|
1218
|
+
client_id: Unique client identifier (optional, auto-generated if not provided)
|
|
1219
|
+
transport: Transport type - "websocket" (default) or "http"
|
|
1220
|
+
method_timeout: Timeout for RPC method calls
|
|
1221
|
+
ssl: SSL configuration (True/False/SSLContext)
|
|
1222
|
+
|
|
1223
|
+
Returns:
|
|
1224
|
+
ServerContextManager that can be used as async context manager
|
|
1225
|
+
|
|
1226
|
+
Example:
|
|
1227
|
+
async with connect_to_server({"server_url": "https://hypha.aicell.io"}) as server:
|
|
1228
|
+
await server.register_service({"id": "my-service", ...})
|
|
1229
|
+
"""
|
|
1230
|
+
return ServerContextManager(config=config, **kwargs)
|
|
1231
|
+
|
|
1232
|
+
|
|
1233
|
+
def get_remote_service(service_uri, config=None, **kwargs):
|
|
1234
|
+
"""Get a remote service by URI.
|
|
1235
|
+
|
|
1236
|
+
Args:
|
|
1237
|
+
service_uri: Service URI in format "server_url/workspace/client_id:service_id"
|
|
1238
|
+
config: Additional configuration options
|
|
1239
|
+
**kwargs: Additional configuration options
|
|
1240
|
+
|
|
1241
|
+
Returns:
|
|
1242
|
+
ServerContextManager that resolves to the service when awaited
|
|
1243
|
+
|
|
1244
|
+
Example:
|
|
1245
|
+
async with get_remote_service("https://hypha.aicell.io/public/client:service") as svc:
|
|
1246
|
+
result = await svc.some_method()
|
|
1247
|
+
"""
|
|
1248
|
+
server_url, workspace, client_id, service_id, app_id = parse_service_url(
|
|
1249
|
+
service_uri
|
|
1250
|
+
)
|
|
1251
|
+
full_service_id = f"{workspace}/{client_id}:{service_id}@{app_id}"
|
|
1252
|
+
config = config or {}
|
|
1253
|
+
config.update(kwargs)
|
|
1254
|
+
if "server_url" in config:
|
|
1255
|
+
assert (
|
|
1256
|
+
config["server_url"] == server_url
|
|
1257
|
+
), "server_url in config does not match the server_url in the url"
|
|
1258
|
+
config["server_url"] = server_url
|
|
1259
|
+
return ServerContextManager(config, service_id=full_service_id)
|
|
1260
|
+
|
|
1261
|
+
|
|
1154
1262
|
def setup_local_client(enable_execution=False, on_ready=None):
|
|
1155
1263
|
"""Set up a local client."""
|
|
1156
1264
|
fut = safe_create_future()
|
|
@@ -1,20 +1,19 @@
|
|
|
1
|
-
hypha_rpc/VERSION,sha256=
|
|
2
|
-
hypha_rpc/__init__.py,sha256=
|
|
3
|
-
hypha_rpc/
|
|
4
|
-
hypha_rpc/http_client.py,sha256=z1fbomvF9wk7ZxFmzfw8qnheE_ueXrg1C4c8Ss5hgWU,23545
|
|
1
|
+
hypha_rpc/VERSION,sha256=oQt6CaFAJvGH-g-tZewKKFq1_1EOjSExWvGzeFGpmac,26
|
|
2
|
+
hypha_rpc/__init__.py,sha256=kWNHbAl-a0RhgKgWm5r0cvs-qd1ujlpmPbXV_0QWuQQ,4727
|
|
3
|
+
hypha_rpc/http_client.py,sha256=9ni8yx_2ZwJ5ibhN4tD8EMtfmvzTEm4UcRRggJ8pnRY,24307
|
|
5
4
|
hypha_rpc/pyodide_sse.py,sha256=o1-6Bqb7bcplSy7pwkmtQb6vKeJsyxex_RebqNd3wX8,2960
|
|
6
5
|
hypha_rpc/pyodide_websocket.py,sha256=XjrgKYySUSNYma-rXjHrSv08YCxj5t4hYEQnK15D6cE,18749
|
|
7
6
|
hypha_rpc/rpc.py,sha256=lnNiPAm_BNT5JjDhAPFRlxs6HioXw77TelUtYd_blYk,115579
|
|
8
7
|
hypha_rpc/sync.py,sha256=HcQwpGHsZjDNcSnDRuyxGu7bquOi5_jWrVL5vTwraZY,12268
|
|
9
8
|
hypha_rpc/webrtc_client.py,sha256=JVbSTWr6Y6vMaeoAPsfecD2SuCtXOuoBVuhpwG5-Qm0,11944
|
|
10
|
-
hypha_rpc/websocket_client.py,sha256=
|
|
9
|
+
hypha_rpc/websocket_client.py,sha256=tk8mID_zd0SaKTnwCHMTDIIeWvmatDbr5LHXbo6WwJ8,52920
|
|
11
10
|
hypha_rpc/utils/__init__.py,sha256=1UWExsUWzNRFkuYa7RSDXH3welrelIxOmGLtzdJ2oIA,20042
|
|
12
11
|
hypha_rpc/utils/launch.py,sha256=GB1Ranb5E_oNFBLw2ARfT78SbqGEwUmWwfMo3E82kAM,3976
|
|
13
12
|
hypha_rpc/utils/mcp.py,sha256=AW48yjCovc0jyekRLeD_1U8mRaA8-nEqh4DotSE_s3Y,17348
|
|
14
13
|
hypha_rpc/utils/pydantic.py,sha256=a09_ys4BSXc4Yi6OgZjdspbtLvQVoRCChr6uInY4fN4,5144
|
|
15
14
|
hypha_rpc/utils/schema.py,sha256=WabBJiDheMKRXUroVe9JRlI5P4Wlv6kc0roxVNQZHH8,22110
|
|
16
15
|
hypha_rpc/utils/serve.py,sha256=xr_3oAQDyignQbz1fcm4kuRMBOb52-i0VSYCjZou51c,11882
|
|
17
|
-
hypha_rpc-0.20.
|
|
18
|
-
hypha_rpc-0.20.
|
|
19
|
-
hypha_rpc-0.20.
|
|
20
|
-
hypha_rpc-0.20.
|
|
16
|
+
hypha_rpc-0.20.93.dist-info/METADATA,sha256=HHPwYXpCX8PcZFYANkT5KTuDUPQ3S6-c_i2OCyIY2BI,924
|
|
17
|
+
hypha_rpc-0.20.93.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
18
|
+
hypha_rpc-0.20.93.dist-info/top_level.txt,sha256=uShPbaPGP-Ig8OVnQcT6sEzV0Qhb6wfxSJ3uCmYaB58,10
|
|
19
|
+
hypha_rpc-0.20.93.dist-info/RECORD,,
|
hypha_rpc/client.py
DELETED
|
@@ -1,123 +0,0 @@
|
|
|
1
|
-
"""Hypha RPC client - unified connection interface.
|
|
2
|
-
|
|
3
|
-
This module provides the main entry point for connecting to Hypha servers.
|
|
4
|
-
It supports multiple transport types:
|
|
5
|
-
- "websocket" (default): Traditional WebSocket connection
|
|
6
|
-
- "http": HTTP streaming connection (more resilient to network issues)
|
|
7
|
-
"""
|
|
8
|
-
|
|
9
|
-
import os
|
|
10
|
-
from .utils import parse_service_url
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
class ServerContextManager:
|
|
14
|
-
"""Server context manager.
|
|
15
|
-
|
|
16
|
-
Supports multiple transport types:
|
|
17
|
-
- "websocket" (default): Traditional WebSocket connection
|
|
18
|
-
- "http": HTTP streaming connection (more resilient to network issues)
|
|
19
|
-
"""
|
|
20
|
-
|
|
21
|
-
def __init__(self, config=None, service_id=None, **kwargs):
|
|
22
|
-
self.config = config or {}
|
|
23
|
-
self.config.update(kwargs)
|
|
24
|
-
|
|
25
|
-
if not self.config:
|
|
26
|
-
# try to load from env
|
|
27
|
-
if not os.environ.get("HYPHA_SERVER_URL"):
|
|
28
|
-
try:
|
|
29
|
-
from dotenv import load_dotenv, find_dotenv
|
|
30
|
-
load_dotenv(dotenv_path=find_dotenv(usecwd=True))
|
|
31
|
-
# use info from .env file
|
|
32
|
-
print("✅ Loaded connection configuration from .env file.")
|
|
33
|
-
except ImportError:
|
|
34
|
-
pass
|
|
35
|
-
self.config = {
|
|
36
|
-
"server_url": os.getenv("HYPHA_SERVER_URL"),
|
|
37
|
-
"token": os.getenv("HYPHA_TOKEN"),
|
|
38
|
-
"client_id": os.getenv("HYPHA_CLIENT_ID"),
|
|
39
|
-
"workspace": os.getenv("HYPHA_WORKSPACE"),
|
|
40
|
-
}
|
|
41
|
-
if not self.config["server_url"]:
|
|
42
|
-
raise ValueError(
|
|
43
|
-
"Please set the HYPHA_SERVER_URL, HYPHA_TOKEN, "
|
|
44
|
-
"HYPHA_CLIENT_ID, and HYPHA_WORKSPACE environment variables"
|
|
45
|
-
)
|
|
46
|
-
self._service_id = service_id
|
|
47
|
-
self._transport = self.config.pop("transport", "websocket")
|
|
48
|
-
self.wm = None
|
|
49
|
-
|
|
50
|
-
async def __aenter__(self):
|
|
51
|
-
if self._transport == "http":
|
|
52
|
-
from .http_client import _connect_to_server_http
|
|
53
|
-
self.wm = await _connect_to_server_http(self.config)
|
|
54
|
-
else:
|
|
55
|
-
from .websocket_client import _connect_to_server
|
|
56
|
-
self.wm = await _connect_to_server(self.config)
|
|
57
|
-
if self._service_id:
|
|
58
|
-
return await self.wm.get_service(
|
|
59
|
-
self._service_id,
|
|
60
|
-
{"case_conversion": self.config.get("case_conversion")},
|
|
61
|
-
)
|
|
62
|
-
return self.wm
|
|
63
|
-
|
|
64
|
-
async def __aexit__(self, exc_type, exc, tb):
|
|
65
|
-
await self.wm.disconnect()
|
|
66
|
-
|
|
67
|
-
def __await__(self):
|
|
68
|
-
return self.__aenter__().__await__()
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
def connect_to_server(config=None, **kwargs):
|
|
72
|
-
"""Connect to a Hypha server.
|
|
73
|
-
|
|
74
|
-
Args:
|
|
75
|
-
config: Configuration dict with connection options
|
|
76
|
-
**kwargs: Additional configuration options
|
|
77
|
-
|
|
78
|
-
Configuration options:
|
|
79
|
-
server_url: The server URL (required)
|
|
80
|
-
workspace: Target workspace (optional)
|
|
81
|
-
token: Authentication token (optional)
|
|
82
|
-
client_id: Unique client identifier (optional, auto-generated if not provided)
|
|
83
|
-
transport: Transport type - "websocket" (default) or "http"
|
|
84
|
-
method_timeout: Timeout for RPC method calls
|
|
85
|
-
ssl: SSL configuration (True/False/SSLContext)
|
|
86
|
-
|
|
87
|
-
Returns:
|
|
88
|
-
ServerContextManager that can be used as async context manager
|
|
89
|
-
|
|
90
|
-
Example:
|
|
91
|
-
async with connect_to_server({"server_url": "https://hypha.aicell.io"}) as server:
|
|
92
|
-
await server.register_service({"id": "my-service", ...})
|
|
93
|
-
"""
|
|
94
|
-
return ServerContextManager(config=config, **kwargs)
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
def get_remote_service(service_uri, config=None, **kwargs):
|
|
98
|
-
"""Get a remote service by URI.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
service_uri: Service URI in format "server_url/workspace/client_id:service_id"
|
|
102
|
-
config: Additional configuration options
|
|
103
|
-
**kwargs: Additional configuration options
|
|
104
|
-
|
|
105
|
-
Returns:
|
|
106
|
-
ServerContextManager that resolves to the service when awaited
|
|
107
|
-
|
|
108
|
-
Example:
|
|
109
|
-
async with get_remote_service("https://hypha.aicell.io/public/client:service") as svc:
|
|
110
|
-
result = await svc.some_method()
|
|
111
|
-
"""
|
|
112
|
-
server_url, workspace, client_id, service_id, app_id = parse_service_url(
|
|
113
|
-
service_uri
|
|
114
|
-
)
|
|
115
|
-
full_service_id = f"{workspace}/{client_id}:{service_id}@{app_id}"
|
|
116
|
-
config = config or {}
|
|
117
|
-
config.update(kwargs)
|
|
118
|
-
if "server_url" in config:
|
|
119
|
-
assert (
|
|
120
|
-
config["server_url"] == server_url
|
|
121
|
-
), "server_url in config does not match the server_url in the url"
|
|
122
|
-
config["server_url"] = server_url
|
|
123
|
-
return ServerContextManager(config, service_id=full_service_id)
|
|
File without changes
|
|
File without changes
|