unique_web_search 2026.38.0.dev0__tar.gz → 2026.38.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.
Files changed (126) hide show
  1. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/PKG-INFO +5 -5
  2. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/README.md +1 -1
  3. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/pyproject.toml +4 -4
  4. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/README.md +35 -3
  5. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/bing.py +20 -20
  6. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/bing/runner.py +0 -1
  7. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/__init__.py +0 -0
  8. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/client_settings.py +0 -0
  9. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/config.py +0 -0
  10. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/invocation_stats.py +0 -0
  11. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/metrics.py +0 -0
  12. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/prompts.py +0 -0
  13. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/schema.py +0 -0
  14. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/service.py +0 -0
  15. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/_registry.py +0 -0
  16. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/__init__.py +0 -0
  17. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/config.py +0 -0
  18. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/exceptions.py +0 -0
  19. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/__init__.py +0 -0
  20. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/guidelines.j2 +0 -0
  21. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/guidelines_with_keywords.j2 +0 -0
  22. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/rejection_response.j2 +0 -0
  23. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/system_prompt.j2 +0 -0
  24. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/prompts/user_prompt.j2 +0 -0
  25. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/argument_screening/service.py +0 -0
  26. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/client/proxy_config.py +0 -0
  27. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/__init__.py +0 -0
  28. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/cleaning/__init__.py +0 -0
  29. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/cleaning/character_sanitize.py +0 -0
  30. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/cleaning/clean.py +0 -0
  31. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/cleaning/config.py +0 -0
  32. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/config.py +0 -0
  33. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/base.py +0 -0
  34. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/config.py +0 -0
  35. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/llm_guard_judge.py +0 -0
  36. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/llm_keyword_redact.py +0 -0
  37. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/llm_process.py +0 -0
  38. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/__init__.py +0 -0
  39. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/judge_and_sanitize_prompt.j2 +0 -0
  40. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/judge_prompt.j2 +0 -0
  41. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/keyword_extract_prompt.j2 +0 -0
  42. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/page_context.j2 +0 -0
  43. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/sanitize_rules.j2 +0 -0
  44. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/system_prompt.j2 +0 -0
  45. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/prompts/user_prompt.j2 +0 -0
  46. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/schema.py +0 -0
  47. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/settings.py +0 -0
  48. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/processing_strategies/truncate.py +0 -0
  49. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/content_processing/service.py +0 -0
  50. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/README.md +0 -0
  51. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/__init__.py +0 -0
  52. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/base.py +0 -0
  53. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/basic.py +0 -0
  54. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/firecrawl.py +0 -0
  55. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/jina.py +0 -0
  56. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/registry.py +0 -0
  57. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/tavily.py +0 -0
  58. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/url_safety/__init__.py +0 -0
  59. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/crawlers/utils.py +0 -0
  60. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/README.md +0 -0
  61. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/__init__.py +0 -0
  62. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/base_config.py +0 -0
  63. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/base_executor.py +0 -0
  64. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/context.py +0 -0
  65. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/modes.py +0 -0
  66. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/__init__.py +0 -0
  67. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/config.py +0 -0
  68. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/executor.py +0 -0
  69. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/prompts/__init__.py +0 -0
  70. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/prompts/refine_query_system_prompt.j2 +0 -0
  71. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/prompts/tool_description.j2 +0 -0
  72. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/prompts/tool_description_for_system_prompt.j2 +0 -0
  73. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/schema.py +0 -0
  74. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v1/strategy.py +0 -0
  75. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/__init__.py +0 -0
  76. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/config.py +0 -0
  77. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/executor.py +0 -0
  78. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/prompts/__init__.py +0 -0
  79. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/prompts/step_query_description.j2 +0 -0
  80. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/prompts/tool_description.j2 +0 -0
  81. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/prompts/tool_description_for_system_prompt.j2 +0 -0
  82. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/schema.py +0 -0
  83. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v2/strategy.py +0 -0
  84. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/__init__.py +0 -0
  85. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/config.py +0 -0
  86. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/executor.py +0 -0
  87. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/prompts/__init__.py +0 -0
  88. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/prompts/tool_description.j2 +0 -0
  89. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/prompts/tool_description_for_system_prompt.j2 +0 -0
  90. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/schema.py +0 -0
  91. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/executors/v3/strategy.py +0 -0
  92. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/helpers.py +0 -0
  93. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/message_log.py +0 -0
  94. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/proxy/__init__.py +0 -0
  95. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/proxy/bridge.py +0 -0
  96. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/proxy/mappers.py +0 -0
  97. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/query_elicitation.py +0 -0
  98. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/__init__.py +0 -0
  99. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/base.py +0 -0
  100. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/brave.py +0 -0
  101. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/custom_api.py +0 -0
  102. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/google.py +0 -0
  103. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/perplexity.py +0 -0
  104. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/registry.py +0 -0
  105. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/schema.py +0 -0
  106. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/google/schema.py +0 -0
  107. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/__init__.py +0 -0
  108. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/bing/__init__.py +0 -0
  109. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/bing/client.py +0 -0
  110. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/bing/models.py +0 -0
  111. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/models.py +0 -0
  112. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/response_parsing.py +0 -0
  113. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/vertexai/__init__.py +0 -0
  114. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/vertexai/client.py +0 -0
  115. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/vertexai/exceptions.py +0 -0
  116. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/vertexai/gemini.py +0 -0
  117. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/utils/grounding/vertexai/response_handler.py +0 -0
  118. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/search_engine/vertexai.py +0 -0
  119. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/snippet_judge/__init__.py +0 -0
  120. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/snippet_judge/prompts.py +0 -0
  121. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/snippet_judge/schema.py +0 -0
  122. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/snippet_judge/service.py +0 -0
  123. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/services/structured_llm.py +0 -0
  124. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/settings.py +0 -0
  125. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/skills/web-search-v3.md +0 -0
  126. {unique_web_search-2026.38.0.dev0 → unique_web_search-2026.38.0.dev2}/src/unique_web_search/utils.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-web-search
3
- Version: 2026.38.0.dev0
3
+ Version: 2026.38.0.dev2
4
4
  Summary:
5
5
  Author: Andreas Hauri, Gustav Hartz, Rami Azouz
6
6
  Author-email: Andreas Hauri <andreas@unique.ch>, Gustav Hartz <gustav.hartz.ext@unique.ch>, Rami Azouz <rami.ext@unique.ch>
@@ -16,7 +16,7 @@ Requires-Dist: tavily-python>=0.7.11,<1
16
16
  Requires-Dist: unidecode>=1.4.0,<2
17
17
  Requires-Dist: azure-ai-projects>=2.3,<3
18
18
  Requires-Dist: azure-identity>=1.25.0,<2
19
- Requires-Dist: unique-toolkit[monitoring]>=2026.38.0.dev0,<2026.38.0rc0
19
+ Requires-Dist: unique-toolkit[monitoring]>=2026.38.0.dev11,<2026.38.0rc0
20
20
  Requires-Dist: azure-core>=1.36.0,<2
21
21
  Requires-Dist: google-cloud-aiplatform>=1.128.0,<2
22
22
  Requires-Dist: google-auth>=2.43.0,<3
@@ -25,8 +25,8 @@ Requires-Dist: rapidfuzz>=3.0.0,<4
25
25
  Requires-Dist: httpx>=0.28.1
26
26
  Requires-Dist: certifi>=2025.11.12
27
27
  Requires-Dist: jinja2>=3.1.6
28
- Requires-Dist: unique-search-proxy-core>=2026.38.0.dev0,<2026.38.0rc0
29
- Requires-Dist: unique-search-proxy-sdk>=2026.38.0.dev0,<2026.38.0rc0
28
+ Requires-Dist: unique-search-proxy-core>=2026.38.0.dev3,<2026.38.0rc0
29
+ Requires-Dist: unique-search-proxy-sdk>=2026.38.0.dev2,<2026.38.0rc0
30
30
  Requires-Dist: openai>=1.105.0,<3
31
31
  Requires-Python: >=3.12, <4.0
32
32
  Description-Content-Type: text/markdown
@@ -75,7 +75,7 @@ An upstream AI agent / grounded model searches and returns opaque text that this
75
75
 
76
76
  | Engine | Proxy | Notes |
77
77
  |--------|-------|-------|
78
- | Bing (Azure AI Foundry grounding) | legacy + proxy | Configurable `requires_scraping`; `market` / `setLang` / `freshness` are `ExposableParam` knobs |
78
+ | Bing (Azure AI Foundry grounding) | legacy + proxy | Configurable `requires_scraping`; fixed `market` / `freshness` chosen by an admin, with `market` falling back to `BING_AGENT_DEFAULT_MARKET` |
79
79
  | VertexAI (Gemini grounding) | legacy + proxy | Configurable `requires_scraping` |
80
80
 
81
81
  Bing's grounding knobs are baked into the hashed Foundry agent name, so changing
@@ -42,7 +42,7 @@ An upstream AI agent / grounded model searches and returns opaque text that this
42
42
 
43
43
  | Engine | Proxy | Notes |
44
44
  |--------|-------|-------|
45
- | Bing (Azure AI Foundry grounding) | legacy + proxy | Configurable `requires_scraping`; `market` / `setLang` / `freshness` are `ExposableParam` knobs |
45
+ | Bing (Azure AI Foundry grounding) | legacy + proxy | Configurable `requires_scraping`; fixed `market` / `freshness` chosen by an admin, with `market` falling back to `BING_AGENT_DEFAULT_MARKET` |
46
46
  | VertexAI (Gemini grounding) | legacy + proxy | Configurable `requires_scraping` |
47
47
 
48
48
  Bing's grounding knobs are baked into the hashed Foundry agent name, so changing
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique_web_search"
3
- version = "2026.38.0.dev0"
3
+ version = "2026.38.0.dev2"
4
4
  description = ""
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.12,<4.0"
@@ -22,7 +22,7 @@ dependencies = [
22
22
  "unidecode>=1.4.0,<2",
23
23
  "azure-ai-projects>=2.3,<3",
24
24
  "azure-identity>=1.25.0,<2",
25
- "unique-toolkit[monitoring]>=2026.38.0.dev0,<2026.38.0rc0",
25
+ "unique-toolkit[monitoring]>=2026.38.0.dev11,<2026.38.0rc0",
26
26
  "azure-core>=1.36.0,<2",
27
27
  "google-cloud-aiplatform>=1.128.0,<2",
28
28
  "google-auth>=2.43.0,<3",
@@ -31,8 +31,8 @@ dependencies = [
31
31
  "httpx>=0.28.1",
32
32
  "certifi>=2025.11.12",
33
33
  "jinja2>=3.1.6",
34
- "unique-search-proxy-core>=2026.38.0.dev0,<2026.38.0rc0",
35
- "unique-search-proxy-sdk>=2026.38.0.dev0,<2026.38.0rc0",
34
+ "unique-search-proxy-core>=2026.38.0.dev3,<2026.38.0rc0",
35
+ "unique-search-proxy-sdk>=2026.38.0.dev2,<2026.38.0rc0",
36
36
  "openai>=1.105.0,<3",
37
37
  ]
38
38
 
@@ -151,8 +151,39 @@ CUSTOM_WEB_SEARCH_API_HEADERS='{"Authorization": "Bearer ..."}'
151
151
 
152
152
  | Field | Notes |
153
153
  |-------|-------|
154
- | `fetch_size` | Bing result count |
155
- | `market`, `set_lang`, `freshness` | `ExposableParam`; `market` / `set_lang` restricted to Bing's documented codes; forwarded to `BingGroundingSearchConfiguration` |
154
+ | `fetch_size` | Bing result count (`count` on the tool configuration) |
155
+ | `market` | Region **and** language Bing favours (Bing `mkt`). A bias, not a filter — other regions can still appear |
156
+ | `freshness` | Recency cut-off applied to every search in the space (Bing `freshness`): `Day` / `Week` / `Month` |
157
+
158
+ Both are optional **fixed** values an admin picks for the whole space and are
159
+ never offered to the LLM, and both are restricted to Bing's documented values so
160
+ they render as one dropdown each; blank values are omitted so Bing applies its
161
+ own defaults.
162
+
163
+ `freshness` also accepts absolute days and ranges (`2026-01-01..2026-03-31`),
164
+ which we deliberately do **not** offer: pinned space-wide, an absolute window
165
+ freezes the space to a range that rots the day after it is saved. Presets only
166
+ also keep the admin schema fully enumerated, so a typo cannot save.
167
+
168
+ `BingGroundingSearchConfiguration` also accepts `setLang`, which we deliberately
169
+ do **not** expose: it only localizes the labels Bing puts around results, so an
170
+ admin reading "language" would set it expecting French results and leave `mkt`
171
+ unset. Beyond these, Bing grounding has no `safeSearch`, `responseFilter`, or
172
+ `answerCount`, so `count` / `market` / `freshness` is the whole useful surface.
173
+
174
+ Spaces saved on 2026.36 hold an `ExposableParam` `{expose, value}` object under
175
+ both keys. node-chat data migration
176
+ `20260908120000_drop_bing_grounding_exposable_params` deletes them, and
177
+ `BingAgentConfig` reads that shape as unset for rows the migration has not
178
+ reached — an invalid tool config disables the whole tool silently, so tolerating
179
+ it is not optional. The migration deletes rather than unwraps, which keeps a
180
+ rollback to 2026.36 valid.
181
+
182
+ A blank `market` falls back to the `BING_AGENT_DEFAULT_MARKET` environment
183
+ variable (below), so a deployment serving a single country pins its market once
184
+ instead of per space. With neither set, `mkt` is left off the call entirely and
185
+ Bing may favour the region where the underlying Microsoft Foundry resource is
186
+ deployed.
156
187
 
157
188
  Bing bakes the tool configuration into the *agent version*, so these knobs take
158
189
  part in the hashed agent name (`unique-grounding-with-bing-<hash>`): changing one
@@ -162,7 +193,8 @@ provisions a new agent version instead of reusing a mismatched one.
162
193
  AZURE_AI_PROJECT_ENDPOINT=...
163
194
  AZURE_AI_AGENT_ID=... # optional; empty → auto-provision
164
195
  AZURE_IDENTITY_CREDENTIAL_TYPE=workload # or default
165
- BING_AGENT_MARKET={"default": "fr-CH", "enforce": false} # optional environment default
196
+ # Market applied to spaces that fix none; omit to send no market at all.
197
+ BING_AGENT_DEFAULT_MARKET=fr-FR
166
198
  ```
167
199
 
168
200
  ### VertexAI (Grounding with VertexAI)
@@ -1,5 +1,5 @@
1
1
  import asyncio
2
- from typing import override
2
+ from typing import Any, override
3
3
 
4
4
  from pydantic import Field
5
5
  from unique_search_proxy_core.agent_engines.base import AgentEngineType
@@ -7,10 +7,8 @@ from unique_search_proxy_core.agent_engines.bing.grounding import (
7
7
  BingGroundingConfiguration,
8
8
  )
9
9
  from unique_search_proxy_core.agent_engines.bing.schema import BingAgentConfig
10
+ from unique_search_proxy_core.agent_engines.bing.settings import resolve_market
10
11
  from unique_search_proxy_core.context import LOCAL_REQUEST_CONTEXT, RequestContext
11
- from unique_search_proxy_core.param_policy.exposable_param import (
12
- resolve_exposable_value,
13
- )
14
12
  from unique_search_proxy_core.param_policy.exposed_params import ExposedParams
15
13
  from unique_toolkit._common.default_language_model import DEFAULT_LANGUAGE_MODEL
16
14
  from unique_toolkit._common.validators import LMI, get_LMI_default_field
@@ -88,25 +86,27 @@ class BingSearch(SearchEngine[BingSearchConfig]):
88
86
  def requires_scraping(self) -> bool:
89
87
  return self.config.requires_scraping
90
88
 
91
- def _grounding_configuration(
92
- self,
93
- params: ExposedParams | None,
94
- ) -> BingGroundingConfiguration:
95
- """Resolve the Bing tool knobs from deployment defaults + LLM overrides."""
96
- overrides = params.model_dump(exclude_none=True) if params else {}
97
-
98
- def knob(field_name: str) -> str | None:
99
- if field_name in overrides:
100
- return overrides[field_name]
101
- return resolve_exposable_value(getattr(self.config, field_name))
102
-
89
+ def _grounding_configuration(self) -> BingGroundingConfiguration:
90
+ """The Bing tool knobs this space has fixed, with the market resolved."""
103
91
  return BingGroundingConfiguration(
104
92
  fetch_size=self.config.fetch_size,
105
- market=knob("market"),
106
- set_lang=knob("set_lang"),
107
- freshness=knob("freshness"),
93
+ market=resolve_market(self.config.market),
94
+ freshness=self.config.freshness,
108
95
  )
109
96
 
97
+ @override
98
+ def _agent_proxy_invocation(
99
+ self,
100
+ engine: AgentEngineType,
101
+ params: ExposedParams | None,
102
+ ) -> dict[str, Any]:
103
+ """Resolve the market here too, so the env default works on either service."""
104
+ invocation = super()._agent_proxy_invocation(engine, params)
105
+ market = resolve_market(invocation.get("market"))
106
+ if market is not None:
107
+ invocation["market"] = market
108
+ return invocation
109
+
110
110
  @override
111
111
  async def _legacy_search(
112
112
  self,
@@ -119,7 +119,7 @@ class BingSearch(SearchEngine[BingSearchConfig]):
119
119
  search_results = await create_and_process_run(
120
120
  agent_client,
121
121
  query=query,
122
- grounding=self._grounding_configuration(params),
122
+ grounding=self._grounding_configuration(),
123
123
  response_parsers_strategies=self.response_parsers,
124
124
  generation_instructions=self.config.generation_instructions,
125
125
  )
@@ -138,7 +138,6 @@ def get_bing_grounding_tool(
138
138
  project_connection_id=connection_id,
139
139
  count=grounding.fetch_size,
140
140
  market=grounding.market,
141
- set_lang=grounding.set_lang,
142
141
  freshness=grounding.freshness,
143
142
  )
144
143
  ]