Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
1b4807d
feat(decisions): add the OpenAI Decisions spec types and the System O…
devin-ai-integration[bot] Oct 8, 2026
806480c
refactor(decisions): dispatch /v1/decisions through provider configs …
devin-ai-integration[bot] Oct 8, 2026
42ce1ab
test(decisions): post System One bodies to /v1/systemone in the trans…
yuneng-berri Oct 8, 2026
3e78f8d
test: realign stale decisions and lens tests with merged behaviour (#…
devin-ai-integration[bot] Oct 8, 2026
65ef103
feat(ui): add TypeSafe and Strands Decider to the Add Model provider …
devin-ai-integration[bot] Oct 8, 2026
7520db8
chore(decisions): remove the System One converters and OpenAI spec ty…
devin-ai-integration[bot] Oct 8, 2026
8b469a8
feat(decisions): add hosted_vllm provider (#45501)
devin-ai-integration[bot] Oct 9, 2026
645ba71
feat(azure): add azure_ai/Microsoft-Decision-1 (#45639)
berriai-litellm-provider-info-sync[bot] Oct 9, 2026
ecc5a8a
fix(openrouter): bill responses, decisions and pass-through from usag…
devin-ai-integration[bot] Oct 9, 2026
05b1c7a
feat(azure_ai): support Microsoft-Decision-1 on the decisions API (#4…
devin-ai-integration[bot] Oct 9, 2026
39d294d
fix(decisions)!: refuse safety_identifier on providers that cannot ta…
devin-ai-integration[bot] Oct 10, 2026
73387e7
fix(model_prices): drop unverified output price for azure_ai/Microsof…
devin-ai-integration[bot] Oct 10, 2026
8500823
feat(strands_decider): call a Strands Decider on an AgentCore runtime…
devin-ai-integration[bot] Oct 10, 2026
a49e9e6
docs(proxy): describe /v1/decisions and /v1/systemone in Swagger UI (…
devin-ai-integration[bot] Oct 10, 2026
7143366
test(decisions): bill the OpenAI-format openrouter case from provider…
devin-ai-integration[bot] Oct 10, 2026
59c675c
feat(sdk): add litellm.systemone and trim litellm.decisions to the Op…
devin-ai-integration[bot] Oct 10, 2026
c482275
chore(backport): regenerate dashboard API types and adapt the picks t…
mateo-berri Oct 11, 2026
c332420
test(unit): flush queued logging tasks after each test so systemone c…
mateo-berri Oct 11, 2026
0f130e5
chore(backport): regenerate the dashboard API types for stable/1.104.x
mateo-berri Oct 11, 2026
fd7aec3
bump: version 1.104.3
mateo-berri Oct 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 52 additions & 4 deletions ci_cd/cost_map_guard.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,9 @@
import json
import subprocess
import sys
from collections.abc import Sequence
from collections.abc import Mapping, Sequence
from dataclasses import dataclass
from types import MappingProxyType
from typing import Final

from generate_model_prices_schema import SPECIAL_ROOT_KEYS, build_schema, render, validation_errors
Expand All @@ -25,6 +26,7 @@
SCHEMA_PATH: Final = "model_prices_and_context_window.schema.json"
GUARDED_PATHS: Final = (COST_MAP_PATH, BACKUP_PATH, SCHEMA_PATH)
BOT_BRANCH_PREFIX: Final = "litellm_cost_map_sync_"
EVALUATION_OUTPUT_PRICE_SOURCES: Final[Mapping[str, str]] = MappingProxyType({})

CostMap = dict[str, object]

Expand All @@ -51,7 +53,31 @@ def _rendered_schema(cost_map: CostMap) -> str:
return str(error)


def _file_failures(head: Snapshot, head_map: CostMap) -> tuple[str, ...]:
def _evaluation_output_price_failure(
key: str, entry: object, evaluation_output_price_sources: Mapping[str, str]
) -> str | None:
if not isinstance(entry, dict) or entry.get("mode") != "evaluation":
return None
output_cost: Final = entry.get("output_cost_per_token")
if (
not isinstance(output_cost, (int, float))
or isinstance(output_cost, bool)
or output_cost <= 0
or key in evaluation_output_price_sources
):
return None
return (
f"{key}: mode evaluation rows bill input only; output_cost_per_token must be 0 unless the vendor "
"prices output tokens for this model (add the source to EVALUATION_OUTPUT_PRICE_SOURCES)"
)


def _file_failures(
head: Snapshot,
head_map: CostMap,
*,
evaluation_output_price_sources: Mapping[str, str] = EVALUATION_OUTPUT_PRICE_SOURCES,
) -> tuple[str, ...]:
schema_text: Final = _rendered_schema(head_map)
if not schema_text.startswith("{"):
return (schema_text,)
Expand All @@ -75,6 +101,16 @@ def _file_failures(head: Snapshot, head_map: CostMap) -> tuple[str, ...]:
f"{COST_MAP_PATH} does not validate against its schema: {error}"
for error in validation_errors(head_map, json.loads(schema_text))[:20]
),
*(
failure
for key, entry in head_map.items()
if (
failure := _evaluation_output_price_failure(
key, entry, evaluation_output_price_sources
)
)
is not None
),
)


Expand Down Expand Up @@ -121,13 +157,25 @@ def contract_for(bot: bool, changed_files: Sequence[str]) -> str:
return "human PR, file checks only" if touches_cost_map(changed_files) else "human PR, cost map untouched"


def guard_failures(base: Snapshot, head: Snapshot, changed_files: Sequence[str], bot: bool) -> tuple[str, ...]:
def guard_failures(
base: Snapshot,
head: Snapshot,
changed_files: Sequence[str],
bot: bool,
*,
evaluation_output_price_sources: Mapping[str, str] = EVALUATION_OUTPUT_PRICE_SOURCES,
) -> tuple[str, ...]:
if not bot and not touches_cost_map(changed_files):
return ()
head_map: Final = _parse_object(head.cost_map, COST_MAP_PATH)
if isinstance(head_map, str):
return (head_map,)
return (*_file_failures(head, head_map), *(_bot_failures(base, head_map, changed_files) if bot else ()))
return (
*_file_failures(
head, head_map, evaluation_output_price_sources=evaluation_output_price_sources
),
*(_bot_failures(base, head_map, changed_files) if bot else ()),
)


def _git(*args: str) -> str | None:
Expand Down
25 changes: 25 additions & 0 deletions litellm/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1468,6 +1468,7 @@ def _build_models_by_provider() -> dict:
from .rag.main import *
from .sandbox.main import *
from .decisions.main import *
from .systemone.main import *
from .search.main import *
from .realtime_api.main import (
_arealtime,
Expand Down Expand Up @@ -1648,6 +1649,30 @@ def set_global_gitlab_config(config: Dict[str, Any]) -> None:
from .llms.hosted_vllm.rerank.transformation import (
HostedVLLMRerankConfig as HostedVLLMRerankConfig,
)
from .llms.perplexity.decisions.transformation import (
PerplexityDecisionsConfig as PerplexityDecisionsConfig,
)
from .llms.typesafe.decisions.transformation import (
TypeSafeDecisionsConfig as TypeSafeDecisionsConfig,
)
from .llms.openrouter.decisions.transformation import (
OpenRouterDecisionsConfig as OpenRouterDecisionsConfig,
)
from .llms.cloudflare.decisions.transformation import (
CloudflareDecisionsConfig as CloudflareDecisionsConfig,
)
from .llms.strands_decider.decisions.transformation import (
StrandsDeciderDecisionsConfig as StrandsDeciderDecisionsConfig,
)
from .llms.hosted_vllm.decisions.transformation import (
HostedVLLMDecisionsConfig as HostedVLLMDecisionsConfig,
)
from .llms.openai.decisions.transformation import (
OpenAIDecisionsConfig as OpenAIDecisionsConfig,
)
from .llms.azure_ai.decisions.transformation import (
AzureAIDecisionsConfig as AzureAIDecisionsConfig,
)
from .llms.nvidia_nim.rerank.transformation import (
NvidiaNimRerankConfig as NvidiaNimRerankConfig,
)
Expand Down
22 changes: 22 additions & 0 deletions litellm/_lazy_imports_registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,14 @@
"JinaAIRerankConfig",
"DeepinfraRerankConfig",
"HostedVLLMRerankConfig",
"PerplexityDecisionsConfig",
"TypeSafeDecisionsConfig",
"OpenRouterDecisionsConfig",
"CloudflareDecisionsConfig",
"StrandsDeciderDecisionsConfig",
"HostedVLLMDecisionsConfig",
"OpenAIDecisionsConfig",
"AzureAIDecisionsConfig",
"NvidiaNimRerankConfig",
"NvidiaNimRankingConfig",
"VertexAIRerankConfig",
Expand Down Expand Up @@ -695,6 +703,20 @@
".llms.hosted_vllm.rerank.transformation",
"HostedVLLMRerankConfig",
),
"PerplexityDecisionsConfig": (".llms.perplexity.decisions.transformation", "PerplexityDecisionsConfig"),
"TypeSafeDecisionsConfig": (".llms.typesafe.decisions.transformation", "TypeSafeDecisionsConfig"),
"OpenRouterDecisionsConfig": (".llms.openrouter.decisions.transformation", "OpenRouterDecisionsConfig"),
"CloudflareDecisionsConfig": (".llms.cloudflare.decisions.transformation", "CloudflareDecisionsConfig"),
"StrandsDeciderDecisionsConfig": (
".llms.strands_decider.decisions.transformation",
"StrandsDeciderDecisionsConfig",
),
"HostedVLLMDecisionsConfig": (
".llms.hosted_vllm.decisions.transformation",
"HostedVLLMDecisionsConfig",
),
"OpenAIDecisionsConfig": (".llms.openai.decisions.transformation", "OpenAIDecisionsConfig"),
"AzureAIDecisionsConfig": (".llms.azure_ai.decisions.transformation", "AzureAIDecisionsConfig"),
"NvidiaNimRerankConfig": (
".llms.nvidia_nim.rerank.transformation",
"NvidiaNimRerankConfig",
Expand Down
1 change: 1 addition & 0 deletions litellm/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@

# Provider-specific API base URLs
XAI_API_BASE: Final = "https://api.x.ai/v1"
PLACEHOLDER_API_KEY: Final = "fake-api-key"
OPEN_SANDBOX_API_BASE_ENV_VAR: Final = "OPEN_SANDBOX_API_BASE"
OPEN_SANDBOX_API_KEY_ENV_VAR: Final = "OPEN_SANDBOX_API_KEY"
OPEN_SANDBOX_DEFAULT_TEMPLATE: Final = "opensandbox/code-interpreter:v1.1.0"
Expand Down
2 changes: 2 additions & 0 deletions litellm/cost_calculator.py
Original file line number Diff line number Diff line change
Expand Up @@ -1990,6 +1990,8 @@ def response_cost_calculator(
"asearch",
"decisions",
"adecisions",
"systemone",
"asystemone",
],
optional_params: dict,
cache_hit: bool | None = None,
Expand Down
Loading
Loading