unique-search-proxy 2026.44.0.dev0__tar.gz → 2026.44.0.dev1__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 (116) hide show
  1. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/PKG-INFO +4 -3
  2. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/pyproject.toml +4 -3
  3. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/agent_search.py +17 -0
  4. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/app.py +1 -1
  5. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/bing/cleanup.py +19 -7
  6. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/bing/client.py +38 -7
  7. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/bing/runner.py +13 -1
  8. unique_search_proxy-2026.44.0.dev1/unique_search_proxy_client/web/core/agent_engines/bing/service.py +185 -0
  9. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/factory.py +7 -2
  10. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/service_base.py +1 -11
  11. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/vertexai/client.py +18 -6
  12. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/vertexai/service.py +1 -1
  13. unique_search_proxy-2026.44.0.dev1/unique_search_proxy_client/web/core/client/azure_transport.py +146 -0
  14. unique_search_proxy-2026.44.0.dev0/unique_search_proxy_client/web/core/agent_engines/bing/service.py +0 -109
  15. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/README.md +0 -0
  16. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/__init__.py +0 -0
  17. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/__init__.py +0 -0
  18. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/__init__.py +0 -0
  19. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/health.py +0 -0
  20. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/__init__.py +0 -0
  21. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/configuration.py +0 -0
  22. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/context_headers.py +0 -0
  23. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/crawl.py +0 -0
  24. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/openapi_examples.py +0 -0
  25. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/api/v1/search.py +0 -0
  26. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/context.py +0 -0
  27. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/__init__.py +0 -0
  28. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/__init__.py +0 -0
  29. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/structured_output.py +0 -0
  30. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/agent_engines/vertexai/gemini.py +0 -0
  31. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/client/__init__.py +0 -0
  32. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/client/credentials.py +0 -0
  33. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/client/service.py +0 -0
  34. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/__init__.py +0 -0
  35. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/__init__.py +0 -0
  36. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/__init__.py +0 -0
  37. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/errors.py +0 -0
  38. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/html_markdown.py +0 -0
  39. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/__init__.py +0 -0
  40. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/html.py +0 -0
  41. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/pdf.py +0 -0
  42. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/processors/plain_text.py +0 -0
  43. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/processing/registry.py +0 -0
  44. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/service.py +0 -0
  45. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/settings.py +0 -0
  46. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/basic/user_agent.py +0 -0
  47. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/factory.py +0 -0
  48. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/firecrawl/polling.py +0 -0
  49. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/firecrawl/request_body.py +0 -0
  50. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/firecrawl/service.py +0 -0
  51. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/jina/request_body.py +0 -0
  52. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/jina/service.py +0 -0
  53. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/pinned_egress.py +0 -0
  54. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/tavily/request_body.py +0 -0
  55. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/crawlers/tavily/service.py +0 -0
  56. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/provider_response.py +0 -0
  57. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/providers.py +0 -0
  58. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/registry.py +0 -0
  59. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/__init__.py +0 -0
  60. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/brave/__init__.py +0 -0
  61. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/brave/pagination.py +0 -0
  62. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/brave/query_params.py +0 -0
  63. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/brave/service.py +0 -0
  64. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/descriptor.py +0 -0
  65. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/factory.py +0 -0
  66. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/google/__init__.py +0 -0
  67. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/google/pagination.py +0 -0
  68. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/google/query_params.py +0 -0
  69. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/google/service.py +0 -0
  70. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/pagination.py +0 -0
  71. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/perplexity/__init__.py +0 -0
  72. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/perplexity/request_body.py +0 -0
  73. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/perplexity/service.py +0 -0
  74. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/search_engines/service_base.py +0 -0
  75. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/url_safety/__init__.py +0 -0
  76. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/core/url_safety/gate.py +0 -0
  77. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/error_handlers.py +0 -0
  78. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/__init__.py +0 -0
  79. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/__init__.py +0 -0
  80. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/introspect.py +0 -0
  81. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/schema.py +0 -0
  82. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/template.py +0 -0
  83. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/templates/provider_values_yaml.j2 +0 -0
  84. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/generator/values_yaml.py +0 -0
  85. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/metadata.py +0 -0
  86. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/registry.py +0 -0
  87. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/helm/url_safety_registration.py +0 -0
  88. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/logging_config.py +0 -0
  89. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/middleware/context.py +0 -0
  90. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/monitoring/__init__.py +0 -0
  91. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/monitoring/metrics.py +0 -0
  92. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/monitoring/setup.py +0 -0
  93. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/presets/__init__.py +0 -0
  94. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/presets/common.py +0 -0
  95. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/presets/crawl.py +0 -0
  96. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/presets/search.py +0 -0
  97. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/presets/types.py +0 -0
  98. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/__init__.py +0 -0
  99. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/app.py +0 -0
  100. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/base.py +0 -0
  101. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/client.py +0 -0
  102. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/monitoring.py +0 -0
  103. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/__init__.py +0 -0
  104. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/base.py +0 -0
  105. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/bing_agent.py +0 -0
  106. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/brave.py +0 -0
  107. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/firecrawl.py +0 -0
  108. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/google.py +0 -0
  109. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/jina.py +0 -0
  110. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/perplexity.py +0 -0
  111. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/tavily.py +0 -0
  112. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/providers/vertexai_agent.py +0 -0
  113. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/settings/secret_str.py +0 -0
  114. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/startup_report.py +0 -0
  115. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/utils/__init__.py +0 -0
  116. {unique_search_proxy-2026.44.0.dev0 → unique_search_proxy-2026.44.0.dev1}/unique_search_proxy_client/web/utils/url.py +0 -0
@@ -1,9 +1,10 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-search-proxy
3
- Version: 2026.44.0.dev0
3
+ Version: 2026.44.0.dev1
4
4
  Summary: Web Search Proxy implementation
5
5
  Author: ThePhilAz
6
6
  Author-email: ThePhilAz <rami.azouz@philico.com>
7
+ Requires-Dist: aiohttp>=3.14.1,<4
7
8
  Requires-Dist: fastapi>=0.133.0,<1.0.0
8
9
  Requires-Dist: starlette>=1.3.1,<2.0.0
9
10
  Requires-Dist: uvicorn[standard]>=0.32.0,<1.0.0
@@ -19,8 +20,8 @@ Requires-Dist: certifi>=2025.11.12,<2027
19
20
  Requires-Dist: google-genai>=1.73.0,<2
20
21
  Requires-Dist: google-auth>=2.43.0,<3
21
22
  Requires-Dist: jinja2>=3.1.6,<4
22
- Requires-Dist: unique-toolkit[monitoring]>=2026.44.0.dev0,<2026.44.0rc0
23
- Requires-Dist: unique-search-proxy-core>=2026.44.0.dev0,<2026.44.0rc0
23
+ Requires-Dist: unique-toolkit[monitoring]>=2026.44.0.dev2,<2026.44.0rc0
24
+ Requires-Dist: unique-search-proxy-core>=2026.44.0.dev1,<2026.44.0rc0
24
25
  Requires-Dist: openai>=1.105.0,<3
25
26
  Requires-Python: >=3.12
26
27
  Description-Content-Type: text/markdown
@@ -1,11 +1,12 @@
1
1
  [project]
2
2
  name = "unique-search-proxy"
3
- version = "2026.44.0.dev0"
3
+ version = "2026.44.0.dev1"
4
4
  description = "Web Search Proxy implementation"
5
5
  authors = [{ name = "ThePhilAz", email = "rami.azouz@philico.com" }]
6
6
  readme = "README.md"
7
7
  requires-python = ">=3.12"
8
8
  dependencies = [
9
+ "aiohttp>=3.14.1,<4",
9
10
  "fastapi>=0.133.0,<1.0.0",
10
11
  "starlette>=1.3.1,<2.0.0",
11
12
  "uvicorn[standard]>=0.32.0,<1.0.0",
@@ -21,8 +22,8 @@ dependencies = [
21
22
  "google-genai>=1.73.0,<2",
22
23
  "google-auth>=2.43.0,<3",
23
24
  "jinja2>=3.1.6,<4",
24
- "unique-toolkit[monitoring]>=2026.44.0.dev0,<2026.44.0rc0",
25
- "unique-search-proxy-core>=2026.44.0.dev0,<2026.44.0rc0",
25
+ "unique-toolkit[monitoring]>=2026.44.0.dev2,<2026.44.0rc0",
26
+ "unique-search-proxy-core>=2026.44.0.dev1,<2026.44.0rc0",
26
27
  "openai>=1.105.0,<3",
27
28
  ]
28
29
 
@@ -23,9 +23,11 @@ from unique_search_proxy_core.schema import (
23
23
  ProxyErrorCode,
24
24
  )
25
25
 
26
+ from unique_search_proxy_client.web.context import get_request_context
26
27
  from unique_search_proxy_client.web.core.agent_engines.factory import (
27
28
  get_agent_engine_service,
28
29
  )
30
+ from unique_search_proxy_client.web.core.client import get_http_client_registry
29
31
  from unique_search_proxy_client.web.monitoring.metrics import (
30
32
  record_agent_search_error,
31
33
  record_agent_search_success,
@@ -84,8 +86,12 @@ async def agent_search(
84
86
  )
85
87
 
86
88
  try:
89
+ registry = get_http_client_registry(request.app)
90
+ egress = await registry.egress_for(get_request_context())
87
91
  engine_service = get_agent_engine_service(
88
92
  AgentEngineType(engine_id) if isinstance(engine, str) else engine,
93
+ http_client=egress.http_client,
94
+ egress_route=egress.route,
89
95
  )
90
96
  async with asyncio.timeout(timeout):
91
97
  result = await engine_service.search(body)
@@ -162,9 +168,20 @@ async def agent_search_stream(
162
168
  )
163
169
 
164
170
  try:
171
+ registry = get_http_client_registry(request.app)
172
+ egress = await registry.egress_for(get_request_context())
165
173
  engine_service = get_agent_engine_service(
166
174
  AgentEngineType(engine_id) if isinstance(engine, str) else engine,
175
+ http_client=egress.http_client,
176
+ egress_route=egress.route,
167
177
  )
178
+ except ProxyError as exc:
179
+ record_agent_search_error(
180
+ engine_id,
181
+ exc.code.value if hasattr(exc.code, "value") else str(exc.code),
182
+ time.perf_counter() - started,
183
+ )
184
+ raise _agent_search_request_context(exc, engine_id=engine_id) from exc
168
185
  except Exception as exc:
169
186
  record_agent_search_error(engine_id, "INTERNAL_ERROR", 0.0)
170
187
  _LOGGER.exception(
@@ -59,10 +59,10 @@ logging.getLogger("uvicorn.access").addFilter(HealthCheckFilter())
59
59
  async def lifespan(app: FastAPI):
60
60
  _LOGGER.info("Starting Unique Search Proxy...")
61
61
  log_startup_settings_report(_LOGGER)
62
- await maybe_cleanup_auto_provisioned_bing_agents_on_start()
63
62
  registry = await create_http_client_registry()
64
63
  app.state.http_client_registry = registry
65
64
  try:
65
+ await maybe_cleanup_auto_provisioned_bing_agents_on_start(registry)
66
66
  yield
67
67
  finally:
68
68
  await aclose_private_endpoint_http_client()
@@ -1,6 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from typing import TYPE_CHECKING
4
5
 
5
6
  from azure.ai.projects.aio import AIProjectClient
6
7
  from azure.core.exceptions import ResourceNotFoundError
@@ -10,6 +11,7 @@ from unique_search_proxy_core.agent_engines.bing.grounding import (
10
11
  from unique_search_proxy_core.errors import EngineNotConfiguredError
11
12
 
12
13
  from unique_search_proxy_client.web.core.agent_engines.bing.client import (
14
+ bing_azure_transport,
13
15
  get_credentials,
14
16
  get_project_client,
15
17
  )
@@ -18,6 +20,9 @@ from unique_search_proxy_client.web.settings.providers.bing_agent import (
18
20
  )
19
21
  from unique_search_proxy_client.web.settings.secret_str import read_secret
20
22
 
23
+ if TYPE_CHECKING:
24
+ from unique_search_proxy_core.http_client import HttpClientRegistry
25
+
21
26
  _LOGGER = logging.getLogger(__name__)
22
27
  _LIST_PAGE_SIZE = 100
23
28
 
@@ -53,11 +58,15 @@ async def cleanup_auto_provisioned_bing_agents(project_client: AIProjectClient)
53
58
  return deleted
54
59
 
55
60
 
56
- async def maybe_cleanup_auto_provisioned_bing_agents_on_start() -> None:
61
+ async def maybe_cleanup_auto_provisioned_bing_agents_on_start(
62
+ registry: HttpClientRegistry,
63
+ ) -> None:
57
64
  """Best-effort startup cleanup when ``BING_AGENT_CLEANUP_ON_START`` is enabled.
58
65
 
59
66
  Never raises: credential, client, list, or delete failures are logged and
60
67
  swallowed so multi-worker/replica races cannot block process startup.
68
+ Uses settings-backed proxy credentials because no request identity exists
69
+ during process startup; missing technical credentials fail closed.
61
70
  Transient Bing request failures during a race are recovered by create-on-miss.
62
71
  """
63
72
  if not bing_agent_credentials.cleanup_on_start:
@@ -73,12 +82,15 @@ async def maybe_cleanup_auto_provisioned_bing_agents_on_start() -> None:
73
82
  return
74
83
 
75
84
  try:
76
- async with get_credentials() as credential:
77
- async with get_project_client(
78
- credential,
79
- endpoint=read_secret(bing_agent_credentials.endpoint),
80
- ) as project_client:
81
- deleted = await cleanup_auto_provisioned_bing_agents(project_client)
85
+ egress = await registry.settings_egress()
86
+ async with bing_azure_transport(egress.route) as azure_transport:
87
+ async with get_credentials(transport=azure_transport) as credential:
88
+ async with get_project_client(
89
+ credential,
90
+ endpoint=read_secret(bing_agent_credentials.endpoint),
91
+ transport=azure_transport,
92
+ ) as project_client:
93
+ deleted = await cleanup_auto_provisioned_bing_agents(project_client)
82
94
  _LOGGER.info(
83
95
  "Bing agent startup cleanup finished; deleted %s auto-provisioned agent(s)",
84
96
  deleted,
@@ -1,15 +1,21 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
+ from collections.abc import AsyncIterator
5
+ from contextlib import asynccontextmanager
4
6
 
5
7
  import certifi
6
8
  import httpx
7
9
  from azure.ai.projects.aio import AIProjectClient
8
10
  from azure.core.credentials_async import AsyncTokenCredential
9
- from azure.core.pipeline.transport import AsyncioRequestsTransport
11
+ from azure.core.pipeline.transport import AsyncHttpTransport, AsyncioRequestsTransport
10
12
  from azure.identity.aio import DefaultAzureCredential, WorkloadIdentityCredential
11
13
  from openai import AsyncOpenAI
14
+ from unique_search_proxy_core.http_client import EgressRoute
12
15
 
16
+ from unique_search_proxy_client.web.core.client.azure_transport import (
17
+ azure_transport_for_route,
18
+ )
13
19
  from unique_search_proxy_client.web.settings.providers.bing_agent import (
14
20
  bing_agent_credentials,
15
21
  )
@@ -19,15 +25,32 @@ _LOGGER = logging.getLogger(__name__)
19
25
  _private_endpoint_http_client: httpx.AsyncClient | None = None
20
26
 
21
27
 
22
- def get_credentials() -> AsyncTokenCredential:
28
+ @asynccontextmanager
29
+ async def bing_azure_transport(
30
+ route: EgressRoute,
31
+ ) -> AsyncIterator[AsyncHttpTransport | None]:
32
+ """Yield proxied Azure transport, preserving explicit private endpoints."""
33
+ if bing_agent_credentials.use_private_endpoint_transport:
34
+ yield None
35
+ return
36
+ async with azure_transport_for_route(route) as transport:
37
+ yield transport
38
+
39
+
40
+ def get_credentials(
41
+ *,
42
+ transport: AsyncHttpTransport | None = None,
43
+ ) -> AsyncTokenCredential:
23
44
  match bing_agent_credentials.azure_identity_credential_type:
24
45
  case "workload":
25
46
  if bing_agent_credentials.use_private_endpoint_transport:
26
- transport = AsyncioRequestsTransport(connection_verify=certifi.where())
27
- return WorkloadIdentityCredential(transport=transport)
28
- return WorkloadIdentityCredential()
47
+ private_transport = AsyncioRequestsTransport(
48
+ connection_verify=certifi.where()
49
+ )
50
+ return WorkloadIdentityCredential(transport=private_transport)
51
+ return WorkloadIdentityCredential(transport=transport)
29
52
  case "default":
30
- return DefaultAzureCredential()
53
+ return DefaultAzureCredential(transport=transport)
31
54
  case other:
32
55
  msg = f"Invalid Azure identity credential type: {other}"
33
56
  raise ValueError(msg)
@@ -37,6 +60,7 @@ def get_project_client(
37
60
  credential: AsyncTokenCredential,
38
61
  *,
39
62
  endpoint: str | None = None,
63
+ transport: AsyncHttpTransport | None = None,
40
64
  ) -> AIProjectClient:
41
65
  resolved_endpoint = endpoint or read_secret(bing_agent_credentials.endpoint)
42
66
  if not resolved_endpoint or resolved_endpoint == NOT_PROVIDED:
@@ -53,6 +77,7 @@ def get_project_client(
53
77
  return AIProjectClient(
54
78
  credential=credential,
55
79
  endpoint=resolved_endpoint,
80
+ transport=transport,
56
81
  )
57
82
 
58
83
 
@@ -75,7 +100,11 @@ async def aclose_private_endpoint_http_client() -> None:
75
100
  _private_endpoint_http_client = None
76
101
 
77
102
 
78
- def get_openai_client(project_client: AIProjectClient) -> AsyncOpenAI:
103
+ def get_openai_client(
104
+ project_client: AIProjectClient,
105
+ *,
106
+ http_client: httpx.AsyncClient | None = None,
107
+ ) -> AsyncOpenAI:
79
108
  """Return an authenticated AsyncOpenAI client from the Foundry project client.
80
109
 
81
110
  When private-endpoint transport is enabled, reuse a shared certifi-backed
@@ -86,6 +115,8 @@ def get_openai_client(project_client: AIProjectClient) -> AsyncOpenAI:
86
115
  return project_client.get_openai_client(
87
116
  http_client=_get_private_endpoint_http_client(),
88
117
  )
118
+ if http_client is not None:
119
+ return project_client.get_openai_client(http_client=http_client)
89
120
  return project_client.get_openai_client()
90
121
 
91
122
 
@@ -12,6 +12,7 @@ from azure.ai.projects.models import (
12
12
  BingGroundingTool,
13
13
  PromptAgentDefinition,
14
14
  )
15
+ from httpx import AsyncClient
15
16
  from openai.types.responses import ResponseStreamEvent
16
17
  from openai.types.responses.response_completed_event import ResponseCompletedEvent
17
18
  from openai.types.responses.response_output_item_done_event import (
@@ -140,10 +141,12 @@ def _is_missing_agent_error(exc: BaseException, *, agent_name: str) -> bool:
140
141
  async def stream_bing_grounding_agent(
141
142
  project_client: AIProjectClient,
142
143
  *,
144
+ http_client: AsyncClient | None = None,
143
145
  query: str,
144
146
  model: str,
145
147
  instructions: str,
146
148
  grounding: BingGroundingConfiguration,
149
+ timeout: float,
147
150
  ) -> AsyncIterator[tuple[str, dict]]:
148
151
  """Stream Bing-grounded Responses events as ``(delta_text, raw_event)`` pairs.
149
152
 
@@ -158,13 +161,17 @@ async def stream_bing_grounding_agent(
158
161
  instructions=instructions,
159
162
  grounding=grounding,
160
163
  )
161
- openai_client = get_openai_client(project_client)
164
+ openai_client = get_openai_client(
165
+ project_client,
166
+ http_client=http_client,
167
+ )
162
168
 
163
169
  try:
164
170
  stream = await _create_responses_stream(
165
171
  openai_client,
166
172
  agent_name=resolved_name,
167
173
  query=query,
174
+ timeout=timeout,
168
175
  )
169
176
  except Exception as exc:
170
177
  if not _is_missing_agent_error(exc, agent_name=resolved_name):
@@ -185,6 +192,7 @@ async def stream_bing_grounding_agent(
185
192
  openai_client,
186
193
  agent_name=resolved_name,
187
194
  query=query,
195
+ timeout=timeout,
188
196
  )
189
197
 
190
198
  emitted_text = False
@@ -225,6 +233,7 @@ async def _create_responses_stream(
225
233
  *,
226
234
  agent_name: str,
227
235
  query: str,
236
+ timeout: float,
228
237
  ) -> openai.AsyncStream[ResponseStreamEvent]:
229
238
  started = time.perf_counter()
230
239
  stream = await openai_client.responses.create(
@@ -236,6 +245,9 @@ async def _create_responses_stream(
236
245
  "type": "agent_reference",
237
246
  }
238
247
  },
248
+ # The shared egress client defaults to 30s, while Bing requests allow
249
+ # longer runs. The API's outer deadline still caps total request time.
250
+ timeout=timeout,
239
251
  )
240
252
  elapsed_ms = (time.perf_counter() - started) * 1000
241
253
  _LOGGER.info(
@@ -0,0 +1,185 @@
1
+ from __future__ import annotations
2
+
3
+ import asyncio
4
+ import logging
5
+ from collections.abc import AsyncIterator
6
+ from typing import TYPE_CHECKING
7
+
8
+ import openai
9
+ from unique_search_proxy_core.agent_engines.base import AgentEngineType
10
+ from unique_search_proxy_core.agent_engines.bing.grounding import (
11
+ BingGroundingConfiguration,
12
+ )
13
+ from unique_search_proxy_core.agent_engines.bing.schema import BingAgentSearchRequest
14
+ from unique_search_proxy_core.agent_engines.bing.settings import resolve_market
15
+ from unique_search_proxy_core.agent_engines.resolve import (
16
+ resolve_output_schema_for_engine,
17
+ )
18
+ from unique_search_proxy_core.errors import UpstreamError
19
+ from unique_search_proxy_core.schema import (
20
+ AgentSearchDelta,
21
+ AgentSearchDone,
22
+ AgentSearchResponse,
23
+ AgentSearchStreamEvent,
24
+ )
25
+
26
+ from unique_search_proxy_client.web.core.agent_engines.bing.client import (
27
+ bing_azure_transport,
28
+ get_credentials,
29
+ get_project_client,
30
+ )
31
+ from unique_search_proxy_client.web.core.agent_engines.bing.runner import (
32
+ stream_bing_grounding_agent,
33
+ )
34
+ from unique_search_proxy_client.web.core.agent_engines.service_base import (
35
+ AgentSearchEngineService,
36
+ )
37
+ from unique_search_proxy_client.web.core.agent_engines.structured_output import (
38
+ build_agent_instructions,
39
+ )
40
+ from unique_search_proxy_client.web.core.provider_response import transport_error_raw
41
+ from unique_search_proxy_client.web.settings.providers.bing_agent import (
42
+ bing_agent_credentials,
43
+ )
44
+ from unique_search_proxy_client.web.settings.secret_str import read_secret
45
+
46
+ if TYPE_CHECKING:
47
+ from httpx import AsyncClient
48
+ from unique_search_proxy_core.http_client import EgressRoute
49
+
50
+ _LOGGER = logging.getLogger(__name__)
51
+ # Foundry can report transient backend failures inside an HTTP 200 SSE stream,
52
+ # beyond the reach of the OpenAI client's HTTP retry policy.
53
+ _RETRYABLE_STREAM_ERROR_CODES = frozenset({"server_error", "internal_error"})
54
+ _RETRYABLE_STREAM_ERROR_MESSAGES = (
55
+ "model deployment encountered an error processing your request",
56
+ "invalid or expired token",
57
+ )
58
+ _STREAM_RETRY_DELAYS_SECONDS = (2.0, 8.0)
59
+ _STREAM_MAX_ATTEMPTS = len(_STREAM_RETRY_DELAYS_SECONDS) + 1
60
+
61
+
62
+ def _is_retryable_bing_stream_error(exc: BaseException) -> bool:
63
+ """Return whether a pre-output Foundry stream failure is safe to retry."""
64
+ if isinstance(exc, openai.APIStatusError):
65
+ # The OpenAI client already retries retryable HTTP statuses. This
66
+ # classifier is only for errors embedded in an HTTP 200 SSE stream.
67
+ return False
68
+ if not isinstance(exc, openai.APIError):
69
+ return False
70
+
71
+ code = exc.code.lower() if isinstance(exc.code, str) else None
72
+ if code in _RETRYABLE_STREAM_ERROR_CODES:
73
+ return True
74
+
75
+ message = str(exc).lower()
76
+ return any(marker in message for marker in _RETRYABLE_STREAM_ERROR_MESSAGES)
77
+
78
+
79
+ class BingAgentSearchService(AgentSearchEngineService[BingAgentSearchRequest]):
80
+ engine_id = AgentEngineType.BING.value
81
+
82
+ def __init__(
83
+ self,
84
+ *,
85
+ http_client: AsyncClient,
86
+ egress_route: EgressRoute,
87
+ ) -> None:
88
+ super().__init__(http_client=http_client)
89
+ self._egress_route = egress_route
90
+
91
+ async def search(self, request: BingAgentSearchRequest) -> AgentSearchResponse: # type: ignore[override]
92
+ response: AgentSearchResponse | None = None
93
+ async for event in self.stream(request):
94
+ if isinstance(event, AgentSearchDone):
95
+ response = event.response
96
+ if response is None:
97
+ msg = "Bing agent search stream ended without a done event"
98
+ raise UpstreamError(msg)
99
+ return response
100
+
101
+ async def stream(
102
+ self,
103
+ request: BingAgentSearchRequest, # type: ignore[override]
104
+ ) -> AsyncIterator[AgentSearchStreamEvent]:
105
+ bing_agent_credentials.check_credentials()
106
+ creds = bing_agent_credentials
107
+ http_client = self._http_client
108
+ egress_route = self._egress_route
109
+ if http_client is None:
110
+ raise RuntimeError("HTTP client is required for Bing")
111
+
112
+ answer_parts: list[str] = []
113
+ raw_chunks: list[dict] = []
114
+
115
+ output_schema = resolve_output_schema_for_engine(request.engine)
116
+ instructions = build_agent_instructions(
117
+ generation_instructions=request.generation_instructions,
118
+ output_schema=output_schema,
119
+ )
120
+ grounding = BingGroundingConfiguration(
121
+ fetch_size=request.fetch_size,
122
+ market=resolve_market(request.market),
123
+ freshness=request.freshness,
124
+ )
125
+
126
+ for attempt in range(1, _STREAM_MAX_ATTEMPTS + 1):
127
+ try:
128
+ async with bing_azure_transport(egress_route) as azure_transport:
129
+ async with get_credentials(transport=azure_transport) as credential:
130
+ async with get_project_client(
131
+ credential,
132
+ endpoint=read_secret(creds.endpoint),
133
+ transport=azure_transport,
134
+ ) as project_client:
135
+ async for (
136
+ delta,
137
+ raw_event,
138
+ ) in stream_bing_grounding_agent(
139
+ project_client,
140
+ http_client=http_client,
141
+ query=request.query,
142
+ model=read_secret(creds.bing_agent_model),
143
+ instructions=instructions,
144
+ grounding=grounding,
145
+ timeout=request.timeout,
146
+ ):
147
+ if delta:
148
+ answer_parts.append(delta)
149
+ yield AgentSearchDelta(text=delta)
150
+ if raw_event:
151
+ raw_chunks.append(raw_event)
152
+ break
153
+ except Exception as exc:
154
+ retryable = (
155
+ attempt < _STREAM_MAX_ATTEMPTS
156
+ and not answer_parts
157
+ and _is_retryable_bing_stream_error(exc)
158
+ )
159
+ if not retryable:
160
+ raise UpstreamError(
161
+ f"Bing agent search failed: {exc}",
162
+ upstream_raw=transport_error_raw(exc),
163
+ ) from exc
164
+
165
+ raw_chunks.clear()
166
+ retry_delay = _STREAM_RETRY_DELAYS_SECONDS[attempt - 1]
167
+ _LOGGER.warning(
168
+ "Bing response failed before output; retrying attempt %d/%d "
169
+ "after %.1fs (type=%s, code=%s)",
170
+ attempt + 1,
171
+ _STREAM_MAX_ATTEMPTS,
172
+ retry_delay,
173
+ type(exc).__name__,
174
+ getattr(exc, "code", None),
175
+ )
176
+ await asyncio.sleep(retry_delay)
177
+
178
+ answer = "".join(answer_parts)
179
+ response = AgentSearchResponse(
180
+ engine=AgentEngineType.BING.value,
181
+ query=request.query,
182
+ answer=answer,
183
+ raw=raw_chunks if len(raw_chunks) != 1 else raw_chunks[0],
184
+ )
185
+ yield AgentSearchDone(response=response)
@@ -17,17 +17,22 @@ from unique_search_proxy_client.web.core.agent_engines.vertexai.service import (
17
17
 
18
18
  if TYPE_CHECKING:
19
19
  from httpx import AsyncClient
20
+ from unique_search_proxy_core.http_client import EgressRoute
20
21
 
21
22
 
22
23
  def get_agent_engine_service(
23
24
  engine: AgentEngineType,
24
25
  *,
25
- http_client: AsyncClient | None = None,
26
+ http_client: AsyncClient,
27
+ egress_route: EgressRoute,
26
28
  ) -> AgentSearchEngine[Any]:
27
29
  """Instantiate an agent search engine by registered id."""
28
30
  match engine:
29
31
  case AgentEngineType.BING:
30
- return BingAgentSearchService(http_client=http_client)
32
+ return BingAgentSearchService(
33
+ http_client=http_client,
34
+ egress_route=egress_route,
35
+ )
31
36
  case AgentEngineType.VERTEXAI:
32
37
  return VertexAIAgentSearchService(http_client=http_client)
33
38
  case _:
@@ -1,28 +1,18 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Generic
3
+ from typing import Generic
4
4
 
5
5
  from unique_search_proxy_core.agent_engines.base import (
6
6
  AgentRequestT,
7
7
  AgentSearchEngine,
8
8
  )
9
9
 
10
- if TYPE_CHECKING:
11
- from httpx import AsyncClient
12
-
13
10
 
14
11
  class AgentSearchEngineService(
15
12
  AgentSearchEngine[AgentRequestT], Generic[AgentRequestT]
16
13
  ):
17
14
  """Client-side agent search engine base (HTTP client wiring)."""
18
15
 
19
- def __init__(
20
- self,
21
- *,
22
- http_client: AsyncClient | None = None,
23
- ) -> None:
24
- super().__init__(http_client=http_client)
25
-
26
16
  @property
27
17
  def mode(self) -> str:
28
18
  return "agent"
@@ -7,6 +7,8 @@ from base64 import b64decode
7
7
  from google.auth import load_credentials_from_dict
8
8
  from google.genai._api_client import BaseApiClient
9
9
  from google.genai.client import AsyncClient
10
+ from google.genai.types import HttpOptions
11
+ from httpx import AsyncClient as HttpxAsyncClient
10
12
 
11
13
  from unique_search_proxy_client.web.settings.providers.vertexai_agent import (
12
14
  vertexai_agent_credentials,
@@ -19,7 +21,9 @@ from unique_search_proxy_client.web.settings.secret_str import (
19
21
  _LOGGER = logging.getLogger(__name__)
20
22
 
21
23
 
22
- def _get_base_api_client_from_service_account() -> BaseApiClient:
24
+ def _get_base_api_client_from_service_account(
25
+ http_client: HttpxAsyncClient | None = None,
26
+ ) -> BaseApiClient:
23
27
  if not is_secret_configured(vertexai_agent_credentials.service_account_credentials):
24
28
  msg = (
25
29
  "VERTEXAI_AGENT_CREDENTIAL_TYPE is 'service_account' but "
@@ -43,20 +47,28 @@ def _get_base_api_client_from_service_account() -> BaseApiClient:
43
47
  vertexai=True,
44
48
  credentials=credentials,
45
49
  project=project_id,
50
+ http_options=HttpOptions(httpx_async_client=http_client),
46
51
  )
47
52
 
48
53
 
49
- def _get_base_api_client_from_adc() -> BaseApiClient:
50
- return BaseApiClient(vertexai=True)
54
+ def _get_base_api_client_from_adc(
55
+ http_client: HttpxAsyncClient | None = None,
56
+ ) -> BaseApiClient:
57
+ return BaseApiClient(
58
+ vertexai=True,
59
+ http_options=HttpOptions(httpx_async_client=http_client),
60
+ )
51
61
 
52
62
 
53
- def get_vertex_client() -> AsyncClient:
63
+ def get_vertex_client(
64
+ http_client: HttpxAsyncClient | None = None,
65
+ ) -> AsyncClient:
54
66
  if vertexai_agent_credentials.credential_type == "service_account":
55
67
  _LOGGER.info("Using explicit service account credentials for VertexAI agent")
56
- base_api_client = _get_base_api_client_from_service_account()
68
+ base_api_client = _get_base_api_client_from_service_account(http_client)
57
69
  else:
58
70
  _LOGGER.info("Using workload identity (ADC) for VertexAI agent")
59
- base_api_client = _get_base_api_client_from_adc()
71
+ base_api_client = _get_base_api_client_from_adc(http_client)
60
72
  return AsyncClient(api_client=base_api_client)
61
73
 
62
74
 
@@ -42,7 +42,7 @@ class VertexAIAgentSearchService(
42
42
 
43
43
  def __init__(self, **kwargs: Any) -> None:
44
44
  super().__init__(**kwargs)
45
- self._client = get_vertex_client()
45
+ self._client = get_vertex_client(self._http_client)
46
46
 
47
47
  async def search(self, request: VertexAIAgentSearchRequest) -> AgentSearchResponse: # type: ignore[override]
48
48
  response: AgentSearchResponse | None = None