unique-search-proxy-core 2026.28.0.dev2__tar.gz → 2026.28.0.dev4__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 (59) hide show
  1. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/PKG-INFO +2 -1
  2. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/pyproject.toml +6 -1
  3. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/base.py +8 -2
  4. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/bing/schema.py +5 -2
  5. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/vertexai/schema.py +5 -2
  6. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/brave/schema.py +27 -11
  7. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/google/schema.py +19 -15
  8. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/perplexity/schema.py +30 -27
  9. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/README.md +0 -0
  10. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/__init__.py +0 -0
  11. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/__init__.py +0 -0
  12. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/bing/__init__.py +0 -0
  13. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/config_types.py +0 -0
  14. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/output_schema.py +0 -0
  15. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/projection.py +0 -0
  16. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/resolve.py +0 -0
  17. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/response_parsing.py +0 -0
  18. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/agent_engines/vertexai/__init__.py +0 -0
  19. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/__init__.py +0 -0
  20. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/base.py +0 -0
  21. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/basic/__init__.py +0 -0
  22. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/basic/content_types.py +0 -0
  23. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/basic/processing/policy.py +0 -0
  24. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/basic/schema.py +0 -0
  25. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/config_types.py +0 -0
  26. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/firecrawl/schema.py +0 -0
  27. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/jina/schema.py +0 -0
  28. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/params.py +0 -0
  29. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/projection.py +0 -0
  30. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/crawlers/tavily/schema.py +0 -0
  31. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/errors.py +0 -0
  32. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/logging.py +0 -0
  33. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/model_derivation/__init__.py +0 -0
  34. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/model_derivation/derive.py +0 -0
  35. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/model_derivation/fields.py +0 -0
  36. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/param_policy/__init__.py +0 -0
  37. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/param_policy/exposable_param.py +0 -0
  38. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/param_policy/policy.py +0 -0
  39. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/projection.py +0 -0
  40. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/providers/schema.py +0 -0
  41. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/schema.py +0 -0
  42. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/__init__.py +0 -0
  43. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/base.py +0 -0
  44. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/brave/__init__.py +0 -0
  45. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/call_schema.py +0 -0
  46. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/config_types.py +0 -0
  47. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/google/__init__.py +0 -0
  48. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/params.py +0 -0
  49. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/search_engines/perplexity/__init__.py +0 -0
  50. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/__init__.py +0 -0
  51. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/dns.py +0 -0
  52. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/egress.py +0 -0
  53. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/models.py +0 -0
  54. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/netloc.py +0 -0
  55. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/policy.py +0 -0
  56. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/redirect.py +0 -0
  57. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/resolver.py +0 -0
  58. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/service.py +0 -0
  59. {unique_search_proxy_core-2026.28.0.dev2 → unique_search_proxy_core-2026.28.0.dev4}/unique_search_proxy_core/url_safety/settings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: unique-search-proxy-core
3
- Version: 2026.28.0.dev2
3
+ Version: 2026.28.0.dev4
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,6 +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.28.0.dev13,<2026.28.0rc0
11
12
  Requires-Python: >=3.12
12
13
  Description-Content-Type: text/markdown
13
14
 
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "unique-search-proxy-core"
3
- version = "2026.28.0.dev2"
3
+ version = "2026.28.0.dev4"
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,6 +10,8 @@ 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.28.0.dev13,<2026.28.0rc0",
14
+
13
15
  ]
14
16
 
15
17
  [dependency-groups]
@@ -59,3 +61,6 @@ depcheck = "deptry ."
59
61
  [tool.pytest.ini_options]
60
62
  addopts = "--strict-markers --import-mode=importlib"
61
63
  asyncio_mode = "auto"
64
+
65
+ [tool.uv.sources]
66
+ unique-toolkit = { workspace = true }
@@ -2,10 +2,11 @@ from __future__ import annotations
2
2
 
3
3
  from abc import ABC, abstractmethod
4
4
  from enum import StrEnum
5
- from typing import TYPE_CHECKING, AsyncIterator, Generic, TypeVar
5
+ from typing import TYPE_CHECKING, Annotated, AsyncIterator, Generic, TypeVar
6
6
 
7
7
  from pydantic import BaseModel, Field
8
8
  from pydantic.json_schema import SkipJsonSchema
9
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
9
10
 
10
11
  from unique_search_proxy_core.agent_engines.output_schema import AgentSearchOutput
11
12
  from unique_search_proxy_core.schema import (
@@ -47,7 +48,12 @@ class BaseAgentEngineConfig(BaseModel, Generic[T]):
47
48
  model_config = camelized_model_config
48
49
 
49
50
  engine: T
50
- generation_instructions: str = Field(
51
+ generation_instructions: Annotated[
52
+ str,
53
+ RJSFMetaTag.StringWidget.textarea(
54
+ rows=10,
55
+ ),
56
+ ] = Field(
51
57
  default=DEFAULT_GENERATION_INSTRUCTIONS,
52
58
  description="Instructions injected into the grounding agent.",
53
59
  )
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Literal
3
+ from typing import Annotated, Literal
4
4
 
5
5
  from pydantic import BaseModel, Field
6
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
7
 
7
8
  from unique_search_proxy_core.agent_engines.base import (
8
9
  AgentEngineType,
@@ -14,7 +15,9 @@ from unique_search_proxy_core.agent_engines.projection import build_agent_reques
14
15
  class BingAgentConfig(BaseAgentEngineConfig[Literal[AgentEngineType.BING]]):
15
16
  """Deployment + request defaults for Bing grounding via Azure AI Projects."""
16
17
 
17
- engine: Literal[AgentEngineType.BING] = Field(
18
+ engine: Annotated[
19
+ Literal[AgentEngineType.BING], RJSFMetaTag.SpecialWidget.hidden()
20
+ ] = Field(
18
21
  default=AgentEngineType.BING,
19
22
  title="Agent engine",
20
23
  description="Provider discriminator; must be `bing` for this config.",
@@ -1,8 +1,9 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import Literal
3
+ from typing import Annotated, Literal
4
4
 
5
5
  from pydantic import BaseModel, Field
6
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
7
 
7
8
  from unique_search_proxy_core.agent_engines.base import (
8
9
  AgentEngineType,
@@ -14,7 +15,9 @@ from unique_search_proxy_core.agent_engines.projection import build_agent_reques
14
15
  class VertexAIAgentConfig(BaseAgentEngineConfig[Literal[AgentEngineType.VERTEXAI]]):
15
16
  """Deployment + request defaults for Vertex AI grounding (Google GenAI)."""
16
17
 
17
- engine: Literal[AgentEngineType.VERTEXAI] = Field(
18
+ engine: Annotated[
19
+ Literal[AgentEngineType.VERTEXAI], RJSFMetaTag.SpecialWidget.hidden()
20
+ ] = Field(
18
21
  default=AgentEngineType.VERTEXAI,
19
22
  title="Agent engine",
20
23
  description="Provider discriminator; must be `vertexai` for this config.",
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from typing import Annotated, Literal, TypeAlias
4
4
 
5
5
  from pydantic import BaseModel, Field
6
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
7
 
7
8
  from unique_search_proxy_core.param_policy.exposable_param import ExposableParam
8
9
  from unique_search_proxy_core.projection import build_request_model
@@ -15,9 +16,22 @@ from unique_search_proxy_core.search_engines.base import (
15
16
  BraveSafesearch: TypeAlias = Literal["off", "moderate", "strict"]
16
17
  BraveUnits: TypeAlias = Literal["metric", "imperial"]
17
18
 
18
- StrOrNone: TypeAlias = Annotated[str | None, DeactivatedNone]
19
- SafesearchOrNone: TypeAlias = Annotated[BraveSafesearch | None, DeactivatedNone]
20
- ResultFilterOrNone: TypeAlias = Annotated[list[str] | None, DeactivatedNone]
19
+ GogglesOrNone: TypeAlias = (
20
+ Annotated[str, Field(title="String")]
21
+ | Annotated[list[str], Field(title="Array")]
22
+ | DeactivatedNone
23
+ )
24
+
25
+ BraveUnitsOrNone: TypeAlias = (
26
+ Annotated[BraveUnits, Field(title="Brave Units")] | DeactivatedNone
27
+ )
28
+ StrOrNone: TypeAlias = Annotated[str, Field(title="String")] | DeactivatedNone
29
+ SafesearchOrNone: TypeAlias = (
30
+ Annotated[BraveSafesearch, Field(title="Brave Safe Search")] | DeactivatedNone
31
+ )
32
+ ResultFilterOrNone: TypeAlias = (
33
+ Annotated[list[str], Field(title="Result Filter")] | DeactivatedNone
34
+ )
21
35
 
22
36
  ExposableStrOrNone = ExposableParam[StrOrNone]
23
37
  ExposableSafesearch = ExposableParam[SafesearchOrNone]
@@ -39,7 +53,9 @@ def _default_safesearch_exposable() -> ExposableSafesearch:
39
53
  class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
40
54
  """Single source of truth for Brave deployment + derived request/LLM surfaces."""
41
55
 
42
- engine: Literal[SearchEngineType.BRAVE] = Field(
56
+ engine: Annotated[
57
+ Literal[SearchEngineType.BRAVE], RJSFMetaTag.SpecialWidget.hidden()
58
+ ] = Field(
43
59
  default=SearchEngineType.BRAVE,
44
60
  title="Search engine",
45
61
  description="Provider discriminator; must be `brave` for this config.",
@@ -75,7 +91,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
75
91
  "e.g. `en-US`. Distinct from `search_lang`."
76
92
  ),
77
93
  )
78
- units: BraveUnits | None = Field(
94
+ units: BraveUnitsOrNone = Field(
79
95
  default=None,
80
96
  title="Measurement units",
81
97
  description="Measurement units for location-rich results: `metric` or `imperial`.",
@@ -90,7 +106,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
90
106
  title="Include fetch metadata",
91
107
  description="Include fetch metadata in the Brave response.",
92
108
  )
93
- goggles: str | list[str] | None = Field(
109
+ goggles: GogglesOrNone = Field(
94
110
  default=None,
95
111
  title="Goggles",
96
112
  description=(
@@ -99,7 +115,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
99
115
  )
100
116
 
101
117
  country: ExposableStrOrNone = Field(
102
- default_factory=_inactive_str_exposable,
118
+ default=_inactive_str_exposable(),
103
119
  title="Country",
104
120
  description=(
105
121
  "Two-letter ISO 3166-1 alpha-2 country code for result origin (Brave `country`). "
@@ -107,7 +123,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
107
123
  ),
108
124
  )
109
125
  freshness: ExposableStrOrNone = Field(
110
- default_factory=_inactive_str_exposable,
126
+ default=_inactive_str_exposable(),
111
127
  title="Freshness",
112
128
  description=(
113
129
  "Recency filter: `pd`, `pw`, `pm`, `py`, or `YYYY-MM-DDtoYYYY-MM-DD`. "
@@ -115,7 +131,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
115
131
  ),
116
132
  )
117
133
  search_lang: ExposableStrOrNone = Field(
118
- default_factory=_inactive_str_exposable,
134
+ default=_inactive_str_exposable(),
119
135
  alias="searchLang",
120
136
  title="Search language",
121
137
  description=(
@@ -124,7 +140,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
124
140
  ),
125
141
  )
126
142
  safesearch: ExposableSafesearch = Field(
127
- default_factory=_default_safesearch_exposable,
143
+ default=_default_safesearch_exposable(),
128
144
  title="Safe search",
129
145
  description=(
130
146
  "Adult content filter: `off`, `moderate` (API default), or `strict`. "
@@ -132,7 +148,7 @@ class BraveConfig(BaseSearchEngineConfig[Literal[SearchEngineType.BRAVE]]):
132
148
  ),
133
149
  )
134
150
  result_filter: ExposableResultFilter = Field(
135
- default_factory=_inactive_result_filter_exposable,
151
+ default=_inactive_result_filter_exposable(),
136
152
  alias="resultFilter",
137
153
  title="Result filter",
138
154
  description=(
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from typing import Annotated, Literal, TypeAlias
4
4
 
5
5
  from pydantic import BaseModel, Field
6
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
7
 
7
8
  from unique_search_proxy_core.param_policy.exposable_param import ExposableParam
8
9
  from unique_search_proxy_core.projection import build_request_model
@@ -15,10 +16,11 @@ from unique_search_proxy_core.search_engines.base import (
15
16
  GoogleSafeDefault: TypeAlias = Literal["active", "off"]
16
17
  GoogleSiteSearchFilter: TypeAlias = Literal["e", "i"]
17
18
 
18
- StrOrNone: TypeAlias = Annotated[str | None, DeactivatedNone]
19
- SiteSearchFilterOrNone: TypeAlias = Annotated[
20
- GoogleSiteSearchFilter | None, DeactivatedNone
21
- ]
19
+ StrOrNone: TypeAlias = Annotated[str, Field(title="String")] | DeactivatedNone
20
+ SiteSearchFilterOrNone: TypeAlias = (
21
+ Annotated[GoogleSiteSearchFilter, Field(title="Site Search Filter")]
22
+ | DeactivatedNone
23
+ )
22
24
 
23
25
  ExposableStrOrNone = ExposableParam[StrOrNone]
24
26
  ExposableSiteSearchFilter = ExposableParam[SiteSearchFilterOrNone]
@@ -35,7 +37,9 @@ def _inactive_site_search_filter_exposable() -> ExposableSiteSearchFilter:
35
37
  class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
36
38
  """Single source of truth for Google deployment + derived request/LLM surfaces."""
37
39
 
38
- engine: Literal[SearchEngineType.GOOGLE] = Field(
40
+ engine: Annotated[
41
+ Literal[SearchEngineType.GOOGLE], RJSFMetaTag.SpecialWidget.hidden()
42
+ ] = Field(
39
43
  default=SearchEngineType.GOOGLE,
40
44
  title="Search engine",
41
45
  description="Provider discriminator; must be `google` for this config.",
@@ -61,7 +65,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
61
65
  )
62
66
 
63
67
  gl: ExposableStrOrNone = Field(
64
- default_factory=_inactive_str_exposable,
68
+ default=_inactive_str_exposable(),
65
69
  title="Geolocation (gl)",
66
70
  description=(
67
71
  "Two-letter ISO 3166-1 alpha-2 country code (Google `gl`). "
@@ -69,7 +73,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
69
73
  ),
70
74
  )
71
75
  hl: ExposableStrOrNone = Field(
72
- default_factory=_inactive_str_exposable,
76
+ default=_inactive_str_exposable(),
73
77
  title="Interface language (hl)",
74
78
  description=(
75
79
  "Language for snippets/UI (Google `hl`). "
@@ -77,7 +81,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
77
81
  ),
78
82
  )
79
83
  lr: ExposableStrOrNone = Field(
80
- default_factory=_inactive_str_exposable,
84
+ default=_inactive_str_exposable(),
81
85
  title="Language restrict (lr)",
82
86
  description=(
83
87
  "Document language restrict (Google `lr`), e.g. `lang_en`. "
@@ -85,7 +89,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
85
89
  ),
86
90
  )
87
91
  date_restrict: ExposableStrOrNone = Field(
88
- default_factory=_inactive_str_exposable,
92
+ default=_inactive_str_exposable(),
89
93
  alias="dateRestrict",
90
94
  title="Date restrict",
91
95
  description=(
@@ -94,7 +98,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
94
98
  ),
95
99
  )
96
100
  exact_terms: ExposableStrOrNone = Field(
97
- default_factory=_inactive_str_exposable,
101
+ default=_inactive_str_exposable(),
98
102
  alias="exactTerms",
99
103
  title="Exact terms",
100
104
  description=(
@@ -103,7 +107,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
103
107
  ),
104
108
  )
105
109
  exclude_terms: ExposableStrOrNone = Field(
106
- default_factory=_inactive_str_exposable,
110
+ default=_inactive_str_exposable(),
107
111
  alias="excludeTerms",
108
112
  title="Exclude terms",
109
113
  description=(
@@ -112,7 +116,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
112
116
  ),
113
117
  )
114
118
  file_type: ExposableStrOrNone = Field(
115
- default_factory=_inactive_str_exposable,
119
+ default=_inactive_str_exposable(),
116
120
  alias="fileType",
117
121
  title="File type",
118
122
  description=(
@@ -121,7 +125,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
121
125
  ),
122
126
  )
123
127
  site_search: ExposableStrOrNone = Field(
124
- default_factory=_inactive_str_exposable,
128
+ default=_inactive_str_exposable(),
125
129
  alias="siteSearch",
126
130
  title="Site search",
127
131
  description=(
@@ -130,7 +134,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
130
134
  ),
131
135
  )
132
136
  site_search_filter: ExposableSiteSearchFilter = Field(
133
- default_factory=_inactive_site_search_filter_exposable,
137
+ default=_inactive_site_search_filter_exposable(),
134
138
  alias="siteSearchFilter",
135
139
  title="Site search filter",
136
140
  description=(
@@ -139,7 +143,7 @@ class GoogleConfig(BaseSearchEngineConfig[Literal[SearchEngineType.GOOGLE]]):
139
143
  ),
140
144
  )
141
145
  sort: ExposableStrOrNone = Field(
142
- default_factory=_inactive_str_exposable,
146
+ default=_inactive_str_exposable(),
143
147
  title="Sort",
144
148
  description=(
145
149
  "Sort expression (Google `sort`), e.g. `date`. "
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
  from typing import Annotated, Literal, TypeAlias
4
4
 
5
5
  from pydantic import BaseModel, Field
6
+ from unique_toolkit._common.pydantic.rjsf_tags import RJSFMetaTag
6
7
 
7
8
  from unique_search_proxy_core.param_policy.exposable_param import ExposableParam
8
9
  from unique_search_proxy_core.projection import build_request_model
@@ -15,19 +16,23 @@ from unique_search_proxy_core.search_engines.base import (
15
16
  PerplexitySearchContextSize: TypeAlias = Literal["low", "medium", "high"]
16
17
  PerplexityRecencyFilter: TypeAlias = Literal["hour", "day", "week", "month", "year"]
17
18
 
18
-
19
- IntOrNone: TypeAlias = Annotated[int | None, DeactivatedNone]
20
-
21
- StrOrNone: TypeAlias = Annotated[str | None, DeactivatedNone]
22
- SearchContextSizeOrNone: TypeAlias = Annotated[
23
- PerplexitySearchContextSize | None,
24
- DeactivatedNone,
25
- ]
26
- RecencyFilterOrNone: TypeAlias = Annotated[
27
- PerplexityRecencyFilter | None, DeactivatedNone
28
- ]
29
- LanguageFilterOrNone: TypeAlias = Annotated[list[str] | None, DeactivatedNone]
30
- DomainFilterOrNone: TypeAlias = Annotated[list[str] | None, DeactivatedNone]
19
+ IntOrNone: TypeAlias = (
20
+ Annotated[int, Field(title="Integer", ge=1, le=1_000_000)] | DeactivatedNone
21
+ )
22
+ StrOrNone: TypeAlias = Annotated[str, Field(title="String")] | DeactivatedNone
23
+ SearchContextSizeOrNone: TypeAlias = (
24
+ Annotated[PerplexitySearchContextSize, Field(title="Search Context Size")]
25
+ | DeactivatedNone
26
+ )
27
+ RecencyFilterOrNone: TypeAlias = (
28
+ Annotated[PerplexityRecencyFilter, Field(title="Recency Filter")] | DeactivatedNone
29
+ )
30
+ LanguageFilterOrNone: TypeAlias = (
31
+ Annotated[list[str], Field(title="Language Filter")] | DeactivatedNone
32
+ )
33
+ DomainFilterOrNone: TypeAlias = (
34
+ Annotated[list[str], Field(title="Domain Filter")] | DeactivatedNone
35
+ )
31
36
 
32
37
  ExposableStrOrNone = ExposableParam[StrOrNone]
33
38
  ExposableSearchContextSize = ExposableParam[SearchContextSizeOrNone]
@@ -63,7 +68,9 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
63
68
  (``POST https://api.perplexity.ai/search``).
64
69
  """
65
70
 
66
- engine: Literal[SearchEngineType.PERPLEXITY] = Field(
71
+ engine: Annotated[
72
+ Literal[SearchEngineType.PERPLEXITY], RJSFMetaTag.SpecialWidget.hidden()
73
+ ] = Field(
67
74
  default=SearchEngineType.PERPLEXITY,
68
75
  title="Search engine",
69
76
  description="Provider discriminator; must be `perplexity` for this config.",
@@ -71,8 +78,6 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
71
78
 
72
79
  max_tokens: IntOrNone = Field(
73
80
  default=None,
74
- ge=1,
75
- le=1_000_000,
76
81
  title="Max tokens",
77
82
  description=(
78
83
  "Maximum total webpage content tokens across all results "
@@ -82,8 +87,6 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
82
87
  )
83
88
  max_tokens_per_page: IntOrNone = Field(
84
89
  default=None,
85
- ge=1,
86
- le=1_000_000,
87
90
  alias="maxTokensPerPage",
88
91
  title="Max tokens per page",
89
92
  description=(
@@ -94,7 +97,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
94
97
  )
95
98
 
96
99
  country: ExposableStrOrNone = Field(
97
- default_factory=_inactive_str_exposable,
100
+ default=_inactive_str_exposable(),
98
101
  title="Country",
99
102
  description=(
100
103
  "ISO 3166-1 alpha-2 country code (Perplexity `country`, two letters). "
@@ -102,7 +105,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
102
105
  ),
103
106
  )
104
107
  search_context_size: ExposableSearchContextSize = Field(
105
- default_factory=_inactive_search_context_size_exposable,
108
+ default=_inactive_search_context_size_exposable(),
106
109
  alias="searchContextSize",
107
110
  title="Search context size",
108
111
  description=(
@@ -113,7 +116,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
113
116
  ),
114
117
  )
115
118
  search_language_filter: ExposableLanguageFilter = Field(
116
- default_factory=_inactive_language_filter_exposable,
119
+ default=_inactive_language_filter_exposable(),
117
120
  alias="searchLanguageFilter",
118
121
  title="Search language filter",
119
122
  description=(
@@ -122,7 +125,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
122
125
  ),
123
126
  )
124
127
  search_domain_filter: ExposableDomainFilter = Field(
125
- default_factory=_inactive_domain_filter_exposable,
128
+ default=_inactive_domain_filter_exposable(),
126
129
  alias="searchDomainFilter",
127
130
  title="Search domain filter",
128
131
  description=(
@@ -131,7 +134,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
131
134
  ),
132
135
  )
133
136
  search_recency_filter: ExposableRecencyFilter = Field(
134
- default_factory=_inactive_recency_filter_exposable,
137
+ default=_inactive_recency_filter_exposable(),
135
138
  alias="searchRecencyFilter",
136
139
  title="Search recency filter",
137
140
  description=(
@@ -140,7 +143,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
140
143
  ),
141
144
  )
142
145
  last_updated_after_filter: ExposableStrOrNone = Field(
143
- default_factory=_inactive_str_exposable,
146
+ default=_inactive_str_exposable(),
144
147
  alias="lastUpdatedAfterFilter",
145
148
  title="Last updated after",
146
149
  description=(
@@ -149,7 +152,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
149
152
  ),
150
153
  )
151
154
  last_updated_before_filter: ExposableStrOrNone = Field(
152
- default_factory=_inactive_str_exposable,
155
+ default=_inactive_str_exposable(),
153
156
  alias="lastUpdatedBeforeFilter",
154
157
  title="Last updated before",
155
158
  description=(
@@ -158,7 +161,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
158
161
  ),
159
162
  )
160
163
  search_after_date_filter: ExposableStrOrNone = Field(
161
- default_factory=_inactive_str_exposable,
164
+ default=_inactive_str_exposable(),
162
165
  alias="searchAfterDateFilter",
163
166
  title="Search after date",
164
167
  description=(
@@ -167,7 +170,7 @@ class PerplexityConfig(BaseSearchEngineConfig[Literal[SearchEngineType.PERPLEXIT
167
170
  ),
168
171
  )
169
172
  search_before_date_filter: ExposableStrOrNone = Field(
170
- default_factory=_inactive_str_exposable,
173
+ default=_inactive_str_exposable(),
171
174
  alias="searchBeforeDateFilter",
172
175
  title="Search before date",
173
176
  description=(