feat(exa): reuse provider list-price fallback

Adapted the fallback estimator and Exa catalog entries from #46525. Follow-up refinements by Kes and Mateo retain native count precedence, summary charges, Lite pricing, and compatibility tiers.

Source commits: d0a37501fc, d150fb91db, 8185114b5b, 78acd12678, f691d27d5f, 43c59c2cd7, 96a2b14005

Co-authored-by: kesku <admin@kesku.me>

Co-authored-by: mateo-berri <277851410+mateo-berri@users.noreply.github.com>
This commit is contained in:
Aaron Rodrigues 2026-10-28 22:13:56 -07:00 • committed by shrey kharbanda
parent f7c34a3331
commit e9727d2738
3 changed files with 134 additions and 0 deletions

View file

@ -59,3 +59,49 @@ def exa_ai_price_set(entry: object) -> bool:
fields: Final = _ENTRY.validate_python(entry)
tiers: Final = fields.get("tiered_pricing")
return fields.get("input_cost_per_query") is not None or (tiers is not None and not _legacy_tiers(tiers))
EXA_AI_INCLUDED_RESULTS: Final = 10
EXA_AI_ADDITIONAL_RESULT_COST: Final = 0.001
EXA_AI_SUMMARY_COST_PER_PAGE: Final = 0.001
EXA_AI_TYPES_WITHOUT_SUMMARIES: Final = frozenset({"lite"})
_CONTENTS: Final = TypeAdapter(Mapping[str, object])
def _non_negative_int(value: object) -> int | None:
if isinstance(value, bool) or not isinstance(value, int) or value < 0:
return None
return value
def _requested_results(optional_params: Mapping[str, object]) -> int:
for key in ("max_results", "numResults"):
requested: Final = _non_negative_int(optional_params.get(key))
if requested is not None:
return requested
return EXA_AI_INCLUDED_RESULTS
def _requests_summaries(optional_params: Mapping[str, object]) -> bool:
if optional_params.get("type") in EXA_AI_TYPES_WITHOUT_SUMMARIES:
return False
contents: Final = optional_params.get("contents")
return isinstance(contents, Mapping) and _CONTENTS.validate_python(contents).get("summary") not in (None, False)
def exa_ai_list_price(base_price: float, optional_params: Mapping[str, object]) -> float:
"""
List price of one Exa /search request, for responses that carry no `costDollars.total`.
Multi-query searches are joined into a single request, so this prices one request:
the search type's base price, a per-result charge above the results that price includes,
and a per-page charge for each requested result when summaries are requested on a type that offers them.
"""
results: Final = _requested_results(optional_params)
additional_results: Final = max(results - EXA_AI_INCLUDED_RESULTS, 0)
summarized_pages: Final = results if _requests_summaries(optional_params) else 0
return (
base_price
+ additional_results * EXA_AI_ADDITIONAL_RESULT_COST
+ summarized_pages * EXA_AI_SUMMARY_COST_PER_PAGE
)

View file

@ -24315,7 +24315,11 @@
"output_vector_size": 2560
},
"exa_ai/search": {
"input_cost_per_query": 0.007,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request, covering up to 10 results. Each result above 10 adds $0.001, and each summarized page adds $0.001. Exa's reported costDollars.total takes precedence when present, unless an operator priced this entry. tiered_pricing keeps what older releases bill for this entry. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search",
"tiered_pricing": [
{
@ -24334,6 +24338,46 @@
}
]
},
"exa_ai/search-lite": {
"input_cost_per_query": 0.004,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type lite, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-22)"
},
"mode": "search"
},
"exa_ai/search-instant": {
"input_cost_per_query": 0.004,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type instant, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"exa_ai/search-deep": {
"input_cost_per_query": 0.012,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"exa_ai/search-deep-lite": {
"input_cost_per_query": 0.012,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep-lite, covering up to 10 results. Source: https://exa.ai/docs/reference/pricing (2026-10-27)"
},
"mode": "search"
},
"exa_ai/search-deep-reasoning": {
"input_cost_per_query": 0.015,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep-reasoning, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"firecrawl/search": {
"litellm_provider": "firecrawl",
"mode": "search",

View file

@ -24315,7 +24315,11 @@
"output_vector_size": 2560
},
"exa_ai/search": {
"input_cost_per_query": 0.007,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request, covering up to 10 results. Each result above 10 adds $0.001, and each summarized page adds $0.001. Exa's reported costDollars.total takes precedence when present, unless an operator priced this entry. tiered_pricing keeps what older releases bill for this entry. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search",
"tiered_pricing": [
{
@ -24334,6 +24338,46 @@
}
]
},
"exa_ai/search-lite": {
"input_cost_per_query": 0.004,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type lite, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-22)"
},
"mode": "search"
},
"exa_ai/search-instant": {
"input_cost_per_query": 0.004,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type instant, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"exa_ai/search-deep": {
"input_cost_per_query": 0.012,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"exa_ai/search-deep-lite": {
"input_cost_per_query": 0.012,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep-lite, covering up to 10 results. Source: https://exa.ai/docs/reference/pricing (2026-10-27)"
},
"mode": "search"
},
"exa_ai/search-deep-reasoning": {
"input_cost_per_query": 0.015,
"litellm_provider": "exa_ai",
"metadata": {
"notes": "Base price per /search request with type deep-reasoning, covering up to 10 results. Source: https://exa.ai/pricing (2026-10-15)"
},
"mode": "search"
},
"firecrawl/search": {
"litellm_provider": "firecrawl",
"mode": "search",