From 9c8083e323ca6619fe3d28aa653e68952ab7db1b Mon Sep 17 00:00:00 2001 From: nate-berri Date: Sat, 10 Oct 2026 12:06:22 -0700 Subject: [PATCH] refactor(types): move slack alerting leaf types out of proxy/_types.py (#45752) Part of LIT-9423 --- .../SlackAlerting/budget_alert_types.py | 2 +- .../SlackAlerting/slack_alerting.py | 20 ++-- litellm/integrations/email_alerting.py | 2 +- litellm/proxy/_types.py | 95 ++++--------------- litellm/types/integrations/slack_alerting.py | 90 ++++++++++++++++++ 5 files changed, 118 insertions(+), 91 deletions(-) diff --git a/litellm/integrations/SlackAlerting/budget_alert_types.py b/litellm/integrations/SlackAlerting/budget_alert_types.py index 4fe833acecc..d25e24abc11 100644 --- a/litellm/integrations/SlackAlerting/budget_alert_types.py +++ b/litellm/integrations/SlackAlerting/budget_alert_types.py @@ -1,7 +1,7 @@ from abc import ABC, abstractmethod from typing import Final, Literal -from litellm.proxy._types import CallInfo, Litellm_EntityType +from litellm.types.integrations.slack_alerting import CallInfo, Litellm_EntityType class BaseBudgetAlertType(ABC): diff --git a/litellm/integrations/SlackAlerting/slack_alerting.py b/litellm/integrations/SlackAlerting/slack_alerting.py index 7e9a8fe877c..6eeb8f0582e 100644 --- a/litellm/integrations/SlackAlerting/slack_alerting.py +++ b/litellm/integrations/SlackAlerting/slack_alerting.py @@ -38,20 +38,20 @@ from litellm.llms.custom_httpx.http_handler import ( get_async_httpx_client, httpxSpecialProvider, ) -from litellm.proxy._types import ( - CallInfo, - InvitationModel, - InvitationNew, - Litellm_EntityType, - UserAPIKeyAuth, - VirtualKeyEvent, - WebhookEvent, -) +from litellm.proxy._types import UserAPIKeyAuth from litellm.repositories.table_repositories import InvitationLinkRepository from litellm.repositories.team_repository import TeamRepository from litellm.repositories.user_repository import UserRepository from litellm.types.integrations.slack_alerting import * -from litellm.types.integrations.slack_alerting import AlertType +from litellm.types.integrations.slack_alerting import ( + AlertType, + CallInfo, + InvitationModel, + InvitationNew, + Litellm_EntityType, + VirtualKeyEvent, + WebhookEvent, +) from litellm.types.proxy.model_deprecation import ( DEFAULT_DEPRECATION_CHECK_INTERVAL_SECONDS, DEPRECATION_IDLE_POLL_SECONDS, diff --git a/litellm/integrations/email_alerting.py b/litellm/integrations/email_alerting.py index 351896425bb..27ee6bb60b4 100644 --- a/litellm/integrations/email_alerting.py +++ b/litellm/integrations/email_alerting.py @@ -6,8 +6,8 @@ import os from typing import Final from litellm._logging import verbose_logger, verbose_proxy_logger -from litellm.proxy._types import WebhookEvent from litellm.repositories.team_repository import TeamRepository +from litellm.types.integrations.slack_alerting import WebhookEvent # we use this for the email header, please send a test email if you change this. verify it looks good on email LITELLM_LOGO_URL: Final = "https://litellm-listing.s3.amazonaws.com/litellm_logo.png" diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index 5882323bc48..bf62ad81f15 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -186,27 +186,9 @@ class LitellmTableNames(str, enum.Enum): AGENT_TABLE_NAME = "LiteLLM_AgentsTable" -class Litellm_EntityType(enum.Enum): - """ - Enum for types of entities on litellm - - This enum allows specifying the type of entity that is being tracked in the database. - """ - - KEY = "key" - USER = "user" - END_USER = "end_user" - TEAM = "team" - TEAM_MEMBER = "team_member" - ORGANIZATION = "organization" - ORGANIZATION_MEMBER = "organization_member" - PROJECT = "project" - TAG = "tag" - AGENT = "agent" - MODEL_ACCESS_GROUP = "model_access_group" - - # global proxy level entity - PROXY = "proxy" +from litellm.types.integrations.slack_alerting import ( + Litellm_EntityType as Litellm_EntityType, # noqa: E402, PLC0414 # public re-export +) def hash_token(token: str): @@ -3899,47 +3881,10 @@ class TokenCountRequest(LiteLLMPydanticObjectBase): system: Any | None = None -class CallInfo(LiteLLMPydanticObjectBase): - """Used for slack budget alerting""" - - spend: float - max_budget: float | None = None - soft_budget: float | None = None - token: str | None = Field(default=None, description="Hashed value of that key") - customer_id: str | None = None - user_id: str | None = None - team_id: str | None = None - team_alias: str | None = None - organization_id: str | None = None - user_email: str | None = None - key_alias: str | None = None - projected_exceeded_date: str | None = None - projected_spend: float | None = None - event_group: Litellm_EntityType - alert_emails: list[str] | None = Field( - default=None, - description="Additional email addresses to send alerts to (e.g., from team metadata)", - ) - max_budget_alert_emails: dict[str, list[str]] | None = Field( - default=None, - description="Map of threshold percentage to email recipients (e.g., {'50': ['a@co.com'], '75': ['a@co.com', 'b@co.com']})", - ) - - -class WebhookEvent(CallInfo): - event: Literal[ - "budget_crossed", - "max_budget_alert", - "soft_budget_crossed", - "threshold_crossed", - "projected_limit_exceeded", - "key_created", - "key_rotated", - "internal_user_created", - "spend_tracked", - ] - event_message: str # human-readable description of event - event_group: Litellm_EntityType +from litellm.types.integrations.slack_alerting import CallInfo as CallInfo # noqa: E402, PLC0414 # public re-export +from litellm.types.integrations.slack_alerting import ( + WebhookEvent as WebhookEvent, # noqa: E402, PLC0414 # public re-export +) class SpecialModelNames(enum.Enum): @@ -3956,8 +3901,9 @@ class SpecialProxyStrings(enum.Enum): default_user_id = "default_user_id" # global proxy admin -class InvitationNew(LiteLLMPydanticObjectBase): - user_id: str +from litellm.types.integrations.slack_alerting import ( + InvitationNew as InvitationNew, # noqa: E402, PLC0414 # public re-export +) class InvitationUpdate(LiteLLMPydanticObjectBase): @@ -3969,16 +3915,9 @@ class InvitationDelete(LiteLLMPydanticObjectBase): invitation_id: str -class InvitationModel(LiteLLMPydanticObjectBase): - id: str - user_id: str - is_accepted: bool - accepted_at: datetime | None - expires_at: datetime - created_at: datetime - created_by: str - updated_at: datetime - updated_by: str +from litellm.types.integrations.slack_alerting import ( + InvitationModel as InvitationModel, # noqa: E402, PLC0414 # public re-export +) class InvitationClaim(LiteLLMPydanticObjectBase): @@ -4571,11 +4510,9 @@ class SSOUserDefinedValues(TypedDict): budget_duration: str | None -class VirtualKeyEvent(LiteLLMPydanticObjectBase): - created_by_user_id: str - created_by_user_role: str - created_by_key_alias: str | None - request_kwargs: dict +from litellm.types.integrations.slack_alerting import ( + VirtualKeyEvent as VirtualKeyEvent, # noqa: E402, PLC0414 # public re-export +) class CreatePassThroughEndpoint(LiteLLMPydanticObjectBase): diff --git a/litellm/types/integrations/slack_alerting.py b/litellm/types/integrations/slack_alerting.py index 4ba7e277cb6..89c2ad841e8 100644 --- a/litellm/types/integrations/slack_alerting.py +++ b/litellm/types/integrations/slack_alerting.py @@ -1,3 +1,4 @@ +import enum import os import time from collections.abc import Mapping @@ -292,3 +293,92 @@ class DigestEntry(TypedDict): start_time: dt last_time: dt webhook_url: str | list[str] + + +class Litellm_EntityType(enum.Enum): + """ + Enum for types of entities on litellm + + This enum allows specifying the type of entity that is being tracked in the database. + """ + + KEY = "key" + USER = "user" + END_USER = "end_user" + TEAM = "team" + TEAM_MEMBER = "team_member" + ORGANIZATION = "organization" + ORGANIZATION_MEMBER = "organization_member" + PROJECT = "project" + TAG = "tag" + AGENT = "agent" + MODEL_ACCESS_GROUP = "model_access_group" + + # global proxy level entity + PROXY = "proxy" + + +class CallInfo(LiteLLMPydanticObjectBase): + """Used for slack budget alerting""" + + spend: float + max_budget: float | None = None + soft_budget: float | None = None + token: str | None = Field(default=None, description="Hashed value of that key") + customer_id: str | None = None + user_id: str | None = None + team_id: str | None = None + team_alias: str | None = None + organization_id: str | None = None + user_email: str | None = None + key_alias: str | None = None + projected_exceeded_date: str | None = None + projected_spend: float | None = None + event_group: Litellm_EntityType + alert_emails: list[str] | None = Field( + default=None, + description="Additional email addresses to send alerts to (e.g., from team metadata)", + ) + max_budget_alert_emails: dict[str, list[str]] | None = Field( + default=None, + description="Map of threshold percentage to email recipients (e.g., {'50': ['a@co.com'], '75': ['a@co.com', 'b@co.com']})", + ) + + +class WebhookEvent(CallInfo): + event: Literal[ + "budget_crossed", + "max_budget_alert", + "soft_budget_crossed", + "threshold_crossed", + "projected_limit_exceeded", + "key_created", + "key_rotated", + "internal_user_created", + "spend_tracked", + ] + event_message: str # human-readable description of event + event_group: Litellm_EntityType + + +class InvitationNew(LiteLLMPydanticObjectBase): + user_id: str + + +class InvitationModel(LiteLLMPydanticObjectBase): + id: str + user_id: str + is_accepted: bool + accepted_at: dt | None + expires_at: dt + created_at: dt + created_by: str + updated_at: dt + updated_by: str + + +class VirtualKeyEvent(LiteLLMPydanticObjectBase): + created_by_user_id: str + created_by_user_role: str + created_by_key_alias: str | None + request_kwargs: dict # pyright: ignore[reportMissingTypeArgument] # moved verbatim from proxy/_types.py