unique-search-proxy-core 2026.44.0.dev0__tar.gz → 2026.44.0.dev2__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.
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/PKG-INFO +2 -2
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/pyproject.toml +2 -2
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/http_client/__init__.py +2 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/http_client/client.py +51 -7
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/README.md +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/base.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/bing/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/bing/enums.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/bing/grounding.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/bing/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/bing/settings.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/config_types.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/output_schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/resolve.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/response_parsing.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/vertexai/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/vertexai/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/agent_engines/vertexai/settings.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/context.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/base.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/basic/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/basic/content_types.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/basic/processing/policy.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/basic/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/config_types.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/firecrawl/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/jina/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/crawlers/tavily/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/errors.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/http_client/credentials.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/http_client/secrets.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/http_client/settings.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/logging.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/annotations.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/derive.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/exposable_config.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/exposable_param.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/exposed_params.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/param_policy/request_base.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/providers/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/base.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/brave/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/brave/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/config_types.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/google/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/google/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/perplexity/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/search_engines/perplexity/schema.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/__init__.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/dns.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/egress.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/models.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/netloc.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/policy.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/redirect.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/resolver.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/service.py +0 -0
- {unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/unique_search_proxy_core/url_safety/settings.py +0 -0
{unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: unique-search-proxy-core
|
|
3
|
-
Version: 2026.44.0.
|
|
3
|
+
Version: 2026.44.0.dev2
|
|
4
4
|
Summary: Shared Pydantic types for the Unique Search Proxy API
|
|
5
5
|
Author: ThePhilAz
|
|
6
6
|
Author-email: ThePhilAz <rami.azouz@philico.com>
|
|
@@ -8,7 +8,7 @@ Requires-Dist: httpx>=0.28.0,<0.29
|
|
|
8
8
|
Requires-Dist: pydantic>=2.12.5,<3.0.0
|
|
9
9
|
Requires-Dist: pydantic-settings>=2.10.1,<3
|
|
10
10
|
Requires-Dist: pyhumps>=3.8.0,<4
|
|
11
|
-
Requires-Dist: unique-toolkit[monitoring]>=2026.44.0.
|
|
11
|
+
Requires-Dist: unique-toolkit[monitoring]>=2026.44.0.dev7,<2026.44.0rc0
|
|
12
12
|
Requires-Python: >=3.12
|
|
13
13
|
Description-Content-Type: text/markdown
|
|
14
14
|
|
{unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/pyproject.toml
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "unique-search-proxy-core"
|
|
3
|
-
version = "2026.44.0.
|
|
3
|
+
version = "2026.44.0.dev2"
|
|
4
4
|
description = "Shared Pydantic types for the Unique Search Proxy API"
|
|
5
5
|
authors = [{ name = "ThePhilAz", email = "rami.azouz@philico.com" }]
|
|
6
6
|
readme = "README.md"
|
|
@@ -10,7 +10,7 @@ dependencies = [
|
|
|
10
10
|
"pydantic>=2.12.5,<3.0.0",
|
|
11
11
|
"pydantic-settings>=2.10.1,<3",
|
|
12
12
|
"pyhumps>=3.8.0,<4",
|
|
13
|
-
"unique-toolkit[monitoring]>=2026.44.0.
|
|
13
|
+
"unique-toolkit[monitoring]>=2026.44.0.dev7,<2026.44.0rc0",
|
|
14
14
|
|
|
15
15
|
]
|
|
16
16
|
|
|
@@ -5,6 +5,7 @@ from unique_search_proxy_core.http_client.client import (
|
|
|
5
5
|
EgressRoute,
|
|
6
6
|
HttpClientRegistry,
|
|
7
7
|
ProxiedRoute,
|
|
8
|
+
ResolvedEgress,
|
|
8
9
|
async_client_factory,
|
|
9
10
|
build_async_client,
|
|
10
11
|
build_route,
|
|
@@ -38,6 +39,7 @@ __all__ = [
|
|
|
38
39
|
"ProxyProtocol",
|
|
39
40
|
"ProxySettings",
|
|
40
41
|
"ProxyUsernameSource",
|
|
42
|
+
"ResolvedEgress",
|
|
41
43
|
"SettingsProxyCredentials",
|
|
42
44
|
"UserMetadataProxyCredentials",
|
|
43
45
|
"async_client_factory",
|
|
@@ -57,6 +57,14 @@ class ProxiedRoute:
|
|
|
57
57
|
EgressRoute = DirectRoute | ProxiedRoute
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
@dataclass(frozen=True)
|
|
61
|
+
class ResolvedEgress:
|
|
62
|
+
"""HTTP client and route resolved from one request credential set."""
|
|
63
|
+
|
|
64
|
+
http_client: AsyncClient
|
|
65
|
+
route: EgressRoute
|
|
66
|
+
|
|
67
|
+
|
|
60
68
|
def _get_proxy_host_and_port(settings: ProxySettings) -> tuple[str, int]:
|
|
61
69
|
proxy_host = settings.proxy_host
|
|
62
70
|
proxy_port = settings.proxy_port
|
|
@@ -314,20 +322,51 @@ class HttpClientRegistry:
|
|
|
314
322
|
fixed_client=client,
|
|
315
323
|
)
|
|
316
324
|
|
|
317
|
-
async def
|
|
318
|
-
"""Return the cached client for
|
|
319
|
-
if self._fixed_client is not None:
|
|
320
|
-
return self._fixed_client
|
|
325
|
+
async def egress_for(self, context: RequestContext) -> ResolvedEgress:
|
|
326
|
+
"""Return the cached client and route for one credential resolution."""
|
|
321
327
|
if self._closed:
|
|
322
328
|
raise RuntimeError("HTTP client registry is closed")
|
|
323
|
-
|
|
324
329
|
credentials = self._resolver.resolve(context)
|
|
330
|
+
return await self._egress_for_credentials(credentials)
|
|
331
|
+
|
|
332
|
+
async def settings_egress(self) -> ResolvedEgress:
|
|
333
|
+
"""Return egress for process-level work using settings credentials."""
|
|
334
|
+
if self._closed:
|
|
335
|
+
raise RuntimeError("HTTP client registry is closed")
|
|
336
|
+
if (
|
|
337
|
+
self._settings.proxy_username_source == "user_metadata"
|
|
338
|
+
and self._settings.proxy_auth_mode == "none"
|
|
339
|
+
):
|
|
340
|
+
raise ValidationProxyError(
|
|
341
|
+
"Process-level egress cannot use request-scoped proxy credentials; "
|
|
342
|
+
"configure settings-backed username/password or mTLS credentials",
|
|
343
|
+
)
|
|
344
|
+
credentials = SettingsProxyCredentials(self._settings).resolve(
|
|
345
|
+
RequestContext(
|
|
346
|
+
company_id="__settings__",
|
|
347
|
+
user_id="local",
|
|
348
|
+
chat_id="local",
|
|
349
|
+
),
|
|
350
|
+
)
|
|
351
|
+
return await self._egress_for_credentials(credentials)
|
|
352
|
+
|
|
353
|
+
async def _egress_for_credentials(
|
|
354
|
+
self,
|
|
355
|
+
credentials: ProxyCredentials,
|
|
356
|
+
) -> ResolvedEgress:
|
|
357
|
+
if self._closed:
|
|
358
|
+
raise RuntimeError("HTTP client registry is closed")
|
|
359
|
+
|
|
360
|
+
route = build_route(self._settings, credentials)
|
|
361
|
+
if self._fixed_client is not None:
|
|
362
|
+
return ResolvedEgress(http_client=self._fixed_client, route=route)
|
|
363
|
+
|
|
325
364
|
evicted: AsyncClient | None = None
|
|
326
365
|
async with self._lock:
|
|
327
366
|
cached = self._clients.get(credentials)
|
|
328
367
|
if cached is not None:
|
|
329
368
|
self._clients.move_to_end(credentials)
|
|
330
|
-
return cached
|
|
369
|
+
return ResolvedEgress(http_client=cached, route=route)
|
|
331
370
|
|
|
332
371
|
client = build_async_client(
|
|
333
372
|
self._settings,
|
|
@@ -350,7 +389,11 @@ class HttpClientRegistry:
|
|
|
350
389
|
|
|
351
390
|
if evicted is not None:
|
|
352
391
|
await evicted.aclose()
|
|
353
|
-
return client
|
|
392
|
+
return ResolvedEgress(http_client=client, route=route)
|
|
393
|
+
|
|
394
|
+
async def client_for(self, context: RequestContext) -> AsyncClient:
|
|
395
|
+
"""Return the cached client for the request's resolved credentials."""
|
|
396
|
+
return (await self.egress_for(context)).http_client
|
|
354
397
|
|
|
355
398
|
@property
|
|
356
399
|
def is_open(self) -> bool:
|
|
@@ -384,6 +427,7 @@ __all__ = [
|
|
|
384
427
|
"EgressRoute",
|
|
385
428
|
"HttpClientRegistry",
|
|
386
429
|
"ProxiedRoute",
|
|
430
|
+
"ResolvedEgress",
|
|
387
431
|
"async_client_factory",
|
|
388
432
|
"build_async_client",
|
|
389
433
|
"build_route",
|
{unique_search_proxy_core-2026.44.0.dev0 → unique_search_proxy_core-2026.44.0.dev2}/README.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|