diff --git a/docs/my-website/docs/providers/ollama.md b/docs/my-website/docs/providers/ollama.md index 1c913c08c8..c1c8fc57c8 100644 --- a/docs/my-website/docs/providers/ollama.md +++ b/docs/my-website/docs/providers/ollama.md @@ -101,13 +101,19 @@ Ollama supported models: https://github.com/ollama/ollama | Model Name | Function Call | |----------------------|----------------------------------------------------------------------------------- -| Mistral | `completion(model='ollama/mistral', messages, api_base="http://localhost:11434", stream=True)` | +| Mistral | `completion(model='ollama/mistral', messages, api_base="http://localhost:11434", stream=True)` | +| Mistral-7B-Instruct-v0.1 | `completion(model='ollama/mistral-7B-Instruct-v0.1', messages, api_base="http://localhost:11434", stream=False)` | +| Mistral-7B-Instruct-v0.2 | `completion(model='ollama/mistral-7B-Instruct-v0.2', messages, api_base="http://localhost:11434", stream=False)` | +| Mixtral-8x7B-Instruct-v0.1 | `completion(model='ollama/mistral-8x7B-Instruct-v0.1', messages, api_base="http://localhost:11434", stream=False)` | +| Mixtral-8x22B-Instruct-v0.1 | `completion(model='ollama/mixtral-8x22B-Instruct-v0.1', messages, api_base="http://localhost:11434", stream=False)` | | Llama2 7B | `completion(model='ollama/llama2', messages, api_base="http://localhost:11434", stream=True)` | | Llama2 13B | `completion(model='ollama/llama2:13b', messages, api_base="http://localhost:11434", stream=True)` | | Llama2 70B | `completion(model='ollama/llama2:70b', messages, api_base="http://localhost:11434", stream=True)` | | Llama2 Uncensored | `completion(model='ollama/llama2-uncensored', messages, api_base="http://localhost:11434", stream=True)` | | Code Llama | `completion(model='ollama/codellama', messages, api_base="http://localhost:11434", stream=True)` | -| Llama2 Uncensored | `completion(model='ollama/llama2-uncensored', messages, api_base="http://localhost:11434", stream=True)` | +| Llama2 Uncensored | `completion(model='ollama/llama2-uncensored', messages, api_base="http://localhost:11434", stream=True)` | +|Meta LLaMa3 8B | `completion(model='ollama/llama3', messages, api_base="http://localhost:11434", stream=False)` | +| Meta LLaMa3 70B | `completion(model='ollama/llama3:70b', messages, api_base="http://localhost:11434", stream=False)` | | Orca Mini | `completion(model='ollama/orca-mini', messages, api_base="http://localhost:11434", stream=True)` | | Vicuna | `completion(model='ollama/vicuna', messages, api_base="http://localhost:11434", stream=True)` | | Nous-Hermes | `completion(model='ollama/nous-hermes', messages, api_base="http://localhost:11434", stream=True)` | diff --git a/litellm/exceptions.py b/litellm/exceptions.py index d239f1e128..5eb66743b5 100644 --- a/litellm/exceptions.py +++ b/litellm/exceptions.py @@ -15,11 +15,19 @@ from typing import Optional class AuthenticationError(openai.AuthenticationError): # type: ignore - def __init__(self, message, llm_provider, model, response: httpx.Response): + def __init__( + self, + message, + llm_provider, + model, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 401 self.message = message self.llm_provider = llm_provider self.model = model + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs @@ -27,11 +35,19 @@ class AuthenticationError(openai.AuthenticationError): # type: ignore # raise when invalid models passed, example gpt-8 class NotFoundError(openai.NotFoundError): # type: ignore - def __init__(self, message, model, llm_provider, response: httpx.Response): + def __init__( + self, + message, + model, + llm_provider, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 404 self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs @@ -39,12 +55,18 @@ class NotFoundError(openai.NotFoundError): # type: ignore class BadRequestError(openai.BadRequestError): # type: ignore def __init__( - self, message, model, llm_provider, response: Optional[httpx.Response] = None + self, + message, + model, + llm_provider, + response: Optional[httpx.Response] = None, + litellm_debug_info: Optional[str] = None, ): self.status_code = 400 self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info response = response or httpx.Response( status_code=self.status_code, request=httpx.Request( @@ -57,18 +79,28 @@ class BadRequestError(openai.BadRequestError): # type: ignore class UnprocessableEntityError(openai.UnprocessableEntityError): # type: ignore - def __init__(self, message, model, llm_provider, response: httpx.Response): + def __init__( + self, + message, + model, + llm_provider, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 422 self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs class Timeout(openai.APITimeoutError): # type: ignore - def __init__(self, message, model, llm_provider): + def __init__( + self, message, model, llm_provider, litellm_debug_info: Optional[str] = None + ): request = httpx.Request(method="POST", url="https://api.openai.com/v1") super().__init__( request=request @@ -77,6 +109,7 @@ class Timeout(openai.APITimeoutError): # type: ignore self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info # custom function to convert to str def __str__(self): @@ -84,22 +117,38 @@ class Timeout(openai.APITimeoutError): # type: ignore class PermissionDeniedError(openai.PermissionDeniedError): # type:ignore - def __init__(self, message, llm_provider, model, response: httpx.Response): + def __init__( + self, + message, + llm_provider, + model, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 403 self.message = message self.llm_provider = llm_provider self.model = model + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs class RateLimitError(openai.RateLimitError): # type: ignore - def __init__(self, message, llm_provider, model, response: httpx.Response): + def __init__( + self, + message, + llm_provider, + model, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 429 self.message = message self.llm_provider = llm_provider self.modle = model + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs @@ -107,11 +156,19 @@ class RateLimitError(openai.RateLimitError): # type: ignore # sub class of rate limit error - meant to give more granularity for error handling context window exceeded errors class ContextWindowExceededError(BadRequestError): # type: ignore - def __init__(self, message, model, llm_provider, response: httpx.Response): + def __init__( + self, + message, + model, + llm_provider, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 400 self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info super().__init__( message=self.message, model=self.model, # type: ignore @@ -122,11 +179,19 @@ class ContextWindowExceededError(BadRequestError): # type: ignore class ContentPolicyViolationError(BadRequestError): # type: ignore # Error code: 400 - {'error': {'code': 'content_policy_violation', 'message': 'Your request was rejected as a result of our safety system. Image descriptions generated from your prompt may contain text that is not allowed by our safety system. If you believe this was done in error, your request may succeed if retried, or by adjusting your prompt.', 'param': None, 'type': 'invalid_request_error'}} - def __init__(self, message, model, llm_provider, response: httpx.Response): + def __init__( + self, + message, + model, + llm_provider, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 400 self.message = message self.model = model self.llm_provider = llm_provider + self.litellm_debug_info = litellm_debug_info super().__init__( message=self.message, model=self.model, # type: ignore @@ -136,11 +201,19 @@ class ContentPolicyViolationError(BadRequestError): # type: ignore class ServiceUnavailableError(openai.APIStatusError): # type: ignore - def __init__(self, message, llm_provider, model, response: httpx.Response): + def __init__( + self, + message, + llm_provider, + model, + response: httpx.Response, + litellm_debug_info: Optional[str] = None, + ): self.status_code = 503 self.message = message self.llm_provider = llm_provider self.model = model + self.litellm_debug_info = litellm_debug_info super().__init__( self.message, response=response, body=None ) # Call the base class constructor with the parameters it needs @@ -149,33 +222,51 @@ class ServiceUnavailableError(openai.APIStatusError): # type: ignore # raise this when the API returns an invalid response object - https://github.com/openai/openai-python/blob/1be14ee34a0f8e42d3f9aa5451aa4cb161f1781f/openai/api_requestor.py#L401 class APIError(openai.APIError): # type: ignore def __init__( - self, status_code, message, llm_provider, model, request: httpx.Request + self, + status_code, + message, + llm_provider, + model, + request: httpx.Request, + litellm_debug_info: Optional[str] = None, ): self.status_code = status_code self.message = message self.llm_provider = llm_provider self.model = model + self.litellm_debug_info = litellm_debug_info super().__init__(self.message, request=request, body=None) # type: ignore # raised if an invalid request (not get, delete, put, post) is made class APIConnectionError(openai.APIConnectionError): # type: ignore - def __init__(self, message, llm_provider, model, request: httpx.Request): + def __init__( + self, + message, + llm_provider, + model, + request: httpx.Request, + litellm_debug_info: Optional[str] = None, + ): self.message = message self.llm_provider = llm_provider self.model = model self.status_code = 500 + self.litellm_debug_info = litellm_debug_info super().__init__(message=self.message, request=request) # raised if an invalid request (not get, delete, put, post) is made class APIResponseValidationError(openai.APIResponseValidationError): # type: ignore - def __init__(self, message, llm_provider, model): + def __init__( + self, message, llm_provider, model, litellm_debug_info: Optional[str] = None + ): self.message = message self.llm_provider = llm_provider self.model = model request = httpx.Request(method="POST", url="https://api.openai.com/v1") response = httpx.Response(status_code=500, request=request) + self.litellm_debug_info = litellm_debug_info super().__init__(response=response, body=None, message=message) diff --git a/litellm/model_prices_and_context_window_backup.json b/litellm/model_prices_and_context_window_backup.json index a88d6875ca..ff9194578c 100644 --- a/litellm/model_prices_and_context_window_backup.json +++ b/litellm/model_prices_and_context_window_backup.json @@ -1744,6 +1744,30 @@ "litellm_provider": "openrouter", "mode": "chat" }, + "openrouter/openai/gpt-4o": { + "max_tokens": 4096, + "max_input_tokens": 128000, + "max_output_tokens": 4096, + "input_cost_per_token": 0.000005, + "output_cost_per_token": 0.000015, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true + }, + "openrouter/openai/gpt-4o-2024-05-13": { + "max_tokens": 4096, + "max_input_tokens": 128000, + "max_output_tokens": 4096, + "input_cost_per_token": 0.000005, + "output_cost_per_token": 0.000015, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true + }, "openrouter/openai/gpt-4-vision-preview": { "max_tokens": 130000, "input_cost_per_token": 0.00001, @@ -2943,6 +2967,24 @@ "litellm_provider": "ollama", "mode": "completion" }, + "ollama/llama3": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/llama3:70b": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, "ollama/mistral": { "max_tokens": 8192, "max_input_tokens": 8192, @@ -2952,6 +2994,42 @@ "litellm_provider": "ollama", "mode": "completion" }, + "ollama/mistral-7B-Instruct-v0.1": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mistral-7B-Instruct-v0.2": { + "max_tokens": 32768, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mixtral-8x7B-Instruct-v0.1": { + "max_tokens": 32768, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mixtral-8x22B-Instruct-v0.1": { + "max_tokens": 65536, + "max_input_tokens": 65536, + "max_output_tokens": 65536, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, "ollama/codellama": { "max_tokens": 4096, "max_input_tokens": 4096, diff --git a/litellm/proxy/_experimental/out/404.html b/litellm/proxy/_experimental/out/404.html index b70559084d..b0b75d094b 100644 --- a/litellm/proxy/_experimental/out/404.html +++ b/litellm/proxy/_experimental/out/404.html @@ -1 +1 @@ -404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/obp5wqVSVDMiDTC414cR8/_buildManifest.js b/litellm/proxy/_experimental/out/_next/static/2ASoJGxS-D4w-vat00xMy/_buildManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/obp5wqVSVDMiDTC414cR8/_buildManifest.js rename to litellm/proxy/_experimental/out/_next/static/2ASoJGxS-D4w-vat00xMy/_buildManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/obp5wqVSVDMiDTC414cR8/_ssgManifest.js b/litellm/proxy/_experimental/out/_next/static/2ASoJGxS-D4w-vat00xMy/_ssgManifest.js similarity index 100% rename from litellm/proxy/_experimental/out/_next/static/obp5wqVSVDMiDTC414cR8/_ssgManifest.js rename to litellm/proxy/_experimental/out/_next/static/2ASoJGxS-D4w-vat00xMy/_ssgManifest.js diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-6a39771cacf75ea6.js b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-6a39771cacf75ea6.js deleted file mode 100644 index 7d08a80c96..0000000000 --- a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-6a39771cacf75ea6.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,l,t){Promise.resolve().then(t.bind(t,7926))},7926:function(e,l,t){"use strict";t.r(l),t.d(l,{default:function(){return lb}});var s,a,r=t(3827),n=t(64090),o=t(47907),i=t(8792),c=t(40491),d=t(65270),m=e=>{let{userID:l,userRole:t,userEmail:s,showSSOBanner:a}=e;console.log("User ID:",l),console.log("userEmail:",s),console.log("showSSOBanner:",a);let n=[{key:"1",label:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("p",{children:["Role: ",t]}),(0,r.jsxs)("p",{children:["ID: ",l]})]})}];return(0,r.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,r.jsx)("div",{className:"text-left my-2 absolute top-0 left-0",children:(0,r.jsx)("div",{className:"flex flex-col items-center",children:(0,r.jsx)(i.default,{href:"/",children:(0,r.jsx)("button",{className:"text-gray-800 rounded text-center",children:(0,r.jsx)("img",{src:"/get_image",width:160,height:160,alt:"LiteLLM Brand",className:"mr-2"})})})})}),(0,r.jsxs)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2",children:[a?(0,r.jsx)("div",{style:{padding:"6px",borderRadius:"8px"},children:(0,r.jsx)("a",{href:"https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat",target:"_blank",style:{fontSize:"14px",textDecoration:"underline"},children:"Request hosted proxy"})}):null,(0,r.jsx)("div",{style:{border:"1px solid #391085",padding:"6px",borderRadius:"8px"},children:(0,r.jsx)(c.Z,{menu:{items:n},children:(0,r.jsx)(d.Z,{children:s})})})]})]})},u=t(80588);let h=async()=>{try{let e=await fetch("https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"),l=await e.json();return console.log("received data: ".concat(l)),l}catch(e){throw console.error("Failed to get model cost map:",e),e}},x=async(e,l)=>{try{let t=await fetch("/model/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model created successfully. Wait 60s and refresh on 'All Models' page"),s}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,l)=>{console.log("model_id in model delete call: ".concat(l));try{let t=await fetch("/model/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({id:l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model deleted successfully. Restart server to see this."),s}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/user/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},y=async(e,l)=>{try{console.log("in keyDeleteCall:",l);let t=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},f=async(e,l)=>{try{console.log("in teamDeleteCall:",l);let t=await fetch("/team/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_ids:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete team: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to delete key:",e),e}},Z=async function(e,l,t){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=arguments.length>4?arguments[4]:void 0,r=arguments.length>5?arguments[5]:void 0;try{let n="/user/info";"App Owner"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),"App User"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),console.log("in userInfoCall viewAll=",s),s&&r&&null!=a&&void 0!=a&&(n="".concat(n,"?view_all=true&page=").concat(a,"&page_size=").concat(r));let o=await fetch(n,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let i=await o.json();return console.log("API Response:",i),i}catch(e){throw console.error("Failed to create key:",e),e}},_=async(e,l)=>{try{let t="/team/info";l&&(t="".concat(t,"?team_id=").concat(l)),console.log("in teamInfoCall");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},w=async e=>{try{let l=await fetch("/global/spend",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},b=async(e,l,t)=>{try{let l=await fetch("/v2/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log("modelInfoCall:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},k=async(e,l,t,s,a,r)=>{try{let l="/model/metrics";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},v=async(e,l,t,s,a,r)=>{try{let l="/model/metrics/slow_responses";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},S=async(e,l,t,s,a,r)=>{try{let l="/model/metrics/exceptions";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},N=async(e,l,t)=>{try{let l=await fetch("/models",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},A=async e=>{try{let l="/global/spend/teams";console.log("in teamSpendLogsCall:",l);let t=await fetch("".concat(l),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},E=async(e,l,t)=>{try{let s="/global/spend/tags";l&&t&&(s="".concat(s,"?start_date=").concat(l,"&end_date=").concat(t)),console.log("in tagsSpendLogsCall:",s);let a=await fetch("".concat(s),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await a.json();return console.log(r),r}catch(e){throw console.error("Failed to create key:",e),e}},I=async(e,l,t,s,a,r)=>{try{console.log("user role in spend logs call: ".concat(t));let l="/spend/logs";l="App Owner"==t?"".concat(l,"?user_id=").concat(s,"&start_date=").concat(a,"&end_date=").concat(r):"".concat(l,"?start_date=").concat(a,"&end_date=").concat(r);let n=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},C=async e=>{try{let l=await fetch("/global/spend/logs",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},P=async e=>{try{let l=await fetch("/global/spend/keys?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},T=async(e,l,t,s)=>{try{let a="";a=l?JSON.stringify({api_key:l,startTime:t,endTime:s}):JSON.stringify({startTime:t,endTime:s});let r={method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}};r.body=a;let n=await fetch("/global/spend/end_users",r);if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},O=async e=>{try{let l=await fetch("/global/spend/models?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},F=async(e,l)=>{try{let t=await fetch("/v2/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},R=async(e,l)=>{try{let t="/user/get_users?role=".concat(l);console.log("in userGetAllUsersCall:",t);let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let a=await s.json();return console.log(a),a}catch(e){throw console.error("Failed to get requested models:",e),e}},M=async(e,l)=>{try{console.log("Form Values in teamCreateCall:",l);let t=await fetch("/team/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},L=async(e,l)=>{try{console.log("Form Values in keyUpdateCall:",l);let t=await fetch("/key/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update key Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},U=async(e,l)=>{try{console.log("Form Values in teamUpateCall:",l);let t=await fetch("/team/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update team: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update Team Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},D=async(e,l)=>{try{console.log("Form Values in modelUpateCall:",l);let t=await fetch("/model/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update model: "+e,10),console.error("Error update from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update model Response:",s),s}catch(e){throw console.error("Failed to update model:",e),e}},K=async(e,l,t)=>{try{console.log("Form Values in teamMemberAddCall:",t);let s=await fetch("/team/member_add",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_id:l,member:t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},B=async(e,l,t)=>{try{console.log("Form Values in userUpdateUserCall:",l);let s={...l};null!==t&&(s.user_role=t),s=JSON.stringify(s);let a=await fetch("/user/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:s});if(!a.ok){let e=await a.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await a.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},z=async(e,l)=>{try{let t="/health/services?service=".concat(l);console.log("Checking Slack Budget Alerts service health");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed ".concat(l," service health check ")+e),Error(e)}let a=await s.json();return u.ZP.success("Test request to ".concat(l," made - check logs/alerts on ").concat(l," to verify")),a}catch(e){throw console.error("Failed to perform health check:",e),e}},q=async(e,l,t)=>{try{let l=await fetch("/get/config/callbacks",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},V=async(e,l)=>{try{let t=await fetch("/config/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to set callbacks:",e),e}},G=async e=>{try{let l=await fetch("/health",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to call /health:",e),e}};var Y=t(10384),W=t(46453),J=t(16450),H=t(52273),$=t(26780),X=t(15595),Q=t(6698),ee=t(71801),el=t(42440),et=t(42308),es=t(50670),ea=t(81583),er=t(99129),en=t(44839),eo=t(88707),ei=t(1861);let{Option:ec}=es.default;var ed=e=>{let{userID:l,team:t,userRole:s,accessToken:a,data:o,setData:i}=e,[c]=ea.Z.useForm(),[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(null),[p,g]=(0,n.useState)(null),[y,f]=(0,n.useState)([]),[Z,_]=(0,n.useState)([]),w=()=>{m(!1),c.resetFields()},b=()=>{m(!1),x(null),c.resetFields()};(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===s)return;if(null!==a){let e=(await N(a,l,s)).data.map(e=>e.id);console.log("available_model_names:",e),f(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[a,l,s]);let k=async e=>{try{var t,s,r;let n=null!==(t=null==e?void 0:e.key_alias)&&void 0!==t?t:"",d=null!==(s=null==e?void 0:e.team_id)&&void 0!==s?s:null;if((null!==(r=null==o?void 0:o.filter(e=>e.team_id===d).map(e=>e.key_alias))&&void 0!==r?r:[]).includes(n))throw Error("Key alias ".concat(n," already exists for team with ID ").concat(d,", please provide another key alias"));u.ZP.info("Making API Call"),m(!0);let h=await j(a,l,e);console.log("key create Response:",h),i(e=>e?[...e,h]:[h]),x(h.key),g(h.soft_budget),u.ZP.success("API Key Created"),c.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the key:",e),u.ZP.error("Error creating the key: ".concat(e),20)}};return(0,n.useEffect)(()=>{_(t&&t.models.length>0?t.models.includes("all-proxy-models")?y:t.models:y)},[t,y]),(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>m(!0),children:"+ Create New Key"}),(0,r.jsx)(er.Z,{title:"Create Key",visible:d,width:800,footer:null,onOk:w,onCancel:b,children:(0,r.jsxs)(ea.Z,{form:c,onFinish:k,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"team_id",hidden:!0,initialValue:t?t.team_id:null,valuePropName:"team_id",className:"mt-8",children:(0,r.jsx)(en.Z,{value:t?t.team_alias:"",disabled:!0})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},onChange:e=>{e.includes("all-team-models")&&c.setFieldsValue({models:["all-team-models"]})},children:[(0,r.jsx)(ec,{value:"all-team-models",children:"All Team Models"},"all-team-models"),Z.map(e=>(0,r.jsx)(ec,{value:e,children:e},e))]})}),(0,r.jsxs)($.Z,{className:"mt-20 mb-8",children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)("b",{children:"Optional Settings"})}),(0,r.jsxs)(X.Z,{children:[(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat(t.max_budget))}}],children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Reset Budget",name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,r.jsxs)(es.default,{defaultValue:null,placeholder:"n/a",children:[(0,r.jsx)(es.default.Option,{value:"24h",children:"daily"}),(0,r.jsx)(es.default.Option,{value:"30d",children:"monthly"})]})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Tokens per minute Limit (TPM)",name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Requests per minute Limit (RPM)",name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Expire Key (eg: 30s, 30h, 30d)",name:"duration",className:"mt-8",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(en.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]})]})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create Key"})})]})}),h&&(0,r.jsx)(er.Z,{visible:d,onOk:w,onCancel:b,footer:null,children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(el.Z,{children:"Save your Key"}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,r.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:null!=h?(0,r.jsxs)("div",{children:[(0,r.jsx)(ee.Z,{className:"mt-3",children:"API Key:"}),(0,r.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,r.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:h})}),(0,r.jsx)(et.CopyToClipboard,{text:h,onCopy:()=>{u.ZP.success("API Key copied to clipboard")},children:(0,r.jsx)(J.Z,{className:"mt-3",children:"Copy API Key"})})]}):(0,r.jsx)(ee.Z,{children:"Key being created, this might take 30s"})})]})})]})},em=t(9454),eu=t(98941),eh=t(33393),ex=t(5),ep=t(13810),ej=t(61244),eg=t(10827),ey=t(3851),ef=t(2044),eZ=t(64167),e_=t(74480),ew=t(7178),eb=t(95093),ek=t(27166);let{Option:ev}=es.default;var eS=e=>{let{userID:l,userRole:t,accessToken:s,selectedTeam:a,data:o,setData:i,teams:c}=e,[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(!1),[p,j]=(0,n.useState)(null),[g,f]=(0,n.useState)(null),[Z,_]=(0,n.useState)(null),[w,b]=(0,n.useState)(""),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)(!1),[E,I]=(0,n.useState)(null),[C,P]=(0,n.useState)([]),T=new Set,[O,F]=(0,n.useState)(T);(0,n.useEffect)(()=>{(async()=>{try{if(null===l)return;if(null!==s&&null!==t){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),P(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[s,l,t]),(0,n.useEffect)(()=>{if(c){let e=new Set;c.forEach((l,t)=>{let s=l.team_id;e.add(s)}),F(e)}},[c]);let R=e=>{console.log("handleEditClick:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),I(e),v(!0)},M=async e=>{if(null==s)return;let l=e.token;e.key=l,console.log("handleEditSubmit:",e);let t=await L(s,e);console.log("handleEditSubmit: newKeyValues",t),o&&i(o.map(e=>e.token===l?t:e)),u.ZP.success("Key updated successfully"),v(!1),I(null)},U=async e=>{console.log("handleDelete:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),null!=o&&(j(e.token),localStorage.removeItem("userData"+l),x(!0))},D=async()=>{if(null!=p&&null!=o){try{await y(s,p);let e=o.filter(e=>e.token!==p);i(e)}catch(e){console.error("Error deleting the key:",e)}x(!1),j(null)}};if(null!=o)return console.log("RERENDER TRIGGERED"),(0,r.jsxs)("div",{children:[(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4 mt-2",children:[(0,r.jsxs)(eg.Z,{className:"mt-5 max-h-[300px] min-h-[300px]",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Key Alias"}),(0,r.jsx)(e_.Z,{children:"Secret Key"}),(0,r.jsx)(e_.Z,{children:"Spend (USD)"}),(0,r.jsx)(e_.Z,{children:"Budget (USD)"}),(0,r.jsx)(e_.Z,{children:"Models"}),(0,r.jsx)(e_.Z,{children:"TPM / RPM Limits"})]})}),(0,r.jsx)(ey.Z,{children:o.map(e=>{if(console.log(e),"litellm-dashboard"===e.team_id)return null;if(a){if(console.log("item team id: ".concat(e.team_id,", knownTeamIDs.has(item.team_id): ").concat(O.has(e.team_id),", selectedTeam id: ").concat(a.team_id)),(null!=a.team_id||null===e.team_id||O.has(e.team_id))&&e.team_id!=a.team_id)return null;console.log("item team id: ".concat(e.team_id,", is returned"))}return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{style:{maxWidth:"2px",whiteSpace:"pre-wrap",overflow:"hidden"},children:null!=e.key_alias?(0,r.jsx)(ee.Z,{children:e.key_alias}):(0,r.jsx)(ee.Z,{children:"Not Set"})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:e.key_name})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:(()=>{try{return parseFloat(e.spend).toFixed(4)}catch(l){return e.spend}})()})}),(0,r.jsx)(ef.Z,{children:null!=e.max_budget?(0,r.jsx)(ee.Z,{children:e.max_budget}):(0,r.jsx)(ee.Z,{children:"Unlimited"})}),(0,r.jsx)(ef.Z,{children:Array.isArray(e.models)?(0,r.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,r.jsx)(r.Fragment,{children:a&&a.models&&a.models.length>0?a.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Team Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l)):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:"all-proxy-models"})})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Team Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,r.jsx)(ef.Z,{children:(0,r.jsxs)(ee.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,r.jsx)("br",{})," RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{onClick:()=>{I(e),A(!0)},icon:em.Z,size:"sm"}),(0,r.jsx)(er.Z,{open:S,onCancel:()=>{A(!1),I(null)},footer:null,width:800,children:E&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 mt-8",children:[(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Spend"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:(()=>{try{return parseFloat(E.spend).toFixed(4)}catch(e){return E.spend}})()})})]}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Budget"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.max_budget?(0,r.jsx)(r.Fragment,{children:E.max_budget}):(0,r.jsx)(r.Fragment,{children:"Unlimited"})})})]},e.name),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Expires"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor-default font-small text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.expires?(0,r.jsx)(r.Fragment,{children:new Date(E.expires).toLocaleString(void 0,{day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric"})}):(0,r.jsx)(r.Fragment,{children:"Never"})})})]},e.name)]}),(0,r.jsxs)(ep.Z,{className:"my-4",children:[(0,r.jsx)(el.Z,{children:"Token Name"}),(0,r.jsx)(ee.Z,{className:"my-1",children:E.key_alias?E.key_alias:E.key_name}),(0,r.jsx)(el.Z,{children:"Token ID"}),(0,r.jsx)(ee.Z,{className:"my-1 text-[12px]",children:E.token}),(0,r.jsx)(el.Z,{children:"Metadata"}),(0,r.jsx)(ee.Z,{className:"my-1",children:(0,r.jsxs)("pre",{children:[JSON.stringify(E.metadata)," "]})})]}),(0,r.jsx)(J.Z,{className:"mx-auto flex items-center",onClick:()=>{A(!1),I(null)},children:"Close"})]})}),(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>R(e)}),(0,r.jsx)(ej.Z,{onClick:()=>U(e),icon:eh.Z,size:"sm"})]})]},e.token)})})]}),h&&(0,r.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,r.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,r.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,r.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,r.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,r.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,r.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,r.jsx)("div",{className:"sm:flex sm:items-start",children:(0,r.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,r.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,r.jsx)("div",{className:"mt-2",children:(0,r.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,r.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,r.jsx)(J.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,r.jsx)(J.Z,{onClick:()=>{x(!1),j(null)},children:"Cancel"})]})]})]})})]}),E&&(0,r.jsx)(e=>{let{visible:l,onCancel:t,token:s,onSubmit:o}=e,[i]=ea.Z.useForm(),[d,m]=(0,n.useState)(a),[u,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1);return(0,r.jsx)(er.Z,{title:"Edit Key",visible:l,width:800,footer:null,onOk:()=>{i.validateFields().then(e=>{i.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:i,onFinish:M,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",rules:[{validator:(e,l)=>{let t=l.filter(e=>!d.models.includes(e)&&"all-team-models"!==e&&"all-proxy-models"!==e&&!d.models.includes("all-proxy-models"));return(console.log("errorModels: ".concat(t)),t.length>0)?Promise.reject("Some models are not part of the new team's models - ".concat(t,"Team models: ").concat(d.models)):Promise.resolve()}}],children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(ev,{value:"all-team-models",children:"All Team Models"},"all-team-models"),d&&d.models?d.models.includes("all-proxy-models")?C.filter(e=>"all-proxy-models"!==e).map(e=>(0,r.jsx)(ev,{value:e,children:e},e)):d.models.map(e=>(0,r.jsx)(ev,{value:e,children:e},e)):C.map(e=>(0,r.jsx)(ev,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: ".concat((null==d?void 0:d.max_budget)!==null&&(null==d?void 0:d.max_budget)!==void 0?null==d?void 0:d.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&d&&null!==d.max_budget&&l>d.max_budget)throw console.log("keyTeam.max_budget: ".concat(d.max_budget)),Error("Budget cannot exceed team max budget: $".concat(d.max_budget))}}],children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"token",name:"token",hidden:!0}),(0,r.jsx)(ea.Z.Item,{label:"Team",name:"team_id",help:"the team this key belongs to",children:(0,r.jsx)(eb.Z,{value:s.team_alias,children:null==c?void 0:c.map((e,l)=>(0,r.jsx)(ek.Z,{value:e.team_id,onClick:()=>m(e),children:e.team_alias},l))})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Edit Key"})})]})})},{visible:k,onCancel:()=>{v(!1),I(null)},token:E,onSubmit:M})]})},eN=t(76032),eA=t(35152),eE=e=>{let{userID:l,userRole:t,accessToken:s,userSpend:a,selectedTeam:o}=e;console.log("userSpend: ".concat(a));let[i,c]=(0,n.useState)(null!==a?a:0),[d,m]=(0,n.useState)(0),[u,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{let e=async()=>{if(s&&l&&t&&"Admin"===t&&null==a)try{let e=await w(s);e&&(e.spend?c(e.spend):c(0),e.max_budget?m(e.max_budget):m(0))}catch(e){console.error("Error fetching global spend data:",e)}};(async()=>{try{if(null===l||null===t)return;if(null!==s){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),h(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[t,s,l]),(0,n.useEffect)(()=>{null!==a&&c(a)},[a]);let x=[];o&&o.models&&(x=o.models),x&&x.includes("all-proxy-models")?(console.log("user models:",u),x=u):x&&x.includes("all-team-models")?x=o.models:x&&0===x.length&&(x=u);let p=void 0!==i?i.toFixed(4):null;return console.log("spend in view user spend: ".concat(i)),(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsxs)("div",{children:[(0,r.jsxs)("p",{className:"text-tremor-default text-tremor-content dark:text-dark-tremor-content",children:["Total Spend"," "]}),(0,r.jsxs)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:["$",p]})]}),(0,r.jsx)("div",{className:"ml-auto",children:(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)(ee.Z,{children:"Team Models"})}),(0,r.jsx)(X.Z,{className:"absolute right-0 z-10 bg-white p-2 shadow-lg max-w-xs",children:(0,r.jsx)(eN.Z,{children:x.map(e=>(0,r.jsx)(eA.Z,{children:(0,r.jsx)(ee.Z,{children:e})},e))})})]})})]})},eI=e=>{let{userID:l,userRole:t,selectedTeam:s,accessToken:a}=e,[o,i]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===t)return;if(null!==a){let e=(await N(a,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),i(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[a,l,t]);let c=[];return s&&s.models&&(c=s.models),c&&c.includes("all-proxy-models")&&(console.log("user models:",o),c=o),(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("div",{className:"mb-5",children:(0,r.jsx)("p",{className:"text-3xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:null==s?void 0:s.team_alias})})})},eC=e=>{let l,{teams:t,setSelectedTeam:s,userRole:a}=e,o={models:[],team_id:null,team_alias:"Default Team"},[i,c]=(0,n.useState)(o);return(l="App User"===a?t:t?[...t,o]:[o],"App User"===a)?null:(0,r.jsxs)("div",{className:"mt-5 mb-5",children:[(0,r.jsx)(el.Z,{children:"Select Team"}),(0,r.jsx)(ee.Z,{children:"If you belong to multiple teams, this setting controls which team is used by default when creating new API Keys."}),(0,r.jsxs)(ee.Z,{className:"mt-3 mb-3",children:[(0,r.jsx)("b",{children:"Default Team:"})," If no team_id is set for a key, it will be grouped under here."]}),l&&l.length>0?(0,r.jsx)(eb.Z,{defaultValue:"0",children:l.map((e,l)=>(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>s(e),children:e.team_alias},l))}):(0,r.jsxs)(ee.Z,{children:["No team created. ",(0,r.jsx)("b",{children:"Defaulting to personal account."})]})]})},eP=t(37963),eT=t(36083);console.log("isLocal:",!1);var eO=e=>{let{userID:l,userRole:t,teams:s,keys:a,setUserRole:i,userEmail:c,setUserEmail:d,setTeams:m,setKeys:u}=e,[h,x]=(0,n.useState)(null),p=(0,o.useSearchParams)();p.get("viewSpend"),(0,o.useRouter)();let j=p.get("token"),[g,y]=(0,n.useState)(null),[f,_]=(0,n.useState)(null),[b,k]=(0,n.useState)([]),v={models:[],team_alias:"Default Team",team_id:null},[S,A]=(0,n.useState)(s?s[0]:v);if(window.addEventListener("beforeunload",function(){sessionStorage.clear()}),(0,n.useEffect)(()=>{if(j){let e=(0,eP.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),y(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),i(l)}else console.log("User role not defined");e.user_email?d(e.user_email):console.log("User Email is not set ".concat(e))}}if(l&&g&&t&&!a&&!h){let e=sessionStorage.getItem("userModels"+l);e?k(JSON.parse(e)):(async()=>{try{let e=await Z(g,l,t,!1,null,null);if(console.log("received teams in user dashboard: ".concat(Object.keys(e),"; team values: ").concat(Object.entries(e.teams))),"Admin"==t){let e=await w(g);x(e),console.log("globalSpend:",e)}else x(e.user_info);u(e.keys),m(e.teams);let s=[...e.teams];s.length>0?(console.log("response['teams']: ".concat(s)),A(s[0])):A(v),sessionStorage.setItem("userData"+l,JSON.stringify(e.keys)),sessionStorage.setItem("userSpendData"+l,JSON.stringify(e.user_info));let a=(await N(g,l,t)).data.map(e=>e.id);console.log("available_model_names:",a),k(a),console.log("userModels:",b),sessionStorage.setItem("userModels"+l,JSON.stringify(a))}catch(e){console.error("There was an error fetching the data",e)}})()}},[l,j,g,a,t]),(0,n.useEffect)(()=>{if(null!==a&&null!=S){let e=0;for(let l of a)S.hasOwnProperty("team_id")&&null!==l.team_id&&l.team_id===S.team_id&&(e+=l.spend);_(e)}else if(null!==a){let e=0;for(let l of a)e+=l.spend;_(e)}},[S]),null==l||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}if(null==g)return null;if(null==t&&i("App Owner"),t&&"Admin Viewer"==t){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to create keys"})]})}return console.log("inside user dashboard, selected team",S),console.log("teamSpend: ".concat(f)),(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsx)(W.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(eI,{userID:l,userRole:t,selectedTeam:S||null,accessToken:g}),(0,r.jsx)(eE,{userID:l,userRole:t,accessToken:g,userSpend:f,selectedTeam:S||null}),(0,r.jsx)(eS,{userID:l,userRole:t,accessToken:g,selectedTeam:S||null,data:a,setData:u,teams:s}),(0,r.jsx)(ed,{userID:l,team:S||null,userRole:t,accessToken:g,data:a,setData:u},S?S.team_id:null),(0,r.jsx)(eC,{teams:s,setSelectedTeam:A,userRole:t})]})})})},eF=t(35087),eR=t(92836),eM=t(26734),eL=t(41608),eU=t(32126),eD=t(23682),eK=t(47047),eB=t(76628),ez=t(57750),eq=t(44041),eV=t(38302),eG=t(28683),eY=t(1460),eW=t(78578),eJ=t(63954),eH=t(90252),e$=t(7905),eX=e=>{let{modelID:l,accessToken:t}=e,[s,a]=(0,n.useState)(!1),o=async()=>{try{u.ZP.info("Making API Call"),a(!0);let e=await p(t,l);console.log("model delete Response:",e),u.ZP.success("Model ".concat(l," deleted successfully")),a(!1)}catch(e){console.error("Error deleting the model:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(ej.Z,{onClick:()=>a(!0),icon:eh.Z,size:"sm"}),(0,r.jsx)(er.Z,{open:s,onOk:o,okType:"danger",onCancel:()=>a(!1),children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(el.Z,{children:"Delete Model"}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsx)("p",{children:"Are you sure you want to delete this model? This action is irreversible."})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("p",{children:["Model ID: ",(0,r.jsx)("b",{children:l})]})})]})})]})},eQ=t(97766),e0=t(46495);let{Title:e1,Link:e2}=eT.default;(s=a||(a={})).OpenAI="OpenAI",s.Azure="Azure",s.Anthropic="Anthropic",s.Google_AI_Studio="Gemini (Google AI Studio)",s.Bedrock="Amazon Bedrock",s.OpenAI_Compatible="OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)",s.Vertex_AI="Vertex AI (Anthropic, Gemini, etc.)";let e4={OpenAI:"openai",Azure:"azure",Anthropic:"anthropic",Google_AI_Studio:"gemini",Bedrock:"bedrock",OpenAI_Compatible:"openai",Vertex_AI:"vertex_ai"},e8={"BadRequestError (400)":"BadRequestErrorRetries","AuthenticationError (401)":"AuthenticationErrorRetries","TimeoutError (408)":"TimeoutErrorRetries","RateLimitError (429)":"RateLimitErrorRetries","ContentPolicyViolationError (400)":"ContentPolicyViolationErrorRetries","InternalServerError (500)":"InternalServerErrorRetries"},e5=async(e,l,t)=>{try{let s=Array.isArray(e.model)?e.model:[e.model];console.log("received deployments: ".concat(s)),console.log("received type of deployments: ".concat(typeof s)),s.forEach(async t=>{console.log("litellm_model: ".concat(t));let s={},a={};s.model=t;let r="";for(let[l,t]of Object.entries(e))if(""!==t){if("model_name"==l)r+=t;else if("custom_llm_provider"==l)continue;else if("model"==l)continue;else if("base_model"===l)a[l]=t;else if("litellm_extra_params"==l){console.log("litellm_extra_params:",t);let e={};if(t&&void 0!=t){try{e=JSON.parse(t)}catch(e){throw u.ZP.error("Failed to parse LiteLLM Extra Params: "+e,10),Error("Failed to parse litellm_extra_params: "+e)}for(let[l,t]of Object.entries(e))s[l]=t}}else s[l]=t}let n={model_name:r,litellm_params:s,model_info:a},o=await x(l,n);console.log("response for model create call: ".concat(o.data))}),t.resetFields()}catch(e){u.ZP.error("Failed to create model: "+e,10)}};var e3=e=>{var l,t,s;let{accessToken:o,token:i,userRole:c,userID:d,modelData:m={data:[]},setModelData:x}=e,[p,j]=(0,n.useState)([]),[g]=ea.Z.useForm(),[y,f]=(0,n.useState)(null),[Z,_]=(0,n.useState)(""),[w,N]=(0,n.useState)([]),A=Object.values(a).filter(e=>isNaN(Number(e))),[E,I]=(0,n.useState)("OpenAI"),[C,P]=(0,n.useState)(""),[T,O]=(0,n.useState)(!1),[F,R]=(0,n.useState)(null),[M,L]=(0,n.useState)([]),[U,K]=(0,n.useState)(null),[B,z]=(0,n.useState)([]),[Y,et]=(0,n.useState)([]),[es,en]=(0,n.useState)([]),[ec,ed]=(0,n.useState)([]),[em,eh]=(0,n.useState)([]),[ev,eS]=(0,n.useState)([]),[eN,eA]=(0,n.useState)([]),[eE,eI]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),[eC,eP]=(0,n.useState)(null),[eO,e3]=(0,n.useState)(0),e6=e=>{R(e),O(!0)},e7=async e=>{if(console.log("handleEditSubmit:",e),null==o)return;let l={},t=null;for(let[s,a]of Object.entries(e))"model_id"!==s?l[s]=a:t=a;let s={litellm_params:l,model_info:{id:t}};console.log("handleEditSubmit payload:",s);try{await D(o,s),u.ZP.success("Model updated successfully, restart server to see updates"),O(!1),R(null)}catch(e){console.log("Error occurred")}},e9=()=>{_(new Date().toLocaleString())},le=async()=>{if(!o){console.error("Access token is missing");return}console.log("new modelGroupRetryPolicy:",eC);try{await V(o,{router_settings:{model_group_retry_policy:eC}}),u.ZP.success("Retry settings saved successfully")}catch(e){console.error("Failed to save retry settings:",e),u.ZP.error("Failed to save retry settings")}};if((0,n.useEffect)(()=>{if(!o||!i||!c||!d)return;let e=async()=>{try{var e,l,t,s,a,r;let n=await b(o,d,c);console.log("Model data response:",n.data),x(n);let i=new Set;for(let e=0;e0&&(u=m[m.length-1],console.log("_initial_model_group:",u),K(u)),console.log("selectedModelGroup:",U);let h=await k(o,d,c,u,null===(e=eE.from)||void 0===e?void 0:e.toISOString(),null===(l=eE.to)||void 0===l?void 0:l.toISOString());console.log("Model metrics response:",h),et(h.data),en(h.all_api_bases);let p=await S(o,d,c,u,null===(t=eE.from)||void 0===t?void 0:t.toISOString(),null===(s=eE.to)||void 0===s?void 0:s.toISOString());console.log("Model exceptions response:",p),ed(p.data),eh(p.exception_types);let j=await v(o,d,c,u,null===(a=eE.from)||void 0===a?void 0:a.toISOString(),null===(r=eE.to)||void 0===r?void 0:r.toISOString());console.log("slowResponses:",j),eA(j);let g=(await q(o,d,c)).router_settings;console.log("routerSettingsInfo:",g);let y=g.model_group_retry_policy,f=g.num_retries;console.log("model_group_retry_policy:",y),console.log("default_retries:",f),eP(y),e3(f)}catch(e){console.error("There was an error fetching the model data",e)}};o&&i&&c&&d&&e();let l=async()=>{let e=await h();console.log("received model cost map data: ".concat(Object.keys(e))),f(e)};null==y&&l(),e9()},[o,i,c,d,y,Z]),!m||!o||!i||!c||!d)return(0,r.jsx)("div",{children:"Loading..."});let ll=[];for(let e=0;e(console.log("GET PROVIDER CALLED! - ".concat(y)),null!=y&&"object"==typeof y&&e in y)?y[e].litellm_provider:"openai";if(a){let e=a.split("/"),l=e[0];n=1===e.length?u(a):l}else n="openai";r&&(o=null==r?void 0:r.input_cost_per_token,i=null==r?void 0:r.output_cost_per_token,c=null==r?void 0:r.max_tokens),(null==s?void 0:s.litellm_params)&&(d=Object.fromEntries(Object.entries(null==s?void 0:s.litellm_params).filter(e=>{let[l]=e;return"model"!==l&&"api_base"!==l}))),m.data[e].provider=n,m.data[e].input_cost=o,m.data[e].output_cost=i,m.data[e].max_tokens=c,m.data[e].api_base=null==s?void 0:null===(t=s.litellm_params)||void 0===t?void 0:t.api_base,m.data[e].cleanedLitellmParams=d,ll.push(s.model_name),console.log(m.data[e])}if(c&&"Admin Viewer"==c){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to view all models"})]})}let lt=e=>{console.log("received provider string: ".concat(e));let l=Object.keys(a).find(l=>a[l]===e);if(l){let e=e4[l];console.log("mappingResult: ".concat(e));let t=[];"object"==typeof y&&Object.entries(y).forEach(l=>{let[s,a]=l;null!==a&&"object"==typeof a&&"litellm_provider"in a&&(a.litellm_provider===e||a.litellm_provider.includes(e))&&t.push(s)}),N(t),console.log("providerModels: ".concat(w))}},ls=async()=>{try{u.ZP.info("Running health check..."),P("");let e=await G(o);P(e)}catch(e){console.error("Error running health check:",e),P("Error running health check")}},la=async(e,l,t)=>{if(console.log("Updating model metrics for group:",e),o&&d&&c&&l&&t){console.log("inside updateModelMetrics - startTime:",l,"endTime:",t),K(e);try{let s=await k(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model metrics response:",s),et(s.data),en(s.all_api_bases);let a=await S(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model exceptions response:",a),ed(a.data),eh(a.exception_types);let r=await v(o,d,c,e,l.toISOString(),t.toISOString());console.log("slowResponses:",r),eA(r)}catch(e){console.error("Failed to fetch model metrics",e)}}};return console.log("selectedProvider: ".concat(E)),console.log("providerModels.length: ".concat(w.length)),(0,r.jsx)("div",{style:{width:"100%",height:"100%"},children:(0,r.jsxs)(eM.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(eL.Z,{className:"flex justify-between mt-2 w-full items-center",children:[(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)(eR.Z,{children:"All Models"}),(0,r.jsx)(eR.Z,{children:"Add Model"}),(0,r.jsx)(eR.Z,{children:(0,r.jsx)("pre",{children:"/health Models"})}),(0,r.jsx)(eR.Z,{children:"Model Analytics"}),(0,r.jsx)(eR.Z,{children:"Model Retry Settings"})]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[Z&&(0,r.jsxs)(ee.Z,{children:["Last Refreshed: ",Z]}),(0,r.jsx)(ej.Z,{icon:eJ.Z,variant:"shadow",size:"xs",className:"self-center",onClick:e9})]})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(W.Z,{children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(ee.Z,{children:"Filter by Public Model Name"}),(0,r.jsxs)(eb.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:"all",onValueChange:e=>K("all"===e?"all":e),children:[(0,r.jsx)(ek.Z,{value:"all",children:"All Models"}),M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>K(e),children:e},l))]})]}),(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{className:"mt-5",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Public Model Name "}),(0,r.jsx)(e_.Z,{children:"Provider"}),"Admin"===c&&(0,r.jsx)(e_.Z,{children:"API Base"}),(0,r.jsx)(e_.Z,{children:"Extra litellm Params"}),(0,r.jsx)(e_.Z,{children:"Input Price per token ($)"}),(0,r.jsx)(e_.Z,{children:"Output Price per token ($)"}),(0,r.jsx)(e_.Z,{children:"Max Tokens"}),(0,r.jsx)(e_.Z,{children:"Status"})]})}),(0,r.jsx)(ey.Z,{children:m.data.filter(e=>"all"===U||e.model_name===U||null==U||""===U).map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:e.model_name})}),(0,r.jsx)(ef.Z,{children:e.provider}),"Admin"===c&&(0,r.jsx)(ef.Z,{children:e.api_base}),(0,r.jsx)(ef.Z,{children:(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)(ee.Z,{children:"Litellm params"})}),(0,r.jsx)(X.Z,{children:(0,r.jsx)("pre",{children:JSON.stringify(e.cleanedLitellmParams,null,2)})})]})}),(0,r.jsx)(ef.Z,{children:e.input_cost||e.litellm_params.input_cost_per_token||null}),(0,r.jsx)(ef.Z,{children:e.output_cost||e.litellm_params.output_cost_per_token||null}),(0,r.jsx)(ef.Z,{children:e.max_tokens}),(0,r.jsx)(ef.Z,{children:e.model_info.db_model?(0,r.jsx)(ex.Z,{icon:eH.Z,className:"text-white",children:"DB Model"}):(0,r.jsx)(ex.Z,{icon:e$.Z,className:"text-black",children:"Config Model"})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>e6(e)}),(0,r.jsx)(eX,{modelID:e.model_info.id,accessToken:o})]})]},l))})]})})]}),(0,r.jsx)(e=>{let{visible:l,onCancel:t,model:s,onSubmit:a}=e,[n]=ea.Z.useForm(),o={},i="",c="";if(s){o=s.litellm_params,i=s.model_name;let e=s.model_info;e&&(c=e.id,console.log("model_id: ".concat(c)),o.model_id=c)}return(0,r.jsx)(er.Z,{title:"Edit Model "+i,visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{a(e),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:n,onFinish:e7,initialValues:o,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"api_base",name:"api_base",children:(0,r.jsx)(H.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"tpm",name:"tpm",tooltip:"int (optional) - Tokens limit for this deployment: in tokens per minute (tpm). Find this information on your model/providers website",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"rpm",name:"rpm",tooltip:"int (optional) - Rate limit for this deployment: in requests per minute (rpm). Find this information on your model/providers website",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"max_retries",name:"max_retries",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"timeout",name:"timeout",tooltip:"int (optional) - Timeout in seconds for LLM requests (Defaults to 600 seconds)",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"stream_timeout",name:"stream_timeout",tooltip:"int (optional) - Timeout for stream requests (seconds)",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"input_cost_per_token",name:"input_cost_per_token",tooltip:"float (optional) - Input cost per token",children:(0,r.jsx)(eo.Z,{min:0,step:1e-4})}),(0,r.jsx)(ea.Z.Item,{label:"output_cost_per_token",name:"output_cost_per_token",tooltip:"float (optional) - Output cost per token",children:(0,r.jsx)(eo.Z,{min:0,step:1e-4})}),(0,r.jsx)(ea.Z.Item,{label:"model_id",name:"model_id",hidden:!0})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})})},{visible:T,onCancel:()=>{O(!1),R(null)},model:F,onSubmit:e7})]}),(0,r.jsxs)(eU.Z,{className:"h-full",children:[(0,r.jsx)(e1,{level:2,children:"Add new model"}),(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(ea.Z,{form:g,onFinish:()=>{g.validateFields().then(e=>{e5(e,o,g)}).catch(e=>{console.error("Validation failed:",e)})},labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"E.g. OpenAI, Azure OpenAI, Anthropic, Bedrock, etc.",labelCol:{span:10},labelAlign:"left",children:(0,r.jsx)(eb.Z,{value:E.toString(),children:A.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>{lt(e),I(e)},children:e},l))})}),(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Public Model Name",name:"model_name",tooltip:"Model name your users will pass in. Also used for load-balancing, LiteLLM will load balance between all models with this public name.",className:"mb-0",children:(0,r.jsx)(H.Z,{placeholder:"Vertex AI (Anthropic, Gemini, etc.)"===(s=E.toString())?"gemini-pro":"Anthropic"==s?"claude-3-opus":"Amazon Bedrock"==s?"claude-3-opus":"Gemini (Google AI Studio)"==s?"gemini-pro":"gpt-3.5-turbo"})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsx)(ee.Z,{className:"mb-3 mt-1",children:"Model name your users will pass in."})})]}),(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"LiteLLM Model Name(s)",name:"model",tooltip:"Actual model name used for making litellm.completion() call.",className:"mb-0",children:"Azure"===E?(0,r.jsx)(H.Z,{placeholder:"Enter model name"}):w.length>0?(0,r.jsx)(eK.Z,{value:w,children:w.map((e,l)=>(0,r.jsx)(eB.Z,{value:e,children:e},l))}):(0,r.jsx)(H.Z,{placeholder:"gpt-3.5-turbo-0125"})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsxs)(ee.Z,{className:"mb-3 mt-1",children:["Actual model name used for making ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/providers",target:"_blank",children:"litellm.completion() call"}),". We'll ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/proxy/reliability#step-1---set-deployments-on-config",target:"_blank",children:"loadbalance"})," models with the same 'public name'"]})})]}),"Amazon Bedrock"!=E&&"Vertex AI (Anthropic, Gemini, etc.)"!=E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Key",name:"api_key",children:(0,r.jsx)(H.Z,{placeholder:"sk-",type:"password"})}),"OpenAI"==E&&(0,r.jsx)(ea.Z.Item,{label:"Organization ID",name:"organization_id",children:(0,r.jsx)(H.Z,{placeholder:"[OPTIONAL] my-unique-org"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Project",name:"vertex_project",children:(0,r.jsx)(H.Z,{placeholder:"adroit-cadet-1234.."})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Location",name:"vertex_location",children:(0,r.jsx)(H.Z,{placeholder:"us-east-1"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Credentials",name:"vertex_credentials",className:"mb-0",children:(0,r.jsx)(e0.Z,{name:"file",accept:".json",beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;g.setFieldsValue({vertex_credentials:l})}},l.readAsText(e)}return!1},onChange(e){"uploading"!==e.file.status&&console.log(e.file,e.fileList),"done"===e.file.status?u.ZP.success("".concat(e.file.name," file uploaded successfully")):"error"===e.file.status&&u.ZP.error("".concat(e.file.name," file upload failed."))},children:(0,r.jsx)(ei.ZP,{icon:(0,r.jsx)(eQ.Z,{}),children:"Click to Upload"})})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsx)(ee.Z,{className:"mb-3 mt-1",children:"Give litellm a gcp service account(.json file), so it can make the relevant calls"})})]}),("Azure"==E||"OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)"==E)&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Base",name:"api_base",children:(0,r.jsx)(H.Z,{placeholder:"https://..."})}),"Azure"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Version",name:"api_version",children:(0,r.jsx)(H.Z,{placeholder:"2023-07-01-preview"})}),"Azure"==E&&(0,r.jsxs)(ea.Z.Item,{label:"Base Model",name:"base_model",children:[(0,r.jsx)(H.Z,{placeholder:"azure/gpt-3.5-turbo"}),(0,r.jsxs)(ee.Z,{children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from ",(0,r.jsx)(e2,{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",children:"here"})]})]}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Access Key ID",name:"aws_access_key_id",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Secret Access Key",name:"aws_secret_access_key",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Region Name",name:"aws_region_name",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:"us-east-1"})}),(0,r.jsx)(ea.Z.Item,{label:"LiteLLM Params",name:"litellm_extra_params",tooltip:"Optional litellm params used for making a litellm.completion() call.",className:"mb-0",children:(0,r.jsx)(eW.Z,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsxs)(ee.Z,{className:"mb-3 mt-1",children:["Pass JSON of litellm supported params ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",children:"litellm.completion() call"})]})})]})]}),(0,r.jsx)("div",{style:{textAlign:"center",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add Model"})}),(0,r.jsx)(eY.Z,{title:"Get help on our github",children:(0,r.jsx)(eT.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})})]})})]}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(ee.Z,{children:"`/health` will run a very small request through your models configured on litellm"}),(0,r.jsx)(J.Z,{onClick:ls,children:"Run `/health`"}),C&&(0,r.jsx)("pre",{children:JSON.stringify(C,null,2)})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(W.Z,{numItems:2,className:"mt-2",children:[(0,r.jsxs)(eG.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Time Range"}),(0,r.jsx)(eF.Z,{enableSelect:!0,value:eE,onValueChange:e=>{eI(e),la(U,e.from,e.to)}})]}),(0,r.jsxs)(eG.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Model Group"}),(0,r.jsx)(eb.Z,{className:"mb-4 mt-2",defaultValue:U||M[0],value:U||M[0],children:M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>la(e,eE.from,eE.to),children:e},l))})]})]}),(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsx)(eG.Z,{children:(0,r.jsxs)(ep.Z,{className:"mr-2 max-h-[400px] min-h-[400px]",children:[(0,r.jsx)(el.Z,{children:"Avg Latency per Token"}),(0,r.jsx)("p",{className:"text-gray-500 italic",children:" (seconds/token)"}),(0,r.jsx)(ee.Z,{className:"text-gray-500 italic mt-1 mb-1",children:"average Latency for successfull requests divided by the total tokens"}),Y&&es&&(0,r.jsx)(ez.Z,{title:"Model Latency",className:"h-72",data:Y,showLegend:!1,index:"date",categories:es,connectNulls:!0,customTooltip:e=>{var l,t;let{payload:s,active:a}=e;if(!a||!s)return null;let n=null===(t=s[0])||void 0===t?void 0:null===(l=t.payload)||void 0===l?void 0:l.date,o=s.sort((e,l)=>l.value-e.value);if(o.length>5){let e=o.length-5;(o=o.slice(0,5)).push({dataKey:"".concat(e," other deployments"),value:s.slice(5).reduce((e,l)=>e+l.value,0),color:"gray"})}return(0,r.jsxs)("div",{className:"w-150 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[n&&(0,r.jsxs)("p",{className:"text-tremor-content-emphasis mb-2",children:["Date: ",n]}),o.map((e,l)=>{let t=parseFloat(e.value.toFixed(5)),s=0===t&&e.value>0?"<0.00001":t.toFixed(5);return(0,r.jsxs)("div",{className:"flex justify-between",children:[(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)("div",{className:"w-2 h-2 mt-1 rounded-full bg-".concat(e.color,"-500")}),(0,r.jsx)("p",{className:"text-tremor-content",children:e.dataKey})]}),(0,r.jsx)("p",{className:"font-medium text-tremor-content-emphasis text-righ ml-2",children:s})]},l)})]})}})]})}),(0,r.jsx)(eG.Z,{children:(0,r.jsx)(ep.Z,{className:"ml-2 max-h-[400px] min-h-[400px] overflow-y-auto",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Deployment"}),(0,r.jsx)(e_.Z,{children:"Success Responses"}),(0,r.jsxs)(e_.Z,{children:["Slow Responses ",(0,r.jsx)("p",{children:"Success Responses taking 600+s"})]})]})}),(0,r.jsx)(ey.Z,{children:eN.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.api_base}),(0,r.jsx)(ef.Z,{children:e.total_count}),(0,r.jsx)(ef.Z,{children:e.slow_count})]},l))})]})})})]}),(0,r.jsxs)(ep.Z,{className:"mt-4",children:[(0,r.jsx)(el.Z,{children:"Exceptions per Model"}),(0,r.jsx)(eq.Z,{className:"h-72",data:ec,index:"model",categories:em,stack:!0,colors:["indigo-300","rose-200","#ffcc33"],yAxisWidth:30})]})]}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(ee.Z,{children:"Filter by Public Model Name"}),(0,r.jsx)(eb.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:U||M[0],value:U||M[0],onValueChange:e=>K(e),children:M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>K(e),children:e},l))})]}),(0,r.jsxs)(el.Z,{children:["Retry Policy for ",U]}),(0,r.jsx)(ee.Z,{className:"mb-6",children:"How many retries should be attempted based on the Exception"}),e8&&(0,r.jsx)("table",{children:(0,r.jsx)("tbody",{children:Object.entries(e8).map((e,l)=>{var t;let[s,a]=e,n=null==eC?void 0:null===(t=eC[U])||void 0===t?void 0:t[a];return null==n&&(n=eO),(0,r.jsxs)("tr",{className:"flex justify-between items-center mt-2",children:[(0,r.jsx)("td",{children:(0,r.jsx)(ee.Z,{children:s})}),(0,r.jsx)("td",{children:(0,r.jsx)(eo.Z,{className:"ml-5",value:n,min:0,step:1,onChange:e=>{eP(l=>{var t;let s=null!==(t=null==l?void 0:l[U])&&void 0!==t?t:{};return{...null!=l?l:{},[U]:{...s,[a]:e}}})}})})]},l)})})}),(0,r.jsx)(J.Z,{className:"mt-6 mr-8",onClick:le,children:"Save"})]})]})]})})};let{Option:e6}=es.default;var e7=e=>{let{userID:l,accessToken:t,teams:s}=e,[a]=ea.Z.useForm(),[o,i]=(0,n.useState)(!1),[c,d]=(0,n.useState)(null),[m,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{let e=await N(t,l,"any"),s=[];for(let l=0;l{i(!1),a.resetFields()},p=()=>{i(!1),d(null),a.resetFields()},j=async e=>{try{u.ZP.info("Making API Call"),i(!0),console.log("formValues in create user:",e);let s=await g(t,null,e);console.log("user create Response:",s),d(s.key),u.ZP.success("API user Created"),a.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the user:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>i(!0),children:"+ Invite User"}),(0,r.jsxs)(er.Z,{title:"Invite User",visible:o,width:800,footer:null,onOk:x,onCancel:p,children:[(0,r.jsx)(ee.Z,{className:"mb-1",children:"Invite a user to login to the Admin UI and create Keys"}),(0,r.jsx)(ee.Z,{className:"mb-6",children:(0,r.jsx)("b",{children:"Note: SSO Setup Required for this"})}),(0,r.jsxs)(ea.Z,{form:a,onFinish:j,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsx)(ea.Z.Item,{label:"User Email",name:"user_email",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"team_id",children:(0,r.jsx)(es.default,{placeholder:"Select Team ID",style:{width:"100%"},children:s?s.map(e=>(0,r.jsx)(e6,{value:e.team_id,children:e.team_alias},e.team_id)):(0,r.jsx)(e6,{value:null,children:"Default Team"},"default")})}),(0,r.jsx)(ea.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(en.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create User"})})]})]}),c&&(0,r.jsxs)(er.Z,{title:"User Created Successfully",visible:o,onOk:x,onCancel:p,footer:null,children:[(0,r.jsx)("p",{children:"User has been created to access your proxy. Please Ask them to Log In."}),(0,r.jsx)("br",{}),(0,r.jsx)("p",{children:(0,r.jsx)("b",{children:"Note: This Feature is only supported through SSO on the Admin UI"})})]})]})},e9=e=>{let{accessToken:l,token:t,keys:s,userRole:a,userID:o,teams:i,setKeys:c}=e,[d,m]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(0),[j,g]=n.useState(null),[y,f]=(0,n.useState)(null);return((0,n.useEffect)(()=>{if(!l||!t||!a||!o)return;let e=async()=>{try{let e=await Z(l,null,a,!0,x,25);console.log("user data response:",e),m(e)}catch(e){console.error("There was an error fetching the model data",e)}};l&&t&&a&&o&&e()},[l,t,a,o,x]),d&&l&&t&&a&&o)?(0,r.jsx)("div",{style:{width:"100%"},children:(0,r.jsxs)(W.Z,{className:"gap-2 p-2 h-[80vh] w-full mt-8",children:[(0,r.jsx)(e7,{userID:o,accessToken:l,teams:i}),(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[80vh] mb-4",children:[(0,r.jsx)("div",{className:"mb-4 mt-1",children:(0,r.jsx)(ee.Z,{children:"These are Users on LiteLLM that created API Keys. Automatically tracked by LiteLLM"})}),(0,r.jsx)(eM.Z,{children:(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(eg.Z,{className:"mt-5",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"User ID"}),(0,r.jsx)(e_.Z,{children:"User Email"}),(0,r.jsx)(e_.Z,{children:"User Models"}),(0,r.jsx)(e_.Z,{children:"User Spend ($ USD)"}),(0,r.jsx)(e_.Z,{children:"User Max Budget ($ USD)"}),(0,r.jsx)(e_.Z,{children:"User API Key Aliases"})]})}),(0,r.jsx)(ey.Z,{children:d.map(e=>{var l;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_id}),(0,r.jsx)(ef.Z,{children:e.user_email}),(0,r.jsx)(ef.Z,{children:e.models&&e.models.length>0?e.models:"All Models"}),(0,r.jsx)(ef.Z,{children:e.spend?null===(l=e.spend)||void 0===l?void 0:l.toFixed(2):0}),(0,r.jsx)(ef.Z,{children:e.max_budget?e.max_budget:"Unlimited"}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(W.Z,{numItems:2,children:e&&e.key_aliases&&e.key_aliases.filter(e=>null!==e).length>0?(0,r.jsx)(ex.Z,{size:"xs",color:"indigo",children:e.key_aliases.filter(e=>null!==e).join(", ")}):(0,r.jsx)(ex.Z,{size:"xs",color:"gray",children:"No Keys"})})})]},e.user_id)})})]})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("div",{className:"flex-1"}),(0,r.jsx)("div",{className:"flex-1 flex justify-between items-center"})]})})]})})]}),function(){if(!d)return null;let e=Math.ceil(d.length/25);return(0,r.jsxs)("div",{className:"flex justify-between items-center",children:[(0,r.jsxs)("div",{children:["Showing Page ",x+1," of ",e]}),(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-l focus:outline-none",disabled:0===x,onClick:()=>p(x-1),children:"← Prev"}),(0,r.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r focus:outline-none",onClick:()=>{p(x+1)},children:"Next →"})]})]})}()]})}):(0,r.jsx)("div",{children:"Loading..."})},le=e=>{let{teams:l,searchParams:t,accessToken:s,setTeams:a,userID:o,userRole:i}=e,[c]=ea.Z.useForm(),[d]=ea.Z.useForm(),{Title:m,Paragraph:h}=eT.default,[x,p]=(0,n.useState)(""),[j,g]=(0,n.useState)(!1),[y,Z]=(0,n.useState)(l?l[0]:null),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)([]),[E,I]=(0,n.useState)(!1),[C,P]=(0,n.useState)(null),[T,O]=(0,n.useState)({}),F=e=>{Z(e),g(!0)},R=async e=>{let t=e.team_id;if(console.log("handleEditSubmit:",e),null==s)return;let r=await U(s,e);l&&a(l.map(e=>e.team_id===t?r.data:e)),u.ZP.success("Team updated successfully"),g(!1),Z(null)},L=async e=>{P(e),I(!0)},D=async()=>{if(null!=C&&null!=l&&null!=s){try{await f(s,C);let e=l.filter(e=>e.team_id!==C);a(e)}catch(e){console.error("Error deleting the team:",e)}I(!1),P(null)}};(0,n.useEffect)(()=>{let e=async()=>{try{if(null===o||null===i||null===s||null===l)return;console.log("fetching team info:");let e={};for(let t=0;t<(null==l?void 0:l.length);t++){let a=l[t].team_id,r=await _(s,a);console.log("teamInfo response:",r),null!==r&&(e={...e,[a]:r})}O(e)}catch(e){console.error("Error fetching team info:",e)}};(async()=>{try{if(null===o||null===i)return;if(null!==s){let e=(await N(s,o,i)).data.map(e=>e.id);console.log("available_model_names:",e),A(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[s,o,i,l]);let B=async e=>{try{if(null!=s){var t;let r=null==e?void 0:e.team_alias;if((null!==(t=null==l?void 0:l.map(e=>e.team_alias))&&void 0!==t?t:[]).includes(r))throw Error("Team alias ".concat(r," already exists, please pick another alias"));u.ZP.info("Creating Team");let n=await M(s,e);null!==l?a([...l,n]):a([n]),console.log("response for team create call: ".concat(n)),u.ZP.success("Team created"),b(!1)}}catch(e){console.error("Error creating the team:",e),u.ZP.error("Error creating the team: "+e,20)}},z=async e=>{try{if(null!=s&&null!=l){u.ZP.info("Adding Member");let t={role:"user",user_email:e.user_email,user_id:e.user_id},r=await K(s,y.team_id,t);console.log("response for team create call: ".concat(r.data));let n=l.findIndex(e=>(console.log("team.team_id=".concat(e.team_id,"; response.data.team_id=").concat(r.data.team_id)),e.team_id===r.data.team_id));if(console.log("foundIndex: ".concat(n)),-1!==n){let e=[...l];e[n]=r.data,a(e),Z(r.data)}v(!1)}}catch(e){console.error("Error creating the team:",e)}};return console.log("received teams ".concat(JSON.stringify(l))),(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(m,{level:4,children:"All Teams"}),(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Team Name"}),(0,r.jsx)(e_.Z,{children:"Spend (USD)"}),(0,r.jsx)(e_.Z,{children:"Budget (USD)"}),(0,r.jsx)(e_.Z,{children:"Models"}),(0,r.jsx)(e_.Z,{children:"TPM / RPM Limits"}),(0,r.jsx)(e_.Z,{children:"Info"})]})}),(0,r.jsx)(ey.Z,{children:l&&l.length>0?l.map(e=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.team_alias}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.spend}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.max_budget?e.max_budget:"No limit"}),(0,r.jsx)(ef.Z,{style:{maxWidth:"8-x",whiteSpace:"pre-wrap",overflow:"hidden"},children:Array.isArray(e.models)?(0,r.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:(0,r.jsxs)(ee.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,r.jsx)("br",{}),"RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsxs)(ee.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].keys&&T[e.team_id].keys.length," ","Keys"]}),(0,r.jsxs)(ee.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].team_info&&T[e.team_id].team_info.members_with_roles&&T[e.team_id].team_info.members_with_roles.length," ","Members"]})]}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>F(e)}),(0,r.jsx)(ej.Z,{onClick:()=>L(e.team_id),icon:eh.Z,size:"sm"})]})]},e.team_id)):null})]}),E&&(0,r.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,r.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,r.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,r.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,r.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,r.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,r.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,r.jsx)("div",{className:"sm:flex sm:items-start",children:(0,r.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,r.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Team"}),(0,r.jsx)("div",{className:"mt-2",children:(0,r.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this team ?"})})]})})}),(0,r.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,r.jsx)(J.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,r.jsx)(J.Z,{onClick:()=>{I(!1),P(null)},children:"Cancel"})]})]})]})})]})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>b(!0),children:"+ Create New Team"}),(0,r.jsx)(er.Z,{title:"Create Team",visible:w,width:800,footer:null,onOk:()=>{b(!1),c.resetFields()},onCancel:()=>{b(!1),c.resetFields()},children:(0,r.jsxs)(ea.Z,{form:c,onFinish:B,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(es.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S.map(e=>(0,r.jsx)(es.default.Option,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create Team"})})]})})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(m,{level:4,children:"Team Members"}),(0,r.jsx)(h,{children:"If you belong to multiple teams, this setting controls which teams members you see."}),l&&l.length>0?(0,r.jsx)(eb.Z,{defaultValue:"0",children:l.map((e,l)=>(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>{Z(e)},children:e.team_alias},l))}):(0,r.jsxs)(h,{children:["No team created. ",(0,r.jsx)("b",{children:"Defaulting to personal account."})]})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Member Name"}),(0,r.jsx)(e_.Z,{children:"Role"})]})}),(0,r.jsx)(ey.Z,{children:y?y.members_with_roles.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,r.jsx)(ef.Z,{children:e.role})]},l)):null})]})}),y&&(0,r.jsx)(e=>{let{visible:l,onCancel:t,team:s,onSubmit:a}=e,[n]=ea.Z.useForm();return(0,r.jsx)(er.Z,{title:"Edit Team",visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{a({...e,team_id:s.team_id}),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:n,onFinish:R,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,r.jsx)(H.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(es.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S&&S.map(e=>(0,r.jsx)(es.default.Option,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"team_id",hidden:!0})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Edit Team"})})]})})},{visible:j,onCancel:()=>{g(!1),Z(null)},team:y,onSubmit:R})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(J.Z,{className:"mx-auto mb-5",onClick:()=>v(!0),children:"+ Add member"}),(0,r.jsx)(er.Z,{title:"Add member",visible:k,width:800,footer:null,onOk:()=>{v(!1),d.resetFields()},onCancel:()=>{v(!1),d.resetFields()},children:(0,r.jsxs)(ea.Z,{form:c,onFinish:z,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,r.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,r.jsx)(ea.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add member"})})]})})]})]})})},ll=t(18190),lt=e=>{let l,{searchParams:t,accessToken:s,showSSOBanner:a}=e,[o]=ea.Z.useForm(),[i]=ea.Z.useForm(),{Title:c,Paragraph:d}=eT.default,[m,h]=(0,n.useState)(""),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)(!1),[y,f]=(0,n.useState)(!1),[Z,_]=(0,n.useState)(!1),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1);try{l=window.location.origin}catch(e){l=""}l+="/fallback/login";let S=()=>{v(!1)},N=["proxy_admin","proxy_admin_viewer"];(0,n.useEffect)(()=>{(async()=>{if(null!=s){let e=[],l=await R(s,"proxy_admin_viewer");l.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy viewers: ".concat(l));let t=await R(s,"proxy_admin");t.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy admins: ".concat(t)),console.log("combinedList: ".concat(e)),p(e)}})()},[s]);let A=()=>{_(!1),i.resetFields()},E=()=>{_(!1),i.resetFields()},I=e=>(0,r.jsxs)(ea.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,r.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,r.jsx)(ea.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add member"})})]}),C=(e,l,t)=>(0,r.jsxs)(ea.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"User Role",name:"user_role",labelCol:{span:10},labelAlign:"left",children:(0,r.jsx)(eb.Z,{value:l,children:N.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,children:e},l))})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"user_id",hidden:!0,initialValue:t,valuePropName:"user_id",className:"mt-8",children:(0,r.jsx)(en.Z,{value:t,disabled:!0})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Update role"})})]}),P=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,null);console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),u.ZP.success("Refresh tab to see updated user role"),_(!1)}}catch(e){console.error("Error creating the key:",e)}},T=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,"proxy_admin_viewer");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),g(!1)}}catch(e){console.error("Error creating the key:",e)}},O=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call"),e.user_email,e.user_id;let l=await B(s,e,"proxy_admin");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),f(!1)}}catch(e){console.error("Error creating the key:",e)}},F=async e=>{null!=s&&V(s,{environment_variables:{PROXY_BASE_URL:e.proxy_base_url,GOOGLE_CLIENT_ID:e.google_client_id,GOOGLE_CLIENT_SECRET:e.google_client_secret}})};return console.log("admins: ".concat(null==x?void 0:x.length)),(0,r.jsxs)("div",{className:"w-full m-2 mt-2 p-8",children:[(0,r.jsx)(c,{level:4,children:"Admin Access "}),(0,r.jsxs)(d,{children:[a&&(0,r.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/ui#restrict-ui-access",children:"Requires SSO Setup"}),(0,r.jsx)("br",{}),(0,r.jsx)("b",{children:"Proxy Admin: "})," Can create keys, teams, users, add models, etc. ",(0,r.jsx)("br",{}),(0,r.jsx)("b",{children:"Proxy Admin Viewer: "}),"Can just view spend. They cannot create keys, teams or grant users access to new models."," "]}),(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-2 w-full",children:[(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsx)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Member Name"}),(0,r.jsx)(e_.Z,{children:"Role"})]})}),(0,r.jsx)(ey.Z,{children:x?x.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,r.jsx)(ef.Z,{children:e.user_role}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>_(!0)}),(0,r.jsx)(er.Z,{title:"Update role",visible:Z,width:800,footer:null,onOk:A,onCancel:E,children:C(P,e.user_role,e.user_id)})]})]},l)):null})]})})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("div",{className:"flex justify-start",children:[(0,r.jsx)(J.Z,{className:"mr-4 mb-5",onClick:()=>f(!0),children:"+ Add admin"}),(0,r.jsx)(er.Z,{title:"Add admin",visible:y,width:800,footer:null,onOk:()=>{f(!1),i.resetFields()},onCancel:()=>{f(!1),i.resetFields()},children:I(O)}),(0,r.jsx)(J.Z,{className:"mb-5",onClick:()=>g(!0),children:"+ Add viewer"}),(0,r.jsx)(er.Z,{title:"Add viewer",visible:j,width:800,footer:null,onOk:()=>{g(!1),i.resetFields()},onCancel:()=>{g(!1),i.resetFields()},children:I(T)})]})})]}),(0,r.jsxs)(W.Z,{children:[(0,r.jsx)(c,{level:4,children:"Add SSO"}),(0,r.jsxs)("div",{className:"flex justify-start mb-4",children:[(0,r.jsx)(J.Z,{onClick:()=>b(!0),children:"Add SSO"}),(0,r.jsx)(er.Z,{title:"Add SSO",visible:w,width:800,footer:null,onOk:()=>{b(!1),o.resetFields()},onCancel:()=>{b(!1),o.resetFields()},children:(0,r.jsxs)(ea.Z,{form:o,onFinish:e=>{O(e),F(e),b(!1),v(!0)},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"PROXY BASE URL",name:"proxy_base_url",rules:[{required:!0,message:"Please enter the proxy base url"}],children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"GOOGLE CLIENT ID",name:"google_client_id",rules:[{required:!0,message:"Please enter the google client id"}],children:(0,r.jsx)(en.Z.Password,{})}),(0,r.jsx)(ea.Z.Item,{label:"GOOGLE CLIENT SECRET",name:"google_client_secret",rules:[{required:!0,message:"Please enter the google client secret"}],children:(0,r.jsx)(en.Z.Password,{})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})}),(0,r.jsxs)(er.Z,{title:"SSO Setup Instructions",visible:k,width:800,footer:null,onOk:S,onCancel:()=>{v(!1)},children:[(0,r.jsx)("p",{children:"Follow these steps to complete the SSO setup:"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"1. DO NOT Exit this TAB"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"2. Open a new tab, visit your proxy base url"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"3. Confirm your SSO is configured correctly and you can login on the new Tab"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"4. If Step 3 is successful, you can close this tab"}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{onClick:S,children:"Done"})})]})]}),(0,r.jsxs)(ll.Z,{title:"Login without SSO",color:"teal",children:["If you need to login without sso, you can access ",(0,r.jsxs)("a",{href:l,target:"_blank",children:[(0,r.jsx)("b",{children:l})," "]})]})]})]})},ls=t(42556);let la=[{name:"slack",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"langfuse",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"openmeter",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}}];var lr=e=>{let{accessToken:l,userRole:t,userID:s}=e,[a,o]=(0,n.useState)(la),[i,c]=(0,n.useState)([]),[d,m]=(0,n.useState)(!1),[h]=ea.Z.useForm(),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)([]),[y,f]=(0,n.useState)(""),[Z,_]=(0,n.useState)({}),[w,b]=(0,n.useState)([]),k=e=>{w.includes(e)?b(w.filter(l=>l!==e)):b([...w,e])},v={llm_exceptions:"LLM Exceptions",llm_too_slow:"LLM Responses Too Slow",llm_requests_hanging:"LLM Requests Hanging",budget_alerts:"Budget Alerts (API Keys, Users)",db_exceptions:"Database Exceptions (Read/Write)",daily_reports:"Weekly/Monthly Spend Reports"};(0,n.useEffect)(()=>{l&&t&&s&&q(l,s,t).then(e=>{console.log("callbacks",e);let l=la;o(l=l.map(l=>{let t=e.callbacks.find(e=>e.name===l.name);return t?{...l,variables:{...l.variables,...t.variables}}:l}));let t=e.alerts;if(console.log("alerts_data",t),t&&t.length>0){let e=t[0];console.log("_alert_info",e);let l=e.variables.SLACK_WEBHOOK_URL;console.log("catch_all_webhook",l),b(e.active_alerts),f(l),_(e.alerts_to_webhook)}c(t)})},[l,t,s]);let S=e=>w&&w.includes(e),N=e=>{if(!l)return;let t=Object.fromEntries(Object.entries(e.variables).map(e=>{var l;let[t,s]=e;return[t,(null===(l=document.querySelector('input[name="'.concat(t,'"]')))||void 0===l?void 0:l.value)||s]}));console.log("updatedVariables",t),console.log("updateAlertTypes",j);let s={environment_variables:t,litellm_settings:{success_callback:[e.name]}};try{V(l,s)}catch(e){u.ZP.error("Failed to update callback: "+e,20)}u.ZP.success("Callback updated successfully")},A=()=>{l&&h.validateFields().then(e=>{if(console.log("Form values:",e),"langfuse"===e.callback){V(l,{environment_variables:{LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey,OPENMETER_API_KEY:null}};o(a?[...a,t]:[t])}else if("slack"===e.callback){console.log("values.slackWebhookUrl: ".concat(e.slackWebhookUrl)),V(l,{general_settings:{alerting:["slack"],alerting_threshold:300},environment_variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl}}),console.log("values.callback: ".concat(e.callback));let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null}};o(a?[...a,t]:[t])}else if("openmeter"==e.callback){console.log("values.openMeterApiKey: ".concat(e.openMeterApiKey)),V(l,{environment_variables:{OPENMETER_API_KEY:e.openMeterApiKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:e.openMeterAPIKey}};o(a?[...a,t]:[t])}m(!1),h.resetFields(),p(null)})};return l?(console.log("callbacks: ".concat(a)),(0,r.jsxs)("div",{className:"w-full mx-4",children:[(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,r.jsx)(ll.Z,{title:"[UI] Presidio PII + Guardrails Coming Soon. https://docs.litellm.ai/docs/proxy/pii_masking",color:"sky"}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{variant:"line",defaultValue:"1",children:[(0,r.jsx)(eR.Z,{value:"1",children:"Logging Callbacks"}),(0,r.jsx)(eR.Z,{value:"2",children:"Alerting"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Callback"}),(0,r.jsx)(e_.Z,{children:"Callback Env Vars"})]})}),(0,r.jsx)(ey.Z,{children:a.filter(e=>"slack"!==e.name).map((e,t)=>{var s;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ex.Z,{color:"emerald",children:e.name})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)("ul",{children:Object.entries(null!==(s=e.variables)&&void 0!==s?s:{}).filter(l=>{let[t,s]=l;return t.toLowerCase().includes(e.name)}).map(e=>{let[l,t]=e;return(0,r.jsxs)("li",{children:[(0,r.jsx)(ee.Z,{className:"mt-2",children:l}),"LANGFUSE_HOST"===l?(0,r.jsx)("p",{children:"default value=https://cloud.langfuse.com"}):(0,r.jsx)("div",{}),(0,r.jsx)(H.Z,{name:l,defaultValue:t,type:"password"})]},l)})}),(0,r.jsx)(J.Z,{className:"mt-2",onClick:()=>N(e),children:"Save Changes"}),(0,r.jsx)(J.Z,{onClick:()=>z(l,e.name),className:"mx-2",children:"Test Callback"})]})]},t)})})]})})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsxs)(ee.Z,{className:"my-2",children:["Alerts are only supported for Slack Webhook URLs. Get your webhook urls from ",(0,r.jsx)("a",{href:"https://api.slack.com/messaging/webhooks",target:"_blank",style:{color:"blue"},children:"here"})]}),(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{}),(0,r.jsx)(e_.Z,{}),(0,r.jsx)(e_.Z,{children:"Slack Webhook URL"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(v).map((e,l)=>{let[t,s]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ls.Z,{id:"switch",name:"switch",checked:S(t),onChange:()=>k(t)})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:s})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(H.Z,{name:t,type:"password",defaultValue:Z&&Z[t]?Z[t]:y})})]},l)})})]}),(0,r.jsx)(J.Z,{size:"xs",className:"mt-2",onClick:()=>{if(!l)return;let e={};Object.entries(v).forEach(l=>{let[t,s]=l,a=document.querySelector('input[name="'.concat(t,'"]'));console.log("key",t),console.log("webhookInput",a);let r=(null==a?void 0:a.value)||"";console.log("newWebhookValue",r),e[t]=r}),console.log("updatedAlertToWebhooks",e);let t={general_settings:{alert_to_webhook_url:e,alert_types:w}};console.log("payload",t);try{V(l,t)}catch(e){u.ZP.error("Failed to update alerts: "+e,20)}u.ZP.success("Alerts updated successfully")},children:"Save Changes"}),(0,r.jsx)(J.Z,{onClick:()=>z(l,"slack"),className:"mx-2",children:"Test Alerts"})]})})]})]})]}),(0,r.jsx)(er.Z,{title:"Add Callback",visible:d,onOk:A,width:800,onCancel:()=>{m(!1),h.resetFields(),p(null)},footer:null,children:(0,r.jsxs)(ea.Z,{form:h,layout:"vertical",onFinish:A,children:[(0,r.jsx)(ea.Z.Item,{label:"Callback",name:"callback",rules:[{required:!0,message:"Please select a callback"}],children:(0,r.jsxs)(es.default,{onChange:e=>{p(e)},children:[(0,r.jsx)(es.default.Option,{value:"langfuse",children:"langfuse"}),(0,r.jsx)(es.default.Option,{value:"openmeter",children:"openmeter"})]})}),"langfuse"===x&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"LANGFUSE_PUBLIC_KEY",name:"langfusePublicKey",rules:[{required:!0,message:"Please enter the public key"}],children:(0,r.jsx)(H.Z,{type:"password"})}),(0,r.jsx)(ea.Z.Item,{label:"LANGFUSE_PRIVATE_KEY",name:"langfusePrivateKey",rules:[{required:!0,message:"Please enter the private key"}],children:(0,r.jsx)(H.Z,{type:"password"})})]}),"openmeter"==x&&(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(ea.Z.Item,{label:"OPENMETER_API_KEY",name:"openMeterApiKey",rules:[{required:!0,message:"Please enter the openmeter api key"}],children:(0,r.jsx)(H.Z,{type:"password"})})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})})]})):null};let{Option:ln}=es.default;var lo=e=>{let{models:l,accessToken:t,routerSettings:s,setRouterSettings:a}=e,[o]=ea.Z.useForm(),[i,c]=(0,n.useState)(!1),[d,m]=(0,n.useState)("");return(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>c(!0),children:"+ Add Fallbacks"}),(0,r.jsx)(er.Z,{title:"Add Fallbacks",visible:i,width:800,footer:null,onOk:()=>{c(!1),o.resetFields()},onCancel:()=>{c(!1),o.resetFields()},children:(0,r.jsxs)(ea.Z,{form:o,onFinish:e=>{console.log(e);let{model_name:l,models:r}=e,n=[...s.fallbacks||[],{[l]:r}],i={...s,fallbacks:n};console.log(i);try{V(t,{router_settings:i}),a(i)}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully"),c(!1),o.resetFields()},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Public Model Name",name:"model_name",rules:[{required:!0,message:"Set the model to fallback for"}],help:"required",children:(0,r.jsx)(eb.Z,{defaultValue:d,children:l&&l.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>m(e),children:e},l))})}),(0,r.jsx)(ea.Z.Item,{label:"Fallback Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,r.jsx)(eK.Z,{value:l,children:l&&l.filter(e=>e!=d).map(e=>(0,r.jsx)(eB.Z,{value:e,children:e},e))})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add Fallbacks"})})]})})]})},li=t(12968);async function lc(e,l){console.log("isLocal:",!1);let t=window.location.origin,s=new li.ZP.OpenAI({apiKey:l,baseURL:t,dangerouslyAllowBrowser:!0});try{let l=await s.chat.completions.create({model:e,messages:[{role:"user",content:"Hi, this is a test message"}],mock_testing_fallbacks:!0});u.ZP.success((0,r.jsxs)("span",{children:["Test model=",(0,r.jsx)("strong",{children:e}),", received model=",(0,r.jsx)("strong",{children:l.model}),". See ",(0,r.jsx)("a",{href:"#",onClick:()=>window.open("https://docs.litellm.ai/docs/proxy/reliability","_blank"),style:{textDecoration:"underline",color:"blue"},children:"curl"})]}))}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}let ld={ttl:3600,lowest_latency_buffer:0},lm=e=>{let{selectedStrategy:l,strategyArgs:t,paramExplanation:s}=e;return(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{className:"text-sm font-medium text-tremor-content-strong dark:text-dark-tremor-content-strong",children:"Routing Strategy Specific Args"}),(0,r.jsx)(X.Z,{children:"latency-based-routing"==l?(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Setting"}),(0,r.jsx)(e_.Z,{children:"Value"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(t).map(e=>{let[l,t]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ee.Z,{children:l}),(0,r.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:s[l]})]}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(H.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]})}):(0,r.jsx)(ee.Z,{children:"No specific settings"})})]})};var lu=e=>{let{accessToken:l,userRole:t,userID:s,modelData:a}=e,[o,i]=(0,n.useState)({}),[c,d]=(0,n.useState)(!1),[m]=ea.Z.useForm(),[h,x]=(0,n.useState)(null),[p,j]=(0,n.useState)(null),[g,y]=(0,n.useState)(null),f={routing_strategy_args:"(dict) Arguments to pass to the routing strategy",routing_strategy:"(string) Routing strategy to use",allowed_fails:"(int) Number of times a deployment can fail before being added to cooldown",cooldown_time:"(int) time in seconds to cooldown a deployment after failure",num_retries:"(int) Number of retries for failed requests. Defaults to 0.",timeout:"(float) Timeout for requests. Defaults to None.",retry_after:"(int) Minimum time to wait before retrying a failed request",ttl:"(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};(0,n.useEffect)(()=>{l&&t&&s&&q(l,s,t).then(e=>{console.log("callbacks",e),i(e.router_settings)})},[l,t,s]);let Z=async e=>{if(l){console.log("received key: ".concat(e)),console.log("routerSettings['fallbacks']: ".concat(o.fallbacks)),o.fallbacks.map(l=>(e in l&&delete l[e],l));try{await V(l,{router_settings:o}),i({...o}),j(o.routing_strategy),u.ZP.success("Router settings updated successfully")}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}}},_=e=>{if(!l)return;console.log("router_settings",e);let t=Object.fromEntries(Object.entries(e).map(e=>{let[l,t]=e;if("routing_strategy_args"!==l&&"routing_strategy"!==l){var s;return[l,(null===(s=document.querySelector('input[name="'.concat(l,'"]')))||void 0===s?void 0:s.value)||t]}if("routing_strategy"==l)return[l,p];if("routing_strategy_args"==l&&"latency-based-routing"==p){let e={},l=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]');return(null==l?void 0:l.value)&&(e.lowest_latency_buffer=Number(l.value)),(null==t?void 0:t.value)&&(e.ttl=Number(t.value)),console.log("setRoutingStrategyArgs: ".concat(e)),["routing_strategy_args",e]}return null}).filter(e=>null!=e));console.log("updatedVariables",t);try{V(l,{router_settings:t})}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully")};return l?(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsxs)(eM.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(eL.Z,{variant:"line",defaultValue:"1",children:[(0,r.jsx)(eR.Z,{value:"1",children:"General Settings"}),(0,r.jsx)(eR.Z,{value:"2",children:"Fallbacks"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,r.jsx)(el.Z,{children:"Router Settings"}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Setting"}),(0,r.jsx)(e_.Z,{children:"Value"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(o).filter(e=>{let[l,t]=e;return"fallbacks"!=l&&"context_window_fallbacks"!=l&&"routing_strategy_args"!=l}).map(e=>{let[l,t]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ee.Z,{children:l}),(0,r.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:f[l]})]}),(0,r.jsx)(ef.Z,{children:"routing_strategy"==l?(0,r.jsxs)(eb.Z,{defaultValue:t,className:"w-full max-w-md",onValueChange:j,children:[(0,r.jsx)(ek.Z,{value:"usage-based-routing",children:"usage-based-routing"}),(0,r.jsx)(ek.Z,{value:"latency-based-routing",children:"latency-based-routing"}),(0,r.jsx)(ek.Z,{value:"simple-shuffle",children:"simple-shuffle"})]}):(0,r.jsx)(H.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]}),(0,r.jsx)(lm,{selectedStrategy:p,strategyArgs:o&&o.routing_strategy_args&&Object.keys(o.routing_strategy_args).length>0?o.routing_strategy_args:ld,paramExplanation:f})]}),(0,r.jsx)(Y.Z,{children:(0,r.jsx)(J.Z,{className:"mt-2",onClick:()=>_(o),children:"Save Changes"})})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Model Name"}),(0,r.jsx)(e_.Z,{children:"Fallbacks"})]})}),(0,r.jsx)(ey.Z,{children:o.fallbacks&&o.fallbacks.map((e,t)=>Object.entries(e).map(e=>{let[s,a]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:s}),(0,r.jsx)(ef.Z,{children:Array.isArray(a)?a.join(", "):a}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(J.Z,{onClick:()=>lc(s,l),children:"Test Fallback"})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ej.Z,{icon:eh.Z,size:"sm",onClick:()=>Z(s)})})]},t.toString()+s)}))})]}),(0,r.jsx)(lo,{models:(null==a?void 0:a.data)?a.data.map(e=>e.model_name):[],accessToken:l,routerSettings:o,setRouterSettings:i})]})]})]})}):null},lh=t(67951),lx=e=>{let{}=e;return(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(W.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,r.jsxs)("div",{className:"mb-5",children:[(0,r.jsx)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:"OpenAI Compatible Proxy: API Reference"}),(0,r.jsx)(ee.Z,{className:"mt-2 mb-2",children:"LiteLLM is OpenAI Compatible. This means your API Key works with the OpenAI SDK. Just replace the base_url to point to your litellm proxy. Example Below "}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{children:[(0,r.jsx)(eR.Z,{children:"OpenAI Python SDK"}),(0,r.jsx)(eR.Z,{children:"LlamaIndex"}),(0,r.jsx)(eR.Z,{children:"Langchain Py"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # LiteLLM Proxy is OpenAI compatible, Read More: https://docs.litellm.ai/docs/proxy/user_keys\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to send to the proxy\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ]\n)\n\nprint(response)\n '})}),(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:4000",\n model = "gpt-3.5-turbo",\n temperature=0.1\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})]})})})};async function lp(e,l,t,s){console.log("isLocal:",!1);let a=window.location.origin,r=new li.ZP.OpenAI({apiKey:s,baseURL:a,dangerouslyAllowBrowser:!0});try{for await(let s of(await r.chat.completions.create({model:t,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&l(s.choices[0].delta.content)}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}var lj=e=>{let{accessToken:l,token:t,userRole:s,userID:a}=e,[o,i]=(0,n.useState)(""),[c,d]=(0,n.useState)(""),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)(void 0),[p,j]=(0,n.useState)([]);(0,n.useEffect)(()=>{l&&t&&s&&a&&(async()=>{try{let e=await N(l,a,s);if(console.log("model_info:",e),(null==e?void 0:e.data.length)>0){let l=e.data.map(e=>({value:e.id,label:e.id}));console.log(l),j(l),x(e.data[0].id)}}catch(e){console.error("Error fetching model info:",e)}})()},[l,a,s]);let g=(e,l)=>{u(t=>{let s=t[t.length-1];return s&&s.role===e?[...t.slice(0,t.length-1),{role:e,content:s.content+l}]:[...t,{role:e,content:l}]})},y=async()=>{if(""!==c.trim()&&o&&t&&s&&a){u(e=>[...e,{role:"user",content:c}]);try{h&&await lp(c,e=>g("assistant",e),h,o)}catch(e){console.error("Error fetching model response",e),g("assistant","Error fetching model response")}d("")}};if(s&&"Admin Viewer"==s){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to test models"})]})}return(0,r.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,r.jsx)(W.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eM.Z,{children:[(0,r.jsx)(eL.Z,{children:(0,r.jsx)(eR.Z,{children:"Chat"})}),(0,r.jsx)(eD.Z,{children:(0,r.jsxs)(eU.Z,{children:[(0,r.jsx)("div",{className:"sm:max-w-2xl",children:(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"API Key"}),(0,r.jsx)(H.Z,{placeholder:"Type API Key here",type:"password",onValueChange:i,value:o})]}),(0,r.jsxs)(Y.Z,{className:"mx-2",children:[(0,r.jsx)(ee.Z,{children:"Select Model:"}),(0,r.jsx)(es.default,{placeholder:"Select a Model",onChange:e=>{console.log("selected ".concat(e)),x(e)},options:p,style:{width:"200px"}})]})]})}),(0,r.jsxs)(eg.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsx)(ew.Z,{children:(0,r.jsx)(ef.Z,{})})}),(0,r.jsx)(ey.Z,{children:m.map((e,l)=>(0,r.jsx)(ew.Z,{children:(0,r.jsx)(ef.Z,{children:"".concat(e.role,": ").concat(e.content)})},l))})]}),(0,r.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)(H.Z,{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"Type your message..."}),(0,r.jsx)(J.Z,{onClick:y,className:"ml-2",children:"Send"})]})})]})})]})})})})},lg=t(33509),ly=t(95781);let{Sider:lf}=lg.default;var lZ=e=>{let{setPage:l,userRole:t,defaultSelectedKey:s}=e;return"Admin Viewer"==t?(0,r.jsx)(lg.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,r.jsx)(lf,{width:120,children:(0,r.jsxs)(ly.Z,{mode:"inline",defaultSelectedKeys:s||["4"],style:{height:"100%",borderRight:0},children:[(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api-keys"),children:"API Keys"},"4"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("models"),children:"Models"},"2"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("llm-playground"),children:"Chat UI"},"3"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("usage"),children:"Usage"},"1")]})})}):(0,r.jsx)(lg.default,{style:{minHeight:"100vh",maxWidth:"145px"},children:(0,r.jsx)(lf,{width:145,children:(0,r.jsxs)(ly.Z,{mode:"inline",defaultSelectedKeys:s||["1"],style:{height:"100%",borderRight:0},children:[(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api-keys"),children:(0,r.jsx)(ee.Z,{children:"API Keys"})},"1"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("llm-playground"),children:(0,r.jsx)(ee.Z,{children:"Test Key"})},"3"),"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("models"),children:(0,r.jsx)(ee.Z,{children:"Models"})},"2"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("usage"),children:(0,r.jsx)(ee.Z,{children:"Usage"})},"4"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("teams"),children:(0,r.jsx)(ee.Z,{children:"Teams"})},"6"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("users"),children:(0,r.jsx)(ee.Z,{children:"Users"})},"5"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("settings"),children:(0,r.jsx)(ee.Z,{children:"Logging & Alerts"})},"8"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("general-settings"),children:(0,r.jsx)(ee.Z,{children:"Router Settings"})},"9"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("admin-panel"),children:(0,r.jsx)(ee.Z,{children:"Admin"})},"7"):null,(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api_ref"),children:(0,r.jsx)(ee.Z,{children:"API Reference"})},"11")]})})})},l_=t(67989),lw=e=>{let{accessToken:l,token:t,userRole:s,userID:a,keys:o}=e,i=new Date,[c,d]=(0,n.useState)([]),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)([]),[p,j]=(0,n.useState)([]),[g,y]=(0,n.useState)([]),[f,Z]=(0,n.useState)([]),[_,w]=(0,n.useState)([]),[b,k]=(0,n.useState)([]),[v,S]=(0,n.useState)(""),[N,R]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),M=new Date(i.getFullYear(),i.getMonth(),1),L=new Date(i.getFullYear(),i.getMonth()+1,0),U=z(M),D=z(L);console.log("keys in usage",o);let K=async(e,t,s)=>{if(!e||!t||!l)return;console.log("uiSelectedKey",s);let a=await T(l,s,e.toISOString(),t.toISOString());console.log("End user data updated successfully",a),j(a)},B=async(e,t)=>{e&&t&&l&&(Z((await E(l,e.toISOString(),t.toISOString())).spend_per_tag),console.log("Tag spend data updated successfully"))};function z(e){let l=e.getFullYear(),t=e.getMonth()+1,s=e.getDate();return"".concat(l,"-").concat(t<10?"0"+t:t,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(U)),console.log("End date is ".concat(D)),(0,n.useEffect)(()=>{l&&t&&s&&a&&(async()=>{try{if(console.log("user role: ".concat(s)),"Admin"==s||"Admin Viewer"==s){var e,r;let t=await C(l);d(t);let s=(await P(l)).map(e=>({key:(e.key_name||e.key_alias||e.api_key).substring(0,10),spend:e.total_spend}));u(s);let a=(await O(l)).map(e=>({key:e.model,spend:e.total_spend}));x(a);let n=await A(l);console.log("teamSpend",n),y(n.daily_spend),w(n.teams);let o=n.total_spend_per_team;o=o.map(e=>(e.name=e.team_id||"",e.value=e.total_spend||0,e)),k(o);let i=await E(l,null===(e=N.from)||void 0===e?void 0:e.toISOString(),null===(r=N.to)||void 0===r?void 0:r.toISOString());Z(i.spend_per_tag);let c=await T(l,null,void 0,void 0);j(c),console.log("spend/user result",c)}else"App Owner"==s&&await I(l,t,s,a,U,D).then(async e=>{if(console.log("result from spend logs call",e),"daily_spend"in e){let l=e.daily_spend;console.log("daily spend",l),d(l);let t=e.top_api_keys;u(t)}else{let t=(await F(l,function(e){let l=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[t,s]=e;"spend"!==t&&"startTime"!==t&&"models"!==t&&"users"!==t&&l.push({key:t,spend:s})})}),l.sort((e,l)=>Number(l.spend)-Number(e.spend));let t=l.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(t[0]))),t}(e))).info.map(e=>({key:(e.key_name||e.key_alias).substring(0,10),spend:e.spend}));u(t),d(e)}})}catch(e){console.error("There was an error fetching the data",e)}})()},[l,t,s,a,U,D]),(0,r.jsxs)("div",{style:{width:"100%"},className:"p-8",children:[(0,r.jsx)(eE,{userID:a,userRole:s,accessToken:l,userSpend:null,selectedTeam:null}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{className:"mt-2",children:[(0,r.jsx)(eR.Z,{children:"All Up"}),(0,r.jsx)(eR.Z,{children:"Team Based Usage"}),(0,r.jsx)(eR.Z,{children:"End User Usage"}),(0,r.jsx)(eR.Z,{children:"Tag Based Usage"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,r.jsx)(Y.Z,{numColSpan:2,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Monthly Spend"}),(0,r.jsx)(eq.Z,{data:c,index:"date",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5})]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Top API Keys"}),(0,r.jsx)(eq.Z,{className:"mt-4 h-40",data:m,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Top Models"}),(0,r.jsx)(eq.Z,{className:"mt-4 h-40",data:h,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,r.jsx)(Y.Z,{numColSpan:1})]})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,r.jsxs)(Y.Z,{numColSpan:2,children:[(0,r.jsxs)(ep.Z,{className:"mb-2",children:[(0,r.jsx)(el.Z,{children:"Total Spend Per Team"}),(0,r.jsx)(l_.Z,{data:b})]}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Daily Spend Per Team"}),(0,r.jsx)(eq.Z,{className:"h-72",data:g,showLegend:!0,index:"date",categories:_,yAxisWidth:80,colors:["blue","green","yellow","red","purple"],stack:!0})]})]}),(0,r.jsx)(Y.Z,{numColSpan:2})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)("p",{className:"mb-2 text-gray-500 italic text-[12px]",children:["End-Users of your LLM API calls. Tracked when a `user` param is passed in your LLM calls ",(0,r.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/users",target:"_blank",children:"docs here"})]}),(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Time Range"}),(0,r.jsx)(eF.Z,{enableSelect:!0,value:N,onValueChange:e=>{R(e),K(e.from,e.to,null)}})]}),(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Key"}),(0,r.jsxs)(eb.Z,{defaultValue:"all-keys",children:[(0,r.jsx)(ek.Z,{value:"all-keys",onClick:()=>{K(N.from,N.to,null)},children:"All Keys"},"all-keys"),null==o?void 0:o.map((e,l)=>e&&null!==e.key_alias&&e.key_alias.length>0?(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>{K(N.from,N.to,e.token)},children:e.key_alias},l):null)]})]})]}),(0,r.jsx)(ep.Z,{className:"mt-4",children:(0,r.jsxs)(eg.Z,{className:"max-h-[70vh] min-h-[500px]",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"End User"}),(0,r.jsx)(e_.Z,{children:"Spend"}),(0,r.jsx)(e_.Z,{children:"Total Events"})]})}),(0,r.jsx)(ey.Z,{children:null==p?void 0:p.map((e,l)=>{var t;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.end_user}),(0,r.jsx)(ef.Z,{children:null===(t=e.total_spend)||void 0===t?void 0:t.toFixed(4)}),(0,r.jsx)(ef.Z,{children:e.total_count})]},l)})})]})})]}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full mb-4",children:[(0,r.jsxs)(Y.Z,{numColSpan:2,children:[(0,r.jsx)(eF.Z,{className:"mb-4",enableSelect:!0,value:N,onValueChange:e=>{R(e),B(e.from,e.to)}}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Spend Per Tag"}),(0,r.jsxs)(ee.Z,{children:["Get Started Tracking cost per tag ",(0,r.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags",target:"_blank",children:"here"})]}),(0,r.jsx)(eq.Z,{className:"h-72",data:f,index:"name",categories:["spend"],colors:["blue"]})]})]}),(0,r.jsx)(Y.Z,{numColSpan:2})]})})]})]})]})},lb=()=>{let{Title:e,Paragraph:l}=eT.default,[t,s]=(0,n.useState)(""),[a,i]=(0,n.useState)(null),[c,d]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(!0),j=(0,o.useSearchParams)(),[g,y]=(0,n.useState)({data:[]}),f=j.get("userID"),Z=j.get("token"),[_,w]=(0,n.useState)("api-keys"),[b,k]=(0,n.useState)(null);return(0,n.useEffect)(()=>{if(Z){let e=(0,eP.o)(Z);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),k(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e.toLowerCase())),console.log("Received user role length: ".concat(e.toLowerCase().length)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),s(l),"Admin Viewer"==l&&w("usage")}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e)),e.login_method?p("username_password"==e.login_method):console.log("User Email is not set ".concat(e))}}},[Z]),(0,r.jsx)(n.Suspense,{fallback:(0,r.jsx)("div",{children:"Loading..."}),children:(0,r.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,r.jsx)(m,{userID:f,userRole:t,userEmail:a,showSSOBanner:x}),(0,r.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,r.jsx)("div",{className:"mt-8",children:(0,r.jsx)(lZ,{setPage:w,userRole:t,defaultSelectedKey:null})}),"api-keys"==_?(0,r.jsx)(eO,{userID:f,userRole:t,teams:c,keys:u,setUserRole:s,userEmail:a,setUserEmail:i,setTeams:d,setKeys:h}):"models"==_?(0,r.jsx)(e3,{userID:f,userRole:t,token:Z,accessToken:b,modelData:g,setModelData:y}):"llm-playground"==_?(0,r.jsx)(lj,{userID:f,userRole:t,token:Z,accessToken:b}):"users"==_?(0,r.jsx)(e9,{userID:f,userRole:t,token:Z,keys:u,teams:c,accessToken:b,setKeys:h}):"teams"==_?(0,r.jsx)(le,{teams:c,setTeams:d,searchParams:j,accessToken:b,userID:f,userRole:t}):"admin-panel"==_?(0,r.jsx)(lt,{setTeams:d,searchParams:j,accessToken:b,showSSOBanner:x}):"api_ref"==_?(0,r.jsx)(lx,{}):"settings"==_?(0,r.jsx)(lr,{userID:f,userRole:t,accessToken:b}):"general-settings"==_?(0,r.jsx)(lu,{userID:f,userRole:t,accessToken:b,modelData:g}):(0,r.jsx)(lw,{userID:f,userRole:t,token:Z,accessToken:b,keys:u})]})]})})}}},function(e){e.O(0,[936,884,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-c35c14c9afd091ec.js b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-c35c14c9afd091ec.js new file mode 100644 index 0000000000..e8b5c33a1c --- /dev/null +++ b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-c35c14c9afd091ec.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,l,t){Promise.resolve().then(t.bind(t,4858))},4858:function(e,l,t){"use strict";t.r(l),t.d(l,{default:function(){return lS}});var s,r,a=t(3827),n=t(64090),o=t(47907),i=t(8792),c=t(40491),d=t(65270),m=e=>{let{userID:l,userRole:t,userEmail:s,showSSOBanner:r}=e;console.log("User ID:",l),console.log("userEmail:",s),console.log("showSSOBanner:",r);let n=[{key:"1",label:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["Role: ",t]}),(0,a.jsxs)("p",{children:["ID: ",l]})]})}];return(0,a.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,a.jsx)("div",{className:"text-left my-2 absolute top-0 left-0",children:(0,a.jsx)("div",{className:"flex flex-col items-center",children:(0,a.jsx)(i.default,{href:"/",children:(0,a.jsx)("button",{className:"text-gray-800 rounded text-center",children:(0,a.jsx)("img",{src:"/get_image",width:160,height:160,alt:"LiteLLM Brand",className:"mr-2"})})})})}),(0,a.jsxs)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2",children:[r?(0,a.jsx)("div",{style:{padding:"6px",borderRadius:"8px"},children:(0,a.jsx)("a",{href:"https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat",target:"_blank",style:{fontSize:"14px",textDecoration:"underline"},children:"Request hosted proxy"})}):null,(0,a.jsx)("div",{style:{border:"1px solid #391085",padding:"6px",borderRadius:"8px"},children:(0,a.jsx)(c.Z,{menu:{items:n},children:(0,a.jsx)(d.Z,{children:s})})})]})]})},u=t(80588);let h=async()=>{try{let e=await fetch("https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"),l=await e.json();return console.log("received data: ".concat(l)),l}catch(e){throw console.error("Failed to get model cost map:",e),e}},x=async(e,l)=>{try{let t=await fetch("/model/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model created successfully. Wait 60s and refresh on 'All Models' page"),s}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,l)=>{console.log("model_id in model delete call: ".concat(l));try{let t=await fetch("/model/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({id:l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model deleted successfully. Restart server to see this."),s}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/user/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},f=async(e,l)=>{try{console.log("in keyDeleteCall:",l);let t=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},y=async(e,l)=>{try{console.log("in teamDeleteCall:",l);let t=await fetch("/team/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_ids:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete team: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to delete key:",e),e}},Z=async function(e,l,t){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],r=arguments.length>4?arguments[4]:void 0,a=arguments.length>5?arguments[5]:void 0;try{let n="/user/info";"App Owner"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),"App User"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),console.log("in userInfoCall viewAll=",s),s&&a&&null!=r&&void 0!=r&&(n="".concat(n,"?view_all=true&page=").concat(r,"&page_size=").concat(a));let o=await fetch(n,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let i=await o.json();return console.log("API Response:",i),i}catch(e){throw console.error("Failed to create key:",e),e}},_=async(e,l)=>{try{let t="/team/info";l&&(t="".concat(t,"?team_id=").concat(l)),console.log("in teamInfoCall");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},w=async e=>{try{let l=await fetch("/global/spend",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},b=async(e,l,t)=>{try{let l=await fetch("/v2/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log("modelInfoCall:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},k=async(e,l,t,s,r,a)=>{try{let l="/model/metrics";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},v=async(e,l,t,s,r,a)=>{try{let l="/model/metrics/slow_responses";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},S=async(e,l,t,s,r,a)=>{try{let l="/model/metrics/exceptions";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},N=async(e,l,t)=>{try{let l=await fetch("/models",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},A=async e=>{try{let l="/global/spend/teams";console.log("in teamSpendLogsCall:",l);let t=await fetch("".concat(l),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},E=async(e,l,t)=>{try{let s="/global/spend/tags";l&&t&&(s="".concat(s,"?start_date=").concat(l,"&end_date=").concat(t)),console.log("in tagsSpendLogsCall:",s);let r=await fetch("".concat(s),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let a=await r.json();return console.log(a),a}catch(e){throw console.error("Failed to create key:",e),e}},I=async(e,l,t,s,r,a)=>{try{console.log("user role in spend logs call: ".concat(t));let l="/spend/logs";l="App Owner"==t?"".concat(l,"?user_id=").concat(s,"&start_date=").concat(r,"&end_date=").concat(a):"".concat(l,"?start_date=").concat(r,"&end_date=").concat(a);let n=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},C=async e=>{try{let l=await fetch("/global/spend/logs",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},P=async e=>{try{let l=await fetch("/global/spend/keys?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},T=async(e,l,t,s)=>{try{let r="";r=l?JSON.stringify({api_key:l,startTime:t,endTime:s}):JSON.stringify({startTime:t,endTime:s});let a={method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}};a.body=r;let n=await fetch("/global/spend/end_users",a);if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},O=async e=>{try{let l=await fetch("/global/spend/models?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},F=async(e,l)=>{try{let t=await fetch("/v2/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},R=async(e,l)=>{try{let t="/user/get_users?role=".concat(l);console.log("in userGetAllUsersCall:",t);let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let r=await s.json();return console.log(r),r}catch(e){throw console.error("Failed to get requested models:",e),e}},M=async(e,l)=>{try{console.log("Form Values in teamCreateCall:",l);let t=await fetch("/team/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},L=async(e,l)=>{try{console.log("Form Values in keyUpdateCall:",l);let t=await fetch("/key/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update key Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},U=async(e,l)=>{try{console.log("Form Values in teamUpateCall:",l);let t=await fetch("/team/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update team: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update Team Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},D=async(e,l)=>{try{console.log("Form Values in modelUpateCall:",l);let t=await fetch("/model/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update model: "+e,10),console.error("Error update from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update model Response:",s),s}catch(e){throw console.error("Failed to update model:",e),e}},K=async(e,l,t)=>{try{console.log("Form Values in teamMemberAddCall:",t);let s=await fetch("/team/member_add",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_id:l,member:t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},B=async(e,l,t)=>{try{console.log("Form Values in userUpdateUserCall:",l);let s={...l};null!==t&&(s.user_role=t),s=JSON.stringify(s);let r=await fetch("/user/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:s});if(!r.ok){let e=await r.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await r.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},z=async(e,l)=>{try{let t="/health/services?service=".concat(l);console.log("Checking Slack Budget Alerts service health");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed ".concat(l," service health check ")+e),Error(e)}let r=await s.json();return u.ZP.success("Test request to ".concat(l," made - check logs/alerts on ").concat(l," to verify")),r}catch(e){throw console.error("Failed to perform health check:",e),e}},V=async(e,l,t)=>{try{let l=await fetch("/get/config/callbacks",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},q=async e=>{try{let l=await fetch("/config/list?config_type=general_settings",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},G=async(e,l,t)=>{try{let s=await fetch("/config/field/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({field_name:l,field_value:t,config_type:"general_settings"})});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await s.json();return u.ZP.success("Successfully updated value!"),r}catch(e){throw console.error("Failed to set callbacks:",e),e}},Y=async(e,l)=>{try{let t=await fetch("/config/field/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({field_name:l,config_type:"general_settings"})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return u.ZP.success("Field reset on proxy"),s}catch(e){throw console.error("Failed to get callbacks:",e),e}},W=async(e,l)=>{try{let t=await fetch("/config/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to set callbacks:",e),e}},J=async e=>{try{let l=await fetch("/health",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to call /health:",e),e}};var H=t(10384),$=t(46453),X=t(16450),Q=t(52273),ee=t(26780),el=t(15595),et=t(6698),es=t(71801),er=t(42440),ea=t(42308),en=t(50670),eo=t(81583),ei=t(99129),ec=t(44839),ed=t(88707),em=t(1861);let{Option:eu}=en.default;var eh=e=>{let{userID:l,team:t,userRole:s,accessToken:r,data:o,setData:i}=e,[c]=eo.Z.useForm(),[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(null),[p,g]=(0,n.useState)(null),[f,y]=(0,n.useState)([]),[Z,_]=(0,n.useState)([]),w=()=>{m(!1),c.resetFields()},b=()=>{m(!1),x(null),c.resetFields()};(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===s)return;if(null!==r){let e=(await N(r,l,s)).data.map(e=>e.id);console.log("available_model_names:",e),y(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[r,l,s]);let k=async e=>{try{var t,s,a;let n=null!==(t=null==e?void 0:e.key_alias)&&void 0!==t?t:"",d=null!==(s=null==e?void 0:e.team_id)&&void 0!==s?s:null;if((null!==(a=null==o?void 0:o.filter(e=>e.team_id===d).map(e=>e.key_alias))&&void 0!==a?a:[]).includes(n))throw Error("Key alias ".concat(n," already exists for team with ID ").concat(d,", please provide another key alias"));u.ZP.info("Making API Call"),m(!0);let h=await j(r,l,e);console.log("key create Response:",h),i(e=>e?[...e,h]:[h]),x(h.key),g(h.soft_budget),u.ZP.success("API Key Created"),c.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the key:",e),u.ZP.error("Error creating the key: ".concat(e),20)}};return(0,n.useEffect)(()=>{_(t&&t.models.length>0?t.models.includes("all-proxy-models")?f:t.models:f)},[t,f]),(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>m(!0),children:"+ Create New Key"}),(0,a.jsx)(ei.Z,{title:"Create Key",visible:d,width:800,footer:null,onOk:w,onCancel:b,children:(0,a.jsxs)(eo.Z,{form:c,onFinish:k,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"team_id",hidden:!0,initialValue:t?t.team_id:null,valuePropName:"team_id",className:"mt-8",children:(0,a.jsx)(ec.Z,{value:t?t.team_alias:"",disabled:!0})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},onChange:e=>{e.includes("all-team-models")&&c.setFieldsValue({models:["all-team-models"]})},children:[(0,a.jsx)(eu,{value:"all-team-models",children:"All Team Models"},"all-team-models"),Z.map(e=>(0,a.jsx)(eu,{value:e,children:e},e))]})}),(0,a.jsxs)(ee.Z,{className:"mt-20 mb-8",children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)("b",{children:"Optional Settings"})}),(0,a.jsxs)(el.Z,{children:[(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat(t.max_budget))}}],children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Reset Budget",name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,a.jsxs)(en.default,{defaultValue:null,placeholder:"n/a",children:[(0,a.jsx)(en.default.Option,{value:"24h",children:"daily"}),(0,a.jsx)(en.default.Option,{value:"30d",children:"monthly"})]})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Tokens per minute Limit (TPM)",name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Requests per minute Limit (RPM)",name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Expire Key (eg: 30s, 30h, 30d)",name:"duration",className:"mt-8",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Metadata",name:"metadata",children:(0,a.jsx)(ec.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]})]})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create Key"})})]})}),h&&(0,a.jsx)(ei.Z,{visible:d,onOk:w,onCancel:b,footer:null,children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 w-full",children:[(0,a.jsx)(er.Z,{children:"Save your Key"}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,a.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:null!=h?(0,a.jsxs)("div",{children:[(0,a.jsx)(es.Z,{className:"mt-3",children:"API Key:"}),(0,a.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,a.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:h})}),(0,a.jsx)(ea.CopyToClipboard,{text:h,onCopy:()=>{u.ZP.success("API Key copied to clipboard")},children:(0,a.jsx)(X.Z,{className:"mt-3",children:"Copy API Key"})})]}):(0,a.jsx)(es.Z,{children:"Key being created, this might take 30s"})})]})})]})},ex=t(9454),ep=t(98941),ej=t(33393),eg=t(5),ef=t(13810),ey=t(61244),eZ=t(10827),e_=t(3851),ew=t(2044),eb=t(64167),ek=t(74480),ev=t(7178),eS=t(95093),eN=t(27166);let{Option:eA}=en.default;var eE=e=>{let{userID:l,userRole:t,accessToken:s,selectedTeam:r,data:o,setData:i,teams:c}=e,[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(!1),[p,j]=(0,n.useState)(null),[g,y]=(0,n.useState)(null),[Z,_]=(0,n.useState)(null),[w,b]=(0,n.useState)(""),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)(!1),[E,I]=(0,n.useState)(null),[C,P]=(0,n.useState)([]),T=new Set,[O,F]=(0,n.useState)(T);(0,n.useEffect)(()=>{(async()=>{try{if(null===l)return;if(null!==s&&null!==t){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),P(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[s,l,t]),(0,n.useEffect)(()=>{if(c){let e=new Set;c.forEach((l,t)=>{let s=l.team_id;e.add(s)}),F(e)}},[c]);let R=e=>{console.log("handleEditClick:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),I(e),v(!0)},M=async e=>{if(null==s)return;let l=e.token;e.key=l,console.log("handleEditSubmit:",e);let t=await L(s,e);console.log("handleEditSubmit: newKeyValues",t),o&&i(o.map(e=>e.token===l?t:e)),u.ZP.success("Key updated successfully"),v(!1),I(null)},U=async e=>{console.log("handleDelete:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),null!=o&&(j(e.token),localStorage.removeItem("userData"+l),x(!0))},D=async()=>{if(null!=p&&null!=o){try{await f(s,p);let e=o.filter(e=>e.token!==p);i(e)}catch(e){console.error("Error deleting the key:",e)}x(!1),j(null)}};if(null!=o)return console.log("RERENDER TRIGGERED"),(0,a.jsxs)("div",{children:[(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4 mt-2",children:[(0,a.jsxs)(eZ.Z,{className:"mt-5 max-h-[300px] min-h-[300px]",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Key Alias"}),(0,a.jsx)(ek.Z,{children:"Secret Key"}),(0,a.jsx)(ek.Z,{children:"Spend (USD)"}),(0,a.jsx)(ek.Z,{children:"Budget (USD)"}),(0,a.jsx)(ek.Z,{children:"Models"}),(0,a.jsx)(ek.Z,{children:"TPM / RPM Limits"})]})}),(0,a.jsx)(e_.Z,{children:o.map(e=>{if(console.log(e),"litellm-dashboard"===e.team_id)return null;if(r){if(console.log("item team id: ".concat(e.team_id,", knownTeamIDs.has(item.team_id): ").concat(O.has(e.team_id),", selectedTeam id: ").concat(r.team_id)),(null!=r.team_id||null===e.team_id||O.has(e.team_id))&&e.team_id!=r.team_id)return null;console.log("item team id: ".concat(e.team_id,", is returned"))}return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{style:{maxWidth:"2px",whiteSpace:"pre-wrap",overflow:"hidden"},children:null!=e.key_alias?(0,a.jsx)(es.Z,{children:e.key_alias}):(0,a.jsx)(es.Z,{children:"Not Set"})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:e.key_name})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:(()=>{try{return parseFloat(e.spend).toFixed(4)}catch(l){return e.spend}})()})}),(0,a.jsx)(ew.Z,{children:null!=e.max_budget?(0,a.jsx)(es.Z,{children:e.max_budget}):(0,a.jsx)(es.Z,{children:"Unlimited"})}),(0,a.jsx)(ew.Z,{children:Array.isArray(e.models)?(0,a.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,a.jsx)(a.Fragment,{children:r&&r.models&&r.models.length>0?r.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Team Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l)):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:"all-proxy-models"})})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Team Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,a.jsx)(ew.Z,{children:(0,a.jsxs)(es.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,a.jsx)("br",{})," RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{onClick:()=>{I(e),A(!0)},icon:ex.Z,size:"sm"}),(0,a.jsx)(ei.Z,{open:S,onCancel:()=>{A(!1),I(null)},footer:null,width:800,children:E&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("div",{className:"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 mt-8",children:[(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Spend"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:(()=>{try{return parseFloat(E.spend).toFixed(4)}catch(e){return E.spend}})()})})]}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Budget"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.max_budget?(0,a.jsx)(a.Fragment,{children:E.max_budget}):(0,a.jsx)(a.Fragment,{children:"Unlimited"})})})]},e.name),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Expires"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor-default font-small text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.expires?(0,a.jsx)(a.Fragment,{children:new Date(E.expires).toLocaleString(void 0,{day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric"})}):(0,a.jsx)(a.Fragment,{children:"Never"})})})]},e.name)]}),(0,a.jsxs)(ef.Z,{className:"my-4",children:[(0,a.jsx)(er.Z,{children:"Token Name"}),(0,a.jsx)(es.Z,{className:"my-1",children:E.key_alias?E.key_alias:E.key_name}),(0,a.jsx)(er.Z,{children:"Token ID"}),(0,a.jsx)(es.Z,{className:"my-1 text-[12px]",children:E.token}),(0,a.jsx)(er.Z,{children:"Metadata"}),(0,a.jsx)(es.Z,{className:"my-1",children:(0,a.jsxs)("pre",{children:[JSON.stringify(E.metadata)," "]})})]}),(0,a.jsx)(X.Z,{className:"mx-auto flex items-center",onClick:()=>{A(!1),I(null)},children:"Close"})]})}),(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>R(e)}),(0,a.jsx)(ey.Z,{onClick:()=>U(e),icon:ej.Z,size:"sm"})]})]},e.token)})})]}),h&&(0,a.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,a.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,a.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,a.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,a.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,a.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,a.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,a.jsx)("div",{className:"sm:flex sm:items-start",children:(0,a.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,a.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,a.jsx)("div",{className:"mt-2",children:(0,a.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,a.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,a.jsx)(X.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,a.jsx)(X.Z,{onClick:()=>{x(!1),j(null)},children:"Cancel"})]})]})]})})]}),E&&(0,a.jsx)(e=>{let{visible:l,onCancel:t,token:s,onSubmit:o}=e,[i]=eo.Z.useForm(),[d,m]=(0,n.useState)(r),[u,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1);return(0,a.jsx)(ei.Z,{title:"Edit Key",visible:l,width:800,footer:null,onOk:()=>{i.validateFields().then(e=>{i.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:i,onFinish:M,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",rules:[{validator:(e,l)=>{let t=l.filter(e=>!d.models.includes(e)&&"all-team-models"!==e&&"all-proxy-models"!==e&&!d.models.includes("all-proxy-models"));return(console.log("errorModels: ".concat(t)),t.length>0)?Promise.reject("Some models are not part of the new team's models - ".concat(t,"Team models: ").concat(d.models)):Promise.resolve()}}],children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(eA,{value:"all-team-models",children:"All Team Models"},"all-team-models"),d&&d.models?d.models.includes("all-proxy-models")?C.filter(e=>"all-proxy-models"!==e).map(e=>(0,a.jsx)(eA,{value:e,children:e},e)):d.models.map(e=>(0,a.jsx)(eA,{value:e,children:e},e)):C.map(e=>(0,a.jsx)(eA,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: ".concat((null==d?void 0:d.max_budget)!==null&&(null==d?void 0:d.max_budget)!==void 0?null==d?void 0:d.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&d&&null!==d.max_budget&&l>d.max_budget)throw console.log("keyTeam.max_budget: ".concat(d.max_budget)),Error("Budget cannot exceed team max budget: $".concat(d.max_budget))}}],children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"token",name:"token",hidden:!0}),(0,a.jsx)(eo.Z.Item,{label:"Team",name:"team_id",help:"the team this key belongs to",children:(0,a.jsx)(eS.Z,{value:s.team_alias,children:null==c?void 0:c.map((e,l)=>(0,a.jsx)(eN.Z,{value:e.team_id,onClick:()=>m(e),children:e.team_alias},l))})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Edit Key"})})]})})},{visible:k,onCancel:()=>{v(!1),I(null)},token:E,onSubmit:M})]})},eI=t(76032),eC=t(35152),eP=e=>{let{userID:l,userRole:t,accessToken:s,userSpend:r,selectedTeam:o}=e;console.log("userSpend: ".concat(r));let[i,c]=(0,n.useState)(null!==r?r:0),[d,m]=(0,n.useState)(0),[u,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{let e=async()=>{if(s&&l&&t&&"Admin"===t&&null==r)try{let e=await w(s);e&&(e.spend?c(e.spend):c(0),e.max_budget?m(e.max_budget):m(0))}catch(e){console.error("Error fetching global spend data:",e)}};(async()=>{try{if(null===l||null===t)return;if(null!==s){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),h(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[t,s,l]),(0,n.useEffect)(()=>{null!==r&&c(r)},[r]);let x=[];o&&o.models&&(x=o.models),x&&x.includes("all-proxy-models")?(console.log("user models:",u),x=u):x&&x.includes("all-team-models")?x=o.models:x&&0===x.length&&(x=u);let p=void 0!==i?i.toFixed(4):null;return console.log("spend in view user spend: ".concat(i)),(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsxs)("div",{children:[(0,a.jsxs)("p",{className:"text-tremor-default text-tremor-content dark:text-dark-tremor-content",children:["Total Spend"," "]}),(0,a.jsxs)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:["$",p]})]}),(0,a.jsx)("div",{className:"ml-auto",children:(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)(es.Z,{children:"Team Models"})}),(0,a.jsx)(el.Z,{className:"absolute right-0 z-10 bg-white p-2 shadow-lg max-w-xs",children:(0,a.jsx)(eI.Z,{children:x.map(e=>(0,a.jsx)(eC.Z,{children:(0,a.jsx)(es.Z,{children:e})},e))})})]})})]})},eT=e=>{let{userID:l,userRole:t,selectedTeam:s,accessToken:r}=e,[o,i]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===t)return;if(null!==r){let e=(await N(r,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),i(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[r,l,t]);let c=[];return s&&s.models&&(c=s.models),c&&c.includes("all-proxy-models")&&(console.log("user models:",o),c=o),(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("div",{className:"mb-5",children:(0,a.jsx)("p",{className:"text-3xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:null==s?void 0:s.team_alias})})})},eO=e=>{let l,{teams:t,setSelectedTeam:s,userRole:r}=e,o={models:[],team_id:null,team_alias:"Default Team"},[i,c]=(0,n.useState)(o);return(l="App User"===r?t:t?[...t,o]:[o],"App User"===r)?null:(0,a.jsxs)("div",{className:"mt-5 mb-5",children:[(0,a.jsx)(er.Z,{children:"Select Team"}),(0,a.jsx)(es.Z,{children:"If you belong to multiple teams, this setting controls which team is used by default when creating new API Keys."}),(0,a.jsxs)(es.Z,{className:"mt-3 mb-3",children:[(0,a.jsx)("b",{children:"Default Team:"})," If no team_id is set for a key, it will be grouped under here."]}),l&&l.length>0?(0,a.jsx)(eS.Z,{defaultValue:"0",children:l.map((e,l)=>(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>s(e),children:e.team_alias},l))}):(0,a.jsxs)(es.Z,{children:["No team created. ",(0,a.jsx)("b",{children:"Defaulting to personal account."})]})]})},eF=t(37963),eR=t(36083);console.log("isLocal:",!1);var eM=e=>{let{userID:l,userRole:t,teams:s,keys:r,setUserRole:i,userEmail:c,setUserEmail:d,setTeams:m,setKeys:u}=e,[h,x]=(0,n.useState)(null),p=(0,o.useSearchParams)();p.get("viewSpend"),(0,o.useRouter)();let j=p.get("token"),[g,f]=(0,n.useState)(null),[y,_]=(0,n.useState)(null),[b,k]=(0,n.useState)([]),v={models:[],team_alias:"Default Team",team_id:null},[S,A]=(0,n.useState)(s?s[0]:v);if(window.addEventListener("beforeunload",function(){sessionStorage.clear()}),(0,n.useEffect)(()=>{if(j){let e=(0,eF.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),f(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),i(l)}else console.log("User role not defined");e.user_email?d(e.user_email):console.log("User Email is not set ".concat(e))}}if(l&&g&&t&&!r&&!h){let e=sessionStorage.getItem("userModels"+l);e?k(JSON.parse(e)):(async()=>{try{let e=await Z(g,l,t,!1,null,null);if(console.log("received teams in user dashboard: ".concat(Object.keys(e),"; team values: ").concat(Object.entries(e.teams))),"Admin"==t){let e=await w(g);x(e),console.log("globalSpend:",e)}else x(e.user_info);u(e.keys),m(e.teams);let s=[...e.teams];s.length>0?(console.log("response['teams']: ".concat(s)),A(s[0])):A(v),sessionStorage.setItem("userData"+l,JSON.stringify(e.keys)),sessionStorage.setItem("userSpendData"+l,JSON.stringify(e.user_info));let r=(await N(g,l,t)).data.map(e=>e.id);console.log("available_model_names:",r),k(r),console.log("userModels:",b),sessionStorage.setItem("userModels"+l,JSON.stringify(r))}catch(e){console.error("There was an error fetching the data",e)}})()}},[l,j,g,r,t]),(0,n.useEffect)(()=>{if(null!==r&&null!=S){let e=0;for(let l of r)S.hasOwnProperty("team_id")&&null!==l.team_id&&l.team_id===S.team_id&&(e+=l.spend);_(e)}else if(null!==r){let e=0;for(let l of r)e+=l.spend;_(e)}},[S]),null==l||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}if(null==g)return null;if(null==t&&i("App Owner"),t&&"Admin Viewer"==t){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to create keys"})]})}return console.log("inside user dashboard, selected team",S),console.log("teamSpend: ".concat(y)),(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsx)($.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(eT,{userID:l,userRole:t,selectedTeam:S||null,accessToken:g}),(0,a.jsx)(eP,{userID:l,userRole:t,accessToken:g,userSpend:y,selectedTeam:S||null}),(0,a.jsx)(eE,{userID:l,userRole:t,accessToken:g,selectedTeam:S||null,data:r,setData:u,teams:s}),(0,a.jsx)(eh,{userID:l,team:S||null,userRole:t,accessToken:g,data:r,setData:u},S?S.team_id:null),(0,a.jsx)(eO,{teams:s,setSelectedTeam:A,userRole:t})]})})})},eL=t(35087),eU=t(92836),eD=t(26734),eK=t(41608),eB=t(32126),ez=t(23682),eV=t(47047),eq=t(76628),eG=t(57750),eY=t(44041),eW=t(38302),eJ=t(28683),eH=t(1460),e$=t(78578),eX=t(63954),eQ=t(90252),e0=t(7905),e1=e=>{let{modelID:l,accessToken:t}=e,[s,r]=(0,n.useState)(!1),o=async()=>{try{u.ZP.info("Making API Call"),r(!0);let e=await p(t,l);console.log("model delete Response:",e),u.ZP.success("Model ".concat(l," deleted successfully")),r(!1)}catch(e){console.error("Error deleting the model:",e)}};return(0,a.jsxs)("div",{children:[(0,a.jsx)(ey.Z,{onClick:()=>r(!0),icon:ej.Z,size:"sm"}),(0,a.jsx)(ei.Z,{open:s,onOk:o,okType:"danger",onCancel:()=>r(!1),children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 w-full",children:[(0,a.jsx)(er.Z,{children:"Delete Model"}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsx)("p",{children:"Are you sure you want to delete this model? This action is irreversible."})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("p",{children:["Model ID: ",(0,a.jsx)("b",{children:l})]})})]})})]})},e2=t(97766),e4=t(46495);let{Title:e8,Link:e5}=eR.default;(s=r||(r={})).OpenAI="OpenAI",s.Azure="Azure",s.Anthropic="Anthropic",s.Google_AI_Studio="Gemini (Google AI Studio)",s.Bedrock="Amazon Bedrock",s.OpenAI_Compatible="OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)",s.Vertex_AI="Vertex AI (Anthropic, Gemini, etc.)";let e3={OpenAI:"openai",Azure:"azure",Anthropic:"anthropic",Google_AI_Studio:"gemini",Bedrock:"bedrock",OpenAI_Compatible:"openai",Vertex_AI:"vertex_ai"},e6={"BadRequestError (400)":"BadRequestErrorRetries","AuthenticationError (401)":"AuthenticationErrorRetries","TimeoutError (408)":"TimeoutErrorRetries","RateLimitError (429)":"RateLimitErrorRetries","ContentPolicyViolationError (400)":"ContentPolicyViolationErrorRetries","InternalServerError (500)":"InternalServerErrorRetries"},e7=async(e,l,t)=>{try{let s=Array.isArray(e.model)?e.model:[e.model];console.log("received deployments: ".concat(s)),console.log("received type of deployments: ".concat(typeof s)),s.forEach(async t=>{console.log("litellm_model: ".concat(t));let s={},r={};s.model=t;let a="";for(let[l,t]of Object.entries(e))if(""!==t){if("model_name"==l)a+=t;else if("custom_llm_provider"==l)continue;else if("model"==l)continue;else if("base_model"===l)r[l]=t;else if("litellm_extra_params"==l){console.log("litellm_extra_params:",t);let e={};if(t&&void 0!=t){try{e=JSON.parse(t)}catch(e){throw u.ZP.error("Failed to parse LiteLLM Extra Params: "+e,10),Error("Failed to parse litellm_extra_params: "+e)}for(let[l,t]of Object.entries(e))s[l]=t}}else s[l]=t}let n={model_name:a,litellm_params:s,model_info:r},o=await x(l,n);console.log("response for model create call: ".concat(o.data))}),t.resetFields()}catch(e){u.ZP.error("Failed to create model: "+e,10)}};var e9=e=>{var l,t,s;let{accessToken:o,token:i,userRole:c,userID:d,modelData:m={data:[]},setModelData:x}=e,[p,j]=(0,n.useState)([]),[g]=eo.Z.useForm(),[f,y]=(0,n.useState)(null),[Z,_]=(0,n.useState)(""),[w,N]=(0,n.useState)([]),A=Object.values(r).filter(e=>isNaN(Number(e))),[E,I]=(0,n.useState)("OpenAI"),[C,P]=(0,n.useState)(""),[T,O]=(0,n.useState)(!1),[F,R]=(0,n.useState)(null),[M,L]=(0,n.useState)([]),[U,K]=(0,n.useState)(null),[B,z]=(0,n.useState)([]),[q,G]=(0,n.useState)([]),[Y,H]=(0,n.useState)([]),[ea,en]=(0,n.useState)([]),[ec,eu]=(0,n.useState)([]),[eh,ex]=(0,n.useState)([]),[ej,eA]=(0,n.useState)([]),[eE,eI]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),[eC,eP]=(0,n.useState)(null),[eT,eO]=(0,n.useState)(0),eF=e=>{R(e),O(!0)},eM=async e=>{if(console.log("handleEditSubmit:",e),null==o)return;let l={},t=null;for(let[s,r]of Object.entries(e))"model_id"!==s?l[s]=r:t=r;let s={litellm_params:l,model_info:{id:t}};console.log("handleEditSubmit payload:",s);try{await D(o,s),u.ZP.success("Model updated successfully, restart server to see updates"),O(!1),R(null)}catch(e){console.log("Error occurred")}},e9=()=>{_(new Date().toLocaleString())},le=async()=>{if(!o){console.error("Access token is missing");return}console.log("new modelGroupRetryPolicy:",eC);try{await W(o,{router_settings:{model_group_retry_policy:eC}}),u.ZP.success("Retry settings saved successfully")}catch(e){console.error("Failed to save retry settings:",e),u.ZP.error("Failed to save retry settings")}};if((0,n.useEffect)(()=>{if(!o||!i||!c||!d)return;let e=async()=>{try{var e,l,t,s,r,a;let n=await b(o,d,c);console.log("Model data response:",n.data),x(n);let i=new Set;for(let e=0;e0&&(u=m[m.length-1],console.log("_initial_model_group:",u),K(u)),console.log("selectedModelGroup:",U);let h=await k(o,d,c,u,null===(e=eE.from)||void 0===e?void 0:e.toISOString(),null===(l=eE.to)||void 0===l?void 0:l.toISOString());console.log("Model metrics response:",h),G(h.data),H(h.all_api_bases);let p=await S(o,d,c,u,null===(t=eE.from)||void 0===t?void 0:t.toISOString(),null===(s=eE.to)||void 0===s?void 0:s.toISOString());console.log("Model exceptions response:",p),en(p.data),eu(p.exception_types);let j=await v(o,d,c,u,null===(r=eE.from)||void 0===r?void 0:r.toISOString(),null===(a=eE.to)||void 0===a?void 0:a.toISOString());console.log("slowResponses:",j),eA(j);let g=(await V(o,d,c)).router_settings;console.log("routerSettingsInfo:",g);let f=g.model_group_retry_policy,y=g.num_retries;console.log("model_group_retry_policy:",f),console.log("default_retries:",y),eP(f),eO(y)}catch(e){console.error("There was an error fetching the model data",e)}};o&&i&&c&&d&&e();let l=async()=>{let e=await h();console.log("received model cost map data: ".concat(Object.keys(e))),y(e)};null==f&&l(),e9()},[o,i,c,d,f,Z]),!m||!o||!i||!c||!d)return(0,a.jsx)("div",{children:"Loading..."});let ll=[];for(let e=0;e(console.log("GET PROVIDER CALLED! - ".concat(f)),null!=f&&"object"==typeof f&&e in f)?f[e].litellm_provider:"openai";if(r){let e=r.split("/"),l=e[0];n=1===e.length?u(r):l}else n="openai";a&&(o=null==a?void 0:a.input_cost_per_token,i=null==a?void 0:a.output_cost_per_token,c=null==a?void 0:a.max_tokens),(null==s?void 0:s.litellm_params)&&(d=Object.fromEntries(Object.entries(null==s?void 0:s.litellm_params).filter(e=>{let[l]=e;return"model"!==l&&"api_base"!==l}))),m.data[e].provider=n,m.data[e].input_cost=o,m.data[e].output_cost=i,m.data[e].max_tokens=c,m.data[e].api_base=null==s?void 0:null===(t=s.litellm_params)||void 0===t?void 0:t.api_base,m.data[e].cleanedLitellmParams=d,ll.push(s.model_name),console.log(m.data[e])}if(c&&"Admin Viewer"==c){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to view all models"})]})}let lt=e=>{console.log("received provider string: ".concat(e));let l=Object.keys(r).find(l=>r[l]===e);if(l){let e=e3[l];console.log("mappingResult: ".concat(e));let t=[];"object"==typeof f&&Object.entries(f).forEach(l=>{let[s,r]=l;null!==r&&"object"==typeof r&&"litellm_provider"in r&&(r.litellm_provider===e||r.litellm_provider.includes(e))&&t.push(s)}),N(t),console.log("providerModels: ".concat(w))}},ls=async()=>{try{u.ZP.info("Running health check..."),P("");let e=await J(o);P(e)}catch(e){console.error("Error running health check:",e),P("Error running health check")}},lr=async(e,l,t)=>{if(console.log("Updating model metrics for group:",e),o&&d&&c&&l&&t){console.log("inside updateModelMetrics - startTime:",l,"endTime:",t),K(e);try{let s=await k(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model metrics response:",s),G(s.data),H(s.all_api_bases);let r=await S(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model exceptions response:",r),en(r.data),eu(r.exception_types);let a=await v(o,d,c,e,l.toISOString(),t.toISOString());console.log("slowResponses:",a),eA(a)}catch(e){console.error("Failed to fetch model metrics",e)}}};return console.log("selectedProvider: ".concat(E)),console.log("providerModels.length: ".concat(w.length)),(0,a.jsx)("div",{style:{width:"100%",height:"100%"},children:(0,a.jsxs)(eD.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(eK.Z,{className:"flex justify-between mt-2 w-full items-center",children:[(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)(eU.Z,{children:"All Models"}),(0,a.jsx)(eU.Z,{children:"Add Model"}),(0,a.jsx)(eU.Z,{children:(0,a.jsx)("pre",{children:"/health Models"})}),(0,a.jsx)(eU.Z,{children:"Model Analytics"}),(0,a.jsx)(eU.Z,{children:"Model Retry Settings"})]}),(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[Z&&(0,a.jsxs)(es.Z,{children:["Last Refreshed: ",Z]}),(0,a.jsx)(ey.Z,{icon:eX.Z,variant:"shadow",size:"xs",className:"self-center",onClick:e9})]})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)($.Z,{children:[(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)(es.Z,{children:"Filter by Public Model Name"}),(0,a.jsxs)(eS.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:"all",onValueChange:e=>K("all"===e?"all":e),children:[(0,a.jsx)(eN.Z,{value:"all",children:"All Models"}),M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>K(e),children:e},l))]})]}),(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{className:"mt-5",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Public Model Name "}),(0,a.jsx)(ek.Z,{children:"Provider"}),"Admin"===c&&(0,a.jsx)(ek.Z,{children:"API Base"}),(0,a.jsx)(ek.Z,{children:"Extra litellm Params"}),(0,a.jsx)(ek.Z,{children:"Input Price per token ($)"}),(0,a.jsx)(ek.Z,{children:"Output Price per token ($)"}),(0,a.jsx)(ek.Z,{children:"Max Tokens"}),(0,a.jsx)(ek.Z,{children:"Status"})]})}),(0,a.jsx)(e_.Z,{children:m.data.filter(e=>"all"===U||e.model_name===U||null==U||""===U).map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:e.model_name})}),(0,a.jsx)(ew.Z,{children:e.provider}),"Admin"===c&&(0,a.jsx)(ew.Z,{children:e.api_base}),(0,a.jsx)(ew.Z,{children:(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)(es.Z,{children:"Litellm params"})}),(0,a.jsx)(el.Z,{children:(0,a.jsx)("pre",{children:JSON.stringify(e.cleanedLitellmParams,null,2)})})]})}),(0,a.jsx)(ew.Z,{children:e.input_cost||e.litellm_params.input_cost_per_token||null}),(0,a.jsx)(ew.Z,{children:e.output_cost||e.litellm_params.output_cost_per_token||null}),(0,a.jsx)(ew.Z,{children:e.max_tokens}),(0,a.jsx)(ew.Z,{children:e.model_info.db_model?(0,a.jsx)(eg.Z,{icon:eQ.Z,className:"text-white",children:"DB Model"}):(0,a.jsx)(eg.Z,{icon:e0.Z,className:"text-black",children:"Config Model"})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>eF(e)}),(0,a.jsx)(e1,{modelID:e.model_info.id,accessToken:o})]})]},l))})]})})]}),(0,a.jsx)(e=>{let{visible:l,onCancel:t,model:s,onSubmit:r}=e,[n]=eo.Z.useForm(),o={},i="",c="";if(s){o=s.litellm_params,i=s.model_name;let e=s.model_info;e&&(c=e.id,console.log("model_id: ".concat(c)),o.model_id=c)}return(0,a.jsx)(ei.Z,{title:"Edit Model "+i,visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{r(e),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:n,onFinish:eM,initialValues:o,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"api_base",name:"api_base",children:(0,a.jsx)(Q.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"tpm",name:"tpm",tooltip:"int (optional) - Tokens limit for this deployment: in tokens per minute (tpm). Find this information on your model/providers website",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"rpm",name:"rpm",tooltip:"int (optional) - Rate limit for this deployment: in requests per minute (rpm). Find this information on your model/providers website",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"max_retries",name:"max_retries",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"timeout",name:"timeout",tooltip:"int (optional) - Timeout in seconds for LLM requests (Defaults to 600 seconds)",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"stream_timeout",name:"stream_timeout",tooltip:"int (optional) - Timeout for stream requests (seconds)",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"input_cost_per_token",name:"input_cost_per_token",tooltip:"float (optional) - Input cost per token",children:(0,a.jsx)(ed.Z,{min:0,step:1e-4})}),(0,a.jsx)(eo.Z.Item,{label:"output_cost_per_token",name:"output_cost_per_token",tooltip:"float (optional) - Output cost per token",children:(0,a.jsx)(ed.Z,{min:0,step:1e-4})}),(0,a.jsx)(eo.Z.Item,{label:"model_id",name:"model_id",hidden:!0})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})})},{visible:T,onCancel:()=>{O(!1),R(null)},model:F,onSubmit:eM})]}),(0,a.jsxs)(eB.Z,{className:"h-full",children:[(0,a.jsx)(e8,{level:2,children:"Add new model"}),(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eo.Z,{form:g,onFinish:()=>{g.validateFields().then(e=>{e7(e,o,g)}).catch(e=>{console.error("Validation failed:",e)})},labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"E.g. OpenAI, Azure OpenAI, Anthropic, Bedrock, etc.",labelCol:{span:10},labelAlign:"left",children:(0,a.jsx)(eS.Z,{value:E.toString(),children:A.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>{lt(e),I(e)},children:e},l))})}),(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Public Model Name",name:"model_name",tooltip:"Model name your users will pass in. Also used for load-balancing, LiteLLM will load balance between all models with this public name.",className:"mb-0",children:(0,a.jsx)(Q.Z,{placeholder:"Vertex AI (Anthropic, Gemini, etc.)"===(s=E.toString())?"gemini-pro":"Anthropic"==s?"claude-3-opus":"Amazon Bedrock"==s?"claude-3-opus":"Gemini (Google AI Studio)"==s?"gemini-pro":"gpt-3.5-turbo"})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsx)(es.Z,{className:"mb-3 mt-1",children:"Model name your users will pass in."})})]}),(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"LiteLLM Model Name(s)",name:"model",tooltip:"Actual model name used for making litellm.completion() call.",className:"mb-0",children:"Azure"===E?(0,a.jsx)(Q.Z,{placeholder:"Enter model name"}):w.length>0?(0,a.jsx)(eV.Z,{value:w,children:w.map((e,l)=>(0,a.jsx)(eq.Z,{value:e,children:e},l))}):(0,a.jsx)(Q.Z,{placeholder:"gpt-3.5-turbo-0125"})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsxs)(es.Z,{className:"mb-3 mt-1",children:["Actual model name used for making ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/providers",target:"_blank",children:"litellm.completion() call"}),". We'll ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/proxy/reliability#step-1---set-deployments-on-config",target:"_blank",children:"loadbalance"})," models with the same 'public name'"]})})]}),"Amazon Bedrock"!=E&&"Vertex AI (Anthropic, Gemini, etc.)"!=E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Key",name:"api_key",children:(0,a.jsx)(Q.Z,{placeholder:"sk-",type:"password"})}),"OpenAI"==E&&(0,a.jsx)(eo.Z.Item,{label:"Organization ID",name:"organization_id",children:(0,a.jsx)(Q.Z,{placeholder:"[OPTIONAL] my-unique-org"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Project",name:"vertex_project",children:(0,a.jsx)(Q.Z,{placeholder:"adroit-cadet-1234.."})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Location",name:"vertex_location",children:(0,a.jsx)(Q.Z,{placeholder:"us-east-1"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Credentials",name:"vertex_credentials",className:"mb-0",children:(0,a.jsx)(e4.Z,{name:"file",accept:".json",beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;g.setFieldsValue({vertex_credentials:l})}},l.readAsText(e)}return!1},onChange(e){"uploading"!==e.file.status&&console.log(e.file,e.fileList),"done"===e.file.status?u.ZP.success("".concat(e.file.name," file uploaded successfully")):"error"===e.file.status&&u.ZP.error("".concat(e.file.name," file upload failed."))},children:(0,a.jsx)(em.ZP,{icon:(0,a.jsx)(e2.Z,{}),children:"Click to Upload"})})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsx)(es.Z,{className:"mb-3 mt-1",children:"Give litellm a gcp service account(.json file), so it can make the relevant calls"})})]}),("Azure"==E||"OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)"==E)&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Base",name:"api_base",children:(0,a.jsx)(Q.Z,{placeholder:"https://..."})}),"Azure"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Version",name:"api_version",children:(0,a.jsx)(Q.Z,{placeholder:"2023-07-01-preview"})}),"Azure"==E&&(0,a.jsxs)(eo.Z.Item,{label:"Base Model",name:"base_model",children:[(0,a.jsx)(Q.Z,{placeholder:"azure/gpt-3.5-turbo"}),(0,a.jsxs)(es.Z,{children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from ",(0,a.jsx)(e5,{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",children:"here"})]})]}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Access Key ID",name:"aws_access_key_id",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Secret Access Key",name:"aws_secret_access_key",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Region Name",name:"aws_region_name",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:"us-east-1"})}),(0,a.jsx)(eo.Z.Item,{label:"LiteLLM Params",name:"litellm_extra_params",tooltip:"Optional litellm params used for making a litellm.completion() call.",className:"mb-0",children:(0,a.jsx)(e$.Z,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsxs)(es.Z,{className:"mb-3 mt-1",children:["Pass JSON of litellm supported params ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",children:"litellm.completion() call"})]})})]})]}),(0,a.jsx)("div",{style:{textAlign:"center",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add Model"})}),(0,a.jsx)(eH.Z,{title:"Get help on our github",children:(0,a.jsx)(eR.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})})]})})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(es.Z,{children:"`/health` will run a very small request through your models configured on litellm"}),(0,a.jsx)(X.Z,{onClick:ls,children:"Run `/health`"}),C&&(0,a.jsx)("pre",{children:JSON.stringify(C,null,2)})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)($.Z,{numItems:2,className:"mt-2",children:[(0,a.jsxs)(eJ.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Time Range"}),(0,a.jsx)(eL.Z,{enableSelect:!0,value:eE,onValueChange:e=>{eI(e),lr(U,e.from,e.to)}})]}),(0,a.jsxs)(eJ.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Model Group"}),(0,a.jsx)(eS.Z,{className:"mb-4 mt-2",defaultValue:U||M[0],value:U||M[0],children:M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>lr(e,eE.from,eE.to),children:e},l))})]})]}),(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsx)(eJ.Z,{children:(0,a.jsxs)(ef.Z,{className:"mr-2 max-h-[400px] min-h-[400px]",children:[(0,a.jsx)(er.Z,{children:"Avg Latency per Token"}),(0,a.jsx)("p",{className:"text-gray-500 italic",children:" (seconds/token)"}),(0,a.jsx)(es.Z,{className:"text-gray-500 italic mt-1 mb-1",children:"average Latency for successfull requests divided by the total tokens"}),q&&Y&&(0,a.jsx)(eG.Z,{title:"Model Latency",className:"h-72",data:q,showLegend:!1,index:"date",categories:Y,connectNulls:!0,customTooltip:e=>{var l,t;let{payload:s,active:r}=e;if(!r||!s)return null;let n=null===(t=s[0])||void 0===t?void 0:null===(l=t.payload)||void 0===l?void 0:l.date,o=s.sort((e,l)=>l.value-e.value);if(o.length>5){let e=o.length-5;(o=o.slice(0,5)).push({dataKey:"".concat(e," other deployments"),value:s.slice(5).reduce((e,l)=>e+l.value,0),color:"gray"})}return(0,a.jsxs)("div",{className:"w-150 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[n&&(0,a.jsxs)("p",{className:"text-tremor-content-emphasis mb-2",children:["Date: ",n]}),o.map((e,l)=>{let t=parseFloat(e.value.toFixed(5)),s=0===t&&e.value>0?"<0.00001":t.toFixed(5);return(0,a.jsxs)("div",{className:"flex justify-between",children:[(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)("div",{className:"w-2 h-2 mt-1 rounded-full bg-".concat(e.color,"-500")}),(0,a.jsx)("p",{className:"text-tremor-content",children:e.dataKey})]}),(0,a.jsx)("p",{className:"font-medium text-tremor-content-emphasis text-righ ml-2",children:s})]},l)})]})}})]})}),(0,a.jsx)(eJ.Z,{children:(0,a.jsx)(ef.Z,{className:"ml-2 max-h-[400px] min-h-[400px] overflow-y-auto",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Deployment"}),(0,a.jsx)(ek.Z,{children:"Success Responses"}),(0,a.jsxs)(ek.Z,{children:["Slow Responses ",(0,a.jsx)("p",{children:"Success Responses taking 600+s"})]})]})}),(0,a.jsx)(e_.Z,{children:ej.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.api_base}),(0,a.jsx)(ew.Z,{children:e.total_count}),(0,a.jsx)(ew.Z,{children:e.slow_count})]},l))})]})})})]}),(0,a.jsxs)(ef.Z,{className:"mt-4",children:[(0,a.jsx)(er.Z,{children:"Exceptions per Model"}),(0,a.jsx)(eY.Z,{className:"h-72",data:ea,index:"model",categories:ec,stack:!0,colors:["indigo-300","rose-200","#ffcc33"],yAxisWidth:30})]})]}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)(es.Z,{children:"Filter by Public Model Name"}),(0,a.jsx)(eS.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:U||M[0],value:U||M[0],onValueChange:e=>K(e),children:M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>K(e),children:e},l))})]}),(0,a.jsxs)(er.Z,{children:["Retry Policy for ",U]}),(0,a.jsx)(es.Z,{className:"mb-6",children:"How many retries should be attempted based on the Exception"}),e6&&(0,a.jsx)("table",{children:(0,a.jsx)("tbody",{children:Object.entries(e6).map((e,l)=>{var t;let[s,r]=e,n=null==eC?void 0:null===(t=eC[U])||void 0===t?void 0:t[r];return null==n&&(n=eT),(0,a.jsxs)("tr",{className:"flex justify-between items-center mt-2",children:[(0,a.jsx)("td",{children:(0,a.jsx)(es.Z,{children:s})}),(0,a.jsx)("td",{children:(0,a.jsx)(ed.Z,{className:"ml-5",value:n,min:0,step:1,onChange:e=>{eP(l=>{var t;let s=null!==(t=null==l?void 0:l[U])&&void 0!==t?t:{};return{...null!=l?l:{},[U]:{...s,[r]:e}}})}})})]},l)})})}),(0,a.jsx)(X.Z,{className:"mt-6 mr-8",onClick:le,children:"Save"})]})]})]})})};let{Option:le}=en.default;var ll=e=>{let{userID:l,accessToken:t,teams:s}=e,[r]=eo.Z.useForm(),[o,i]=(0,n.useState)(!1),[c,d]=(0,n.useState)(null),[m,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{let e=await N(t,l,"any"),s=[];for(let l=0;l{i(!1),r.resetFields()},p=()=>{i(!1),d(null),r.resetFields()},j=async e=>{try{u.ZP.info("Making API Call"),i(!0),console.log("formValues in create user:",e);let s=await g(t,null,e);console.log("user create Response:",s),d(s.key),u.ZP.success("API user Created"),r.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the user:",e)}};return(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>i(!0),children:"+ Invite User"}),(0,a.jsxs)(ei.Z,{title:"Invite User",visible:o,width:800,footer:null,onOk:x,onCancel:p,children:[(0,a.jsx)(es.Z,{className:"mb-1",children:"Invite a user to login to the Admin UI and create Keys"}),(0,a.jsx)(es.Z,{className:"mb-6",children:(0,a.jsx)("b",{children:"Note: SSO Setup Required for this"})}),(0,a.jsxs)(eo.Z,{form:r,onFinish:j,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsx)(eo.Z.Item,{label:"User Email",name:"user_email",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"team_id",children:(0,a.jsx)(en.default,{placeholder:"Select Team ID",style:{width:"100%"},children:s?s.map(e=>(0,a.jsx)(le,{value:e.team_id,children:e.team_alias},e.team_id)):(0,a.jsx)(le,{value:null,children:"Default Team"},"default")})}),(0,a.jsx)(eo.Z.Item,{label:"Metadata",name:"metadata",children:(0,a.jsx)(ec.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create User"})})]})]}),c&&(0,a.jsxs)(ei.Z,{title:"User Created Successfully",visible:o,onOk:x,onCancel:p,footer:null,children:[(0,a.jsx)("p",{children:"User has been created to access your proxy. Please Ask them to Log In."}),(0,a.jsx)("br",{}),(0,a.jsx)("p",{children:(0,a.jsx)("b",{children:"Note: This Feature is only supported through SSO on the Admin UI"})})]})]})},lt=e=>{let{accessToken:l,token:t,keys:s,userRole:r,userID:o,teams:i,setKeys:c}=e,[d,m]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(0),[j,g]=n.useState(null),[f,y]=(0,n.useState)(null);return((0,n.useEffect)(()=>{if(!l||!t||!r||!o)return;let e=async()=>{try{let e=await Z(l,null,r,!0,x,25);console.log("user data response:",e),m(e)}catch(e){console.error("There was an error fetching the model data",e)}};l&&t&&r&&o&&e()},[l,t,r,o,x]),d&&l&&t&&r&&o)?(0,a.jsx)("div",{style:{width:"100%"},children:(0,a.jsxs)($.Z,{className:"gap-2 p-2 h-[80vh] w-full mt-8",children:[(0,a.jsx)(ll,{userID:o,accessToken:l,teams:i}),(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[80vh] mb-4",children:[(0,a.jsx)("div",{className:"mb-4 mt-1",children:(0,a.jsx)(es.Z,{children:"These are Users on LiteLLM that created API Keys. Automatically tracked by LiteLLM"})}),(0,a.jsx)(eD.Z,{children:(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(eZ.Z,{className:"mt-5",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"User ID"}),(0,a.jsx)(ek.Z,{children:"User Email"}),(0,a.jsx)(ek.Z,{children:"User Models"}),(0,a.jsx)(ek.Z,{children:"User Spend ($ USD)"}),(0,a.jsx)(ek.Z,{children:"User Max Budget ($ USD)"}),(0,a.jsx)(ek.Z,{children:"User API Key Aliases"})]})}),(0,a.jsx)(e_.Z,{children:d.map(e=>{var l;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_id}),(0,a.jsx)(ew.Z,{children:e.user_email}),(0,a.jsx)(ew.Z,{children:e.models&&e.models.length>0?e.models:"All Models"}),(0,a.jsx)(ew.Z,{children:e.spend?null===(l=e.spend)||void 0===l?void 0:l.toFixed(2):0}),(0,a.jsx)(ew.Z,{children:e.max_budget?e.max_budget:"Unlimited"}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)($.Z,{numItems:2,children:e&&e.key_aliases&&e.key_aliases.filter(e=>null!==e).length>0?(0,a.jsx)(eg.Z,{size:"xs",color:"indigo",children:e.key_aliases.filter(e=>null!==e).join(", ")}):(0,a.jsx)(eg.Z,{size:"xs",color:"gray",children:"No Keys"})})})]},e.user_id)})})]})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)("div",{className:"flex-1"}),(0,a.jsx)("div",{className:"flex-1 flex justify-between items-center"})]})})]})})]}),function(){if(!d)return null;let e=Math.ceil(d.length/25);return(0,a.jsxs)("div",{className:"flex justify-between items-center",children:[(0,a.jsxs)("div",{children:["Showing Page ",x+1," of ",e]}),(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-l focus:outline-none",disabled:0===x,onClick:()=>p(x-1),children:"← Prev"}),(0,a.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r focus:outline-none",onClick:()=>{p(x+1)},children:"Next →"})]})]})}()]})}):(0,a.jsx)("div",{children:"Loading..."})},ls=e=>{let{teams:l,searchParams:t,accessToken:s,setTeams:r,userID:o,userRole:i}=e,[c]=eo.Z.useForm(),[d]=eo.Z.useForm(),{Title:m,Paragraph:h}=eR.default,[x,p]=(0,n.useState)(""),[j,g]=(0,n.useState)(!1),[f,Z]=(0,n.useState)(l?l[0]:null),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)([]),[E,I]=(0,n.useState)(!1),[C,P]=(0,n.useState)(null),[T,O]=(0,n.useState)({}),F=e=>{Z(e),g(!0)},R=async e=>{let t=e.team_id;if(console.log("handleEditSubmit:",e),null==s)return;let a=await U(s,e);l&&r(l.map(e=>e.team_id===t?a.data:e)),u.ZP.success("Team updated successfully"),g(!1),Z(null)},L=async e=>{P(e),I(!0)},D=async()=>{if(null!=C&&null!=l&&null!=s){try{await y(s,C);let e=l.filter(e=>e.team_id!==C);r(e)}catch(e){console.error("Error deleting the team:",e)}I(!1),P(null)}};(0,n.useEffect)(()=>{let e=async()=>{try{if(null===o||null===i||null===s||null===l)return;console.log("fetching team info:");let e={};for(let t=0;t<(null==l?void 0:l.length);t++){let r=l[t].team_id,a=await _(s,r);console.log("teamInfo response:",a),null!==a&&(e={...e,[r]:a})}O(e)}catch(e){console.error("Error fetching team info:",e)}};(async()=>{try{if(null===o||null===i)return;if(null!==s){let e=(await N(s,o,i)).data.map(e=>e.id);console.log("available_model_names:",e),A(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[s,o,i,l]);let B=async e=>{try{if(null!=s){var t;let a=null==e?void 0:e.team_alias;if((null!==(t=null==l?void 0:l.map(e=>e.team_alias))&&void 0!==t?t:[]).includes(a))throw Error("Team alias ".concat(a," already exists, please pick another alias"));u.ZP.info("Creating Team");let n=await M(s,e);null!==l?r([...l,n]):r([n]),console.log("response for team create call: ".concat(n)),u.ZP.success("Team created"),b(!1)}}catch(e){console.error("Error creating the team:",e),u.ZP.error("Error creating the team: "+e,20)}},z=async e=>{try{if(null!=s&&null!=l){u.ZP.info("Adding Member");let t={role:"user",user_email:e.user_email,user_id:e.user_id},a=await K(s,f.team_id,t);console.log("response for team create call: ".concat(a.data));let n=l.findIndex(e=>(console.log("team.team_id=".concat(e.team_id,"; response.data.team_id=").concat(a.data.team_id)),e.team_id===a.data.team_id));if(console.log("foundIndex: ".concat(n)),-1!==n){let e=[...l];e[n]=a.data,r(e),Z(a.data)}v(!1)}}catch(e){console.error("Error creating the team:",e)}};return console.log("received teams ".concat(JSON.stringify(l))),(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(m,{level:4,children:"All Teams"}),(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Team Name"}),(0,a.jsx)(ek.Z,{children:"Spend (USD)"}),(0,a.jsx)(ek.Z,{children:"Budget (USD)"}),(0,a.jsx)(ek.Z,{children:"Models"}),(0,a.jsx)(ek.Z,{children:"TPM / RPM Limits"}),(0,a.jsx)(ek.Z,{children:"Info"})]})}),(0,a.jsx)(e_.Z,{children:l&&l.length>0?l.map(e=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.team_alias}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.spend}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.max_budget?e.max_budget:"No limit"}),(0,a.jsx)(ew.Z,{style:{maxWidth:"8-x",whiteSpace:"pre-wrap",overflow:"hidden"},children:Array.isArray(e.models)?(0,a.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:(0,a.jsxs)(es.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,a.jsx)("br",{}),"RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsxs)(es.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].keys&&T[e.team_id].keys.length," ","Keys"]}),(0,a.jsxs)(es.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].team_info&&T[e.team_id].team_info.members_with_roles&&T[e.team_id].team_info.members_with_roles.length," ","Members"]})]}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>F(e)}),(0,a.jsx)(ey.Z,{onClick:()=>L(e.team_id),icon:ej.Z,size:"sm"})]})]},e.team_id)):null})]}),E&&(0,a.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,a.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,a.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,a.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,a.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,a.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,a.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,a.jsx)("div",{className:"sm:flex sm:items-start",children:(0,a.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,a.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Team"}),(0,a.jsx)("div",{className:"mt-2",children:(0,a.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this team ?"})})]})})}),(0,a.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,a.jsx)(X.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,a.jsx)(X.Z,{onClick:()=>{I(!1),P(null)},children:"Cancel"})]})]})]})})]})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>b(!0),children:"+ Create New Team"}),(0,a.jsx)(ei.Z,{title:"Create Team",visible:w,width:800,footer:null,onOk:()=>{b(!1),c.resetFields()},onCancel:()=>{b(!1),c.resetFields()},children:(0,a.jsxs)(eo.Z,{form:c,onFinish:B,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(en.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S.map(e=>(0,a.jsx)(en.default.Option,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create Team"})})]})})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(m,{level:4,children:"Team Members"}),(0,a.jsx)(h,{children:"If you belong to multiple teams, this setting controls which teams members you see."}),l&&l.length>0?(0,a.jsx)(eS.Z,{defaultValue:"0",children:l.map((e,l)=>(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>{Z(e)},children:e.team_alias},l))}):(0,a.jsxs)(h,{children:["No team created. ",(0,a.jsx)("b",{children:"Defaulting to personal account."})]})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Member Name"}),(0,a.jsx)(ek.Z,{children:"Role"})]})}),(0,a.jsx)(e_.Z,{children:f?f.members_with_roles.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,a.jsx)(ew.Z,{children:e.role})]},l)):null})]})}),f&&(0,a.jsx)(e=>{let{visible:l,onCancel:t,team:s,onSubmit:r}=e,[n]=eo.Z.useForm();return(0,a.jsx)(ei.Z,{title:"Edit Team",visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{r({...e,team_id:s.team_id}),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:n,onFinish:R,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,a.jsx)(Q.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(en.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S&&S.map(e=>(0,a.jsx)(en.default.Option,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"team_id",hidden:!0})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Edit Team"})})]})})},{visible:j,onCancel:()=>{g(!1),Z(null)},team:f,onSubmit:R})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(X.Z,{className:"mx-auto mb-5",onClick:()=>v(!0),children:"+ Add member"}),(0,a.jsx)(ei.Z,{title:"Add member",visible:k,width:800,footer:null,onOk:()=>{v(!1),d.resetFields()},onCancel:()=>{v(!1),d.resetFields()},children:(0,a.jsxs)(eo.Z,{form:c,onFinish:z,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,a.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,a.jsx)(eo.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add member"})})]})})]})]})})},lr=t(18190),la=e=>{let l,{searchParams:t,accessToken:s,showSSOBanner:r}=e,[o]=eo.Z.useForm(),[i]=eo.Z.useForm(),{Title:c,Paragraph:d}=eR.default,[m,h]=(0,n.useState)(""),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)(!1),[f,y]=(0,n.useState)(!1),[Z,_]=(0,n.useState)(!1),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1);try{l=window.location.origin}catch(e){l=""}l+="/fallback/login";let S=()=>{v(!1)},N=["proxy_admin","proxy_admin_viewer"];(0,n.useEffect)(()=>{(async()=>{if(null!=s){let e=[],l=await R(s,"proxy_admin_viewer");l.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy viewers: ".concat(l));let t=await R(s,"proxy_admin");t.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy admins: ".concat(t)),console.log("combinedList: ".concat(e)),p(e)}})()},[s]);let A=()=>{_(!1),i.resetFields()},E=()=>{_(!1),i.resetFields()},I=e=>(0,a.jsxs)(eo.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,a.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,a.jsx)(eo.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add member"})})]}),C=(e,l,t)=>(0,a.jsxs)(eo.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"User Role",name:"user_role",labelCol:{span:10},labelAlign:"left",children:(0,a.jsx)(eS.Z,{value:l,children:N.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,children:e},l))})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"user_id",hidden:!0,initialValue:t,valuePropName:"user_id",className:"mt-8",children:(0,a.jsx)(ec.Z,{value:t,disabled:!0})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Update role"})})]}),P=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,null);console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),u.ZP.success("Refresh tab to see updated user role"),_(!1)}}catch(e){console.error("Error creating the key:",e)}},T=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,"proxy_admin_viewer");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),g(!1)}}catch(e){console.error("Error creating the key:",e)}},O=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call"),e.user_email,e.user_id;let l=await B(s,e,"proxy_admin");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),y(!1)}}catch(e){console.error("Error creating the key:",e)}},F=async e=>{null!=s&&W(s,{environment_variables:{PROXY_BASE_URL:e.proxy_base_url,GOOGLE_CLIENT_ID:e.google_client_id,GOOGLE_CLIENT_SECRET:e.google_client_secret}})};return console.log("admins: ".concat(null==x?void 0:x.length)),(0,a.jsxs)("div",{className:"w-full m-2 mt-2 p-8",children:[(0,a.jsx)(c,{level:4,children:"Admin Access "}),(0,a.jsxs)(d,{children:[r&&(0,a.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/ui#restrict-ui-access",children:"Requires SSO Setup"}),(0,a.jsx)("br",{}),(0,a.jsx)("b",{children:"Proxy Admin: "})," Can create keys, teams, users, add models, etc. ",(0,a.jsx)("br",{}),(0,a.jsx)("b",{children:"Proxy Admin Viewer: "}),"Can just view spend. They cannot create keys, teams or grant users access to new models."," "]}),(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-2 w-full",children:[(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsx)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Member Name"}),(0,a.jsx)(ek.Z,{children:"Role"})]})}),(0,a.jsx)(e_.Z,{children:x?x.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,a.jsx)(ew.Z,{children:e.user_role}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>_(!0)}),(0,a.jsx)(ei.Z,{title:"Update role",visible:Z,width:800,footer:null,onOk:A,onCancel:E,children:C(P,e.user_role,e.user_id)})]})]},l)):null})]})})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("div",{className:"flex justify-start",children:[(0,a.jsx)(X.Z,{className:"mr-4 mb-5",onClick:()=>y(!0),children:"+ Add admin"}),(0,a.jsx)(ei.Z,{title:"Add admin",visible:f,width:800,footer:null,onOk:()=>{y(!1),i.resetFields()},onCancel:()=>{y(!1),i.resetFields()},children:I(O)}),(0,a.jsx)(X.Z,{className:"mb-5",onClick:()=>g(!0),children:"+ Add viewer"}),(0,a.jsx)(ei.Z,{title:"Add viewer",visible:j,width:800,footer:null,onOk:()=>{g(!1),i.resetFields()},onCancel:()=>{g(!1),i.resetFields()},children:I(T)})]})})]}),(0,a.jsxs)($.Z,{children:[(0,a.jsx)(c,{level:4,children:"Add SSO"}),(0,a.jsxs)("div",{className:"flex justify-start mb-4",children:[(0,a.jsx)(X.Z,{onClick:()=>b(!0),children:"Add SSO"}),(0,a.jsx)(ei.Z,{title:"Add SSO",visible:w,width:800,footer:null,onOk:()=>{b(!1),o.resetFields()},onCancel:()=>{b(!1),o.resetFields()},children:(0,a.jsxs)(eo.Z,{form:o,onFinish:e=>{O(e),F(e),b(!1),v(!0)},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"PROXY BASE URL",name:"proxy_base_url",rules:[{required:!0,message:"Please enter the proxy base url"}],children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"GOOGLE CLIENT ID",name:"google_client_id",rules:[{required:!0,message:"Please enter the google client id"}],children:(0,a.jsx)(ec.Z.Password,{})}),(0,a.jsx)(eo.Z.Item,{label:"GOOGLE CLIENT SECRET",name:"google_client_secret",rules:[{required:!0,message:"Please enter the google client secret"}],children:(0,a.jsx)(ec.Z.Password,{})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})}),(0,a.jsxs)(ei.Z,{title:"SSO Setup Instructions",visible:k,width:800,footer:null,onOk:S,onCancel:()=>{v(!1)},children:[(0,a.jsx)("p",{children:"Follow these steps to complete the SSO setup:"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"1. DO NOT Exit this TAB"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"2. Open a new tab, visit your proxy base url"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"3. Confirm your SSO is configured correctly and you can login on the new Tab"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"4. If Step 3 is successful, you can close this tab"}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{onClick:S,children:"Done"})})]})]}),(0,a.jsxs)(lr.Z,{title:"Login without SSO",color:"teal",children:["If you need to login without sso, you can access ",(0,a.jsxs)("a",{href:l,target:"_blank",children:[(0,a.jsx)("b",{children:l})," "]})]})]})]})},ln=t(42556);let lo=[{name:"slack",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"langfuse",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"openmeter",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}}];var li=e=>{let{accessToken:l,userRole:t,userID:s}=e,[r,o]=(0,n.useState)(lo),[i,c]=(0,n.useState)([]),[d,m]=(0,n.useState)(!1),[h]=eo.Z.useForm(),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)([]),[f,y]=(0,n.useState)(""),[Z,_]=(0,n.useState)({}),[w,b]=(0,n.useState)([]),k=e=>{w.includes(e)?b(w.filter(l=>l!==e)):b([...w,e])},v={llm_exceptions:"LLM Exceptions",llm_too_slow:"LLM Responses Too Slow",llm_requests_hanging:"LLM Requests Hanging",budget_alerts:"Budget Alerts (API Keys, Users)",db_exceptions:"Database Exceptions (Read/Write)",daily_reports:"Weekly/Monthly Spend Reports"};(0,n.useEffect)(()=>{l&&t&&s&&V(l,s,t).then(e=>{console.log("callbacks",e);let l=lo;o(l=l.map(l=>{let t=e.callbacks.find(e=>e.name===l.name);return t?{...l,variables:{...l.variables,...t.variables}}:l}));let t=e.alerts;if(console.log("alerts_data",t),t&&t.length>0){let e=t[0];console.log("_alert_info",e);let l=e.variables.SLACK_WEBHOOK_URL;console.log("catch_all_webhook",l),b(e.active_alerts),y(l),_(e.alerts_to_webhook)}c(t)})},[l,t,s]);let S=e=>w&&w.includes(e),N=e=>{if(!l)return;let t=Object.fromEntries(Object.entries(e.variables).map(e=>{var l;let[t,s]=e;return[t,(null===(l=document.querySelector('input[name="'.concat(t,'"]')))||void 0===l?void 0:l.value)||s]}));console.log("updatedVariables",t),console.log("updateAlertTypes",j);let s={environment_variables:t,litellm_settings:{success_callback:[e.name]}};try{W(l,s)}catch(e){u.ZP.error("Failed to update callback: "+e,20)}u.ZP.success("Callback updated successfully")},A=()=>{l&&h.validateFields().then(e=>{if(console.log("Form values:",e),"langfuse"===e.callback){W(l,{environment_variables:{LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey,OPENMETER_API_KEY:null}};o(r?[...r,t]:[t])}else if("slack"===e.callback){console.log("values.slackWebhookUrl: ".concat(e.slackWebhookUrl)),W(l,{general_settings:{alerting:["slack"],alerting_threshold:300},environment_variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl}}),console.log("values.callback: ".concat(e.callback));let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null}};o(r?[...r,t]:[t])}else if("openmeter"==e.callback){console.log("values.openMeterApiKey: ".concat(e.openMeterApiKey)),W(l,{environment_variables:{OPENMETER_API_KEY:e.openMeterApiKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:e.openMeterAPIKey}};o(r?[...r,t]:[t])}m(!1),h.resetFields(),p(null)})};return l?(console.log("callbacks: ".concat(r)),(0,a.jsxs)("div",{className:"w-full mx-4",children:[(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,a.jsx)(lr.Z,{title:"[UI] Presidio PII + Guardrails Coming Soon. https://docs.litellm.ai/docs/proxy/pii_masking",color:"sky"}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{variant:"line",defaultValue:"1",children:[(0,a.jsx)(eU.Z,{value:"1",children:"Logging Callbacks"}),(0,a.jsx)(eU.Z,{value:"2",children:"Alerting"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Callback"}),(0,a.jsx)(ek.Z,{children:"Callback Env Vars"})]})}),(0,a.jsx)(e_.Z,{children:r.filter(e=>"slack"!==e.name).map((e,t)=>{var s;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(eg.Z,{color:"emerald",children:e.name})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)("ul",{children:Object.entries(null!==(s=e.variables)&&void 0!==s?s:{}).filter(l=>{let[t,s]=l;return t.toLowerCase().includes(e.name)}).map(e=>{let[l,t]=e;return(0,a.jsxs)("li",{children:[(0,a.jsx)(es.Z,{className:"mt-2",children:l}),"LANGFUSE_HOST"===l?(0,a.jsx)("p",{children:"default value=https://cloud.langfuse.com"}):(0,a.jsx)("div",{}),(0,a.jsx)(Q.Z,{name:l,defaultValue:t,type:"password"})]},l)})}),(0,a.jsx)(X.Z,{className:"mt-2",onClick:()=>N(e),children:"Save Changes"}),(0,a.jsx)(X.Z,{onClick:()=>z(l,e.name),className:"mx-2",children:"Test Callback"})]})]},t)})})]})})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsxs)(es.Z,{className:"my-2",children:["Alerts are only supported for Slack Webhook URLs. Get your webhook urls from ",(0,a.jsx)("a",{href:"https://api.slack.com/messaging/webhooks",target:"_blank",style:{color:"blue"},children:"here"})]}),(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{}),(0,a.jsx)(ek.Z,{}),(0,a.jsx)(ek.Z,{children:"Slack Webhook URL"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(v).map((e,l)=>{let[t,s]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(ln.Z,{id:"switch",name:"switch",checked:S(t),onChange:()=>k(t)})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:s})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(Q.Z,{name:t,type:"password",defaultValue:Z&&Z[t]?Z[t]:f})})]},l)})})]}),(0,a.jsx)(X.Z,{size:"xs",className:"mt-2",onClick:()=>{if(!l)return;let e={};Object.entries(v).forEach(l=>{let[t,s]=l,r=document.querySelector('input[name="'.concat(t,'"]'));console.log("key",t),console.log("webhookInput",r);let a=(null==r?void 0:r.value)||"";console.log("newWebhookValue",a),e[t]=a}),console.log("updatedAlertToWebhooks",e);let t={general_settings:{alert_to_webhook_url:e,alert_types:w}};console.log("payload",t);try{W(l,t)}catch(e){u.ZP.error("Failed to update alerts: "+e,20)}u.ZP.success("Alerts updated successfully")},children:"Save Changes"}),(0,a.jsx)(X.Z,{onClick:()=>z(l,"slack"),className:"mx-2",children:"Test Alerts"})]})})]})]})]}),(0,a.jsx)(ei.Z,{title:"Add Callback",visible:d,onOk:A,width:800,onCancel:()=>{m(!1),h.resetFields(),p(null)},footer:null,children:(0,a.jsxs)(eo.Z,{form:h,layout:"vertical",onFinish:A,children:[(0,a.jsx)(eo.Z.Item,{label:"Callback",name:"callback",rules:[{required:!0,message:"Please select a callback"}],children:(0,a.jsxs)(en.default,{onChange:e=>{p(e)},children:[(0,a.jsx)(en.default.Option,{value:"langfuse",children:"langfuse"}),(0,a.jsx)(en.default.Option,{value:"openmeter",children:"openmeter"})]})}),"langfuse"===x&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"LANGFUSE_PUBLIC_KEY",name:"langfusePublicKey",rules:[{required:!0,message:"Please enter the public key"}],children:(0,a.jsx)(Q.Z,{type:"password"})}),(0,a.jsx)(eo.Z.Item,{label:"LANGFUSE_PRIVATE_KEY",name:"langfusePrivateKey",rules:[{required:!0,message:"Please enter the private key"}],children:(0,a.jsx)(Q.Z,{type:"password"})})]}),"openmeter"==x&&(0,a.jsx)(a.Fragment,{children:(0,a.jsx)(eo.Z.Item,{label:"OPENMETER_API_KEY",name:"openMeterApiKey",rules:[{required:!0,message:"Please enter the openmeter api key"}],children:(0,a.jsx)(Q.Z,{type:"password"})})}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})})]})):null};let{Option:lc}=en.default;var ld=e=>{let{models:l,accessToken:t,routerSettings:s,setRouterSettings:r}=e,[o]=eo.Z.useForm(),[i,c]=(0,n.useState)(!1),[d,m]=(0,n.useState)("");return(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>c(!0),children:"+ Add Fallbacks"}),(0,a.jsx)(ei.Z,{title:"Add Fallbacks",visible:i,width:800,footer:null,onOk:()=>{c(!1),o.resetFields()},onCancel:()=>{c(!1),o.resetFields()},children:(0,a.jsxs)(eo.Z,{form:o,onFinish:e=>{console.log(e);let{model_name:l,models:a}=e,n=[...s.fallbacks||[],{[l]:a}],i={...s,fallbacks:n};console.log(i);try{W(t,{router_settings:i}),r(i)}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully"),c(!1),o.resetFields()},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Public Model Name",name:"model_name",rules:[{required:!0,message:"Set the model to fallback for"}],help:"required",children:(0,a.jsx)(eS.Z,{defaultValue:d,children:l&&l.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>m(e),children:e},l))})}),(0,a.jsx)(eo.Z.Item,{label:"Fallback Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,a.jsx)(eV.Z,{value:l,children:l&&l.filter(e=>e!=d).map(e=>(0,a.jsx)(eq.Z,{value:e,children:e},e))})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add Fallbacks"})})]})})]})},lm=t(12968);async function lu(e,l){console.log("isLocal:",!1);let t=window.location.origin,s=new lm.ZP.OpenAI({apiKey:l,baseURL:t,dangerouslyAllowBrowser:!0});try{let l=await s.chat.completions.create({model:e,messages:[{role:"user",content:"Hi, this is a test message"}],mock_testing_fallbacks:!0});u.ZP.success((0,a.jsxs)("span",{children:["Test model=",(0,a.jsx)("strong",{children:e}),", received model=",(0,a.jsx)("strong",{children:l.model}),". See"," ",(0,a.jsx)("a",{href:"#",onClick:()=>window.open("https://docs.litellm.ai/docs/proxy/reliability","_blank"),style:{textDecoration:"underline",color:"blue"},children:"curl"})]}))}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}let lh={ttl:3600,lowest_latency_buffer:0},lx=e=>{let{selectedStrategy:l,strategyArgs:t,paramExplanation:s}=e;return(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{className:"text-sm font-medium text-tremor-content-strong dark:text-dark-tremor-content-strong",children:"Routing Strategy Specific Args"}),(0,a.jsx)(el.Z,{children:"latency-based-routing"==l?(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(t).map(e=>{let[l,t]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:l}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:s[l]})]}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(Q.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]})}):(0,a.jsx)(es.Z,{children:"No specific settings"})})]})};var lp=e=>{let{accessToken:l,userRole:t,userID:s,modelData:r}=e,[o,i]=(0,n.useState)({}),[c,d]=(0,n.useState)({}),[m,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1),[j]=eo.Z.useForm(),[g,f]=(0,n.useState)(null),[y,Z]=(0,n.useState)(null),[_,w]=(0,n.useState)(null),b={routing_strategy_args:"(dict) Arguments to pass to the routing strategy",routing_strategy:"(string) Routing strategy to use",allowed_fails:"(int) Number of times a deployment can fail before being added to cooldown",cooldown_time:"(int) time in seconds to cooldown a deployment after failure",num_retries:"(int) Number of retries for failed requests. Defaults to 0.",timeout:"(float) Timeout for requests. Defaults to None.",retry_after:"(int) Minimum time to wait before retrying a failed request",ttl:"(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};(0,n.useEffect)(()=>{l&&t&&s&&(V(l,s,t).then(e=>{console.log("callbacks",e),i(e.router_settings)}),q(l).then(e=>{h(e)}))},[l,t,s]);let k=async e=>{if(l){console.log("received key: ".concat(e)),console.log("routerSettings['fallbacks']: ".concat(o.fallbacks)),o.fallbacks.map(l=>(e in l&&delete l[e],l));try{await W(l,{router_settings:o}),i({...o}),Z(o.routing_strategy),u.ZP.success("Router settings updated successfully")}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}}},v=(e,l)=>{h(m.map(t=>t.field_name===e?{...t,field_value:l}:t))},S=(e,t)=>{if(!l)return;let s=m[t].field_value;if(null!=s&&void 0!=s)try{G(l,e,s);let t=m.map(l=>l.field_name===e?{...l,stored_in_db:!0}:l);h(t)}catch(e){}},N=(e,t)=>{if(l)try{Y(l,e);let t=m.map(l=>l.field_name===e?{...l,stored_in_db:null,field_value:null}:l);h(t)}catch(e){}},A=e=>{if(!l)return;console.log("router_settings",e);let t=Object.fromEntries(Object.entries(e).map(e=>{let[l,t]=e;if("routing_strategy_args"!==l&&"routing_strategy"!==l){var s;return[l,(null===(s=document.querySelector('input[name="'.concat(l,'"]')))||void 0===s?void 0:s.value)||t]}if("routing_strategy"==l)return[l,y];if("routing_strategy_args"==l&&"latency-based-routing"==y){let e={},l=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]');return(null==l?void 0:l.value)&&(e.lowest_latency_buffer=Number(l.value)),(null==t?void 0:t.value)&&(e.ttl=Number(t.value)),console.log("setRoutingStrategyArgs: ".concat(e)),["routing_strategy_args",e]}return null}).filter(e=>null!=e));console.log("updatedVariables",t);try{W(l,{router_settings:t})}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully")};return l?(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsxs)(eD.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(eK.Z,{variant:"line",defaultValue:"1",children:[(0,a.jsx)(eU.Z,{value:"1",children:"Loadbalancing"}),(0,a.jsx)(eU.Z,{value:"2",children:"Fallbacks"}),(0,a.jsx)(eU.Z,{value:"3",children:"General"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,a.jsx)(er.Z,{children:"Router Settings"}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(o).filter(e=>{let[l,t]=e;return"fallbacks"!=l&&"context_window_fallbacks"!=l&&"routing_strategy_args"!=l}).map(e=>{let[l,t]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:l}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:b[l]})]}),(0,a.jsx)(ew.Z,{children:"routing_strategy"==l?(0,a.jsxs)(eS.Z,{defaultValue:t,className:"w-full max-w-md",onValueChange:Z,children:[(0,a.jsx)(eN.Z,{value:"usage-based-routing",children:"usage-based-routing"}),(0,a.jsx)(eN.Z,{value:"latency-based-routing",children:"latency-based-routing"}),(0,a.jsx)(eN.Z,{value:"simple-shuffle",children:"simple-shuffle"})]}):(0,a.jsx)(Q.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]}),(0,a.jsx)(lx,{selectedStrategy:y,strategyArgs:o&&o.routing_strategy_args&&Object.keys(o.routing_strategy_args).length>0?o.routing_strategy_args:lh,paramExplanation:b})]}),(0,a.jsx)(H.Z,{children:(0,a.jsx)(X.Z,{className:"mt-2",onClick:()=>A(o),children:"Save Changes"})})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Model Name"}),(0,a.jsx)(ek.Z,{children:"Fallbacks"})]})}),(0,a.jsx)(e_.Z,{children:o.fallbacks&&o.fallbacks.map((e,t)=>Object.entries(e).map(e=>{let[s,r]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:s}),(0,a.jsx)(ew.Z,{children:Array.isArray(r)?r.join(", "):r}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(X.Z,{onClick:()=>lu(s,l),children:"Test Fallback"})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(ey.Z,{icon:ej.Z,size:"sm",onClick:()=>k(s)})})]},t.toString()+s)}))})]}),(0,a.jsx)(ld,{models:(null==r?void 0:r.data)?r.data.map(e=>e.model_name):[],accessToken:l,routerSettings:o,setRouterSettings:i})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"}),(0,a.jsx)(ek.Z,{children:"Status"}),(0,a.jsx)(ek.Z,{children:"Action"})]})}),(0,a.jsx)(e_.Z,{children:m.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:e.field_name}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:e.field_description})]}),(0,a.jsx)(ew.Z,{children:"Integer"==e.field_type?(0,a.jsx)(ed.Z,{step:1,value:e.field_value,onChange:l=>v(e.field_name,l)}):null}),(0,a.jsx)(ew.Z,{children:!0==e.stored_in_db?(0,a.jsx)(eg.Z,{icon:eQ.Z,className:"text-white",children:"In DB"}):!1==e.stored_in_db?(0,a.jsx)(eg.Z,{className:"text-gray bg-white outline",children:"In Config"}):(0,a.jsx)(eg.Z,{className:"text-gray bg-white outline",children:"Not Set"})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(X.Z,{onClick:()=>S(e.field_name,l),children:"Update"}),(0,a.jsx)(ey.Z,{icon:ej.Z,color:"red",onClick:()=>N(e.field_name,l),children:"Reset"})]})]},l))})]})})})]})]})}):null},lj=t(67951),lg=e=>{let{}=e;return(0,a.jsx)(a.Fragment,{children:(0,a.jsx)($.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,a.jsxs)("div",{className:"mb-5",children:[(0,a.jsx)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:"OpenAI Compatible Proxy: API Reference"}),(0,a.jsx)(es.Z,{className:"mt-2 mb-2",children:"LiteLLM is OpenAI Compatible. This means your API Key works with the OpenAI SDK. Just replace the base_url to point to your litellm proxy. Example Below "}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{children:[(0,a.jsx)(eU.Z,{children:"OpenAI Python SDK"}),(0,a.jsx)(eU.Z,{children:"LlamaIndex"}),(0,a.jsx)(eU.Z,{children:"Langchain Py"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # LiteLLM Proxy is OpenAI compatible, Read More: https://docs.litellm.ai/docs/proxy/user_keys\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to send to the proxy\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ]\n)\n\nprint(response)\n '})}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:4000",\n model = "gpt-3.5-turbo",\n temperature=0.1\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})]})})})};async function lf(e,l,t,s){console.log("isLocal:",!1);let r=window.location.origin,a=new lm.ZP.OpenAI({apiKey:s,baseURL:r,dangerouslyAllowBrowser:!0});try{for await(let s of(await a.chat.completions.create({model:t,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&l(s.choices[0].delta.content)}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}var ly=e=>{let{accessToken:l,token:t,userRole:s,userID:r}=e,[o,i]=(0,n.useState)(""),[c,d]=(0,n.useState)(""),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)(void 0),[p,j]=(0,n.useState)([]);(0,n.useEffect)(()=>{l&&t&&s&&r&&(async()=>{try{let e=await N(l,r,s);if(console.log("model_info:",e),(null==e?void 0:e.data.length)>0){let l=e.data.map(e=>({value:e.id,label:e.id}));console.log(l),j(l),x(e.data[0].id)}}catch(e){console.error("Error fetching model info:",e)}})()},[l,r,s]);let g=(e,l)=>{u(t=>{let s=t[t.length-1];return s&&s.role===e?[...t.slice(0,t.length-1),{role:e,content:s.content+l}]:[...t,{role:e,content:l}]})},f=async()=>{if(""!==c.trim()&&o&&t&&s&&r){u(e=>[...e,{role:"user",content:c}]);try{h&&await lf(c,e=>g("assistant",e),h,o)}catch(e){console.error("Error fetching model response",e),g("assistant","Error fetching model response")}d("")}};if(s&&"Admin Viewer"==s){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to test models"})]})}return(0,a.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,a.jsx)($.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eD.Z,{children:[(0,a.jsx)(eK.Z,{children:(0,a.jsx)(eU.Z,{children:"Chat"})}),(0,a.jsx)(ez.Z,{children:(0,a.jsxs)(eB.Z,{children:[(0,a.jsx)("div",{className:"sm:max-w-2xl",children:(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"API Key"}),(0,a.jsx)(Q.Z,{placeholder:"Type API Key here",type:"password",onValueChange:i,value:o})]}),(0,a.jsxs)(H.Z,{className:"mx-2",children:[(0,a.jsx)(es.Z,{children:"Select Model:"}),(0,a.jsx)(en.default,{placeholder:"Select a Model",onChange:e=>{console.log("selected ".concat(e)),x(e)},options:p,style:{width:"200px"}})]})]})}),(0,a.jsxs)(eZ.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,a.jsx)(eb.Z,{children:(0,a.jsx)(ev.Z,{children:(0,a.jsx)(ew.Z,{})})}),(0,a.jsx)(e_.Z,{children:m.map((e,l)=>(0,a.jsx)(ev.Z,{children:(0,a.jsx)(ew.Z,{children:"".concat(e.role,": ").concat(e.content)})},l))})]}),(0,a.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)(Q.Z,{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"Type your message..."}),(0,a.jsx)(X.Z,{onClick:f,className:"ml-2",children:"Send"})]})})]})})]})})})})},lZ=t(33509),l_=t(95781);let{Sider:lw}=lZ.default;var lb=e=>{let{setPage:l,userRole:t,defaultSelectedKey:s}=e;return"Admin Viewer"==t?(0,a.jsx)(lZ.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,a.jsx)(lw,{width:120,children:(0,a.jsxs)(l_.Z,{mode:"inline",defaultSelectedKeys:s||["4"],style:{height:"100%",borderRight:0},children:[(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api-keys"),children:"API Keys"},"4"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("models"),children:"Models"},"2"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("llm-playground"),children:"Chat UI"},"3"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("usage"),children:"Usage"},"1")]})})}):(0,a.jsx)(lZ.default,{style:{minHeight:"100vh",maxWidth:"145px"},children:(0,a.jsx)(lw,{width:145,children:(0,a.jsxs)(l_.Z,{mode:"inline",defaultSelectedKeys:s||["1"],style:{height:"100%",borderRight:0},children:[(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api-keys"),children:(0,a.jsx)(es.Z,{children:"API Keys"})},"1"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("llm-playground"),children:(0,a.jsx)(es.Z,{children:"Test Key"})},"3"),"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("models"),children:(0,a.jsx)(es.Z,{children:"Models"})},"2"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("usage"),children:(0,a.jsx)(es.Z,{children:"Usage"})},"4"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("teams"),children:(0,a.jsx)(es.Z,{children:"Teams"})},"6"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("users"),children:(0,a.jsx)(es.Z,{children:"Users"})},"5"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("settings"),children:(0,a.jsx)(es.Z,{children:"Logging & Alerts"})},"8"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("general-settings"),children:(0,a.jsx)(es.Z,{children:"Router Settings"})},"9"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("admin-panel"),children:(0,a.jsx)(es.Z,{children:"Admin"})},"7"):null,(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api_ref"),children:(0,a.jsx)(es.Z,{children:"API Reference"})},"11")]})})})},lk=t(67989),lv=e=>{let{accessToken:l,token:t,userRole:s,userID:r,keys:o}=e,i=new Date,[c,d]=(0,n.useState)([]),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)([]),[p,j]=(0,n.useState)([]),[g,f]=(0,n.useState)([]),[y,Z]=(0,n.useState)([]),[_,w]=(0,n.useState)([]),[b,k]=(0,n.useState)([]),[v,S]=(0,n.useState)(""),[N,R]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),M=new Date(i.getFullYear(),i.getMonth(),1),L=new Date(i.getFullYear(),i.getMonth()+1,0),U=z(M),D=z(L);console.log("keys in usage",o);let K=async(e,t,s)=>{if(!e||!t||!l)return;console.log("uiSelectedKey",s);let r=await T(l,s,e.toISOString(),t.toISOString());console.log("End user data updated successfully",r),j(r)},B=async(e,t)=>{e&&t&&l&&(Z((await E(l,e.toISOString(),t.toISOString())).spend_per_tag),console.log("Tag spend data updated successfully"))};function z(e){let l=e.getFullYear(),t=e.getMonth()+1,s=e.getDate();return"".concat(l,"-").concat(t<10?"0"+t:t,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(U)),console.log("End date is ".concat(D)),(0,n.useEffect)(()=>{l&&t&&s&&r&&(async()=>{try{if(console.log("user role: ".concat(s)),"Admin"==s||"Admin Viewer"==s){var e,a;let t=await C(l);d(t);let s=(await P(l)).map(e=>({key:(e.key_name||e.key_alias||e.api_key).substring(0,10),spend:e.total_spend}));u(s);let r=(await O(l)).map(e=>({key:e.model,spend:e.total_spend}));x(r);let n=await A(l);console.log("teamSpend",n),f(n.daily_spend),w(n.teams);let o=n.total_spend_per_team;o=o.map(e=>(e.name=e.team_id||"",e.value=e.total_spend||0,e)),k(o);let i=await E(l,null===(e=N.from)||void 0===e?void 0:e.toISOString(),null===(a=N.to)||void 0===a?void 0:a.toISOString());Z(i.spend_per_tag);let c=await T(l,null,void 0,void 0);j(c),console.log("spend/user result",c)}else"App Owner"==s&&await I(l,t,s,r,U,D).then(async e=>{if(console.log("result from spend logs call",e),"daily_spend"in e){let l=e.daily_spend;console.log("daily spend",l),d(l);let t=e.top_api_keys;u(t)}else{let t=(await F(l,function(e){let l=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[t,s]=e;"spend"!==t&&"startTime"!==t&&"models"!==t&&"users"!==t&&l.push({key:t,spend:s})})}),l.sort((e,l)=>Number(l.spend)-Number(e.spend));let t=l.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(t[0]))),t}(e))).info.map(e=>({key:(e.key_name||e.key_alias).substring(0,10),spend:e.spend}));u(t),d(e)}})}catch(e){console.error("There was an error fetching the data",e)}})()},[l,t,s,r,U,D]),(0,a.jsxs)("div",{style:{width:"100%"},className:"p-8",children:[(0,a.jsx)(eP,{userID:r,userRole:s,accessToken:l,userSpend:null,selectedTeam:null}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{className:"mt-2",children:[(0,a.jsx)(eU.Z,{children:"All Up"}),(0,a.jsx)(eU.Z,{children:"Team Based Usage"}),(0,a.jsx)(eU.Z,{children:"End User Usage"}),(0,a.jsx)(eU.Z,{children:"Tag Based Usage"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,a.jsx)(H.Z,{numColSpan:2,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Monthly Spend"}),(0,a.jsx)(eY.Z,{data:c,index:"date",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5})]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Top API Keys"}),(0,a.jsx)(eY.Z,{className:"mt-4 h-40",data:m,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Top Models"}),(0,a.jsx)(eY.Z,{className:"mt-4 h-40",data:h,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,a.jsx)(H.Z,{numColSpan:1})]})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,a.jsxs)(H.Z,{numColSpan:2,children:[(0,a.jsxs)(ef.Z,{className:"mb-2",children:[(0,a.jsx)(er.Z,{children:"Total Spend Per Team"}),(0,a.jsx)(lk.Z,{data:b})]}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Daily Spend Per Team"}),(0,a.jsx)(eY.Z,{className:"h-72",data:g,showLegend:!0,index:"date",categories:_,yAxisWidth:80,colors:["blue","green","yellow","red","purple"],stack:!0})]})]}),(0,a.jsx)(H.Z,{numColSpan:2})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)("p",{className:"mb-2 text-gray-500 italic text-[12px]",children:["End-Users of your LLM API calls. Tracked when a `user` param is passed in your LLM calls ",(0,a.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/users",target:"_blank",children:"docs here"})]}),(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Time Range"}),(0,a.jsx)(eL.Z,{enableSelect:!0,value:N,onValueChange:e=>{R(e),K(e.from,e.to,null)}})]}),(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Key"}),(0,a.jsxs)(eS.Z,{defaultValue:"all-keys",children:[(0,a.jsx)(eN.Z,{value:"all-keys",onClick:()=>{K(N.from,N.to,null)},children:"All Keys"},"all-keys"),null==o?void 0:o.map((e,l)=>e&&null!==e.key_alias&&e.key_alias.length>0?(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>{K(N.from,N.to,e.token)},children:e.key_alias},l):null)]})]})]}),(0,a.jsx)(ef.Z,{className:"mt-4",children:(0,a.jsxs)(eZ.Z,{className:"max-h-[70vh] min-h-[500px]",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"End User"}),(0,a.jsx)(ek.Z,{children:"Spend"}),(0,a.jsx)(ek.Z,{children:"Total Events"})]})}),(0,a.jsx)(e_.Z,{children:null==p?void 0:p.map((e,l)=>{var t;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.end_user}),(0,a.jsx)(ew.Z,{children:null===(t=e.total_spend)||void 0===t?void 0:t.toFixed(4)}),(0,a.jsx)(ew.Z,{children:e.total_count})]},l)})})]})})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full mb-4",children:[(0,a.jsxs)(H.Z,{numColSpan:2,children:[(0,a.jsx)(eL.Z,{className:"mb-4",enableSelect:!0,value:N,onValueChange:e=>{R(e),B(e.from,e.to)}}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Spend Per Tag"}),(0,a.jsxs)(es.Z,{children:["Get Started Tracking cost per tag ",(0,a.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags",target:"_blank",children:"here"})]}),(0,a.jsx)(eY.Z,{className:"h-72",data:y,index:"name",categories:["spend"],colors:["blue"]})]})]}),(0,a.jsx)(H.Z,{numColSpan:2})]})})]})]})]})},lS=()=>{let{Title:e,Paragraph:l}=eR.default,[t,s]=(0,n.useState)(""),[r,i]=(0,n.useState)(null),[c,d]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(!0),j=(0,o.useSearchParams)(),[g,f]=(0,n.useState)({data:[]}),y=j.get("userID"),Z=j.get("token"),[_,w]=(0,n.useState)("api-keys"),[b,k]=(0,n.useState)(null);return(0,n.useEffect)(()=>{if(Z){let e=(0,eF.o)(Z);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),k(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e.toLowerCase())),console.log("Received user role length: ".concat(e.toLowerCase().length)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),s(l),"Admin Viewer"==l&&w("usage")}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e)),e.login_method?p("username_password"==e.login_method):console.log("User Email is not set ".concat(e))}}},[Z]),(0,a.jsx)(n.Suspense,{fallback:(0,a.jsx)("div",{children:"Loading..."}),children:(0,a.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,a.jsx)(m,{userID:y,userRole:t,userEmail:r,showSSOBanner:x}),(0,a.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,a.jsx)("div",{className:"mt-8",children:(0,a.jsx)(lb,{setPage:w,userRole:t,defaultSelectedKey:null})}),"api-keys"==_?(0,a.jsx)(eM,{userID:y,userRole:t,teams:c,keys:u,setUserRole:s,userEmail:r,setUserEmail:i,setTeams:d,setKeys:h}):"models"==_?(0,a.jsx)(e9,{userID:y,userRole:t,token:Z,accessToken:b,modelData:g,setModelData:f}):"llm-playground"==_?(0,a.jsx)(ly,{userID:y,userRole:t,token:Z,accessToken:b}):"users"==_?(0,a.jsx)(lt,{userID:y,userRole:t,token:Z,keys:u,teams:c,accessToken:b,setKeys:h}):"teams"==_?(0,a.jsx)(ls,{teams:c,setTeams:d,searchParams:j,accessToken:b,userID:y,userRole:t}):"admin-panel"==_?(0,a.jsx)(la,{setTeams:d,searchParams:j,accessToken:b,showSSOBanner:x}):"api_ref"==_?(0,a.jsx)(lg,{}):"settings"==_?(0,a.jsx)(li,{userID:y,userRole:t,accessToken:b}):"general-settings"==_?(0,a.jsx)(lp,{userID:y,userRole:t,accessToken:b,modelData:g}):(0,a.jsx)(lv,{userID:y,userRole:t,token:Z,accessToken:b,keys:u})]})]})})}}},function(e){e.O(0,[936,884,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/index.html b/litellm/proxy/_experimental/out/index.html index 930018e005..011bb7fc76 100644 --- a/litellm/proxy/_experimental/out/index.html +++ b/litellm/proxy/_experimental/out/index.html @@ -1 +1 @@ -LiteLLM Dashboard \ No newline at end of file +LiteLLM Dashboard \ No newline at end of file diff --git a/litellm/proxy/_experimental/out/index.txt b/litellm/proxy/_experimental/out/index.txt index d67a480b37..ce4099b2cd 100644 --- a/litellm/proxy/_experimental/out/index.txt +++ b/litellm/proxy/_experimental/out/index.txt @@ -1,7 +1,7 @@ 2:I[77831,[],""] -3:I[7926,["936","static/chunks/2f6dbc85-052c4579f80d66ae.js","884","static/chunks/884-7576ee407a2ecbe6.js","931","static/chunks/app/page-6a39771cacf75ea6.js"],""] +3:I[4858,["936","static/chunks/2f6dbc85-052c4579f80d66ae.js","884","static/chunks/884-7576ee407a2ecbe6.js","931","static/chunks/app/page-c35c14c9afd091ec.js"],""] 4:I[5613,[],""] 5:I[31778,[],""] -0:["obp5wqVSVDMiDTC414cR8",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/f04e46b02318b660.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] +0:["2ASoJGxS-D4w-vat00xMy",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/f04e46b02318b660.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] 6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] 1:null diff --git a/litellm/proxy/_super_secret_config.yaml b/litellm/proxy/_super_secret_config.yaml index 0e9e43bc99..8d3e4f5e14 100644 --- a/litellm/proxy/_super_secret_config.yaml +++ b/litellm/proxy/_super_secret_config.yaml @@ -18,11 +18,6 @@ model_list: model: azure/chatgpt-v-2 api_key: os.environ/AZURE_API_KEY api_base: os.environ/AZURE_API_BASE - input_cost_per_token: 0.0 - output_cost_per_token: 0.0 -- model_name: gpt-3.5-turbo - litellm_params: - model: gpt-4o - model_name: bert-classifier litellm_params: model: huggingface/text-classification/shahrukhx01/question-vs-statement-classifier @@ -34,14 +29,17 @@ router_settings: enable_pre_call_checks: true litellm_settings: - set_verbose: True - fallbacks: [{"gpt-3.5-turbo-012": ["gpt-3.5-turbo-0125-preview"]}] + fallbacks: [{"gpt-3.5-turbo-012": ["azure-gpt-3.5-turbo"]}] # service_callback: ["prometheus_system"] # success_callback: ["prometheus"] # failure_callback: ["prometheus"] general_settings: enable_jwt_auth: True + litellm_jwtauth: + team_id_default: "1234" + user_id_jwt_field: + user_id_upsert: True disable_reset_budget: True proxy_batch_write_at: 10 # 👈 Frequency of batch writing logs to server (in seconds) routing_strategy: simple-shuffle # Literal["simple-shuffle", "least-busy", "usage-based-routing","latency-based-routing"], default="simple-shuffle" diff --git a/litellm/proxy/_types.py b/litellm/proxy/_types.py index b1af153e81..d6bf49dca6 100644 --- a/litellm/proxy/_types.py +++ b/litellm/proxy/_types.py @@ -1,37 +1,11 @@ -from pydantic import ConfigDict, BaseModel, Field, root_validator, Json, VERSION +from pydantic import BaseModel, Extra, Field, root_validator, Json, validator +from dataclasses import fields import enum from typing import Optional, List, Union, Dict, Literal, Any from datetime import datetime -import uuid -import json +import uuid, json, sys, os from litellm.types.router import UpdateRouterConfig -try: - from pydantic import model_validator # type: ignore -except ImportError: - from pydantic import root_validator # pydantic v1 - - def model_validator(mode): # type: ignore - pre = mode == "before" - return root_validator(pre=pre) - - -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config(arbitrary_types_allowed: bool = False) -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", arbitrary_types_allowed=arbitrary_types_allowed, protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow, arbitrary_types_allowed=arbitrary_types_allowed) # type: ignore - - return model_config - def hash_token(token: str): import hashlib @@ -61,7 +35,8 @@ class LiteLLMBase(BaseModel): # if using pydantic v1 return self.__fields_set__ - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLM_UpperboundKeyGenerateParams(LiteLLMBase): @@ -104,11 +79,6 @@ class LiteLLMRoutes(enum.Enum): "/v1/models", ] - # NOTE: ROUTES ONLY FOR MASTER KEY - only the Master Key should be able to Reset Spend - master_key_only_routes: List = [ - "/global/spend/reset", - ] - info_routes: List = [ "/key/info", "/team/info", @@ -119,6 +89,11 @@ class LiteLLMRoutes(enum.Enum): "/v2/key/info", ] + # NOTE: ROUTES ONLY FOR MASTER KEY - only the Master Key should be able to Reset Spend + master_key_only_routes: List = [ + "/global/spend/reset", + ] + sso_only_routes: List = [ "/key/generate", "/key/update", @@ -227,13 +202,19 @@ class LiteLLM_JWTAuth(LiteLLMBase): "global_spend_tracking_routes", "info_routes", ] - team_jwt_scope: str = "litellm_team" - team_id_jwt_field: str = "client_id" + team_id_jwt_field: Optional[str] = None team_allowed_routes: List[ Literal["openai_routes", "info_routes", "management_routes"] ] = ["openai_routes", "info_routes"] + team_id_default: Optional[str] = Field( + default=None, + description="If no team_id given, default permissions/spend-tracking to this team.s", + ) org_id_jwt_field: Optional[str] = None user_id_jwt_field: Optional[str] = None + user_id_upsert: bool = Field( + default=False, description="If user doesn't exist, upsert them into the db." + ) end_user_id_jwt_field: Optional[str] = None public_key_ttl: float = 600 @@ -259,7 +240,7 @@ class LiteLLMPromptInjectionParams(LiteLLMBase): llm_api_system_prompt: Optional[str] = None llm_api_fail_call_string: Optional[str] = None - @model_validator(mode="before") + @root_validator(pre=True) def check_llm_api_params(cls, values): llm_api_check = values.get("llm_api_check") if llm_api_check is True: @@ -317,7 +298,8 @@ class ProxyChatCompletionRequest(LiteLLMBase): deployment_id: Optional[str] = None request_timeout: Optional[int] = None - model_config = get_model_config() + class Config: + extra = "allow" # allow params not defined here, these fall in litellm.completion(**kwargs) class ModelInfoDelete(LiteLLMBase): @@ -344,9 +326,11 @@ class ModelInfo(LiteLLMBase): ] ] - model_config = get_model_config() + class Config: + extra = Extra.allow # Allow extra fields + protected_namespaces = () - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): if values.get("id") is None: values.update({"id": str(uuid.uuid4())}) @@ -372,9 +356,10 @@ class ModelParams(LiteLLMBase): litellm_params: dict model_info: ModelInfo - model_config = get_model_config() + class Config: + protected_namespaces = () - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): if values.get("model_info") is None: values.update({"model_info": ModelInfo()}) @@ -410,7 +395,8 @@ class GenerateKeyRequest(GenerateRequestBase): {} ) # {"gpt-4": 5.0, "gpt-3.5-turbo": 5.0}, defaults to {} - model_config = get_model_config() + class Config: + protected_namespaces = () class GenerateKeyResponse(GenerateKeyRequest): @@ -420,7 +406,7 @@ class GenerateKeyResponse(GenerateKeyRequest): user_id: Optional[str] = None token_id: Optional[str] = None - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): if values.get("token") is not None: values.update({"key": values.get("token")}) @@ -460,7 +446,8 @@ class LiteLLM_ModelTable(LiteLLMBase): created_by: str updated_by: str - model_config = get_model_config() + class Config: + protected_namespaces = () class NewUserRequest(GenerateKeyRequest): @@ -488,7 +475,7 @@ class UpdateUserRequest(GenerateRequestBase): user_role: Optional[str] = None max_budget: Optional[float] = None - @model_validator(mode="before") + @root_validator(pre=True) def check_user_info(cls, values): if values.get("user_id") is None and values.get("user_email") is None: raise ValueError("Either user id or user email must be provided") @@ -508,7 +495,7 @@ class NewEndUserRequest(LiteLLMBase): None # if no equivalent model in allowed region - default all requests to this model ) - @model_validator(mode="before") + @root_validator(pre=True) def check_user_info(cls, values): if values.get("max_budget") is not None and values.get("budget_id") is not None: raise ValueError("Set either 'max_budget' or 'budget_id', not both.") @@ -521,7 +508,7 @@ class Member(LiteLLMBase): user_id: Optional[str] = None user_email: Optional[str] = None - @model_validator(mode="before") + @root_validator(pre=True) def check_user_info(cls, values): if values.get("user_id") is None and values.get("user_email") is None: raise ValueError("Either user id or user email must be provided") @@ -546,7 +533,8 @@ class TeamBase(LiteLLMBase): class NewTeamRequest(TeamBase): model_aliases: Optional[dict] = None - model_config = get_model_config() + class Config: + protected_namespaces = () class GlobalEndUsersSpend(LiteLLMBase): @@ -565,7 +553,7 @@ class TeamMemberDeleteRequest(LiteLLMBase): user_id: Optional[str] = None user_email: Optional[str] = None - @model_validator(mode="before") + @root_validator(pre=True) def check_user_info(cls, values): if values.get("user_id") is None and values.get("user_email") is None: raise ValueError("Either user id or user email must be provided") @@ -599,9 +587,10 @@ class LiteLLM_TeamTable(TeamBase): budget_reset_at: Optional[datetime] = None model_id: Optional[int] = None - model_config = get_model_config() + class Config: + protected_namespaces = () - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): dict_fields = [ "metadata", @@ -637,7 +626,8 @@ class LiteLLM_BudgetTable(LiteLLMBase): model_max_budget: Optional[dict] = None budget_duration: Optional[str] = None - model_config = get_model_config() + class Config: + protected_namespaces = () class NewOrganizationRequest(LiteLLM_BudgetTable): @@ -687,7 +677,8 @@ class KeyManagementSettings(LiteLLMBase): class TeamDefaultSettings(LiteLLMBase): team_id: str - model_config = get_model_config() + class Config: + extra = "allow" # allow params not defined here, these fall in litellm.completion(**kwargs) class DynamoDBArgs(LiteLLMBase): @@ -711,6 +702,25 @@ class DynamoDBArgs(LiteLLMBase): assume_role_aws_session_name: Optional[str] = None +class ConfigFieldUpdate(LiteLLMBase): + field_name: str + field_value: Any + config_type: Literal["general_settings"] + + +class ConfigFieldDelete(LiteLLMBase): + config_type: Literal["general_settings"] + field_name: str + + +class ConfigList(LiteLLMBase): + field_name: str + field_type: str + field_description: str + field_value: Any + stored_in_db: Optional[bool] + + class ConfigGeneralSettings(LiteLLMBase): """ Documents all the fields supported by `general_settings` in config.yaml @@ -758,7 +768,11 @@ class ConfigGeneralSettings(LiteLLMBase): description="override user_api_key_auth with your own auth script - https://docs.litellm.ai/docs/proxy/virtual_keys#custom-auth", ) max_parallel_requests: Optional[int] = Field( - None, description="maximum parallel requests for each api key" + None, + description="maximum parallel requests for each api key", + ) + global_max_parallel_requests: Optional[int] = Field( + None, description="global max parallel requests to allow for a proxy instance." ) infer_model_from_keys: Optional[bool] = Field( None, @@ -828,7 +842,8 @@ class ConfigYAML(LiteLLMBase): description="litellm router object settings. See router.py __init__ for all, example router.num_retries=5, router.timeout=5, router.max_retries=5, router.retry_after=5", ) - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLM_VerificationToken(LiteLLMBase): @@ -862,7 +877,8 @@ class LiteLLM_VerificationToken(LiteLLMBase): user_id_rate_limits: Optional[dict] = None team_id_rate_limits: Optional[dict] = None - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLM_VerificationTokenView(LiteLLM_VerificationToken): @@ -892,7 +908,7 @@ class UserAPIKeyAuth( user_role: Optional[Literal["proxy_admin", "app_owner", "app_user"]] = None allowed_model_region: Optional[Literal["eu"]] = None - @model_validator(mode="before") + @root_validator(pre=True) def check_api_key(cls, values): if values.get("api_key") is not None: values.update({"token": hash_token(values.get("api_key"))}) @@ -919,7 +935,7 @@ class LiteLLM_UserTable(LiteLLMBase): tpm_limit: Optional[int] = None rpm_limit: Optional[int] = None - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): if values.get("spend") is None: values.update({"spend": 0.0}) @@ -927,7 +943,8 @@ class LiteLLM_UserTable(LiteLLMBase): values.update({"models": []}) return values - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLM_EndUserTable(LiteLLMBase): @@ -939,13 +956,14 @@ class LiteLLM_EndUserTable(LiteLLMBase): default_model: Optional[str] = None litellm_budget_table: Optional[LiteLLM_BudgetTable] = None - @model_validator(mode="before") + @root_validator(pre=True) def set_model_info(cls, values): if values.get("spend") is None: values.update({"spend": 0.0}) return values - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLM_SpendLogs(LiteLLMBase): diff --git a/litellm/proxy/auth/auth_checks.py b/litellm/proxy/auth/auth_checks.py index 62e5eba013..08da25556d 100644 --- a/litellm/proxy/auth/auth_checks.py +++ b/litellm/proxy/auth/auth_checks.py @@ -26,7 +26,7 @@ all_routes = LiteLLMRoutes.openai_routes.value + LiteLLMRoutes.management_routes def common_checks( request_body: dict, - team_object: LiteLLM_TeamTable, + team_object: Optional[LiteLLM_TeamTable], user_object: Optional[LiteLLM_UserTable], end_user_object: Optional[LiteLLM_EndUserTable], global_proxy_spend: Optional[float], @@ -45,13 +45,14 @@ def common_checks( 6. [OPTIONAL] If 'litellm.max_budget' is set (>0), is proxy under budget """ _model = request_body.get("model", None) - if team_object.blocked == True: + if team_object is not None and team_object.blocked == True: raise Exception( f"Team={team_object.team_id} is blocked. Update via `/team/unblock` if your admin." ) # 2. If user can call model if ( _model is not None + and team_object is not None and len(team_object.models) > 0 and _model not in team_object.models ): @@ -65,7 +66,8 @@ def common_checks( ) # 3. If team is in budget if ( - team_object.max_budget is not None + team_object is not None + and team_object.max_budget is not None and team_object.spend is not None and team_object.spend > team_object.max_budget ): @@ -239,6 +241,7 @@ async def get_user_object( user_id: str, prisma_client: Optional[PrismaClient], user_api_key_cache: DualCache, + user_id_upsert: bool, ) -> Optional[LiteLLM_UserTable]: """ - Check if user id in proxy User Table @@ -252,7 +255,7 @@ async def get_user_object( return None # check if in cache - cached_user_obj = user_api_key_cache.async_get_cache(key=user_id) + cached_user_obj = await user_api_key_cache.async_get_cache(key=user_id) if cached_user_obj is not None: if isinstance(cached_user_obj, dict): return LiteLLM_UserTable(**cached_user_obj) @@ -260,16 +263,27 @@ async def get_user_object( return cached_user_obj # else, check db try: + response = await prisma_client.db.litellm_usertable.find_unique( where={"user_id": user_id} ) if response is None: - raise Exception + if user_id_upsert: + response = await prisma_client.db.litellm_usertable.create( + data={"user_id": user_id} + ) + else: + raise Exception - return LiteLLM_UserTable(**response.dict()) - except Exception as e: # if end-user not in db - raise Exception( + _response = LiteLLM_UserTable(**dict(response)) + + # save the user object to cache + await user_api_key_cache.async_set_cache(key=user_id, value=_response) + + return _response + except Exception as e: # if user not in db + raise ValueError( f"User doesn't exist in db. 'user_id'={user_id}. Create user via `/user/new` call." ) @@ -290,7 +304,7 @@ async def get_team_object( ) # check if in cache - cached_team_obj = user_api_key_cache.async_get_cache(key=team_id) + cached_team_obj = await user_api_key_cache.async_get_cache(key=team_id) if cached_team_obj is not None: if isinstance(cached_team_obj, dict): return LiteLLM_TeamTable(**cached_team_obj) @@ -305,7 +319,11 @@ async def get_team_object( if response is None: raise Exception - return LiteLLM_TeamTable(**response.dict()) + _response = LiteLLM_TeamTable(**response.dict()) + # save the team object to cache + await user_api_key_cache.async_set_cache(key=response.team_id, value=_response) + + return _response except Exception as e: raise Exception( f"Team doesn't exist in db. Team={team_id}. Create team via `/team/new` call." diff --git a/litellm/proxy/auth/handle_jwt.py b/litellm/proxy/auth/handle_jwt.py index 18c0d7b2ce..0a186d7dde 100644 --- a/litellm/proxy/auth/handle_jwt.py +++ b/litellm/proxy/auth/handle_jwt.py @@ -55,12 +55,9 @@ class JWTHandler: return True return False - def is_team(self, scopes: list) -> bool: - if self.litellm_jwtauth.team_jwt_scope in scopes: - return True - return False - - def get_end_user_id(self, token: dict, default_value: Optional[str]) -> str: + def get_end_user_id( + self, token: dict, default_value: Optional[str] + ) -> Optional[str]: try: if self.litellm_jwtauth.end_user_id_jwt_field is not None: user_id = token[self.litellm_jwtauth.end_user_id_jwt_field] @@ -70,13 +67,36 @@ class JWTHandler: user_id = default_value return user_id + def is_required_team_id(self) -> bool: + """ + Returns: + - True: if 'team_id_jwt_field' is set + - False: if not + """ + if self.litellm_jwtauth.team_id_jwt_field is None: + return False + return True + def get_team_id(self, token: dict, default_value: Optional[str]) -> Optional[str]: try: - team_id = token[self.litellm_jwtauth.team_id_jwt_field] + if self.litellm_jwtauth.team_id_jwt_field is not None: + team_id = token[self.litellm_jwtauth.team_id_jwt_field] + elif self.litellm_jwtauth.team_id_default is not None: + team_id = self.litellm_jwtauth.team_id_default + else: + team_id = None except KeyError: team_id = default_value return team_id + def is_upsert_user_id(self) -> bool: + """ + Returns: + - True: if 'user_id_upsert' is set + - False: if not + """ + return self.litellm_jwtauth.user_id_upsert + def get_user_id(self, token: dict, default_value: Optional[str]) -> Optional[str]: try: if self.litellm_jwtauth.user_id_jwt_field is not None: @@ -165,7 +185,7 @@ class JWTHandler: decode_options = None if audience is None: decode_options = {"verify_aud": False} - + from jwt.algorithms import RSAAlgorithm header = jwt.get_unverified_header(token) @@ -207,12 +227,14 @@ class JWTHandler: raise Exception(f"Validation fails: {str(e)}") elif public_key is not None and isinstance(public_key, str): try: - cert = x509.load_pem_x509_certificate(public_key.encode(), default_backend()) + cert = x509.load_pem_x509_certificate( + public_key.encode(), default_backend() + ) # Extract public key key = cert.public_key().public_bytes( serialization.Encoding.PEM, - serialization.PublicFormat.SubjectPublicKeyInfo + serialization.PublicFormat.SubjectPublicKeyInfo, ) # decode the token using the public key @@ -221,7 +243,7 @@ class JWTHandler: key, algorithms=algorithms, audience=audience, - options=decode_options + options=decode_options, ) return payload diff --git a/litellm/proxy/hooks/parallel_request_limiter.py b/litellm/proxy/hooks/parallel_request_limiter.py index 28e6d1853f..26238b6c08 100644 --- a/litellm/proxy/hooks/parallel_request_limiter.py +++ b/litellm/proxy/hooks/parallel_request_limiter.py @@ -79,6 +79,9 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): max_parallel_requests = user_api_key_dict.max_parallel_requests if max_parallel_requests is None: max_parallel_requests = sys.maxsize + global_max_parallel_requests = data.get("metadata", {}).get( + "global_max_parallel_requests", None + ) tpm_limit = getattr(user_api_key_dict, "tpm_limit", sys.maxsize) if tpm_limit is None: tpm_limit = sys.maxsize @@ -91,6 +94,24 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): # Setup values # ------------ + if global_max_parallel_requests is not None: + # get value from cache + _key = "global_max_parallel_requests" + current_global_requests = await cache.async_get_cache( + key=_key, local_only=True + ) + # check if below limit + if current_global_requests is None: + current_global_requests = 1 + # if above -> raise error + if current_global_requests >= global_max_parallel_requests: + raise HTTPException( + status_code=429, detail="Max parallel request limit reached." + ) + # if below -> increment + else: + await cache.async_increment_cache(key=_key, value=1, local_only=True) + current_date = datetime.now().strftime("%Y-%m-%d") current_hour = datetime.now().strftime("%H") current_minute = datetime.now().strftime("%M") @@ -207,6 +228,9 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): async def async_log_success_event(self, kwargs, response_obj, start_time, end_time): try: self.print_verbose(f"INSIDE parallel request limiter ASYNC SUCCESS LOGGING") + global_max_parallel_requests = kwargs["litellm_params"]["metadata"].get( + "global_max_parallel_requests", None + ) user_api_key = kwargs["litellm_params"]["metadata"]["user_api_key"] user_api_key_user_id = kwargs["litellm_params"]["metadata"].get( "user_api_key_user_id", None @@ -222,6 +246,14 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): # Setup values # ------------ + if global_max_parallel_requests is not None: + # get value from cache + _key = "global_max_parallel_requests" + # decrement + await self.user_api_key_cache.async_increment_cache( + key=_key, value=-1, local_only=True + ) + current_date = datetime.now().strftime("%Y-%m-%d") current_hour = datetime.now().strftime("%H") current_minute = datetime.now().strftime("%M") @@ -336,6 +368,9 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): async def async_log_failure_event(self, kwargs, response_obj, start_time, end_time): try: self.print_verbose(f"Inside Max Parallel Request Failure Hook") + global_max_parallel_requests = kwargs["litellm_params"]["metadata"].get( + "global_max_parallel_requests", None + ) user_api_key = ( kwargs["litellm_params"].get("metadata", {}).get("user_api_key", None) ) @@ -347,17 +382,26 @@ class _PROXY_MaxParallelRequestsHandler(CustomLogger): return ## decrement call count if call failed - if ( - hasattr(kwargs["exception"], "status_code") - and kwargs["exception"].status_code == 429 - and "Max parallel request limit reached" in str(kwargs["exception"]) - ): + if "Max parallel request limit reached" in str(kwargs["exception"]): pass # ignore failed calls due to max limit being reached else: # ------------ # Setup values # ------------ + if global_max_parallel_requests is not None: + # get value from cache + _key = "global_max_parallel_requests" + current_global_requests = ( + await self.user_api_key_cache.async_get_cache( + key=_key, local_only=True + ) + ) + # decrement + await self.user_api_key_cache.async_increment_cache( + key=_key, value=-1, local_only=True + ) + current_date = datetime.now().strftime("%Y-%m-%d") current_hour = datetime.now().strftime("%H") current_minute = datetime.now().strftime("%M") diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index 9192198453..83da986f6d 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -234,6 +234,7 @@ class SpecialModelNames(enum.Enum): class CommonProxyErrors(enum.Enum): db_not_connected_error = "DB not connected" no_llm_router = "No models configured on proxy" + not_allowed_access = "Admin-only endpoint. Not allowed to access this." @app.exception_handler(ProxyException) @@ -440,29 +441,32 @@ async def user_api_key_auth( # get team id team_id = jwt_handler.get_team_id(token=valid_token, default_value=None) - if team_id is None: + if team_id is None and jwt_handler.is_required_team_id() == True: raise Exception( f"No team id passed in. Field checked in jwt token - '{jwt_handler.litellm_jwtauth.team_id_jwt_field}'" ) - # check allowed team routes - is_allowed = allowed_routes_check( - user_role="team", - user_route=route, - litellm_proxy_roles=jwt_handler.litellm_jwtauth, - ) - if is_allowed == False: - allowed_routes = jwt_handler.litellm_jwtauth.team_allowed_routes # type: ignore - actual_routes = get_actual_routes(allowed_routes=allowed_routes) - raise Exception( - f"Team not allowed to access this route. Route={route}, Allowed Routes={actual_routes}" - ) - # check if team in db - team_object = await get_team_object( - team_id=team_id, - prisma_client=prisma_client, - user_api_key_cache=user_api_key_cache, - ) + team_object: Optional[LiteLLM_TeamTable] = None + if team_id is not None: + # check allowed team routes + is_allowed = allowed_routes_check( + user_role="team", + user_route=route, + litellm_proxy_roles=jwt_handler.litellm_jwtauth, + ) + if is_allowed == False: + allowed_routes = jwt_handler.litellm_jwtauth.team_allowed_routes # type: ignore + actual_routes = get_actual_routes(allowed_routes=allowed_routes) + raise Exception( + f"Team not allowed to access this route. Route={route}, Allowed Routes={actual_routes}" + ) + + # check if team in db + team_object = await get_team_object( + team_id=team_id, + prisma_client=prisma_client, + user_api_key_cache=user_api_key_cache, + ) # [OPTIONAL] track spend for an org id - `LiteLLM_OrganizationTable` org_id = jwt_handler.get_org_id(token=valid_token, default_value=None) @@ -481,11 +485,9 @@ async def user_api_key_auth( user_id=user_id, prisma_client=prisma_client, user_api_key_cache=user_api_key_cache, + user_id_upsert=jwt_handler.is_upsert_user_id(), ) - # save the user object to cache - await user_api_key_cache.async_set_cache( - key=user_id, value=user_object - ) + # [OPTIONAL] track spend against an external user - `LiteLLM_EndUserTable` end_user_object = None end_user_id = jwt_handler.get_end_user_id( @@ -547,18 +549,18 @@ async def user_api_key_auth( global_proxy_spend=global_proxy_spend, route=route, ) - # save team object in cache - await user_api_key_cache.async_set_cache( - key=team_object.team_id, value=team_object - ) # return UserAPIKeyAuth object return UserAPIKeyAuth( api_key=None, - team_id=team_object.team_id, - team_tpm_limit=team_object.tpm_limit, - team_rpm_limit=team_object.rpm_limit, - team_models=team_object.models, + team_id=team_object.team_id if team_object is not None else None, + team_tpm_limit=( + team_object.tpm_limit if team_object is not None else None + ), + team_rpm_limit=( + team_object.rpm_limit if team_object is not None else None + ), + team_models=team_object.models if team_object is not None else [], user_role="app_owner", user_id=user_id, org_id=org_id, @@ -566,9 +568,9 @@ async def user_api_key_auth( #### ELSE #### if master_key is None: if isinstance(api_key, str): - return UserAPIKeyAuth(api_key=api_key) + return UserAPIKeyAuth(api_key=api_key, user_role="proxy_admin") else: - return UserAPIKeyAuth() + return UserAPIKeyAuth(user_role="proxy_admin") elif api_key is None: # only require api key if master key is set raise Exception("No api key passed in.") elif api_key == "": @@ -659,6 +661,7 @@ async def user_api_key_auth( verbose_proxy_logger.debug("Token from db: %s", valid_token) elif valid_token is not None: verbose_proxy_logger.debug("API Key Cache Hit!") + user_id_information = None if valid_token: # Got Valid Token from Cache, DB @@ -1187,7 +1190,18 @@ async def user_api_key_auth( # No token was found when looking up in the DB raise Exception("Invalid token passed") if valid_token_dict is not None: - return UserAPIKeyAuth(api_key=api_key, **valid_token_dict) + if user_id_information is not None and _is_user_proxy_admin( + user_id_information + ): + return UserAPIKeyAuth( + api_key=api_key, user_role="proxy_admin", **valid_token_dict + ) + elif _has_user_setup_sso() and route in LiteLLMRoutes.sso_only_routes.value: + return UserAPIKeyAuth( + api_key=api_key, user_role="app_owner", **valid_token_dict + ) + else: + return UserAPIKeyAuth(api_key=api_key, **valid_token_dict) else: raise Exception() except Exception as e: @@ -2684,7 +2698,19 @@ class ProxyConfig: "Error setting env variable: %s - %s", k, str(e) ) - # general_settings + # router settings + if llm_router is not None and prisma_client is not None: + db_router_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "router_settings"} + ) + if ( + db_router_settings is not None + and db_router_settings.param_value is not None + ): + _router_settings = db_router_settings.param_value + llm_router.update_settings(**_router_settings) + + ## ALERTING ## [TODO] move this to the _update_general_settings() block _general_settings = config_data.get("general_settings", {}) if "alerting" in _general_settings: general_settings["alerting"] = _general_settings["alerting"] @@ -2708,17 +2734,24 @@ class ProxyConfig: alert_to_webhook_url=general_settings["alert_to_webhook_url"] ) - # router settings - if llm_router is not None and prisma_client is not None: - db_router_settings = await prisma_client.db.litellm_config.find_first( - where={"param_name": "router_settings"} - ) - if ( - db_router_settings is not None - and db_router_settings.param_value is not None - ): - _router_settings = db_router_settings.param_value - llm_router.update_settings(**_router_settings) + async def _update_general_settings(self, db_general_settings: Optional[Json]): + """ + Pull from DB, read general settings value + """ + global general_settings + if db_general_settings is None: + return + _general_settings = dict(db_general_settings) + ## MAX PARALLEL REQUESTS ## + if "max_parallel_requests" in _general_settings: + general_settings["max_parallel_requests"] = _general_settings[ + "max_parallel_requests" + ] + + if "global_max_parallel_requests" in _general_settings: + general_settings["global_max_parallel_requests"] = _general_settings[ + "global_max_parallel_requests" + ] async def add_deployment( self, @@ -2726,7 +2759,7 @@ class ProxyConfig: proxy_logging_obj: ProxyLogging, ): """ - - Check db for new models (last 10 most recently updated) + - Check db for new models - Check if model id's in router already - If not, add to router """ @@ -2739,9 +2772,21 @@ class ProxyConfig: ) verbose_proxy_logger.debug(f"llm_router: {llm_router}") new_models = await prisma_client.db.litellm_proxymodeltable.find_many() + # update llm router await self._update_llm_router( new_models=new_models, proxy_logging_obj=proxy_logging_obj ) + + db_general_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "general_settings"} + ) + + # update general settings + if db_general_settings is not None: + await self._update_general_settings( + db_general_settings=db_general_settings.param_value, + ) + except Exception as e: verbose_proxy_logger.error( "{}\nTraceback:{}".format(str(e), traceback.format_exc()) @@ -2941,27 +2986,6 @@ async def generate_key_helper_fn( data=key_data, table_name="key" ) key_data["token_id"] = getattr(create_key_response, "token", None) - elif custom_db_client is not None: - if table_name is None or table_name == "user": - ## CREATE USER (If necessary) - verbose_proxy_logger.debug( - "CustomDBClient: Creating User= %s", user_data - ) - user_row = await custom_db_client.insert_data( - value=user_data, table_name="user" - ) - if user_row is None: - # GET USER ROW - user_row = await custom_db_client.get_data( - key=user_id, table_name="user" # type: ignore - ) - - ## use default user model list if no key-specific model list provided - if len(user_row.models) > 0 and len(key_data["models"]) == 0: # type: ignore - key_data["models"] = user_row.models - ## CREATE KEY - verbose_proxy_logger.debug("CustomDBClient: Creating Key= %s", key_data) - await custom_db_client.insert_data(value=key_data, table_name="key") except Exception as e: traceback.print_exc() if isinstance(e, HTTPException): @@ -3557,6 +3581,9 @@ async def chat_completion( data["metadata"]["user_api_key_alias"] = getattr( user_api_key_dict, "key_alias", None ) + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id data["metadata"]["user_api_key_org_id"] = user_api_key_dict.org_id data["metadata"]["user_api_key_team_id"] = getattr( @@ -3746,8 +3773,11 @@ async def chat_completion( await proxy_logging_obj.post_call_failure_hook( user_api_key_dict=user_api_key_dict, original_exception=e, request_data=data ) + litellm_debug_info = getattr(e, "litellm_debug_info", "") verbose_proxy_logger.debug( - f"\033[1;31mAn error occurred: {e}\n\n Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`" + "\033[1;31mAn error occurred: %s %s\n\n Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`", + e, + litellm_debug_info, ) router_model_names = llm_router.model_names if llm_router is not None else [] if user_debug: @@ -3795,6 +3825,7 @@ async def completion( user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), ): global user_temperature, user_request_timeout, user_max_tokens, user_api_base + data = {} check_request_disconnected = None try: body = await request.body() @@ -3824,6 +3855,9 @@ async def completion( data["metadata"]["user_api_key_team_id"] = getattr( user_api_key_dict, "team_id", None ) + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_team_alias"] = getattr( user_api_key_dict, "team_alias", None ) @@ -3904,6 +3938,9 @@ async def completion( cache_key = hidden_params.get("cache_key", None) or "" api_base = hidden_params.get("api_base", None) or "" + ### ALERTING ### + data["litellm_status"] = "success" # used for alerting + verbose_proxy_logger.debug("final response: %s", response) if ( "stream" in data and data["stream"] == True @@ -3934,10 +3971,15 @@ async def completion( return response except Exception as e: data["litellm_status"] = "fail" # used for alerting + await proxy_logging_obj.post_call_failure_hook( + user_api_key_dict=user_api_key_dict, original_exception=e, request_data=data + ) verbose_proxy_logger.debug("EXCEPTION RAISED IN PROXY MAIN.PY") + litellm_debug_info = getattr(e, "litellm_debug_info", "") verbose_proxy_logger.debug( - "\033[1;31mAn error occurred: %s\n\n Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`", + "\033[1;31mAn error occurred: %s %s\n\n Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`", e, + litellm_debug_info, ) traceback.print_exc() error_traceback = traceback.format_exc() @@ -4015,6 +4057,9 @@ async def embeddings( data["metadata"]["user_api_key_alias"] = getattr( user_api_key_dict, "key_alias", None ) + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id data["metadata"]["user_api_key_team_id"] = getattr( user_api_key_dict, "team_id", None @@ -4140,6 +4185,12 @@ async def embeddings( await proxy_logging_obj.post_call_failure_hook( user_api_key_dict=user_api_key_dict, original_exception=e, request_data=data ) + litellm_debug_info = getattr(e, "litellm_debug_info", "") + verbose_proxy_logger.debug( + "\033[1;31mAn error occurred: %s %s\n\n Debug this by setting `--debug`, e.g. `litellm --model gpt-3.5-turbo --debug`", + e, + litellm_debug_info, + ) traceback.print_exc() if isinstance(e, HTTPException): raise ProxyException( @@ -4213,6 +4264,9 @@ async def image_generation( data["metadata"]["user_api_key_alias"] = getattr( user_api_key_dict, "key_alias", None ) + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_user_id"] = user_api_key_dict.user_id data["metadata"]["user_api_key_team_id"] = getattr( user_api_key_dict, "team_id", None @@ -4393,6 +4447,9 @@ async def audio_transcriptions( data["metadata"]["user_api_key_team_id"] = getattr( user_api_key_dict, "team_id", None ) + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_team_alias"] = getattr( user_api_key_dict, "team_alias", None ) @@ -4590,6 +4647,9 @@ async def moderations( "authorization", None ) # do not store the original `sk-..` api key in the db data["metadata"]["headers"] = _headers + data["metadata"]["global_max_parallel_requests"] = general_settings.get( + "global_max_parallel_requests", None + ) data["metadata"]["user_api_key_alias"] = getattr( user_api_key_dict, "key_alias", None ) @@ -7697,7 +7757,12 @@ async def new_organization( If none provided, create one based on provided values """ - budget_row = LiteLLM_BudgetTable(**data.json(exclude_none=True)) + budget_params = LiteLLM_BudgetTable.model_fields.keys() + + # Only include Budget Params when creating an entry in litellm_budgettable + _json_data = data.json(exclude_none=True) + _budget_data = {k: v for k, v in _json_data.items() if k in budget_params} + budget_row = LiteLLM_BudgetTable(**_budget_data) new_budget = prisma_client.jsonify_object(budget_row.json(exclude_none=True)) @@ -9288,7 +9353,7 @@ async def auth_callback(request: Request): return RedirectResponse(url=litellm_dashboard_ui) -#### BASIC ENDPOINTS #### +#### CONFIG MANAGEMENT #### @router.post( "/config/update", tags=["config.yaml"], @@ -9424,6 +9489,299 @@ async def update_config(config_info: ConfigYAML): ) +### CONFIG GENERAL SETTINGS +""" +- Update config settings +- Get config settings + +Keep it more precise, to prevent overwrite other values unintentially +""" + + +@router.post( + "/config/field/update", + tags=["config.yaml"], + dependencies=[Depends(user_api_key_auth)], +) +async def update_config_general_settings( + data: ConfigFieldUpdate, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): + """ + Update a specific field in litellm general settings + """ + global prisma_client + ## VALIDATION ## + """ + - Check if prisma_client is None + - Check if user allowed to call this endpoint (admin-only) + - Check if param in general settings + - Check if config value is valid type + """ + + if prisma_client is None: + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.db_not_connected_error.value}, + ) + + if user_api_key_dict.user_role != "proxy_admin": + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.not_allowed_access.value}, + ) + + if data.field_name not in ConfigGeneralSettings.model_fields: + raise HTTPException( + status_code=400, + detail={"error": "Invalid field={} passed in.".format(data.field_name)}, + ) + + try: + cgs = ConfigGeneralSettings(**{data.field_name: data.field_value}) + except: + raise HTTPException( + status_code=400, + detail={ + "error": "Invalid type of field value={} passed in.".format( + type(data.field_value), + ) + }, + ) + + ## get general settings from db + db_general_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "general_settings"} + ) + ### update value + + if db_general_settings is None or db_general_settings.param_value is None: + general_settings = {} + else: + general_settings = dict(db_general_settings.param_value) + + ## update db + + general_settings[data.field_name] = data.field_value + + response = await prisma_client.db.litellm_config.upsert( + where={"param_name": "general_settings"}, + data={ + "create": {"param_name": "general_settings", "param_value": json.dumps(general_settings)}, # type: ignore + "update": {"param_value": json.dumps(general_settings)}, # type: ignore + }, + ) + + return response + + +@router.get( + "/config/field/info", + tags=["config.yaml"], + dependencies=[Depends(user_api_key_auth)], +) +async def get_config_general_settings( + field_name: str, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): + global prisma_client + + ## VALIDATION ## + """ + - Check if prisma_client is None + - Check if user allowed to call this endpoint (admin-only) + - Check if param in general settings + """ + if prisma_client is None: + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.db_not_connected_error.value}, + ) + + if user_api_key_dict.user_role != "proxy_admin": + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.not_allowed_access.value}, + ) + + if field_name not in ConfigGeneralSettings.model_fields: + raise HTTPException( + status_code=400, + detail={"error": "Invalid field={} passed in.".format(field_name)}, + ) + + ## get general settings from db + db_general_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "general_settings"} + ) + ### pop the value + + if db_general_settings is None or db_general_settings.param_value is None: + raise HTTPException( + status_code=400, + detail={"error": "Field name={} not in DB".format(field_name)}, + ) + else: + general_settings = dict(db_general_settings.param_value) + + if field_name in general_settings: + return { + "field_name": field_name, + "field_value": general_settings[field_name], + } + else: + raise HTTPException( + status_code=400, + detail={"error": "Field name={} not in DB".format(field_name)}, + ) + + +@router.get( + "/config/list", + tags=["config.yaml"], + dependencies=[Depends(user_api_key_auth)], +) +async def get_config_list( + config_type: Literal["general_settings"], + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +) -> List[ConfigList]: + """ + List the available fields + current values for a given type of setting (currently just 'general_settings'user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth),) + """ + global prisma_client, general_settings + + ## VALIDATION ## + """ + - Check if prisma_client is None + - Check if user allowed to call this endpoint (admin-only) + - Check if param in general settings + """ + if prisma_client is None: + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.db_not_connected_error.value}, + ) + + if user_api_key_dict.user_role != "proxy_admin": + raise HTTPException( + status_code=400, + detail={ + "error": "{}, your role={}".format( + CommonProxyErrors.not_allowed_access.value, + user_api_key_dict.user_role, + ) + }, + ) + + ## get general settings from db + db_general_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "general_settings"} + ) + + if db_general_settings is not None and db_general_settings.param_value is not None: + db_general_settings_dict = dict(db_general_settings.param_value) + else: + db_general_settings_dict = {} + + allowed_args = { + "max_parallel_requests": {"type": "Integer"}, + "global_max_parallel_requests": {"type": "Integer"}, + } + + return_val = [] + + for field_name, field_info in ConfigGeneralSettings.model_fields.items(): + if field_name in allowed_args: + + _stored_in_db = None + if field_name in db_general_settings_dict: + _stored_in_db = True + elif field_name in general_settings: + _stored_in_db = False + + _response_obj = ConfigList( + field_name=field_name, + field_type=allowed_args[field_name]["type"], + field_description=field_info.description or "", + field_value=general_settings.get(field_name, None), + stored_in_db=_stored_in_db, + ) + return_val.append(_response_obj) + + return return_val + + +@router.post( + "/config/field/delete", + tags=["config.yaml"], + dependencies=[Depends(user_api_key_auth)], +) +async def delete_config_general_settings( + data: ConfigFieldDelete, + user_api_key_dict: UserAPIKeyAuth = Depends(user_api_key_auth), +): + """ + Delete the db value of this field in litellm general settings. Resets it to it's initial default value on litellm. + """ + global prisma_client + ## VALIDATION ## + """ + - Check if prisma_client is None + - Check if user allowed to call this endpoint (admin-only) + - Check if param in general settings + """ + if prisma_client is None: + raise HTTPException( + status_code=400, + detail={"error": CommonProxyErrors.db_not_connected_error.value}, + ) + + if user_api_key_dict.user_role != "proxy_admin": + raise HTTPException( + status_code=400, + detail={ + "error": "{}, your role={}".format( + CommonProxyErrors.not_allowed_access.value, + user_api_key_dict.user_role, + ) + }, + ) + + if data.field_name not in ConfigGeneralSettings.model_fields: + raise HTTPException( + status_code=400, + detail={"error": "Invalid field={} passed in.".format(data.field_name)}, + ) + + ## get general settings from db + db_general_settings = await prisma_client.db.litellm_config.find_first( + where={"param_name": "general_settings"} + ) + ### pop the value + + if db_general_settings is None or db_general_settings.param_value is None: + raise HTTPException( + status_code=400, + detail={"error": "Field name={} not in config".format(data.field_name)}, + ) + else: + general_settings = dict(db_general_settings.param_value) + + ## update db + + general_settings.pop(data.field_name, None) + + response = await prisma_client.db.litellm_config.upsert( + where={"param_name": "general_settings"}, + data={ + "create": {"param_name": "general_settings", "param_value": json.dumps(general_settings)}, # type: ignore + "update": {"param_value": json.dumps(general_settings)}, # type: ignore + }, + ) + + return response + + @router.get( "/get/config/callbacks", tags=["config.yaml"], @@ -9591,6 +9949,7 @@ async def config_yaml_endpoint(config_info: ConfigYAML): return {"hello": "world"} +#### BASIC ENDPOINTS #### @router.get( "/test", tags=["health"], diff --git a/litellm/proxy/utils.py b/litellm/proxy/utils.py index 33127e957a..d1210a504f 100644 --- a/litellm/proxy/utils.py +++ b/litellm/proxy/utils.py @@ -252,8 +252,8 @@ class ProxyLogging: """ Runs the CustomLogger's async_moderation_hook() """ + new_data = copy.deepcopy(data) for callback in litellm.callbacks: - new_data = copy.deepcopy(data) try: if isinstance(callback, CustomLogger): await callback.async_moderation_hook( @@ -418,9 +418,14 @@ class ProxyLogging: Related issue - https://github.com/BerriAI/litellm/issues/3395 """ + litellm_debug_info = getattr(original_exception, "litellm_debug_info", None) + exception_str = str(original_exception) + if litellm_debug_info is not None: + exception_str += litellm_debug_info + asyncio.create_task( self.alerting_handler( - message=f"LLM API call failed: {str(original_exception)}", + message=f"LLM API call failed: {exception_str}", level="High", alert_type="llm_exceptions", request_data=request_data, diff --git a/litellm/router.py b/litellm/router.py index ec7df1124c..08576f78e1 100644 --- a/litellm/router.py +++ b/litellm/router.py @@ -262,13 +262,22 @@ class Router: self.retry_after = retry_after self.routing_strategy = routing_strategy - self.fallbacks = fallbacks or litellm.fallbacks + + ## SETTING FALLBACKS ## + ### validate if it's set + in correct format + _fallbacks = fallbacks or litellm.fallbacks + + self.validate_fallbacks(fallback_param=_fallbacks) + ### set fallbacks + self.fallbacks = _fallbacks + if default_fallbacks is not None or litellm.default_fallbacks is not None: _fallbacks = default_fallbacks or litellm.default_fallbacks if self.fallbacks is not None: self.fallbacks.append({"*": _fallbacks}) else: self.fallbacks = [{"*": _fallbacks}] + self.context_window_fallbacks = ( context_window_fallbacks or litellm.context_window_fallbacks ) @@ -336,6 +345,21 @@ class Router: if self.alerting_config is not None: self._initialize_alerting() + def validate_fallbacks(self, fallback_param: Optional[List]): + if fallback_param is None: + return + if len(fallback_param) > 0: # if set + ## for dictionary in list, check if only 1 key in dict + for _dict in fallback_param: + assert isinstance(_dict, dict), "Item={}, not a dictionary".format( + _dict + ) + assert ( + len(_dict.keys()) == 1 + ), "Only 1 key allows in dictionary. You set={} for dict={}".format( + len(_dict.keys()), _dict + ) + def routing_strategy_init(self, routing_strategy: str, routing_strategy_args: dict): if routing_strategy == "least-busy": self.leastbusy_logger = LeastBusyLoggingHandler( @@ -1962,6 +1986,45 @@ class Router: key=rpm_key, value=request_count, local_only=True ) # don't change existing ttl + def _is_cooldown_required(self, exception_status: Union[str, int]): + """ + A function to determine if a cooldown is required based on the exception status. + + Parameters: + exception_status (Union[str, int]): The status of the exception. + + Returns: + bool: True if a cooldown is required, False otherwise. + """ + try: + + if isinstance(exception_status, str): + exception_status = int(exception_status) + + if exception_status >= 400 and exception_status < 500: + if exception_status == 429: + # Cool down 429 Rate Limit Errors + return True + + elif exception_status == 401: + # Cool down 401 Auth Errors + return True + + elif exception_status == 408: + return True + + else: + # Do NOT cool down all other 4XX Errors + return False + + else: + # should cool down for all other errors + return True + + except: + # Catch all - if any exceptions default to cooling down + return True + def _set_cooldown_deployments( self, exception_status: Union[str, int], deployment: Optional[str] = None ): @@ -1975,6 +2038,9 @@ class Router: if deployment is None: return + if self._is_cooldown_required(exception_status=exception_status) == False: + return + dt = get_utc_datetime() current_minute = dt.strftime("%H-%M") # get current fails for deployment diff --git a/litellm/router_strategy/lowest_latency.py b/litellm/router_strategy/lowest_latency.py index 81a0133a90..c56db83f0b 100644 --- a/litellm/router_strategy/lowest_latency.py +++ b/litellm/router_strategy/lowest_latency.py @@ -27,7 +27,7 @@ class LiteLLMBase(BaseModel): class RoutingArgs(LiteLLMBase): - ttl: int = 1 * 60 * 60 # 1 hour + ttl: float = 1 * 60 * 60 # 1 hour lowest_latency_buffer: float = 0 max_latency_list_size: int = 10 diff --git a/litellm/tests/test_amazing_vertex_completion.py b/litellm/tests/test_amazing_vertex_completion.py index ad3fb3cc3e..b747ca8803 100644 --- a/litellm/tests/test_amazing_vertex_completion.py +++ b/litellm/tests/test_amazing_vertex_completion.py @@ -376,9 +376,8 @@ def test_vertex_ai_stream(): print("making request", model) response = completion( model=model, - messages=[ - {"role": "user", "content": "write 10 line code code for saying hi"} - ], + messages=[{"role": "user", "content": "hello tell me a short story"}], + max_tokens=15, stream=True, ) completed_str = "" diff --git a/litellm/tests/test_completion.py b/litellm/tests/test_completion.py index 2bc167ed09..120a65acbf 100644 --- a/litellm/tests/test_completion.py +++ b/litellm/tests/test_completion.py @@ -38,7 +38,7 @@ def reset_callbacks(): @pytest.mark.skip(reason="Local test") def test_response_model_none(): """ - Addresses - https://github.com/BerriAI/litellm/issues/2972 + Addresses:https://github.com/BerriAI/litellm/issues/2972 """ x = completion( model="mymodel", diff --git a/litellm/tests/test_config.py b/litellm/tests/test_config.py index 96c766919e..e38187e0ea 100644 --- a/litellm/tests/test_config.py +++ b/litellm/tests/test_config.py @@ -5,7 +5,6 @@ import sys, os import traceback from dotenv import load_dotenv -from pydantic import ConfigDict load_dotenv() import os, io @@ -14,36 +13,21 @@ sys.path.insert( 0, os.path.abspath("../..") ) # Adds the parent directory to the, system path import pytest, litellm -from pydantic import BaseModel, VERSION +from pydantic import BaseModel from litellm.proxy.proxy_server import ProxyConfig from litellm.proxy.utils import encrypt_value, ProxyLogging, DualCache from litellm.types.router import Deployment, LiteLLM_Params, ModelInfo from typing import Literal -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config(arbitrary_types_allowed: bool = False) -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", arbitrary_types_allowed=arbitrary_types_allowed, protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow, arbitrary_types_allowed=arbitrary_types_allowed) # type: ignore - - return model_config - - class DBModel(BaseModel): model_id: str model_name: str model_info: dict litellm_params: dict - model_config = get_model_config() + + class Config: + protected_namespaces = () @pytest.mark.asyncio diff --git a/litellm/tests/test_exceptions.py b/litellm/tests/test_exceptions.py index 777fb3f9b3..ee695dcd7c 100644 --- a/litellm/tests/test_exceptions.py +++ b/litellm/tests/test_exceptions.py @@ -53,13 +53,6 @@ async def test_content_policy_exception_azure(): except litellm.ContentPolicyViolationError as e: print("caught a content policy violation error! Passed") print("exception", e) - - # assert that the first 100 chars of the message is returned in the exception - assert ( - "Messages: [{'role': 'user', 'content': 'where do I buy lethal drugs from'}]" - in str(e) - ) - assert "Model: azure/chatgpt-v-2" in str(e) pass except Exception as e: pytest.fail(f"An exception occurred - {str(e)}") @@ -585,9 +578,6 @@ def test_router_completion_vertex_exception(): pytest.fail("Request should have failed - bad api key") except Exception as e: print("exception: ", e) - assert "Model: gemini-pro" in str(e) - assert "model_group: vertex-gemini-pro" in str(e) - assert "deployment: vertex_ai/gemini-pro" in str(e) def test_litellm_completion_vertex_exception(): @@ -604,8 +594,26 @@ def test_litellm_completion_vertex_exception(): pytest.fail("Request should have failed - bad api key") except Exception as e: print("exception: ", e) - assert "Model: gemini-pro" in str(e) - assert "vertex_project: bad-project" in str(e) + + +def test_litellm_predibase_exception(): + """ + Test - Assert that the Predibase API Key is not returned on Authentication Errors + """ + try: + import litellm + + litellm.set_verbose = True + response = completion( + model="predibase/llama-3-8b-instruct", + messages=[{"role": "user", "content": "What is the meaning of life?"}], + tenant_id="c4768f95", + api_key="hf-rawapikey", + ) + pytest.fail("Request should have failed - bad api key") + except Exception as e: + assert "hf-rawapikey" not in str(e) + print("exception: ", e) # # test_invalid_request_error(model="command-nightly") diff --git a/litellm/tests/test_function_calling.py b/litellm/tests/test_function_calling.py index 0d0a593d53..6e4e9d3e86 100644 --- a/litellm/tests/test_function_calling.py +++ b/litellm/tests/test_function_calling.py @@ -105,6 +105,9 @@ def test_parallel_function_call(model): # Step 4: send the info for each function call and function response to the model for tool_call in tool_calls: function_name = tool_call.function.name + if function_name not in available_functions: + # the model called a function that does not exist in available_functions - don't try calling anything + return function_to_call = available_functions[function_name] function_args = json.loads(tool_call.function.arguments) function_response = function_to_call( @@ -124,7 +127,6 @@ def test_parallel_function_call(model): model=model, messages=messages, temperature=0.2, seed=22 ) # get a new response from the model where it can see the function response print("second response\n", second_response) - return second_response except Exception as e: pytest.fail(f"Error occurred: {e}") diff --git a/litellm/tests/test_jwt.py b/litellm/tests/test_jwt.py index b3af9913f6..45f4616290 100644 --- a/litellm/tests/test_jwt.py +++ b/litellm/tests/test_jwt.py @@ -1,7 +1,7 @@ #### What this tests #### # Unit tests for JWT-Auth -import sys, os, asyncio, time, random +import sys, os, asyncio, time, random, uuid import traceback from dotenv import load_dotenv @@ -24,6 +24,7 @@ public_key = { "alg": "RS256", } + def test_load_config_with_custom_role_names(): config = { "general_settings": { @@ -77,7 +78,8 @@ async def test_token_single_public_key(): == "qIgOQfEVrrErJC0E7gsHXi6rs_V0nyFY5qPFui2-tv0o4CwpwDzgfBtLO7o_wLiguq0lnu54sMT2eLNoRiiPuLvv6bg7Iy1H9yc5_4Jf5oYEOrqN5o9ZBOoYp1q68Pv0oNJYyZdGu5ZJfd7V4y953vB2XfEKgXCsAkhVhlvIUMiDNKWoMDWsyb2xela5tRURZ2mJAXcHfSC_sYdZxIA2YYrIHfoevq_vTlaz0qVSe_uOKjEpgOAS08UUrgda4CQL11nzICiIQzc6qmjIQt2cjzB2D_9zb4BYndzEtfl0kwAT0z_I85S3mkwTqHU-1BvKe_4MG4VG3dAAeffLPXJyXQ" ) -@pytest.mark.parametrize('audience', [None, "litellm-proxy"]) + +@pytest.mark.parametrize("audience", [None, "litellm-proxy"]) @pytest.mark.asyncio async def test_valid_invalid_token(audience): """ @@ -90,7 +92,7 @@ async def test_valid_invalid_token(audience): from cryptography.hazmat.primitives.asymmetric import rsa from cryptography.hazmat.backends import default_backend - os.environ.pop('JWT_AUDIENCE', None) + os.environ.pop("JWT_AUDIENCE", None) if audience: os.environ["JWT_AUDIENCE"] = audience @@ -138,7 +140,7 @@ async def test_valid_invalid_token(audience): "sub": "user123", "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm-proxy-admin", - "aud": audience + "aud": audience, } # Generate the JWT token @@ -166,7 +168,7 @@ async def test_valid_invalid_token(audience): "sub": "user123", "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm-NO-SCOPE", - "aud": audience + "aud": audience, } # Generate the JWT token @@ -183,6 +185,7 @@ async def test_valid_invalid_token(audience): except Exception as e: pytest.fail(f"An exception occurred - {str(e)}") + @pytest.fixture def prisma_client(): import litellm @@ -205,7 +208,7 @@ def prisma_client(): return prisma_client -@pytest.mark.parametrize('audience', [None, "litellm-proxy"]) +@pytest.mark.parametrize("audience", [None, "litellm-proxy"]) @pytest.mark.asyncio async def test_team_token_output(prisma_client, audience): import jwt, json @@ -222,7 +225,7 @@ async def test_team_token_output(prisma_client, audience): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) await litellm.proxy.proxy_server.prisma_client.connect() - os.environ.pop('JWT_AUDIENCE', None) + os.environ.pop("JWT_AUDIENCE", None) if audience: os.environ["JWT_AUDIENCE"] = audience @@ -261,7 +264,7 @@ async def test_team_token_output(prisma_client, audience): jwt_handler.user_api_key_cache = cache - jwt_handler.litellm_jwtauth = LiteLLM_JWTAuth() + jwt_handler.litellm_jwtauth = LiteLLM_JWTAuth(team_id_jwt_field="client_id") # VALID TOKEN ## GENERATE A TOKEN @@ -274,7 +277,7 @@ async def test_team_token_output(prisma_client, audience): "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm_team", "client_id": team_id, - "aud": audience + "aud": audience, } # Generate the JWT token @@ -289,7 +292,7 @@ async def test_team_token_output(prisma_client, audience): "sub": "user123", "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm_proxy_admin", - "aud": audience + "aud": audience, } admin_token = jwt.encode(payload, private_key_str, algorithm="RS256") @@ -315,7 +318,13 @@ async def test_team_token_output(prisma_client, audience): ## 1. INITIAL TEAM CALL - should fail # use generated key to auth in - setattr(litellm.proxy.proxy_server, "general_settings", {"enable_jwt_auth": True}) + setattr( + litellm.proxy.proxy_server, + "general_settings", + { + "enable_jwt_auth": True, + }, + ) setattr(litellm.proxy.proxy_server, "jwt_handler", jwt_handler) try: result = await user_api_key_auth(request=request, api_key=bearer_token) @@ -358,9 +367,22 @@ async def test_team_token_output(prisma_client, audience): assert team_result.team_models == ["gpt-3.5-turbo", "gpt-4"] -@pytest.mark.parametrize('audience', [None, "litellm-proxy"]) +@pytest.mark.parametrize("audience", [None, "litellm-proxy"]) +@pytest.mark.parametrize( + "team_id_set, default_team_id", + [(True, False), (False, True)], +) +@pytest.mark.parametrize("user_id_upsert", [True, False]) @pytest.mark.asyncio -async def test_user_token_output(prisma_client, audience): +async def test_user_token_output( + prisma_client, audience, team_id_set, default_team_id, user_id_upsert +): + import uuid + + args = locals() + print(f"received args - {args}") + if default_team_id: + default_team_id = "team_id_12344_{}".format(uuid.uuid4()) """ - If user required, check if it exists - fail initial request (when user doesn't exist) @@ -373,7 +395,12 @@ async def test_user_token_output(prisma_client, audience): from cryptography.hazmat.backends import default_backend from fastapi import Request from starlette.datastructures import URL - from litellm.proxy.proxy_server import user_api_key_auth, new_team, new_user + from litellm.proxy.proxy_server import ( + user_api_key_auth, + new_team, + new_user, + user_info, + ) from litellm.proxy._types import NewTeamRequest, UserAPIKeyAuth, NewUserRequest import litellm import uuid @@ -381,7 +408,7 @@ async def test_user_token_output(prisma_client, audience): setattr(litellm.proxy.proxy_server, "prisma_client", prisma_client) await litellm.proxy.proxy_server.prisma_client.connect() - os.environ.pop('JWT_AUDIENCE', None) + os.environ.pop("JWT_AUDIENCE", None) if audience: os.environ["JWT_AUDIENCE"] = audience @@ -423,6 +450,11 @@ async def test_user_token_output(prisma_client, audience): jwt_handler.litellm_jwtauth = LiteLLM_JWTAuth() jwt_handler.litellm_jwtauth.user_id_jwt_field = "sub" + jwt_handler.litellm_jwtauth.team_id_default = default_team_id + jwt_handler.litellm_jwtauth.user_id_upsert = user_id_upsert + + if team_id_set: + jwt_handler.litellm_jwtauth.team_id_jwt_field = "client_id" # VALID TOKEN ## GENERATE A TOKEN @@ -436,7 +468,7 @@ async def test_user_token_output(prisma_client, audience): "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm_team", "client_id": team_id, - "aud": audience + "aud": audience, } # Generate the JWT token @@ -451,7 +483,7 @@ async def test_user_token_output(prisma_client, audience): "sub": user_id, "exp": expiration_time, # set the token to expire in 10 minutes "scope": "litellm_proxy_admin", - "aud": audience + "aud": audience, } admin_token = jwt.encode(payload, private_key_str, algorithm="RS256") @@ -503,6 +535,16 @@ async def test_user_token_output(prisma_client, audience): ), user_api_key_dict=result, ) + if default_team_id: + await new_team( + data=NewTeamRequest( + team_id=default_team_id, + tpm_limit=100, + rpm_limit=99, + models=["gpt-3.5-turbo", "gpt-4"], + ), + user_api_key_dict=result, + ) except Exception as e: pytest.fail(f"This should not fail - {str(e)}") @@ -513,23 +555,35 @@ async def test_user_token_output(prisma_client, audience): team_result: UserAPIKeyAuth = await user_api_key_auth( request=request, api_key=bearer_token ) - pytest.fail(f"User doesn't exist. this should fail") + if user_id_upsert == False: + pytest.fail(f"User doesn't exist. this should fail") except Exception as e: pass ## 4. Create user - try: - bearer_token = "Bearer " + admin_token + if user_id_upsert: + ## check if user already exists + try: + bearer_token = "Bearer " + admin_token - request._url = URL(url="/team/new") - result = await user_api_key_auth(request=request, api_key=bearer_token) - await new_user( - data=NewUserRequest( - user_id=user_id, - ), - ) - except Exception as e: - pytest.fail(f"This should not fail - {str(e)}") + request._url = URL(url="/team/new") + result = await user_api_key_auth(request=request, api_key=bearer_token) + await user_info(user_id=user_id) + except Exception as e: + pytest.fail(f"This should not fail - {str(e)}") + else: + try: + bearer_token = "Bearer " + admin_token + + request._url = URL(url="/team/new") + result = await user_api_key_auth(request=request, api_key=bearer_token) + await new_user( + data=NewUserRequest( + user_id=user_id, + ), + ) + except Exception as e: + pytest.fail(f"This should not fail - {str(e)}") ## 5. 3rd call w/ same team, same user -> call should succeed bearer_token = "Bearer " + token @@ -543,7 +597,8 @@ async def test_user_token_output(prisma_client, audience): ## 6. ASSERT USER_API_KEY_AUTH format (used for tpm/rpm limiting in parallel_request_limiter.py AND cost tracking) - assert team_result.team_tpm_limit == 100 - assert team_result.team_rpm_limit == 99 - assert team_result.team_models == ["gpt-3.5-turbo", "gpt-4"] + if team_id_set or default_team_id is not None: + assert team_result.team_tpm_limit == 100 + assert team_result.team_rpm_limit == 99 + assert team_result.team_models == ["gpt-3.5-turbo", "gpt-4"] assert team_result.user_id == user_id diff --git a/litellm/tests/test_lowest_latency_routing.py b/litellm/tests/test_lowest_latency_routing.py index 4da8792087..3d79e5c8f7 100644 --- a/litellm/tests/test_lowest_latency_routing.py +++ b/litellm/tests/test_lowest_latency_routing.py @@ -705,7 +705,7 @@ async def test_lowest_latency_routing_first_pick(): ) # type: ignore deployments = {} - for _ in range(5): + for _ in range(10): response = await router.acompletion( model="azure-model", messages=[{"role": "user", "content": "hello"}] ) diff --git a/litellm/tests/test_parallel_request_limiter.py b/litellm/tests/test_parallel_request_limiter.py index d0a28926e8..00da199d99 100644 --- a/litellm/tests/test_parallel_request_limiter.py +++ b/litellm/tests/test_parallel_request_limiter.py @@ -28,6 +28,37 @@ from datetime import datetime ## On Request failure +@pytest.mark.asyncio +async def test_global_max_parallel_requests(): + """ + Test if ParallelRequestHandler respects 'global_max_parallel_requests' + + data["metadata"]["global_max_parallel_requests"] + """ + global_max_parallel_requests = 0 + _api_key = "sk-12345" + _api_key = hash_token("sk-12345") + user_api_key_dict = UserAPIKeyAuth(api_key=_api_key, max_parallel_requests=100) + local_cache = DualCache() + parallel_request_handler = MaxParallelRequestsHandler() + + for _ in range(3): + try: + await parallel_request_handler.async_pre_call_hook( + user_api_key_dict=user_api_key_dict, + cache=local_cache, + data={ + "metadata": { + "global_max_parallel_requests": global_max_parallel_requests + } + }, + call_type="", + ) + pytest.fail("Expected call to fail") + except Exception as e: + pass + + @pytest.mark.asyncio async def test_pre_call_hook(): """ diff --git a/litellm/tests/test_router_cooldowns.py b/litellm/tests/test_router_cooldowns.py new file mode 100644 index 0000000000..35095bb2cf --- /dev/null +++ b/litellm/tests/test_router_cooldowns.py @@ -0,0 +1,64 @@ +#### What this tests #### +# This tests calling router with fallback models + +import sys, os, time +import traceback, asyncio +import pytest + +sys.path.insert( + 0, os.path.abspath("../..") +) # Adds the parent directory to the system path + +import litellm +from litellm import Router +from litellm.integrations.custom_logger import CustomLogger +import openai, httpx + + +@pytest.mark.asyncio +async def test_cooldown_badrequest_error(): + """ + Test 1. It SHOULD NOT cooldown a deployment on a BadRequestError + """ + + router = litellm.Router( + model_list=[ + { + "model_name": "gpt-3.5-turbo", + "litellm_params": { + "model": "azure/chatgpt-v-2", + "api_key": os.getenv("AZURE_API_KEY"), + "api_version": os.getenv("AZURE_API_VERSION"), + "api_base": os.getenv("AZURE_API_BASE"), + }, + } + ], + debug_level="DEBUG", + set_verbose=True, + cooldown_time=300, + num_retries=0, + allowed_fails=0, + ) + + # Act & Assert + try: + + response = await router.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "gm"}], + bad_param=200, + ) + except: + pass + + await asyncio.sleep(3) # wait for deployment to get cooled-down + + response = await router.acompletion( + model="gpt-3.5-turbo", + messages=[{"role": "user", "content": "gm"}], + mock_response="hello", + ) + + assert response is not None + + print(response) diff --git a/litellm/tests/test_router_debug_logs.py b/litellm/tests/test_router_debug_logs.py index 1d908abe81..cde9a8edd1 100644 --- a/litellm/tests/test_router_debug_logs.py +++ b/litellm/tests/test_router_debug_logs.py @@ -82,7 +82,7 @@ def test_async_fallbacks(caplog): # Define the expected log messages # - error request, falling back notice, success notice expected_logs = [ - "litellm.acompletion(model=gpt-3.5-turbo)\x1b[31m Exception OpenAIException - Error code: 401 - {'error': {'message': 'Incorrect API key provided: bad-key. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}} \nModel: gpt-3.5-turbo\nAPI Base: https://api.openai.com\nMessages: [{'content': 'Hello, how are you?', 'role': 'user'}]\nmodel_group: gpt-3.5-turbo\n\ndeployment: gpt-3.5-turbo\n\x1b[0m", + "litellm.acompletion(model=gpt-3.5-turbo)\x1b[31m Exception OpenAIException - Error code: 401 - {'error': {'message': 'Incorrect API key provided: bad-key. You can find your API key at https://platform.openai.com/account/api-keys.', 'type': 'invalid_request_error', 'param': None, 'code': 'invalid_api_key'}}\x1b[0m", "Falling back to model_group = azure/gpt-3.5-turbo", "litellm.acompletion(model=azure/chatgpt-v-2)\x1b[32m 200 OK\x1b[0m", "Successful fallback b/w models.", diff --git a/litellm/types/completion.py b/litellm/types/completion.py index 87a7629daf..78af7667ba 100644 --- a/litellm/types/completion.py +++ b/litellm/types/completion.py @@ -1,27 +1,10 @@ -from typing import List, Optional, Union, Iterable, cast +from typing import List, Optional, Union, Iterable -from pydantic import ConfigDict, BaseModel, validator, VERSION +from pydantic import BaseModel, validator from typing_extensions import Literal, Required, TypedDict -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config() -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow) # type: ignore - - return model_config - - class ChatCompletionSystemMessageParam(TypedDict, total=False): content: Required[str] """The contents of the system message.""" @@ -208,4 +191,6 @@ class CompletionRequest(BaseModel): api_key: Optional[str] = None model_list: Optional[List[str]] = None - model_config = get_model_config() + class Config: + extra = "allow" + protected_namespaces = () diff --git a/litellm/types/embedding.py b/litellm/types/embedding.py index 831c4266c3..9db0ef2907 100644 --- a/litellm/types/embedding.py +++ b/litellm/types/embedding.py @@ -1,23 +1,6 @@ from typing import List, Optional, Union -from pydantic import ConfigDict, BaseModel, validator, VERSION - - -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config(arbitrary_types_allowed: bool = False) -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", arbitrary_types_allowed=arbitrary_types_allowed, protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow, arbitrary_types_allowed=arbitrary_types_allowed) # type: ignore - - return model_config +from pydantic import BaseModel, validator class EmbeddingRequest(BaseModel): @@ -34,4 +17,7 @@ class EmbeddingRequest(BaseModel): litellm_call_id: Optional[str] = None litellm_logging_obj: Optional[dict] = None logger_fn: Optional[str] = None - model_config = get_model_config() + + class Config: + # allow kwargs + extra = "allow" diff --git a/litellm/types/router.py b/litellm/types/router.py index 0cc84d8c30..68ee387fea 100644 --- a/litellm/types/router.py +++ b/litellm/types/router.py @@ -1,42 +1,19 @@ from typing import List, Optional, Union, Dict, Tuple, Literal, TypedDict import httpx -from pydantic import ( - ConfigDict, - BaseModel, - validator, - Field, - __version__ as pydantic_version, - VERSION, -) +from pydantic import BaseModel, validator, Field from .completion import CompletionRequest from .embedding import EmbeddingRequest import uuid, enum -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config(arbitrary_types_allowed: bool = False) -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", arbitrary_types_allowed=arbitrary_types_allowed, protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow, arbitrary_types_allowed=arbitrary_types_allowed) # type: ignore - - return model_config - - class ModelConfig(BaseModel): model_name: str litellm_params: Union[CompletionRequest, EmbeddingRequest] tpm: int rpm: int - model_config = get_model_config() + class Config: + protected_namespaces = () class RouterConfig(BaseModel): @@ -67,7 +44,8 @@ class RouterConfig(BaseModel): "latency-based-routing", ] = "simple-shuffle" - model_config = get_model_config() + class Config: + protected_namespaces = () class UpdateRouterConfig(BaseModel): @@ -87,7 +65,8 @@ class UpdateRouterConfig(BaseModel): fallbacks: Optional[List[dict]] = None context_window_fallbacks: Optional[List[dict]] = None - model_config = get_model_config() + class Config: + protected_namespaces = () class ModelInfo(BaseModel): @@ -105,7 +84,8 @@ class ModelInfo(BaseModel): id = str(id) super().__init__(id=id, **params) - model_config = get_model_config() + class Config: + extra = "allow" def __contains__(self, key): # Define custom behavior for the 'in' operator @@ -200,15 +180,9 @@ class GenericLiteLLMParams(BaseModel): max_retries = int(max_retries) # cast to int super().__init__(max_retries=max_retries, **args, **params) - model_config = get_model_config(arbitrary_types_allowed=True) - if pydantic_version.startswith("1"): - # pydantic v2 warns about using a Config class. - # But without this, pydantic v1 will raise an error: - # RuntimeError: no validator found for , - # see `arbitrary_types_allowed` in Config - # Putting arbitrary_types_allowed = True in the ConfigDict doesn't work in pydantic v1. - class Config: - arbitrary_types_allowed = True + class Config: + extra = "allow" + arbitrary_types_allowed = True def __contains__(self, key): # Define custom behavior for the 'in' operator @@ -267,16 +241,9 @@ class LiteLLM_Params(GenericLiteLLMParams): max_retries = int(max_retries) # cast to int super().__init__(max_retries=max_retries, **args, **params) - model_config = get_model_config(arbitrary_types_allowed=True) - - if pydantic_version.startswith("1"): - # pydantic v2 warns about using a Config class. - # But without this, pydantic v1 will raise an error: - # RuntimeError: no validator found for , - # see `arbitrary_types_allowed` in Config - # Putting arbitrary_types_allowed = True in the ConfigDict doesn't work in pydantic v1. - class Config: - arbitrary_types_allowed = True + class Config: + extra = "allow" + arbitrary_types_allowed = True def __contains__(self, key): # Define custom behavior for the 'in' operator @@ -306,7 +273,8 @@ class updateDeployment(BaseModel): litellm_params: Optional[updateLiteLLMParams] = None model_info: Optional[ModelInfo] = None - model_config = get_model_config() + class Config: + protected_namespaces = () class LiteLLMParamsTypedDict(TypedDict, total=False): @@ -380,7 +348,9 @@ class Deployment(BaseModel): # if using pydantic v1 return self.dict(**kwargs) - model_config = get_model_config() + class Config: + extra = "allow" + protected_namespaces = () def __contains__(self, key): # Define custom behavior for the 'in' operator diff --git a/litellm/utils.py b/litellm/utils.py index 7df79f3736..36f4ad481f 100644 --- a/litellm/utils.py +++ b/litellm/utils.py @@ -19,7 +19,7 @@ from functools import wraps, lru_cache import datetime, time import tiktoken import uuid -from pydantic import ConfigDict, BaseModel, VERSION +from pydantic import BaseModel import aiohttp import textwrap import logging @@ -185,23 +185,6 @@ last_fetched_at_keys = None # } -# Function to get Pydantic version -def is_pydantic_v2() -> int: - return int(VERSION.split(".")[0]) - - -def get_model_config(arbitrary_types_allowed: bool = False) -> ConfigDict: - # Version-specific configuration - if is_pydantic_v2() >= 2: - model_config = ConfigDict(extra="allow", arbitrary_types_allowed=arbitrary_types_allowed, protected_namespaces=()) # type: ignore - else: - from pydantic import Extra - - model_config = ConfigDict(extra=Extra.allow, arbitrary_types_allowed=arbitrary_types_allowed) # type: ignore - - return model_config - - class UnsupportedParamsError(Exception): def __init__(self, status_code, message): self.status_code = status_code @@ -348,7 +331,10 @@ class HiddenParams(OpenAIObject): original_response: Optional[str] = None model_id: Optional[str] = None # used in Router for individual deployments api_base: Optional[str] = None # returns api base used for making completion call - model_config = get_model_config() + + class Config: + extra = "allow" + protected_namespaces = () def get(self, key, default=None): # Custom .get() method to access attributes with a default value if the attribute doesn't exist @@ -2579,7 +2565,7 @@ class Logging: response_obj=result, start_time=start_time, end_time=end_time, - ) + ) # type: ignore if callable(callback): # custom logger functions await customLogger.async_log_event( kwargs=self.model_call_details, @@ -6778,7 +6764,7 @@ def get_max_tokens(model: str): raise Exception() except: raise Exception( - "This model isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json" + f"Model {model} isn't mapped yet. Add it here - https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json" ) @@ -8155,33 +8141,39 @@ def exception_type( # Common Extra information needed for all providers # We pass num retries, api_base, vertex_deployment etc to the exception here ################################################################################ + extra_information = "" + try: + _api_base = litellm.get_api_base( + model=model, optional_params=extra_kwargs + ) + messages = litellm.get_first_chars_messages(kwargs=completion_kwargs) + _vertex_project = extra_kwargs.get("vertex_project") + _vertex_location = extra_kwargs.get("vertex_location") + _metadata = extra_kwargs.get("metadata", {}) or {} + _model_group = _metadata.get("model_group") + _deployment = _metadata.get("deployment") + extra_information = f"\nModel: {model}" + if _api_base: + extra_information += f"\nAPI Base: {_api_base}" + if messages and len(messages) > 0: + extra_information += f"\nMessages: {messages}" - _api_base = litellm.get_api_base(model=model, optional_params=extra_kwargs) - messages = litellm.get_first_chars_messages(kwargs=completion_kwargs) - _vertex_project = extra_kwargs.get("vertex_project") - _vertex_location = extra_kwargs.get("vertex_location") - _metadata = extra_kwargs.get("metadata", {}) or {} - _model_group = _metadata.get("model_group") - _deployment = _metadata.get("deployment") - extra_information = f"\nModel: {model}" - if _api_base: - extra_information += f"\nAPI Base: {_api_base}" - if messages and len(messages) > 0: - extra_information += f"\nMessages: {messages}" + if _model_group is not None: + extra_information += f"\nmodel_group: {_model_group}\n" + if _deployment is not None: + extra_information += f"\ndeployment: {_deployment}\n" + if _vertex_project is not None: + extra_information += f"\nvertex_project: {_vertex_project}\n" + if _vertex_location is not None: + extra_information += f"\nvertex_location: {_vertex_location}\n" - if _model_group is not None: - extra_information += f"\nmodel_group: {_model_group}\n" - if _deployment is not None: - extra_information += f"\ndeployment: {_deployment}\n" - if _vertex_project is not None: - extra_information += f"\nvertex_project: {_vertex_project}\n" - if _vertex_location is not None: - extra_information += f"\nvertex_location: {_vertex_location}\n" - - # on litellm proxy add key name + team to exceptions - extra_information = _add_key_name_and_team_to_alert( - request_info=extra_information, metadata=_metadata - ) + # on litellm proxy add key name + team to exceptions + extra_information = _add_key_name_and_team_to_alert( + request_info=extra_information, metadata=_metadata + ) + except: + # DO NOT LET this Block raising the original exception + pass ################################################################################ # End of Common Extra information Needed for all providers @@ -8194,9 +8186,10 @@ def exception_type( if "Request Timeout Error" in error_str or "Request timed out" in error_str: exception_mapping_worked = True raise Timeout( - message=f"APITimeoutError - Request timed out. {extra_information} \n error_str: {error_str}", + message=f"APITimeoutError - Request timed out. \nerror_str: {error_str}", model=model, llm_provider=custom_llm_provider, + litellm_debug_info=extra_information, ) if ( @@ -8226,10 +8219,11 @@ def exception_type( if "This model's maximum context length is" in error_str: exception_mapping_worked = True raise ContextWindowExceededError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif ( "invalid_request_error" in error_str @@ -8237,10 +8231,11 @@ def exception_type( ): exception_mapping_worked = True raise NotFoundError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif ( "invalid_request_error" in error_str @@ -8248,10 +8243,11 @@ def exception_type( ): exception_mapping_worked = True raise ContentPolicyViolationError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif ( "invalid_request_error" in error_str @@ -8259,17 +8255,19 @@ def exception_type( ): exception_mapping_worked = True raise BadRequestError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif "Request too large" in error_str: raise RateLimitError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, response=original_exception.response, + litellm_debug_info=extra_information, ) elif ( "The api_key client option must be set either by passing api_key to the client or by setting the OPENAI_API_KEY environment variable" @@ -8277,10 +8275,11 @@ def exception_type( ): exception_mapping_worked = True raise AuthenticationError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif "Mistral API raised a streaming error" in error_str: exception_mapping_worked = True @@ -8289,82 +8288,92 @@ def exception_type( ) raise APIError( status_code=500, - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, request=_request, + litellm_debug_info=extra_information, ) elif hasattr(original_exception, "status_code"): exception_mapping_worked = True if original_exception.status_code == 401: exception_mapping_worked = True raise AuthenticationError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, response=original_exception.response, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 404: exception_mapping_worked = True raise NotFoundError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, response=original_exception.response, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 408: exception_mapping_worked = True raise Timeout( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 422: exception_mapping_worked = True raise BadRequestError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, response=original_exception.response, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 429: exception_mapping_worked = True raise RateLimitError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, response=original_exception.response, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 503: exception_mapping_worked = True raise ServiceUnavailableError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, response=original_exception.response, + litellm_debug_info=extra_information, ) elif original_exception.status_code == 504: # gateway timeout error exception_mapping_worked = True raise Timeout( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", model=model, llm_provider=custom_llm_provider, + litellm_debug_info=extra_information, ) else: exception_mapping_worked = True raise APIError( status_code=original_exception.status_code, - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, request=original_exception.request, + litellm_debug_info=extra_information, ) else: # if no status code then it is an APIConnectionError: https://github.com/openai/openai-python#handling-errors raise APIConnectionError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider=custom_llm_provider, model=model, + litellm_debug_info=extra_information, request=httpx.Request( method="POST", url="https://api.openai.com/v1/" ), @@ -8529,6 +8538,28 @@ def exception_type( model=model, response=original_exception.response, ) + elif custom_llm_provider == "predibase": + if "authorization denied for" in error_str: + exception_mapping_worked = True + + # Predibase returns the raw API Key in the response - this block ensures it's not returned in the exception + if ( + error_str is not None + and isinstance(error_str, str) + and "bearer" in error_str.lower() + ): + # only keep the first 10 chars after the occurnence of "bearer" + _bearer_token_start_index = error_str.lower().find("bearer") + error_str = error_str[: _bearer_token_start_index + 14] + error_str += "XXXXXXX" + '"' + + raise AuthenticationError( + message=f"PredibaseException: Authentication Error - {error_str}", + llm_provider="predibase", + model=model, + response=original_exception.response, + litellm_debug_info=extra_information, + ) elif custom_llm_provider == "bedrock": if ( "too many tokens" in error_str @@ -8666,10 +8697,11 @@ def exception_type( ): exception_mapping_worked = True raise BadRequestError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", model=model, llm_provider="vertex_ai", response=original_exception.response, + litellm_debug_info=extra_information, ) elif ( "None Unknown Error." in error_str @@ -8677,26 +8709,29 @@ def exception_type( ): exception_mapping_worked = True raise APIError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", status_code=500, model=model, llm_provider="vertex_ai", request=original_exception.request, + litellm_debug_info=extra_information, ) elif "403" in error_str: exception_mapping_worked = True raise BadRequestError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", model=model, llm_provider="vertex_ai", response=original_exception.response, + litellm_debug_info=extra_information, ) elif "The response was blocked." in error_str: exception_mapping_worked = True raise UnprocessableEntityError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", model=model, llm_provider="vertex_ai", + litellm_debug_info=extra_information, response=httpx.Response( status_code=429, request=httpx.Request( @@ -8713,9 +8748,10 @@ def exception_type( ): exception_mapping_worked = True raise RateLimitError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", model=model, llm_provider="vertex_ai", + litellm_debug_info=extra_information, response=httpx.Response( status_code=429, request=httpx.Request( @@ -8728,18 +8764,20 @@ def exception_type( if original_exception.status_code == 400: exception_mapping_worked = True raise BadRequestError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", model=model, llm_provider="vertex_ai", + litellm_debug_info=extra_information, response=original_exception.response, ) if original_exception.status_code == 500: exception_mapping_worked = True raise APIError( - message=f"VertexAIException - {error_str} {extra_information}", + message=f"VertexAIException - {error_str}", status_code=500, model=model, llm_provider="vertex_ai", + litellm_debug_info=extra_information, request=original_exception.request, ) elif custom_llm_provider == "palm" or custom_llm_provider == "gemini": @@ -9340,25 +9378,28 @@ def exception_type( exception_mapping_worked = True raise APIError( status_code=500, - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, request=httpx.Request(method="POST", url="https://openai.com/"), ) elif "This model's maximum context length is" in error_str: exception_mapping_worked = True raise ContextWindowExceededError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif "DeploymentNotFound" in error_str: exception_mapping_worked = True raise NotFoundError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif ( @@ -9370,17 +9411,19 @@ def exception_type( ): exception_mapping_worked = True raise ContentPolicyViolationError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif "invalid_request_error" in error_str: exception_mapping_worked = True raise BadRequestError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif ( @@ -9389,9 +9432,10 @@ def exception_type( ): exception_mapping_worked = True raise AuthenticationError( - message=f"{exception_provider} - {original_exception.message} {extra_information}", + message=f"{exception_provider} - {original_exception.message}", llm_provider=custom_llm_provider, model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif hasattr(original_exception, "status_code"): @@ -9399,55 +9443,62 @@ def exception_type( if original_exception.status_code == 401: exception_mapping_worked = True raise AuthenticationError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, response=original_exception.response, ) elif original_exception.status_code == 408: exception_mapping_worked = True raise Timeout( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", model=model, + litellm_debug_info=extra_information, llm_provider="azure", ) if original_exception.status_code == 422: exception_mapping_worked = True raise BadRequestError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", model=model, llm_provider="azure", + litellm_debug_info=extra_information, response=original_exception.response, ) elif original_exception.status_code == 429: exception_mapping_worked = True raise RateLimitError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", model=model, llm_provider="azure", + litellm_debug_info=extra_information, response=original_exception.response, ) elif original_exception.status_code == 503: exception_mapping_worked = True raise ServiceUnavailableError( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", model=model, llm_provider="azure", + litellm_debug_info=extra_information, response=original_exception.response, ) elif original_exception.status_code == 504: # gateway timeout error exception_mapping_worked = True raise Timeout( - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", model=model, + litellm_debug_info=extra_information, llm_provider="azure", ) else: exception_mapping_worked = True raise APIError( status_code=original_exception.status_code, - message=f"AzureException - {original_exception.message} {extra_information}", + message=f"AzureException - {original_exception.message}", llm_provider="azure", + litellm_debug_info=extra_information, model=model, request=httpx.Request( method="POST", url="https://openai.com/" @@ -9456,9 +9507,10 @@ def exception_type( else: # if no status code then it is an APIConnectionError: https://github.com/openai/openai-python#handling-errors raise APIConnectionError( - message=f"{exception_provider} - {message} {extra_information}", + message=f"{exception_provider} - {message}", llm_provider="azure", model=model, + litellm_debug_info=extra_information, request=httpx.Request(method="POST", url="https://openai.com/"), ) if ( diff --git a/model_prices_and_context_window.json b/model_prices_and_context_window.json index a88d6875ca..ff9194578c 100644 --- a/model_prices_and_context_window.json +++ b/model_prices_and_context_window.json @@ -1744,6 +1744,30 @@ "litellm_provider": "openrouter", "mode": "chat" }, + "openrouter/openai/gpt-4o": { + "max_tokens": 4096, + "max_input_tokens": 128000, + "max_output_tokens": 4096, + "input_cost_per_token": 0.000005, + "output_cost_per_token": 0.000015, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true + }, + "openrouter/openai/gpt-4o-2024-05-13": { + "max_tokens": 4096, + "max_input_tokens": 128000, + "max_output_tokens": 4096, + "input_cost_per_token": 0.000005, + "output_cost_per_token": 0.000015, + "litellm_provider": "openrouter", + "mode": "chat", + "supports_function_calling": true, + "supports_parallel_function_calling": true, + "supports_vision": true + }, "openrouter/openai/gpt-4-vision-preview": { "max_tokens": 130000, "input_cost_per_token": 0.00001, @@ -2943,6 +2967,24 @@ "litellm_provider": "ollama", "mode": "completion" }, + "ollama/llama3": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/llama3:70b": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, "ollama/mistral": { "max_tokens": 8192, "max_input_tokens": 8192, @@ -2952,6 +2994,42 @@ "litellm_provider": "ollama", "mode": "completion" }, + "ollama/mistral-7B-Instruct-v0.1": { + "max_tokens": 8192, + "max_input_tokens": 8192, + "max_output_tokens": 8192, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mistral-7B-Instruct-v0.2": { + "max_tokens": 32768, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mixtral-8x7B-Instruct-v0.1": { + "max_tokens": 32768, + "max_input_tokens": 32768, + "max_output_tokens": 32768, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, + "ollama/mixtral-8x22B-Instruct-v0.1": { + "max_tokens": 65536, + "max_input_tokens": 65536, + "max_output_tokens": 65536, + "input_cost_per_token": 0.0, + "output_cost_per_token": 0.0, + "litellm_provider": "ollama", + "mode": "chat" + }, "ollama/codellama": { "max_tokens": 4096, "max_input_tokens": 4096, diff --git a/pyproject.toml b/pyproject.toml index 3250eed82f..55e88c30a2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "litellm" -version = "1.37.10" +version = "1.37.12" description = "Library to easily interface with LLM API providers" authors = ["BerriAI"] license = "MIT" @@ -79,7 +79,7 @@ requires = ["poetry-core", "wheel"] build-backend = "poetry.core.masonry.api" [tool.commitizen] -version = "1.37.10" +version = "1.37.12" version_files = [ "pyproject.toml:^version" ] diff --git a/ui/litellm-dashboard/out/404.html b/ui/litellm-dashboard/out/404.html index b70559084d..b0b75d094b 100644 --- a/ui/litellm-dashboard/out/404.html +++ b/ui/litellm-dashboard/out/404.html @@ -1 +1 @@ -404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file +404: This page could not be found.LiteLLM Dashboard

404

This page could not be found.

\ No newline at end of file diff --git a/ui/litellm-dashboard/out/_next/static/obp5wqVSVDMiDTC414cR8/_buildManifest.js b/ui/litellm-dashboard/out/_next/static/2ASoJGxS-D4w-vat00xMy/_buildManifest.js similarity index 100% rename from ui/litellm-dashboard/out/_next/static/obp5wqVSVDMiDTC414cR8/_buildManifest.js rename to ui/litellm-dashboard/out/_next/static/2ASoJGxS-D4w-vat00xMy/_buildManifest.js diff --git a/ui/litellm-dashboard/out/_next/static/obp5wqVSVDMiDTC414cR8/_ssgManifest.js b/ui/litellm-dashboard/out/_next/static/2ASoJGxS-D4w-vat00xMy/_ssgManifest.js similarity index 100% rename from ui/litellm-dashboard/out/_next/static/obp5wqVSVDMiDTC414cR8/_ssgManifest.js rename to ui/litellm-dashboard/out/_next/static/2ASoJGxS-D4w-vat00xMy/_ssgManifest.js diff --git a/ui/litellm-dashboard/out/_next/static/chunks/app/page-6a39771cacf75ea6.js b/ui/litellm-dashboard/out/_next/static/chunks/app/page-6a39771cacf75ea6.js deleted file mode 100644 index 7d08a80c96..0000000000 --- a/ui/litellm-dashboard/out/_next/static/chunks/app/page-6a39771cacf75ea6.js +++ /dev/null @@ -1 +0,0 @@ -(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,l,t){Promise.resolve().then(t.bind(t,7926))},7926:function(e,l,t){"use strict";t.r(l),t.d(l,{default:function(){return lb}});var s,a,r=t(3827),n=t(64090),o=t(47907),i=t(8792),c=t(40491),d=t(65270),m=e=>{let{userID:l,userRole:t,userEmail:s,showSSOBanner:a}=e;console.log("User ID:",l),console.log("userEmail:",s),console.log("showSSOBanner:",a);let n=[{key:"1",label:(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("p",{children:["Role: ",t]}),(0,r.jsxs)("p",{children:["ID: ",l]})]})}];return(0,r.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,r.jsx)("div",{className:"text-left my-2 absolute top-0 left-0",children:(0,r.jsx)("div",{className:"flex flex-col items-center",children:(0,r.jsx)(i.default,{href:"/",children:(0,r.jsx)("button",{className:"text-gray-800 rounded text-center",children:(0,r.jsx)("img",{src:"/get_image",width:160,height:160,alt:"LiteLLM Brand",className:"mr-2"})})})})}),(0,r.jsxs)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2",children:[a?(0,r.jsx)("div",{style:{padding:"6px",borderRadius:"8px"},children:(0,r.jsx)("a",{href:"https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat",target:"_blank",style:{fontSize:"14px",textDecoration:"underline"},children:"Request hosted proxy"})}):null,(0,r.jsx)("div",{style:{border:"1px solid #391085",padding:"6px",borderRadius:"8px"},children:(0,r.jsx)(c.Z,{menu:{items:n},children:(0,r.jsx)(d.Z,{children:s})})})]})]})},u=t(80588);let h=async()=>{try{let e=await fetch("https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"),l=await e.json();return console.log("received data: ".concat(l)),l}catch(e){throw console.error("Failed to get model cost map:",e),e}},x=async(e,l)=>{try{let t=await fetch("/model/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model created successfully. Wait 60s and refresh on 'All Models' page"),s}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,l)=>{console.log("model_id in model delete call: ".concat(l));try{let t=await fetch("/model/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({id:l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model deleted successfully. Restart server to see this."),s}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/user/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},y=async(e,l)=>{try{console.log("in keyDeleteCall:",l);let t=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},f=async(e,l)=>{try{console.log("in teamDeleteCall:",l);let t=await fetch("/team/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_ids:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete team: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to delete key:",e),e}},Z=async function(e,l,t){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],a=arguments.length>4?arguments[4]:void 0,r=arguments.length>5?arguments[5]:void 0;try{let n="/user/info";"App Owner"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),"App User"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),console.log("in userInfoCall viewAll=",s),s&&r&&null!=a&&void 0!=a&&(n="".concat(n,"?view_all=true&page=").concat(a,"&page_size=").concat(r));let o=await fetch(n,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let i=await o.json();return console.log("API Response:",i),i}catch(e){throw console.error("Failed to create key:",e),e}},_=async(e,l)=>{try{let t="/team/info";l&&(t="".concat(t,"?team_id=").concat(l)),console.log("in teamInfoCall");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},w=async e=>{try{let l=await fetch("/global/spend",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},b=async(e,l,t)=>{try{let l=await fetch("/v2/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log("modelInfoCall:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},k=async(e,l,t,s,a,r)=>{try{let l="/model/metrics";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},v=async(e,l,t,s,a,r)=>{try{let l="/model/metrics/slow_responses";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},S=async(e,l,t,s,a,r)=>{try{let l="/model/metrics/exceptions";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(a,"&endTime=").concat(r));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},N=async(e,l,t)=>{try{let l=await fetch("/models",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},A=async e=>{try{let l="/global/spend/teams";console.log("in teamSpendLogsCall:",l);let t=await fetch("".concat(l),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},E=async(e,l,t)=>{try{let s="/global/spend/tags";l&&t&&(s="".concat(s,"?start_date=").concat(l,"&end_date=").concat(t)),console.log("in tagsSpendLogsCall:",s);let a=await fetch("".concat(s),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!a.ok){let e=await a.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await a.json();return console.log(r),r}catch(e){throw console.error("Failed to create key:",e),e}},I=async(e,l,t,s,a,r)=>{try{console.log("user role in spend logs call: ".concat(t));let l="/spend/logs";l="App Owner"==t?"".concat(l,"?user_id=").concat(s,"&start_date=").concat(a,"&end_date=").concat(r):"".concat(l,"?start_date=").concat(a,"&end_date=").concat(r);let n=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},C=async e=>{try{let l=await fetch("/global/spend/logs",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},P=async e=>{try{let l=await fetch("/global/spend/keys?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},T=async(e,l,t,s)=>{try{let a="";a=l?JSON.stringify({api_key:l,startTime:t,endTime:s}):JSON.stringify({startTime:t,endTime:s});let r={method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}};r.body=a;let n=await fetch("/global/spend/end_users",r);if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},O=async e=>{try{let l=await fetch("/global/spend/models?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},F=async(e,l)=>{try{let t=await fetch("/v2/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},R=async(e,l)=>{try{let t="/user/get_users?role=".concat(l);console.log("in userGetAllUsersCall:",t);let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let a=await s.json();return console.log(a),a}catch(e){throw console.error("Failed to get requested models:",e),e}},M=async(e,l)=>{try{console.log("Form Values in teamCreateCall:",l);let t=await fetch("/team/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},L=async(e,l)=>{try{console.log("Form Values in keyUpdateCall:",l);let t=await fetch("/key/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update key Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},U=async(e,l)=>{try{console.log("Form Values in teamUpateCall:",l);let t=await fetch("/team/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update team: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update Team Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},D=async(e,l)=>{try{console.log("Form Values in modelUpateCall:",l);let t=await fetch("/model/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update model: "+e,10),console.error("Error update from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update model Response:",s),s}catch(e){throw console.error("Failed to update model:",e),e}},K=async(e,l,t)=>{try{console.log("Form Values in teamMemberAddCall:",t);let s=await fetch("/team/member_add",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_id:l,member:t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await s.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},B=async(e,l,t)=>{try{console.log("Form Values in userUpdateUserCall:",l);let s={...l};null!==t&&(s.user_role=t),s=JSON.stringify(s);let a=await fetch("/user/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:s});if(!a.ok){let e=await a.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await a.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},z=async(e,l)=>{try{let t="/health/services?service=".concat(l);console.log("Checking Slack Budget Alerts service health");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed ".concat(l," service health check ")+e),Error(e)}let a=await s.json();return u.ZP.success("Test request to ".concat(l," made - check logs/alerts on ").concat(l," to verify")),a}catch(e){throw console.error("Failed to perform health check:",e),e}},q=async(e,l,t)=>{try{let l=await fetch("/get/config/callbacks",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},V=async(e,l)=>{try{let t=await fetch("/config/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to set callbacks:",e),e}},G=async e=>{try{let l=await fetch("/health",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to call /health:",e),e}};var Y=t(10384),W=t(46453),J=t(16450),H=t(52273),$=t(26780),X=t(15595),Q=t(6698),ee=t(71801),el=t(42440),et=t(42308),es=t(50670),ea=t(81583),er=t(99129),en=t(44839),eo=t(88707),ei=t(1861);let{Option:ec}=es.default;var ed=e=>{let{userID:l,team:t,userRole:s,accessToken:a,data:o,setData:i}=e,[c]=ea.Z.useForm(),[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(null),[p,g]=(0,n.useState)(null),[y,f]=(0,n.useState)([]),[Z,_]=(0,n.useState)([]),w=()=>{m(!1),c.resetFields()},b=()=>{m(!1),x(null),c.resetFields()};(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===s)return;if(null!==a){let e=(await N(a,l,s)).data.map(e=>e.id);console.log("available_model_names:",e),f(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[a,l,s]);let k=async e=>{try{var t,s,r;let n=null!==(t=null==e?void 0:e.key_alias)&&void 0!==t?t:"",d=null!==(s=null==e?void 0:e.team_id)&&void 0!==s?s:null;if((null!==(r=null==o?void 0:o.filter(e=>e.team_id===d).map(e=>e.key_alias))&&void 0!==r?r:[]).includes(n))throw Error("Key alias ".concat(n," already exists for team with ID ").concat(d,", please provide another key alias"));u.ZP.info("Making API Call"),m(!0);let h=await j(a,l,e);console.log("key create Response:",h),i(e=>e?[...e,h]:[h]),x(h.key),g(h.soft_budget),u.ZP.success("API Key Created"),c.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the key:",e),u.ZP.error("Error creating the key: ".concat(e),20)}};return(0,n.useEffect)(()=>{_(t&&t.models.length>0?t.models.includes("all-proxy-models")?y:t.models:y)},[t,y]),(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>m(!0),children:"+ Create New Key"}),(0,r.jsx)(er.Z,{title:"Create Key",visible:d,width:800,footer:null,onOk:w,onCancel:b,children:(0,r.jsxs)(ea.Z,{form:c,onFinish:k,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"team_id",hidden:!0,initialValue:t?t.team_id:null,valuePropName:"team_id",className:"mt-8",children:(0,r.jsx)(en.Z,{value:t?t.team_alias:"",disabled:!0})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},onChange:e=>{e.includes("all-team-models")&&c.setFieldsValue({models:["all-team-models"]})},children:[(0,r.jsx)(ec,{value:"all-team-models",children:"All Team Models"},"all-team-models"),Z.map(e=>(0,r.jsx)(ec,{value:e,children:e},e))]})}),(0,r.jsxs)($.Z,{className:"mt-20 mb-8",children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)("b",{children:"Optional Settings"})}),(0,r.jsxs)(X.Z,{children:[(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat(t.max_budget))}}],children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Reset Budget",name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,r.jsxs)(es.default,{defaultValue:null,placeholder:"n/a",children:[(0,r.jsx)(es.default.Option,{value:"24h",children:"daily"}),(0,r.jsx)(es.default.Option,{value:"30d",children:"monthly"})]})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Tokens per minute Limit (TPM)",name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Requests per minute Limit (RPM)",name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Expire Key (eg: 30s, 30h, 30d)",name:"duration",className:"mt-8",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(en.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]})]})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create Key"})})]})}),h&&(0,r.jsx)(er.Z,{visible:d,onOk:w,onCancel:b,footer:null,children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(el.Z,{children:"Save your Key"}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,r.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:null!=h?(0,r.jsxs)("div",{children:[(0,r.jsx)(ee.Z,{className:"mt-3",children:"API Key:"}),(0,r.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,r.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:h})}),(0,r.jsx)(et.CopyToClipboard,{text:h,onCopy:()=>{u.ZP.success("API Key copied to clipboard")},children:(0,r.jsx)(J.Z,{className:"mt-3",children:"Copy API Key"})})]}):(0,r.jsx)(ee.Z,{children:"Key being created, this might take 30s"})})]})})]})},em=t(9454),eu=t(98941),eh=t(33393),ex=t(5),ep=t(13810),ej=t(61244),eg=t(10827),ey=t(3851),ef=t(2044),eZ=t(64167),e_=t(74480),ew=t(7178),eb=t(95093),ek=t(27166);let{Option:ev}=es.default;var eS=e=>{let{userID:l,userRole:t,accessToken:s,selectedTeam:a,data:o,setData:i,teams:c}=e,[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(!1),[p,j]=(0,n.useState)(null),[g,f]=(0,n.useState)(null),[Z,_]=(0,n.useState)(null),[w,b]=(0,n.useState)(""),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)(!1),[E,I]=(0,n.useState)(null),[C,P]=(0,n.useState)([]),T=new Set,[O,F]=(0,n.useState)(T);(0,n.useEffect)(()=>{(async()=>{try{if(null===l)return;if(null!==s&&null!==t){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),P(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[s,l,t]),(0,n.useEffect)(()=>{if(c){let e=new Set;c.forEach((l,t)=>{let s=l.team_id;e.add(s)}),F(e)}},[c]);let R=e=>{console.log("handleEditClick:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),I(e),v(!0)},M=async e=>{if(null==s)return;let l=e.token;e.key=l,console.log("handleEditSubmit:",e);let t=await L(s,e);console.log("handleEditSubmit: newKeyValues",t),o&&i(o.map(e=>e.token===l?t:e)),u.ZP.success("Key updated successfully"),v(!1),I(null)},U=async e=>{console.log("handleDelete:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),null!=o&&(j(e.token),localStorage.removeItem("userData"+l),x(!0))},D=async()=>{if(null!=p&&null!=o){try{await y(s,p);let e=o.filter(e=>e.token!==p);i(e)}catch(e){console.error("Error deleting the key:",e)}x(!1),j(null)}};if(null!=o)return console.log("RERENDER TRIGGERED"),(0,r.jsxs)("div",{children:[(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4 mt-2",children:[(0,r.jsxs)(eg.Z,{className:"mt-5 max-h-[300px] min-h-[300px]",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Key Alias"}),(0,r.jsx)(e_.Z,{children:"Secret Key"}),(0,r.jsx)(e_.Z,{children:"Spend (USD)"}),(0,r.jsx)(e_.Z,{children:"Budget (USD)"}),(0,r.jsx)(e_.Z,{children:"Models"}),(0,r.jsx)(e_.Z,{children:"TPM / RPM Limits"})]})}),(0,r.jsx)(ey.Z,{children:o.map(e=>{if(console.log(e),"litellm-dashboard"===e.team_id)return null;if(a){if(console.log("item team id: ".concat(e.team_id,", knownTeamIDs.has(item.team_id): ").concat(O.has(e.team_id),", selectedTeam id: ").concat(a.team_id)),(null!=a.team_id||null===e.team_id||O.has(e.team_id))&&e.team_id!=a.team_id)return null;console.log("item team id: ".concat(e.team_id,", is returned"))}return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{style:{maxWidth:"2px",whiteSpace:"pre-wrap",overflow:"hidden"},children:null!=e.key_alias?(0,r.jsx)(ee.Z,{children:e.key_alias}):(0,r.jsx)(ee.Z,{children:"Not Set"})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:e.key_name})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:(()=>{try{return parseFloat(e.spend).toFixed(4)}catch(l){return e.spend}})()})}),(0,r.jsx)(ef.Z,{children:null!=e.max_budget?(0,r.jsx)(ee.Z,{children:e.max_budget}):(0,r.jsx)(ee.Z,{children:"Unlimited"})}),(0,r.jsx)(ef.Z,{children:Array.isArray(e.models)?(0,r.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,r.jsx)(r.Fragment,{children:a&&a.models&&a.models.length>0?a.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Team Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l)):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:"all-proxy-models"})})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Team Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,r.jsx)(ef.Z,{children:(0,r.jsxs)(ee.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,r.jsx)("br",{})," RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{onClick:()=>{I(e),A(!0)},icon:em.Z,size:"sm"}),(0,r.jsx)(er.Z,{open:S,onCancel:()=>{A(!1),I(null)},footer:null,width:800,children:E&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsxs)("div",{className:"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 mt-8",children:[(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Spend"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:(()=>{try{return parseFloat(E.spend).toFixed(4)}catch(e){return E.spend}})()})})]}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Budget"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.max_budget?(0,r.jsx)(r.Fragment,{children:E.max_budget}):(0,r.jsx)(r.Fragment,{children:"Unlimited"})})})]},e.name),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Expires"}),(0,r.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,r.jsx)("p",{className:"text-tremor-default font-small text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.expires?(0,r.jsx)(r.Fragment,{children:new Date(E.expires).toLocaleString(void 0,{day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric"})}):(0,r.jsx)(r.Fragment,{children:"Never"})})})]},e.name)]}),(0,r.jsxs)(ep.Z,{className:"my-4",children:[(0,r.jsx)(el.Z,{children:"Token Name"}),(0,r.jsx)(ee.Z,{className:"my-1",children:E.key_alias?E.key_alias:E.key_name}),(0,r.jsx)(el.Z,{children:"Token ID"}),(0,r.jsx)(ee.Z,{className:"my-1 text-[12px]",children:E.token}),(0,r.jsx)(el.Z,{children:"Metadata"}),(0,r.jsx)(ee.Z,{className:"my-1",children:(0,r.jsxs)("pre",{children:[JSON.stringify(E.metadata)," "]})})]}),(0,r.jsx)(J.Z,{className:"mx-auto flex items-center",onClick:()=>{A(!1),I(null)},children:"Close"})]})}),(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>R(e)}),(0,r.jsx)(ej.Z,{onClick:()=>U(e),icon:eh.Z,size:"sm"})]})]},e.token)})})]}),h&&(0,r.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,r.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,r.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,r.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,r.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,r.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,r.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,r.jsx)("div",{className:"sm:flex sm:items-start",children:(0,r.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,r.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,r.jsx)("div",{className:"mt-2",children:(0,r.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,r.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,r.jsx)(J.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,r.jsx)(J.Z,{onClick:()=>{x(!1),j(null)},children:"Cancel"})]})]})]})})]}),E&&(0,r.jsx)(e=>{let{visible:l,onCancel:t,token:s,onSubmit:o}=e,[i]=ea.Z.useForm(),[d,m]=(0,n.useState)(a),[u,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1);return(0,r.jsx)(er.Z,{title:"Edit Key",visible:l,width:800,footer:null,onOk:()=>{i.validateFields().then(e=>{i.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:i,onFinish:M,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",rules:[{validator:(e,l)=>{let t=l.filter(e=>!d.models.includes(e)&&"all-team-models"!==e&&"all-proxy-models"!==e&&!d.models.includes("all-proxy-models"));return(console.log("errorModels: ".concat(t)),t.length>0)?Promise.reject("Some models are not part of the new team's models - ".concat(t,"Team models: ").concat(d.models)):Promise.resolve()}}],children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(ev,{value:"all-team-models",children:"All Team Models"},"all-team-models"),d&&d.models?d.models.includes("all-proxy-models")?C.filter(e=>"all-proxy-models"!==e).map(e=>(0,r.jsx)(ev,{value:e,children:e},e)):d.models.map(e=>(0,r.jsx)(ev,{value:e,children:e},e)):C.map(e=>(0,r.jsx)(ev,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: ".concat((null==d?void 0:d.max_budget)!==null&&(null==d?void 0:d.max_budget)!==void 0?null==d?void 0:d.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&d&&null!==d.max_budget&&l>d.max_budget)throw console.log("keyTeam.max_budget: ".concat(d.max_budget)),Error("Budget cannot exceed team max budget: $".concat(d.max_budget))}}],children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"token",name:"token",hidden:!0}),(0,r.jsx)(ea.Z.Item,{label:"Team",name:"team_id",help:"the team this key belongs to",children:(0,r.jsx)(eb.Z,{value:s.team_alias,children:null==c?void 0:c.map((e,l)=>(0,r.jsx)(ek.Z,{value:e.team_id,onClick:()=>m(e),children:e.team_alias},l))})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Edit Key"})})]})})},{visible:k,onCancel:()=>{v(!1),I(null)},token:E,onSubmit:M})]})},eN=t(76032),eA=t(35152),eE=e=>{let{userID:l,userRole:t,accessToken:s,userSpend:a,selectedTeam:o}=e;console.log("userSpend: ".concat(a));let[i,c]=(0,n.useState)(null!==a?a:0),[d,m]=(0,n.useState)(0),[u,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{let e=async()=>{if(s&&l&&t&&"Admin"===t&&null==a)try{let e=await w(s);e&&(e.spend?c(e.spend):c(0),e.max_budget?m(e.max_budget):m(0))}catch(e){console.error("Error fetching global spend data:",e)}};(async()=>{try{if(null===l||null===t)return;if(null!==s){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),h(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[t,s,l]),(0,n.useEffect)(()=>{null!==a&&c(a)},[a]);let x=[];o&&o.models&&(x=o.models),x&&x.includes("all-proxy-models")?(console.log("user models:",u),x=u):x&&x.includes("all-team-models")?x=o.models:x&&0===x.length&&(x=u);let p=void 0!==i?i.toFixed(4):null;return console.log("spend in view user spend: ".concat(i)),(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsxs)("div",{children:[(0,r.jsxs)("p",{className:"text-tremor-default text-tremor-content dark:text-dark-tremor-content",children:["Total Spend"," "]}),(0,r.jsxs)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:["$",p]})]}),(0,r.jsx)("div",{className:"ml-auto",children:(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)(ee.Z,{children:"Team Models"})}),(0,r.jsx)(X.Z,{className:"absolute right-0 z-10 bg-white p-2 shadow-lg max-w-xs",children:(0,r.jsx)(eN.Z,{children:x.map(e=>(0,r.jsx)(eA.Z,{children:(0,r.jsx)(ee.Z,{children:e})},e))})})]})})]})},eI=e=>{let{userID:l,userRole:t,selectedTeam:s,accessToken:a}=e,[o,i]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===t)return;if(null!==a){let e=(await N(a,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),i(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[a,l,t]);let c=[];return s&&s.models&&(c=s.models),c&&c.includes("all-proxy-models")&&(console.log("user models:",o),c=o),(0,r.jsx)(r.Fragment,{children:(0,r.jsx)("div",{className:"mb-5",children:(0,r.jsx)("p",{className:"text-3xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:null==s?void 0:s.team_alias})})})},eC=e=>{let l,{teams:t,setSelectedTeam:s,userRole:a}=e,o={models:[],team_id:null,team_alias:"Default Team"},[i,c]=(0,n.useState)(o);return(l="App User"===a?t:t?[...t,o]:[o],"App User"===a)?null:(0,r.jsxs)("div",{className:"mt-5 mb-5",children:[(0,r.jsx)(el.Z,{children:"Select Team"}),(0,r.jsx)(ee.Z,{children:"If you belong to multiple teams, this setting controls which team is used by default when creating new API Keys."}),(0,r.jsxs)(ee.Z,{className:"mt-3 mb-3",children:[(0,r.jsx)("b",{children:"Default Team:"})," If no team_id is set for a key, it will be grouped under here."]}),l&&l.length>0?(0,r.jsx)(eb.Z,{defaultValue:"0",children:l.map((e,l)=>(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>s(e),children:e.team_alias},l))}):(0,r.jsxs)(ee.Z,{children:["No team created. ",(0,r.jsx)("b",{children:"Defaulting to personal account."})]})]})},eP=t(37963),eT=t(36083);console.log("isLocal:",!1);var eO=e=>{let{userID:l,userRole:t,teams:s,keys:a,setUserRole:i,userEmail:c,setUserEmail:d,setTeams:m,setKeys:u}=e,[h,x]=(0,n.useState)(null),p=(0,o.useSearchParams)();p.get("viewSpend"),(0,o.useRouter)();let j=p.get("token"),[g,y]=(0,n.useState)(null),[f,_]=(0,n.useState)(null),[b,k]=(0,n.useState)([]),v={models:[],team_alias:"Default Team",team_id:null},[S,A]=(0,n.useState)(s?s[0]:v);if(window.addEventListener("beforeunload",function(){sessionStorage.clear()}),(0,n.useEffect)(()=>{if(j){let e=(0,eP.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),y(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),i(l)}else console.log("User role not defined");e.user_email?d(e.user_email):console.log("User Email is not set ".concat(e))}}if(l&&g&&t&&!a&&!h){let e=sessionStorage.getItem("userModels"+l);e?k(JSON.parse(e)):(async()=>{try{let e=await Z(g,l,t,!1,null,null);if(console.log("received teams in user dashboard: ".concat(Object.keys(e),"; team values: ").concat(Object.entries(e.teams))),"Admin"==t){let e=await w(g);x(e),console.log("globalSpend:",e)}else x(e.user_info);u(e.keys),m(e.teams);let s=[...e.teams];s.length>0?(console.log("response['teams']: ".concat(s)),A(s[0])):A(v),sessionStorage.setItem("userData"+l,JSON.stringify(e.keys)),sessionStorage.setItem("userSpendData"+l,JSON.stringify(e.user_info));let a=(await N(g,l,t)).data.map(e=>e.id);console.log("available_model_names:",a),k(a),console.log("userModels:",b),sessionStorage.setItem("userModels"+l,JSON.stringify(a))}catch(e){console.error("There was an error fetching the data",e)}})()}},[l,j,g,a,t]),(0,n.useEffect)(()=>{if(null!==a&&null!=S){let e=0;for(let l of a)S.hasOwnProperty("team_id")&&null!==l.team_id&&l.team_id===S.team_id&&(e+=l.spend);_(e)}else if(null!==a){let e=0;for(let l of a)e+=l.spend;_(e)}},[S]),null==l||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}if(null==g)return null;if(null==t&&i("App Owner"),t&&"Admin Viewer"==t){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to create keys"})]})}return console.log("inside user dashboard, selected team",S),console.log("teamSpend: ".concat(f)),(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsx)(W.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(eI,{userID:l,userRole:t,selectedTeam:S||null,accessToken:g}),(0,r.jsx)(eE,{userID:l,userRole:t,accessToken:g,userSpend:f,selectedTeam:S||null}),(0,r.jsx)(eS,{userID:l,userRole:t,accessToken:g,selectedTeam:S||null,data:a,setData:u,teams:s}),(0,r.jsx)(ed,{userID:l,team:S||null,userRole:t,accessToken:g,data:a,setData:u},S?S.team_id:null),(0,r.jsx)(eC,{teams:s,setSelectedTeam:A,userRole:t})]})})})},eF=t(35087),eR=t(92836),eM=t(26734),eL=t(41608),eU=t(32126),eD=t(23682),eK=t(47047),eB=t(76628),ez=t(57750),eq=t(44041),eV=t(38302),eG=t(28683),eY=t(1460),eW=t(78578),eJ=t(63954),eH=t(90252),e$=t(7905),eX=e=>{let{modelID:l,accessToken:t}=e,[s,a]=(0,n.useState)(!1),o=async()=>{try{u.ZP.info("Making API Call"),a(!0);let e=await p(t,l);console.log("model delete Response:",e),u.ZP.success("Model ".concat(l," deleted successfully")),a(!1)}catch(e){console.error("Error deleting the model:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(ej.Z,{onClick:()=>a(!0),icon:eh.Z,size:"sm"}),(0,r.jsx)(er.Z,{open:s,onOk:o,okType:"danger",onCancel:()=>a(!1),children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(el.Z,{children:"Delete Model"}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsx)("p",{children:"Are you sure you want to delete this model? This action is irreversible."})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("p",{children:["Model ID: ",(0,r.jsx)("b",{children:l})]})})]})})]})},eQ=t(97766),e0=t(46495);let{Title:e1,Link:e2}=eT.default;(s=a||(a={})).OpenAI="OpenAI",s.Azure="Azure",s.Anthropic="Anthropic",s.Google_AI_Studio="Gemini (Google AI Studio)",s.Bedrock="Amazon Bedrock",s.OpenAI_Compatible="OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)",s.Vertex_AI="Vertex AI (Anthropic, Gemini, etc.)";let e4={OpenAI:"openai",Azure:"azure",Anthropic:"anthropic",Google_AI_Studio:"gemini",Bedrock:"bedrock",OpenAI_Compatible:"openai",Vertex_AI:"vertex_ai"},e8={"BadRequestError (400)":"BadRequestErrorRetries","AuthenticationError (401)":"AuthenticationErrorRetries","TimeoutError (408)":"TimeoutErrorRetries","RateLimitError (429)":"RateLimitErrorRetries","ContentPolicyViolationError (400)":"ContentPolicyViolationErrorRetries","InternalServerError (500)":"InternalServerErrorRetries"},e5=async(e,l,t)=>{try{let s=Array.isArray(e.model)?e.model:[e.model];console.log("received deployments: ".concat(s)),console.log("received type of deployments: ".concat(typeof s)),s.forEach(async t=>{console.log("litellm_model: ".concat(t));let s={},a={};s.model=t;let r="";for(let[l,t]of Object.entries(e))if(""!==t){if("model_name"==l)r+=t;else if("custom_llm_provider"==l)continue;else if("model"==l)continue;else if("base_model"===l)a[l]=t;else if("litellm_extra_params"==l){console.log("litellm_extra_params:",t);let e={};if(t&&void 0!=t){try{e=JSON.parse(t)}catch(e){throw u.ZP.error("Failed to parse LiteLLM Extra Params: "+e,10),Error("Failed to parse litellm_extra_params: "+e)}for(let[l,t]of Object.entries(e))s[l]=t}}else s[l]=t}let n={model_name:r,litellm_params:s,model_info:a},o=await x(l,n);console.log("response for model create call: ".concat(o.data))}),t.resetFields()}catch(e){u.ZP.error("Failed to create model: "+e,10)}};var e3=e=>{var l,t,s;let{accessToken:o,token:i,userRole:c,userID:d,modelData:m={data:[]},setModelData:x}=e,[p,j]=(0,n.useState)([]),[g]=ea.Z.useForm(),[y,f]=(0,n.useState)(null),[Z,_]=(0,n.useState)(""),[w,N]=(0,n.useState)([]),A=Object.values(a).filter(e=>isNaN(Number(e))),[E,I]=(0,n.useState)("OpenAI"),[C,P]=(0,n.useState)(""),[T,O]=(0,n.useState)(!1),[F,R]=(0,n.useState)(null),[M,L]=(0,n.useState)([]),[U,K]=(0,n.useState)(null),[B,z]=(0,n.useState)([]),[Y,et]=(0,n.useState)([]),[es,en]=(0,n.useState)([]),[ec,ed]=(0,n.useState)([]),[em,eh]=(0,n.useState)([]),[ev,eS]=(0,n.useState)([]),[eN,eA]=(0,n.useState)([]),[eE,eI]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),[eC,eP]=(0,n.useState)(null),[eO,e3]=(0,n.useState)(0),e6=e=>{R(e),O(!0)},e7=async e=>{if(console.log("handleEditSubmit:",e),null==o)return;let l={},t=null;for(let[s,a]of Object.entries(e))"model_id"!==s?l[s]=a:t=a;let s={litellm_params:l,model_info:{id:t}};console.log("handleEditSubmit payload:",s);try{await D(o,s),u.ZP.success("Model updated successfully, restart server to see updates"),O(!1),R(null)}catch(e){console.log("Error occurred")}},e9=()=>{_(new Date().toLocaleString())},le=async()=>{if(!o){console.error("Access token is missing");return}console.log("new modelGroupRetryPolicy:",eC);try{await V(o,{router_settings:{model_group_retry_policy:eC}}),u.ZP.success("Retry settings saved successfully")}catch(e){console.error("Failed to save retry settings:",e),u.ZP.error("Failed to save retry settings")}};if((0,n.useEffect)(()=>{if(!o||!i||!c||!d)return;let e=async()=>{try{var e,l,t,s,a,r;let n=await b(o,d,c);console.log("Model data response:",n.data),x(n);let i=new Set;for(let e=0;e0&&(u=m[m.length-1],console.log("_initial_model_group:",u),K(u)),console.log("selectedModelGroup:",U);let h=await k(o,d,c,u,null===(e=eE.from)||void 0===e?void 0:e.toISOString(),null===(l=eE.to)||void 0===l?void 0:l.toISOString());console.log("Model metrics response:",h),et(h.data),en(h.all_api_bases);let p=await S(o,d,c,u,null===(t=eE.from)||void 0===t?void 0:t.toISOString(),null===(s=eE.to)||void 0===s?void 0:s.toISOString());console.log("Model exceptions response:",p),ed(p.data),eh(p.exception_types);let j=await v(o,d,c,u,null===(a=eE.from)||void 0===a?void 0:a.toISOString(),null===(r=eE.to)||void 0===r?void 0:r.toISOString());console.log("slowResponses:",j),eA(j);let g=(await q(o,d,c)).router_settings;console.log("routerSettingsInfo:",g);let y=g.model_group_retry_policy,f=g.num_retries;console.log("model_group_retry_policy:",y),console.log("default_retries:",f),eP(y),e3(f)}catch(e){console.error("There was an error fetching the model data",e)}};o&&i&&c&&d&&e();let l=async()=>{let e=await h();console.log("received model cost map data: ".concat(Object.keys(e))),f(e)};null==y&&l(),e9()},[o,i,c,d,y,Z]),!m||!o||!i||!c||!d)return(0,r.jsx)("div",{children:"Loading..."});let ll=[];for(let e=0;e(console.log("GET PROVIDER CALLED! - ".concat(y)),null!=y&&"object"==typeof y&&e in y)?y[e].litellm_provider:"openai";if(a){let e=a.split("/"),l=e[0];n=1===e.length?u(a):l}else n="openai";r&&(o=null==r?void 0:r.input_cost_per_token,i=null==r?void 0:r.output_cost_per_token,c=null==r?void 0:r.max_tokens),(null==s?void 0:s.litellm_params)&&(d=Object.fromEntries(Object.entries(null==s?void 0:s.litellm_params).filter(e=>{let[l]=e;return"model"!==l&&"api_base"!==l}))),m.data[e].provider=n,m.data[e].input_cost=o,m.data[e].output_cost=i,m.data[e].max_tokens=c,m.data[e].api_base=null==s?void 0:null===(t=s.litellm_params)||void 0===t?void 0:t.api_base,m.data[e].cleanedLitellmParams=d,ll.push(s.model_name),console.log(m.data[e])}if(c&&"Admin Viewer"==c){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to view all models"})]})}let lt=e=>{console.log("received provider string: ".concat(e));let l=Object.keys(a).find(l=>a[l]===e);if(l){let e=e4[l];console.log("mappingResult: ".concat(e));let t=[];"object"==typeof y&&Object.entries(y).forEach(l=>{let[s,a]=l;null!==a&&"object"==typeof a&&"litellm_provider"in a&&(a.litellm_provider===e||a.litellm_provider.includes(e))&&t.push(s)}),N(t),console.log("providerModels: ".concat(w))}},ls=async()=>{try{u.ZP.info("Running health check..."),P("");let e=await G(o);P(e)}catch(e){console.error("Error running health check:",e),P("Error running health check")}},la=async(e,l,t)=>{if(console.log("Updating model metrics for group:",e),o&&d&&c&&l&&t){console.log("inside updateModelMetrics - startTime:",l,"endTime:",t),K(e);try{let s=await k(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model metrics response:",s),et(s.data),en(s.all_api_bases);let a=await S(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model exceptions response:",a),ed(a.data),eh(a.exception_types);let r=await v(o,d,c,e,l.toISOString(),t.toISOString());console.log("slowResponses:",r),eA(r)}catch(e){console.error("Failed to fetch model metrics",e)}}};return console.log("selectedProvider: ".concat(E)),console.log("providerModels.length: ".concat(w.length)),(0,r.jsx)("div",{style:{width:"100%",height:"100%"},children:(0,r.jsxs)(eM.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(eL.Z,{className:"flex justify-between mt-2 w-full items-center",children:[(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)(eR.Z,{children:"All Models"}),(0,r.jsx)(eR.Z,{children:"Add Model"}),(0,r.jsx)(eR.Z,{children:(0,r.jsx)("pre",{children:"/health Models"})}),(0,r.jsx)(eR.Z,{children:"Model Analytics"}),(0,r.jsx)(eR.Z,{children:"Model Retry Settings"})]}),(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[Z&&(0,r.jsxs)(ee.Z,{children:["Last Refreshed: ",Z]}),(0,r.jsx)(ej.Z,{icon:eJ.Z,variant:"shadow",size:"xs",className:"self-center",onClick:e9})]})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(W.Z,{children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(ee.Z,{children:"Filter by Public Model Name"}),(0,r.jsxs)(eb.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:"all",onValueChange:e=>K("all"===e?"all":e),children:[(0,r.jsx)(ek.Z,{value:"all",children:"All Models"}),M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>K(e),children:e},l))]})]}),(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{className:"mt-5",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Public Model Name "}),(0,r.jsx)(e_.Z,{children:"Provider"}),"Admin"===c&&(0,r.jsx)(e_.Z,{children:"API Base"}),(0,r.jsx)(e_.Z,{children:"Extra litellm Params"}),(0,r.jsx)(e_.Z,{children:"Input Price per token ($)"}),(0,r.jsx)(e_.Z,{children:"Output Price per token ($)"}),(0,r.jsx)(e_.Z,{children:"Max Tokens"}),(0,r.jsx)(e_.Z,{children:"Status"})]})}),(0,r.jsx)(ey.Z,{children:m.data.filter(e=>"all"===U||e.model_name===U||null==U||""===U).map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:e.model_name})}),(0,r.jsx)(ef.Z,{children:e.provider}),"Admin"===c&&(0,r.jsx)(ef.Z,{children:e.api_base}),(0,r.jsx)(ef.Z,{children:(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{children:(0,r.jsx)(ee.Z,{children:"Litellm params"})}),(0,r.jsx)(X.Z,{children:(0,r.jsx)("pre",{children:JSON.stringify(e.cleanedLitellmParams,null,2)})})]})}),(0,r.jsx)(ef.Z,{children:e.input_cost||e.litellm_params.input_cost_per_token||null}),(0,r.jsx)(ef.Z,{children:e.output_cost||e.litellm_params.output_cost_per_token||null}),(0,r.jsx)(ef.Z,{children:e.max_tokens}),(0,r.jsx)(ef.Z,{children:e.model_info.db_model?(0,r.jsx)(ex.Z,{icon:eH.Z,className:"text-white",children:"DB Model"}):(0,r.jsx)(ex.Z,{icon:e$.Z,className:"text-black",children:"Config Model"})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>e6(e)}),(0,r.jsx)(eX,{modelID:e.model_info.id,accessToken:o})]})]},l))})]})})]}),(0,r.jsx)(e=>{let{visible:l,onCancel:t,model:s,onSubmit:a}=e,[n]=ea.Z.useForm(),o={},i="",c="";if(s){o=s.litellm_params,i=s.model_name;let e=s.model_info;e&&(c=e.id,console.log("model_id: ".concat(c)),o.model_id=c)}return(0,r.jsx)(er.Z,{title:"Edit Model "+i,visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{a(e),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:n,onFinish:e7,initialValues:o,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{className:"mt-8",label:"api_base",name:"api_base",children:(0,r.jsx)(H.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"tpm",name:"tpm",tooltip:"int (optional) - Tokens limit for this deployment: in tokens per minute (tpm). Find this information on your model/providers website",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"rpm",name:"rpm",tooltip:"int (optional) - Rate limit for this deployment: in requests per minute (rpm). Find this information on your model/providers website",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"max_retries",name:"max_retries",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"timeout",name:"timeout",tooltip:"int (optional) - Timeout in seconds for LLM requests (Defaults to 600 seconds)",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"stream_timeout",name:"stream_timeout",tooltip:"int (optional) - Timeout for stream requests (seconds)",children:(0,r.jsx)(eo.Z,{min:0,step:1})}),(0,r.jsx)(ea.Z.Item,{label:"input_cost_per_token",name:"input_cost_per_token",tooltip:"float (optional) - Input cost per token",children:(0,r.jsx)(eo.Z,{min:0,step:1e-4})}),(0,r.jsx)(ea.Z.Item,{label:"output_cost_per_token",name:"output_cost_per_token",tooltip:"float (optional) - Output cost per token",children:(0,r.jsx)(eo.Z,{min:0,step:1e-4})}),(0,r.jsx)(ea.Z.Item,{label:"model_id",name:"model_id",hidden:!0})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})})},{visible:T,onCancel:()=>{O(!1),R(null)},model:F,onSubmit:e7})]}),(0,r.jsxs)(eU.Z,{className:"h-full",children:[(0,r.jsx)(e1,{level:2,children:"Add new model"}),(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(ea.Z,{form:g,onFinish:()=>{g.validateFields().then(e=>{e5(e,o,g)}).catch(e=>{console.error("Validation failed:",e)})},labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"E.g. OpenAI, Azure OpenAI, Anthropic, Bedrock, etc.",labelCol:{span:10},labelAlign:"left",children:(0,r.jsx)(eb.Z,{value:E.toString(),children:A.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>{lt(e),I(e)},children:e},l))})}),(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Public Model Name",name:"model_name",tooltip:"Model name your users will pass in. Also used for load-balancing, LiteLLM will load balance between all models with this public name.",className:"mb-0",children:(0,r.jsx)(H.Z,{placeholder:"Vertex AI (Anthropic, Gemini, etc.)"===(s=E.toString())?"gemini-pro":"Anthropic"==s?"claude-3-opus":"Amazon Bedrock"==s?"claude-3-opus":"Gemini (Google AI Studio)"==s?"gemini-pro":"gpt-3.5-turbo"})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsx)(ee.Z,{className:"mb-3 mt-1",children:"Model name your users will pass in."})})]}),(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"LiteLLM Model Name(s)",name:"model",tooltip:"Actual model name used for making litellm.completion() call.",className:"mb-0",children:"Azure"===E?(0,r.jsx)(H.Z,{placeholder:"Enter model name"}):w.length>0?(0,r.jsx)(eK.Z,{value:w,children:w.map((e,l)=>(0,r.jsx)(eB.Z,{value:e,children:e},l))}):(0,r.jsx)(H.Z,{placeholder:"gpt-3.5-turbo-0125"})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsxs)(ee.Z,{className:"mb-3 mt-1",children:["Actual model name used for making ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/providers",target:"_blank",children:"litellm.completion() call"}),". We'll ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/proxy/reliability#step-1---set-deployments-on-config",target:"_blank",children:"loadbalance"})," models with the same 'public name'"]})})]}),"Amazon Bedrock"!=E&&"Vertex AI (Anthropic, Gemini, etc.)"!=E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Key",name:"api_key",children:(0,r.jsx)(H.Z,{placeholder:"sk-",type:"password"})}),"OpenAI"==E&&(0,r.jsx)(ea.Z.Item,{label:"Organization ID",name:"organization_id",children:(0,r.jsx)(H.Z,{placeholder:"[OPTIONAL] my-unique-org"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Project",name:"vertex_project",children:(0,r.jsx)(H.Z,{placeholder:"adroit-cadet-1234.."})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Location",name:"vertex_location",children:(0,r.jsx)(H.Z,{placeholder:"us-east-1"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Credentials",name:"vertex_credentials",className:"mb-0",children:(0,r.jsx)(e0.Z,{name:"file",accept:".json",beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;g.setFieldsValue({vertex_credentials:l})}},l.readAsText(e)}return!1},onChange(e){"uploading"!==e.file.status&&console.log(e.file,e.fileList),"done"===e.file.status?u.ZP.success("".concat(e.file.name," file uploaded successfully")):"error"===e.file.status&&u.ZP.error("".concat(e.file.name," file upload failed."))},children:(0,r.jsx)(ei.ZP,{icon:(0,r.jsx)(eQ.Z,{}),children:"Click to Upload"})})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsx)(ee.Z,{className:"mb-3 mt-1",children:"Give litellm a gcp service account(.json file), so it can make the relevant calls"})})]}),("Azure"==E||"OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)"==E)&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Base",name:"api_base",children:(0,r.jsx)(H.Z,{placeholder:"https://..."})}),"Azure"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Version",name:"api_version",children:(0,r.jsx)(H.Z,{placeholder:"2023-07-01-preview"})}),"Azure"==E&&(0,r.jsxs)(ea.Z.Item,{label:"Base Model",name:"base_model",children:[(0,r.jsx)(H.Z,{placeholder:"azure/gpt-3.5-turbo"}),(0,r.jsxs)(ee.Z,{children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from ",(0,r.jsx)(e2,{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",children:"here"})]})]}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Access Key ID",name:"aws_access_key_id",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Secret Access Key",name:"aws_secret_access_key",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Region Name",name:"aws_region_name",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,r.jsx)(H.Z,{placeholder:"us-east-1"})}),(0,r.jsx)(ea.Z.Item,{label:"LiteLLM Params",name:"litellm_extra_params",tooltip:"Optional litellm params used for making a litellm.completion() call.",className:"mb-0",children:(0,r.jsx)(eW.Z,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}),(0,r.jsxs)(eV.Z,{children:[(0,r.jsx)(eG.Z,{span:10}),(0,r.jsx)(eG.Z,{span:10,children:(0,r.jsxs)(ee.Z,{className:"mb-3 mt-1",children:["Pass JSON of litellm supported params ",(0,r.jsx)(e2,{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",children:"litellm.completion() call"})]})})]})]}),(0,r.jsx)("div",{style:{textAlign:"center",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add Model"})}),(0,r.jsx)(eY.Z,{title:"Get help on our github",children:(0,r.jsx)(eT.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})})]})})]}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(ee.Z,{children:"`/health` will run a very small request through your models configured on litellm"}),(0,r.jsx)(J.Z,{onClick:ls,children:"Run `/health`"}),C&&(0,r.jsx)("pre",{children:JSON.stringify(C,null,2)})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(W.Z,{numItems:2,className:"mt-2",children:[(0,r.jsxs)(eG.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Time Range"}),(0,r.jsx)(eF.Z,{enableSelect:!0,value:eE,onValueChange:e=>{eI(e),la(U,e.from,e.to)}})]}),(0,r.jsxs)(eG.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Model Group"}),(0,r.jsx)(eb.Z,{className:"mb-4 mt-2",defaultValue:U||M[0],value:U||M[0],children:M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>la(e,eE.from,eE.to),children:e},l))})]})]}),(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsx)(eG.Z,{children:(0,r.jsxs)(ep.Z,{className:"mr-2 max-h-[400px] min-h-[400px]",children:[(0,r.jsx)(el.Z,{children:"Avg Latency per Token"}),(0,r.jsx)("p",{className:"text-gray-500 italic",children:" (seconds/token)"}),(0,r.jsx)(ee.Z,{className:"text-gray-500 italic mt-1 mb-1",children:"average Latency for successfull requests divided by the total tokens"}),Y&&es&&(0,r.jsx)(ez.Z,{title:"Model Latency",className:"h-72",data:Y,showLegend:!1,index:"date",categories:es,connectNulls:!0,customTooltip:e=>{var l,t;let{payload:s,active:a}=e;if(!a||!s)return null;let n=null===(t=s[0])||void 0===t?void 0:null===(l=t.payload)||void 0===l?void 0:l.date,o=s.sort((e,l)=>l.value-e.value);if(o.length>5){let e=o.length-5;(o=o.slice(0,5)).push({dataKey:"".concat(e," other deployments"),value:s.slice(5).reduce((e,l)=>e+l.value,0),color:"gray"})}return(0,r.jsxs)("div",{className:"w-150 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[n&&(0,r.jsxs)("p",{className:"text-tremor-content-emphasis mb-2",children:["Date: ",n]}),o.map((e,l)=>{let t=parseFloat(e.value.toFixed(5)),s=0===t&&e.value>0?"<0.00001":t.toFixed(5);return(0,r.jsxs)("div",{className:"flex justify-between",children:[(0,r.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,r.jsx)("div",{className:"w-2 h-2 mt-1 rounded-full bg-".concat(e.color,"-500")}),(0,r.jsx)("p",{className:"text-tremor-content",children:e.dataKey})]}),(0,r.jsx)("p",{className:"font-medium text-tremor-content-emphasis text-righ ml-2",children:s})]},l)})]})}})]})}),(0,r.jsx)(eG.Z,{children:(0,r.jsx)(ep.Z,{className:"ml-2 max-h-[400px] min-h-[400px] overflow-y-auto",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Deployment"}),(0,r.jsx)(e_.Z,{children:"Success Responses"}),(0,r.jsxs)(e_.Z,{children:["Slow Responses ",(0,r.jsx)("p",{children:"Success Responses taking 600+s"})]})]})}),(0,r.jsx)(ey.Z,{children:eN.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.api_base}),(0,r.jsx)(ef.Z,{children:e.total_count}),(0,r.jsx)(ef.Z,{children:e.slow_count})]},l))})]})})})]}),(0,r.jsxs)(ep.Z,{className:"mt-4",children:[(0,r.jsx)(el.Z,{children:"Exceptions per Model"}),(0,r.jsx)(eq.Z,{className:"h-72",data:ec,index:"model",categories:em,stack:!0,colors:["indigo-300","rose-200","#ffcc33"],yAxisWidth:30})]})]}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)(ee.Z,{children:"Filter by Public Model Name"}),(0,r.jsx)(eb.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:U||M[0],value:U||M[0],onValueChange:e=>K(e),children:M.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>K(e),children:e},l))})]}),(0,r.jsxs)(el.Z,{children:["Retry Policy for ",U]}),(0,r.jsx)(ee.Z,{className:"mb-6",children:"How many retries should be attempted based on the Exception"}),e8&&(0,r.jsx)("table",{children:(0,r.jsx)("tbody",{children:Object.entries(e8).map((e,l)=>{var t;let[s,a]=e,n=null==eC?void 0:null===(t=eC[U])||void 0===t?void 0:t[a];return null==n&&(n=eO),(0,r.jsxs)("tr",{className:"flex justify-between items-center mt-2",children:[(0,r.jsx)("td",{children:(0,r.jsx)(ee.Z,{children:s})}),(0,r.jsx)("td",{children:(0,r.jsx)(eo.Z,{className:"ml-5",value:n,min:0,step:1,onChange:e=>{eP(l=>{var t;let s=null!==(t=null==l?void 0:l[U])&&void 0!==t?t:{};return{...null!=l?l:{},[U]:{...s,[a]:e}}})}})})]},l)})})}),(0,r.jsx)(J.Z,{className:"mt-6 mr-8",onClick:le,children:"Save"})]})]})]})})};let{Option:e6}=es.default;var e7=e=>{let{userID:l,accessToken:t,teams:s}=e,[a]=ea.Z.useForm(),[o,i]=(0,n.useState)(!1),[c,d]=(0,n.useState)(null),[m,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{let e=await N(t,l,"any"),s=[];for(let l=0;l{i(!1),a.resetFields()},p=()=>{i(!1),d(null),a.resetFields()},j=async e=>{try{u.ZP.info("Making API Call"),i(!0),console.log("formValues in create user:",e);let s=await g(t,null,e);console.log("user create Response:",s),d(s.key),u.ZP.success("API user Created"),a.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the user:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>i(!0),children:"+ Invite User"}),(0,r.jsxs)(er.Z,{title:"Invite User",visible:o,width:800,footer:null,onOk:x,onCancel:p,children:[(0,r.jsx)(ee.Z,{className:"mb-1",children:"Invite a user to login to the Admin UI and create Keys"}),(0,r.jsx)(ee.Z,{className:"mb-6",children:(0,r.jsx)("b",{children:"Note: SSO Setup Required for this"})}),(0,r.jsxs)(ea.Z,{form:a,onFinish:j,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsx)(ea.Z.Item,{label:"User Email",name:"user_email",children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"team_id",children:(0,r.jsx)(es.default,{placeholder:"Select Team ID",style:{width:"100%"},children:s?s.map(e=>(0,r.jsx)(e6,{value:e.team_id,children:e.team_alias},e.team_id)):(0,r.jsx)(e6,{value:null,children:"Default Team"},"default")})}),(0,r.jsx)(ea.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(en.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create User"})})]})]}),c&&(0,r.jsxs)(er.Z,{title:"User Created Successfully",visible:o,onOk:x,onCancel:p,footer:null,children:[(0,r.jsx)("p",{children:"User has been created to access your proxy. Please Ask them to Log In."}),(0,r.jsx)("br",{}),(0,r.jsx)("p",{children:(0,r.jsx)("b",{children:"Note: This Feature is only supported through SSO on the Admin UI"})})]})]})},e9=e=>{let{accessToken:l,token:t,keys:s,userRole:a,userID:o,teams:i,setKeys:c}=e,[d,m]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(0),[j,g]=n.useState(null),[y,f]=(0,n.useState)(null);return((0,n.useEffect)(()=>{if(!l||!t||!a||!o)return;let e=async()=>{try{let e=await Z(l,null,a,!0,x,25);console.log("user data response:",e),m(e)}catch(e){console.error("There was an error fetching the model data",e)}};l&&t&&a&&o&&e()},[l,t,a,o,x]),d&&l&&t&&a&&o)?(0,r.jsx)("div",{style:{width:"100%"},children:(0,r.jsxs)(W.Z,{className:"gap-2 p-2 h-[80vh] w-full mt-8",children:[(0,r.jsx)(e7,{userID:o,accessToken:l,teams:i}),(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[80vh] mb-4",children:[(0,r.jsx)("div",{className:"mb-4 mt-1",children:(0,r.jsx)(ee.Z,{children:"These are Users on LiteLLM that created API Keys. Automatically tracked by LiteLLM"})}),(0,r.jsx)(eM.Z,{children:(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(eg.Z,{className:"mt-5",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"User ID"}),(0,r.jsx)(e_.Z,{children:"User Email"}),(0,r.jsx)(e_.Z,{children:"User Models"}),(0,r.jsx)(e_.Z,{children:"User Spend ($ USD)"}),(0,r.jsx)(e_.Z,{children:"User Max Budget ($ USD)"}),(0,r.jsx)(e_.Z,{children:"User API Key Aliases"})]})}),(0,r.jsx)(ey.Z,{children:d.map(e=>{var l;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_id}),(0,r.jsx)(ef.Z,{children:e.user_email}),(0,r.jsx)(ef.Z,{children:e.models&&e.models.length>0?e.models:"All Models"}),(0,r.jsx)(ef.Z,{children:e.spend?null===(l=e.spend)||void 0===l?void 0:l.toFixed(2):0}),(0,r.jsx)(ef.Z,{children:e.max_budget?e.max_budget:"Unlimited"}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(W.Z,{numItems:2,children:e&&e.key_aliases&&e.key_aliases.filter(e=>null!==e).length>0?(0,r.jsx)(ex.Z,{size:"xs",color:"indigo",children:e.key_aliases.filter(e=>null!==e).join(", ")}):(0,r.jsx)(ex.Z,{size:"xs",color:"gray",children:"No Keys"})})})]},e.user_id)})})]})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)("div",{className:"flex items-center",children:[(0,r.jsx)("div",{className:"flex-1"}),(0,r.jsx)("div",{className:"flex-1 flex justify-between items-center"})]})})]})})]}),function(){if(!d)return null;let e=Math.ceil(d.length/25);return(0,r.jsxs)("div",{className:"flex justify-between items-center",children:[(0,r.jsxs)("div",{children:["Showing Page ",x+1," of ",e]}),(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-l focus:outline-none",disabled:0===x,onClick:()=>p(x-1),children:"← Prev"}),(0,r.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r focus:outline-none",onClick:()=>{p(x+1)},children:"Next →"})]})]})}()]})}):(0,r.jsx)("div",{children:"Loading..."})},le=e=>{let{teams:l,searchParams:t,accessToken:s,setTeams:a,userID:o,userRole:i}=e,[c]=ea.Z.useForm(),[d]=ea.Z.useForm(),{Title:m,Paragraph:h}=eT.default,[x,p]=(0,n.useState)(""),[j,g]=(0,n.useState)(!1),[y,Z]=(0,n.useState)(l?l[0]:null),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)([]),[E,I]=(0,n.useState)(!1),[C,P]=(0,n.useState)(null),[T,O]=(0,n.useState)({}),F=e=>{Z(e),g(!0)},R=async e=>{let t=e.team_id;if(console.log("handleEditSubmit:",e),null==s)return;let r=await U(s,e);l&&a(l.map(e=>e.team_id===t?r.data:e)),u.ZP.success("Team updated successfully"),g(!1),Z(null)},L=async e=>{P(e),I(!0)},D=async()=>{if(null!=C&&null!=l&&null!=s){try{await f(s,C);let e=l.filter(e=>e.team_id!==C);a(e)}catch(e){console.error("Error deleting the team:",e)}I(!1),P(null)}};(0,n.useEffect)(()=>{let e=async()=>{try{if(null===o||null===i||null===s||null===l)return;console.log("fetching team info:");let e={};for(let t=0;t<(null==l?void 0:l.length);t++){let a=l[t].team_id,r=await _(s,a);console.log("teamInfo response:",r),null!==r&&(e={...e,[a]:r})}O(e)}catch(e){console.error("Error fetching team info:",e)}};(async()=>{try{if(null===o||null===i)return;if(null!==s){let e=(await N(s,o,i)).data.map(e=>e.id);console.log("available_model_names:",e),A(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[s,o,i,l]);let B=async e=>{try{if(null!=s){var t;let r=null==e?void 0:e.team_alias;if((null!==(t=null==l?void 0:l.map(e=>e.team_alias))&&void 0!==t?t:[]).includes(r))throw Error("Team alias ".concat(r," already exists, please pick another alias"));u.ZP.info("Creating Team");let n=await M(s,e);null!==l?a([...l,n]):a([n]),console.log("response for team create call: ".concat(n)),u.ZP.success("Team created"),b(!1)}}catch(e){console.error("Error creating the team:",e),u.ZP.error("Error creating the team: "+e,20)}},z=async e=>{try{if(null!=s&&null!=l){u.ZP.info("Adding Member");let t={role:"user",user_email:e.user_email,user_id:e.user_id},r=await K(s,y.team_id,t);console.log("response for team create call: ".concat(r.data));let n=l.findIndex(e=>(console.log("team.team_id=".concat(e.team_id,"; response.data.team_id=").concat(r.data.team_id)),e.team_id===r.data.team_id));if(console.log("foundIndex: ".concat(n)),-1!==n){let e=[...l];e[n]=r.data,a(e),Z(r.data)}v(!1)}}catch(e){console.error("Error creating the team:",e)}};return console.log("received teams ".concat(JSON.stringify(l))),(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(m,{level:4,children:"All Teams"}),(0,r.jsxs)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Team Name"}),(0,r.jsx)(e_.Z,{children:"Spend (USD)"}),(0,r.jsx)(e_.Z,{children:"Budget (USD)"}),(0,r.jsx)(e_.Z,{children:"Models"}),(0,r.jsx)(e_.Z,{children:"TPM / RPM Limits"}),(0,r.jsx)(e_.Z,{children:"Info"})]})}),(0,r.jsx)(ey.Z,{children:l&&l.length>0?l.map(e=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.team_alias}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.spend}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.max_budget?e.max_budget:"No limit"}),(0,r.jsx)(ef.Z,{style:{maxWidth:"8-x",whiteSpace:"pre-wrap",overflow:"hidden"},children:Array.isArray(e.models)?(0,r.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"red",children:(0,r.jsx)(ee.Z,{children:"All Proxy Models"})},l):(0,r.jsx)(ex.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,r.jsx)(ee.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,r.jsx)(ef.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:(0,r.jsxs)(ee.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,r.jsx)("br",{}),"RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsxs)(ee.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].keys&&T[e.team_id].keys.length," ","Keys"]}),(0,r.jsxs)(ee.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].team_info&&T[e.team_id].team_info.members_with_roles&&T[e.team_id].team_info.members_with_roles.length," ","Members"]})]}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>F(e)}),(0,r.jsx)(ej.Z,{onClick:()=>L(e.team_id),icon:eh.Z,size:"sm"})]})]},e.team_id)):null})]}),E&&(0,r.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,r.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,r.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,r.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,r.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,r.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,r.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,r.jsx)("div",{className:"sm:flex sm:items-start",children:(0,r.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,r.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Team"}),(0,r.jsx)("div",{className:"mt-2",children:(0,r.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this team ?"})})]})})}),(0,r.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,r.jsx)(J.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,r.jsx)(J.Z,{onClick:()=>{I(!1),P(null)},children:"Cancel"})]})]})]})})]})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>b(!0),children:"+ Create New Team"}),(0,r.jsx)(er.Z,{title:"Create Team",visible:w,width:800,footer:null,onOk:()=>{b(!1),c.resetFields()},onCancel:()=>{b(!1),c.resetFields()},children:(0,r.jsxs)(ea.Z,{form:c,onFinish:B,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,r.jsx)(H.Z,{placeholder:""})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(es.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S.map(e=>(0,r.jsx)(es.default.Option,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Create Team"})})]})})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(m,{level:4,children:"Team Members"}),(0,r.jsx)(h,{children:"If you belong to multiple teams, this setting controls which teams members you see."}),l&&l.length>0?(0,r.jsx)(eb.Z,{defaultValue:"0",children:l.map((e,l)=>(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>{Z(e)},children:e.team_alias},l))}):(0,r.jsxs)(h,{children:["No team created. ",(0,r.jsx)("b",{children:"Defaulting to personal account."})]})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Member Name"}),(0,r.jsx)(e_.Z,{children:"Role"})]})}),(0,r.jsx)(ey.Z,{children:y?y.members_with_roles.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,r.jsx)(ef.Z,{children:e.role})]},l)):null})]})}),y&&(0,r.jsx)(e=>{let{visible:l,onCancel:t,team:s,onSubmit:a}=e,[n]=ea.Z.useForm();return(0,r.jsx)(er.Z,{title:"Edit Team",visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{a({...e,team_id:s.team_id}),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,r.jsxs)(ea.Z,{form:n,onFinish:R,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,r.jsx)(H.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"Models",name:"models",children:(0,r.jsxs)(es.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,r.jsx)(es.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S&&S.map(e=>(0,r.jsx)(es.default.Option,{value:e,children:e},e))]})}),(0,r.jsx)(ea.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(eo.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(ea.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,r.jsx)(eo.Z,{step:1,width:400})}),(0,r.jsx)(ea.Z.Item,{label:"Requests per minute Limit (RPM)",name:"team_id",hidden:!0})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Edit Team"})})]})})},{visible:j,onCancel:()=>{g(!1),Z(null)},team:y,onSubmit:R})]}),(0,r.jsxs)(Y.Z,{numColSpan:1,children:[(0,r.jsx)(J.Z,{className:"mx-auto mb-5",onClick:()=>v(!0),children:"+ Add member"}),(0,r.jsx)(er.Z,{title:"Add member",visible:k,width:800,footer:null,onOk:()=>{v(!1),d.resetFields()},onCancel:()=>{v(!1),d.resetFields()},children:(0,r.jsxs)(ea.Z,{form:c,onFinish:z,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,r.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,r.jsx)(ea.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add member"})})]})})]})]})})},ll=t(18190),lt=e=>{let l,{searchParams:t,accessToken:s,showSSOBanner:a}=e,[o]=ea.Z.useForm(),[i]=ea.Z.useForm(),{Title:c,Paragraph:d}=eT.default,[m,h]=(0,n.useState)(""),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)(!1),[y,f]=(0,n.useState)(!1),[Z,_]=(0,n.useState)(!1),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1);try{l=window.location.origin}catch(e){l=""}l+="/fallback/login";let S=()=>{v(!1)},N=["proxy_admin","proxy_admin_viewer"];(0,n.useEffect)(()=>{(async()=>{if(null!=s){let e=[],l=await R(s,"proxy_admin_viewer");l.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy viewers: ".concat(l));let t=await R(s,"proxy_admin");t.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy admins: ".concat(t)),console.log("combinedList: ".concat(e)),p(e)}})()},[s]);let A=()=>{_(!1),i.resetFields()},E=()=>{_(!1),i.resetFields()},I=e=>(0,r.jsxs)(ea.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,r.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,r.jsx)(ea.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,r.jsx)(en.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add member"})})]}),C=(e,l,t)=>(0,r.jsxs)(ea.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{rules:[{required:!0,message:"Required"}],label:"User Role",name:"user_role",labelCol:{span:10},labelAlign:"left",children:(0,r.jsx)(eb.Z,{value:l,children:N.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,children:e},l))})}),(0,r.jsx)(ea.Z.Item,{label:"Team ID",name:"user_id",hidden:!0,initialValue:t,valuePropName:"user_id",className:"mt-8",children:(0,r.jsx)(en.Z,{value:t,disabled:!0})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Update role"})})]}),P=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,null);console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),u.ZP.success("Refresh tab to see updated user role"),_(!1)}}catch(e){console.error("Error creating the key:",e)}},T=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,"proxy_admin_viewer");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),g(!1)}}catch(e){console.error("Error creating the key:",e)}},O=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call"),e.user_email,e.user_id;let l=await B(s,e,"proxy_admin");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),f(!1)}}catch(e){console.error("Error creating the key:",e)}},F=async e=>{null!=s&&V(s,{environment_variables:{PROXY_BASE_URL:e.proxy_base_url,GOOGLE_CLIENT_ID:e.google_client_id,GOOGLE_CLIENT_SECRET:e.google_client_secret}})};return console.log("admins: ".concat(null==x?void 0:x.length)),(0,r.jsxs)("div",{className:"w-full m-2 mt-2 p-8",children:[(0,r.jsx)(c,{level:4,children:"Admin Access "}),(0,r.jsxs)(d,{children:[a&&(0,r.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/ui#restrict-ui-access",children:"Requires SSO Setup"}),(0,r.jsx)("br",{}),(0,r.jsx)("b",{children:"Proxy Admin: "})," Can create keys, teams, users, add models, etc. ",(0,r.jsx)("br",{}),(0,r.jsx)("b",{children:"Proxy Admin Viewer: "}),"Can just view spend. They cannot create keys, teams or grant users access to new models."," "]}),(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-2 w-full",children:[(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsx)(ep.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Member Name"}),(0,r.jsx)(e_.Z,{children:"Role"})]})}),(0,r.jsx)(ey.Z,{children:x?x.map((e,l)=>(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,r.jsx)(ef.Z,{children:e.user_role}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ej.Z,{icon:eu.Z,size:"sm",onClick:()=>_(!0)}),(0,r.jsx)(er.Z,{title:"Update role",visible:Z,width:800,footer:null,onOk:A,onCancel:E,children:C(P,e.user_role,e.user_id)})]})]},l)):null})]})})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)("div",{className:"flex justify-start",children:[(0,r.jsx)(J.Z,{className:"mr-4 mb-5",onClick:()=>f(!0),children:"+ Add admin"}),(0,r.jsx)(er.Z,{title:"Add admin",visible:y,width:800,footer:null,onOk:()=>{f(!1),i.resetFields()},onCancel:()=>{f(!1),i.resetFields()},children:I(O)}),(0,r.jsx)(J.Z,{className:"mb-5",onClick:()=>g(!0),children:"+ Add viewer"}),(0,r.jsx)(er.Z,{title:"Add viewer",visible:j,width:800,footer:null,onOk:()=>{g(!1),i.resetFields()},onCancel:()=>{g(!1),i.resetFields()},children:I(T)})]})})]}),(0,r.jsxs)(W.Z,{children:[(0,r.jsx)(c,{level:4,children:"Add SSO"}),(0,r.jsxs)("div",{className:"flex justify-start mb-4",children:[(0,r.jsx)(J.Z,{onClick:()=>b(!0),children:"Add SSO"}),(0,r.jsx)(er.Z,{title:"Add SSO",visible:w,width:800,footer:null,onOk:()=>{b(!1),o.resetFields()},onCancel:()=>{b(!1),o.resetFields()},children:(0,r.jsxs)(ea.Z,{form:o,onFinish:e=>{O(e),F(e),b(!1),v(!0)},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"PROXY BASE URL",name:"proxy_base_url",rules:[{required:!0,message:"Please enter the proxy base url"}],children:(0,r.jsx)(en.Z,{})}),(0,r.jsx)(ea.Z.Item,{label:"GOOGLE CLIENT ID",name:"google_client_id",rules:[{required:!0,message:"Please enter the google client id"}],children:(0,r.jsx)(en.Z.Password,{})}),(0,r.jsx)(ea.Z.Item,{label:"GOOGLE CLIENT SECRET",name:"google_client_secret",rules:[{required:!0,message:"Please enter the google client secret"}],children:(0,r.jsx)(en.Z.Password,{})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})}),(0,r.jsxs)(er.Z,{title:"SSO Setup Instructions",visible:k,width:800,footer:null,onOk:S,onCancel:()=>{v(!1)},children:[(0,r.jsx)("p",{children:"Follow these steps to complete the SSO setup:"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"1. DO NOT Exit this TAB"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"2. Open a new tab, visit your proxy base url"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"3. Confirm your SSO is configured correctly and you can login on the new Tab"}),(0,r.jsx)(ee.Z,{className:"mt-2",children:"4. If Step 3 is successful, you can close this tab"}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{onClick:S,children:"Done"})})]})]}),(0,r.jsxs)(ll.Z,{title:"Login without SSO",color:"teal",children:["If you need to login without sso, you can access ",(0,r.jsxs)("a",{href:l,target:"_blank",children:[(0,r.jsx)("b",{children:l})," "]})]})]})]})},ls=t(42556);let la=[{name:"slack",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"langfuse",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"openmeter",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}}];var lr=e=>{let{accessToken:l,userRole:t,userID:s}=e,[a,o]=(0,n.useState)(la),[i,c]=(0,n.useState)([]),[d,m]=(0,n.useState)(!1),[h]=ea.Z.useForm(),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)([]),[y,f]=(0,n.useState)(""),[Z,_]=(0,n.useState)({}),[w,b]=(0,n.useState)([]),k=e=>{w.includes(e)?b(w.filter(l=>l!==e)):b([...w,e])},v={llm_exceptions:"LLM Exceptions",llm_too_slow:"LLM Responses Too Slow",llm_requests_hanging:"LLM Requests Hanging",budget_alerts:"Budget Alerts (API Keys, Users)",db_exceptions:"Database Exceptions (Read/Write)",daily_reports:"Weekly/Monthly Spend Reports"};(0,n.useEffect)(()=>{l&&t&&s&&q(l,s,t).then(e=>{console.log("callbacks",e);let l=la;o(l=l.map(l=>{let t=e.callbacks.find(e=>e.name===l.name);return t?{...l,variables:{...l.variables,...t.variables}}:l}));let t=e.alerts;if(console.log("alerts_data",t),t&&t.length>0){let e=t[0];console.log("_alert_info",e);let l=e.variables.SLACK_WEBHOOK_URL;console.log("catch_all_webhook",l),b(e.active_alerts),f(l),_(e.alerts_to_webhook)}c(t)})},[l,t,s]);let S=e=>w&&w.includes(e),N=e=>{if(!l)return;let t=Object.fromEntries(Object.entries(e.variables).map(e=>{var l;let[t,s]=e;return[t,(null===(l=document.querySelector('input[name="'.concat(t,'"]')))||void 0===l?void 0:l.value)||s]}));console.log("updatedVariables",t),console.log("updateAlertTypes",j);let s={environment_variables:t,litellm_settings:{success_callback:[e.name]}};try{V(l,s)}catch(e){u.ZP.error("Failed to update callback: "+e,20)}u.ZP.success("Callback updated successfully")},A=()=>{l&&h.validateFields().then(e=>{if(console.log("Form values:",e),"langfuse"===e.callback){V(l,{environment_variables:{LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey,OPENMETER_API_KEY:null}};o(a?[...a,t]:[t])}else if("slack"===e.callback){console.log("values.slackWebhookUrl: ".concat(e.slackWebhookUrl)),V(l,{general_settings:{alerting:["slack"],alerting_threshold:300},environment_variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl}}),console.log("values.callback: ".concat(e.callback));let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null}};o(a?[...a,t]:[t])}else if("openmeter"==e.callback){console.log("values.openMeterApiKey: ".concat(e.openMeterApiKey)),V(l,{environment_variables:{OPENMETER_API_KEY:e.openMeterApiKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:e.openMeterAPIKey}};o(a?[...a,t]:[t])}m(!1),h.resetFields(),p(null)})};return l?(console.log("callbacks: ".concat(a)),(0,r.jsxs)("div",{className:"w-full mx-4",children:[(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,r.jsx)(ll.Z,{title:"[UI] Presidio PII + Guardrails Coming Soon. https://docs.litellm.ai/docs/proxy/pii_masking",color:"sky"}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{variant:"line",defaultValue:"1",children:[(0,r.jsx)(eR.Z,{value:"1",children:"Logging Callbacks"}),(0,r.jsx)(eR.Z,{value:"2",children:"Alerting"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Callback"}),(0,r.jsx)(e_.Z,{children:"Callback Env Vars"})]})}),(0,r.jsx)(ey.Z,{children:a.filter(e=>"slack"!==e.name).map((e,t)=>{var s;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ex.Z,{color:"emerald",children:e.name})}),(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)("ul",{children:Object.entries(null!==(s=e.variables)&&void 0!==s?s:{}).filter(l=>{let[t,s]=l;return t.toLowerCase().includes(e.name)}).map(e=>{let[l,t]=e;return(0,r.jsxs)("li",{children:[(0,r.jsx)(ee.Z,{className:"mt-2",children:l}),"LANGFUSE_HOST"===l?(0,r.jsx)("p",{children:"default value=https://cloud.langfuse.com"}):(0,r.jsx)("div",{}),(0,r.jsx)(H.Z,{name:l,defaultValue:t,type:"password"})]},l)})}),(0,r.jsx)(J.Z,{className:"mt-2",onClick:()=>N(e),children:"Save Changes"}),(0,r.jsx)(J.Z,{onClick:()=>z(l,e.name),className:"mx-2",children:"Test Callback"})]})]},t)})})]})})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsxs)(ee.Z,{className:"my-2",children:["Alerts are only supported for Slack Webhook URLs. Get your webhook urls from ",(0,r.jsx)("a",{href:"https://api.slack.com/messaging/webhooks",target:"_blank",style:{color:"blue"},children:"here"})]}),(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{}),(0,r.jsx)(e_.Z,{}),(0,r.jsx)(e_.Z,{children:"Slack Webhook URL"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(v).map((e,l)=>{let[t,s]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ls.Z,{id:"switch",name:"switch",checked:S(t),onChange:()=>k(t)})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ee.Z,{children:s})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(H.Z,{name:t,type:"password",defaultValue:Z&&Z[t]?Z[t]:y})})]},l)})})]}),(0,r.jsx)(J.Z,{size:"xs",className:"mt-2",onClick:()=>{if(!l)return;let e={};Object.entries(v).forEach(l=>{let[t,s]=l,a=document.querySelector('input[name="'.concat(t,'"]'));console.log("key",t),console.log("webhookInput",a);let r=(null==a?void 0:a.value)||"";console.log("newWebhookValue",r),e[t]=r}),console.log("updatedAlertToWebhooks",e);let t={general_settings:{alert_to_webhook_url:e,alert_types:w}};console.log("payload",t);try{V(l,t)}catch(e){u.ZP.error("Failed to update alerts: "+e,20)}u.ZP.success("Alerts updated successfully")},children:"Save Changes"}),(0,r.jsx)(J.Z,{onClick:()=>z(l,"slack"),className:"mx-2",children:"Test Alerts"})]})})]})]})]}),(0,r.jsx)(er.Z,{title:"Add Callback",visible:d,onOk:A,width:800,onCancel:()=>{m(!1),h.resetFields(),p(null)},footer:null,children:(0,r.jsxs)(ea.Z,{form:h,layout:"vertical",onFinish:A,children:[(0,r.jsx)(ea.Z.Item,{label:"Callback",name:"callback",rules:[{required:!0,message:"Please select a callback"}],children:(0,r.jsxs)(es.default,{onChange:e=>{p(e)},children:[(0,r.jsx)(es.default.Option,{value:"langfuse",children:"langfuse"}),(0,r.jsx)(es.default.Option,{value:"openmeter",children:"openmeter"})]})}),"langfuse"===x&&(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"LANGFUSE_PUBLIC_KEY",name:"langfusePublicKey",rules:[{required:!0,message:"Please enter the public key"}],children:(0,r.jsx)(H.Z,{type:"password"})}),(0,r.jsx)(ea.Z.Item,{label:"LANGFUSE_PRIVATE_KEY",name:"langfusePrivateKey",rules:[{required:!0,message:"Please enter the private key"}],children:(0,r.jsx)(H.Z,{type:"password"})})]}),"openmeter"==x&&(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(ea.Z.Item,{label:"OPENMETER_API_KEY",name:"openMeterApiKey",rules:[{required:!0,message:"Please enter the openmeter api key"}],children:(0,r.jsx)(H.Z,{type:"password"})})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Save"})})]})})]})):null};let{Option:ln}=es.default;var lo=e=>{let{models:l,accessToken:t,routerSettings:s,setRouterSettings:a}=e,[o]=ea.Z.useForm(),[i,c]=(0,n.useState)(!1),[d,m]=(0,n.useState)("");return(0,r.jsxs)("div",{children:[(0,r.jsx)(J.Z,{className:"mx-auto",onClick:()=>c(!0),children:"+ Add Fallbacks"}),(0,r.jsx)(er.Z,{title:"Add Fallbacks",visible:i,width:800,footer:null,onOk:()=>{c(!1),o.resetFields()},onCancel:()=>{c(!1),o.resetFields()},children:(0,r.jsxs)(ea.Z,{form:o,onFinish:e=>{console.log(e);let{model_name:l,models:r}=e,n=[...s.fallbacks||[],{[l]:r}],i={...s,fallbacks:n};console.log(i);try{V(t,{router_settings:i}),a(i)}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully"),c(!1),o.resetFields()},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(ea.Z.Item,{label:"Public Model Name",name:"model_name",rules:[{required:!0,message:"Set the model to fallback for"}],help:"required",children:(0,r.jsx)(eb.Z,{defaultValue:d,children:l&&l.map((e,l)=>(0,r.jsx)(ek.Z,{value:e,onClick:()=>m(e),children:e},l))})}),(0,r.jsx)(ea.Z.Item,{label:"Fallback Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,r.jsx)(eK.Z,{value:l,children:l&&l.filter(e=>e!=d).map(e=>(0,r.jsx)(eB.Z,{value:e,children:e},e))})})]}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(ei.ZP,{htmlType:"submit",children:"Add Fallbacks"})})]})})]})},li=t(12968);async function lc(e,l){console.log("isLocal:",!1);let t=window.location.origin,s=new li.ZP.OpenAI({apiKey:l,baseURL:t,dangerouslyAllowBrowser:!0});try{let l=await s.chat.completions.create({model:e,messages:[{role:"user",content:"Hi, this is a test message"}],mock_testing_fallbacks:!0});u.ZP.success((0,r.jsxs)("span",{children:["Test model=",(0,r.jsx)("strong",{children:e}),", received model=",(0,r.jsx)("strong",{children:l.model}),". See ",(0,r.jsx)("a",{href:"#",onClick:()=>window.open("https://docs.litellm.ai/docs/proxy/reliability","_blank"),style:{textDecoration:"underline",color:"blue"},children:"curl"})]}))}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}let ld={ttl:3600,lowest_latency_buffer:0},lm=e=>{let{selectedStrategy:l,strategyArgs:t,paramExplanation:s}=e;return(0,r.jsxs)($.Z,{children:[(0,r.jsx)(Q.Z,{className:"text-sm font-medium text-tremor-content-strong dark:text-dark-tremor-content-strong",children:"Routing Strategy Specific Args"}),(0,r.jsx)(X.Z,{children:"latency-based-routing"==l?(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Setting"}),(0,r.jsx)(e_.Z,{children:"Value"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(t).map(e=>{let[l,t]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ee.Z,{children:l}),(0,r.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:s[l]})]}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(H.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]})}):(0,r.jsx)(ee.Z,{children:"No specific settings"})})]})};var lu=e=>{let{accessToken:l,userRole:t,userID:s,modelData:a}=e,[o,i]=(0,n.useState)({}),[c,d]=(0,n.useState)(!1),[m]=ea.Z.useForm(),[h,x]=(0,n.useState)(null),[p,j]=(0,n.useState)(null),[g,y]=(0,n.useState)(null),f={routing_strategy_args:"(dict) Arguments to pass to the routing strategy",routing_strategy:"(string) Routing strategy to use",allowed_fails:"(int) Number of times a deployment can fail before being added to cooldown",cooldown_time:"(int) time in seconds to cooldown a deployment after failure",num_retries:"(int) Number of retries for failed requests. Defaults to 0.",timeout:"(float) Timeout for requests. Defaults to None.",retry_after:"(int) Minimum time to wait before retrying a failed request",ttl:"(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};(0,n.useEffect)(()=>{l&&t&&s&&q(l,s,t).then(e=>{console.log("callbacks",e),i(e.router_settings)})},[l,t,s]);let Z=async e=>{if(l){console.log("received key: ".concat(e)),console.log("routerSettings['fallbacks']: ".concat(o.fallbacks)),o.fallbacks.map(l=>(e in l&&delete l[e],l));try{await V(l,{router_settings:o}),i({...o}),j(o.routing_strategy),u.ZP.success("Router settings updated successfully")}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}}},_=e=>{if(!l)return;console.log("router_settings",e);let t=Object.fromEntries(Object.entries(e).map(e=>{let[l,t]=e;if("routing_strategy_args"!==l&&"routing_strategy"!==l){var s;return[l,(null===(s=document.querySelector('input[name="'.concat(l,'"]')))||void 0===s?void 0:s.value)||t]}if("routing_strategy"==l)return[l,p];if("routing_strategy_args"==l&&"latency-based-routing"==p){let e={},l=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]');return(null==l?void 0:l.value)&&(e.lowest_latency_buffer=Number(l.value)),(null==t?void 0:t.value)&&(e.ttl=Number(t.value)),console.log("setRoutingStrategyArgs: ".concat(e)),["routing_strategy_args",e]}return null}).filter(e=>null!=e));console.log("updatedVariables",t);try{V(l,{router_settings:t})}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully")};return l?(0,r.jsx)("div",{className:"w-full mx-4",children:(0,r.jsxs)(eM.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,r.jsxs)(eL.Z,{variant:"line",defaultValue:"1",children:[(0,r.jsx)(eR.Z,{value:"1",children:"General Settings"}),(0,r.jsx)(eR.Z,{value:"2",children:"Fallbacks"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,r.jsx)(el.Z,{children:"Router Settings"}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Setting"}),(0,r.jsx)(e_.Z,{children:"Value"})]})}),(0,r.jsx)(ey.Z,{children:Object.entries(o).filter(e=>{let[l,t]=e;return"fallbacks"!=l&&"context_window_fallbacks"!=l&&"routing_strategy_args"!=l}).map(e=>{let[l,t]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsxs)(ef.Z,{children:[(0,r.jsx)(ee.Z,{children:l}),(0,r.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:f[l]})]}),(0,r.jsx)(ef.Z,{children:"routing_strategy"==l?(0,r.jsxs)(eb.Z,{defaultValue:t,className:"w-full max-w-md",onValueChange:j,children:[(0,r.jsx)(ek.Z,{value:"usage-based-routing",children:"usage-based-routing"}),(0,r.jsx)(ek.Z,{value:"latency-based-routing",children:"latency-based-routing"}),(0,r.jsx)(ek.Z,{value:"simple-shuffle",children:"simple-shuffle"})]}):(0,r.jsx)(H.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]}),(0,r.jsx)(lm,{selectedStrategy:p,strategyArgs:o&&o.routing_strategy_args&&Object.keys(o.routing_strategy_args).length>0?o.routing_strategy_args:ld,paramExplanation:f})]}),(0,r.jsx)(Y.Z,{children:(0,r.jsx)(J.Z,{className:"mt-2",onClick:()=>_(o),children:"Save Changes"})})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)(eg.Z,{children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"Model Name"}),(0,r.jsx)(e_.Z,{children:"Fallbacks"})]})}),(0,r.jsx)(ey.Z,{children:o.fallbacks&&o.fallbacks.map((e,t)=>Object.entries(e).map(e=>{let[s,a]=e;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:s}),(0,r.jsx)(ef.Z,{children:Array.isArray(a)?a.join(", "):a}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(J.Z,{onClick:()=>lc(s,l),children:"Test Fallback"})}),(0,r.jsx)(ef.Z,{children:(0,r.jsx)(ej.Z,{icon:eh.Z,size:"sm",onClick:()=>Z(s)})})]},t.toString()+s)}))})]}),(0,r.jsx)(lo,{models:(null==a?void 0:a.data)?a.data.map(e=>e.model_name):[],accessToken:l,routerSettings:o,setRouterSettings:i})]})]})]})}):null},lh=t(67951),lx=e=>{let{}=e;return(0,r.jsx)(r.Fragment,{children:(0,r.jsx)(W.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,r.jsxs)("div",{className:"mb-5",children:[(0,r.jsx)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:"OpenAI Compatible Proxy: API Reference"}),(0,r.jsx)(ee.Z,{className:"mt-2 mb-2",children:"LiteLLM is OpenAI Compatible. This means your API Key works with the OpenAI SDK. Just replace the base_url to point to your litellm proxy. Example Below "}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{children:[(0,r.jsx)(eR.Z,{children:"OpenAI Python SDK"}),(0,r.jsx)(eR.Z,{children:"LlamaIndex"}),(0,r.jsx)(eR.Z,{children:"Langchain Py"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # LiteLLM Proxy is OpenAI compatible, Read More: https://docs.litellm.ai/docs/proxy/user_keys\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to send to the proxy\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ]\n)\n\nprint(response)\n '})}),(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,r.jsx)(eU.Z,{children:(0,r.jsx)(lh.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:4000",\n model = "gpt-3.5-turbo",\n temperature=0.1\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})]})})})};async function lp(e,l,t,s){console.log("isLocal:",!1);let a=window.location.origin,r=new li.ZP.OpenAI({apiKey:s,baseURL:a,dangerouslyAllowBrowser:!0});try{for await(let s of(await r.chat.completions.create({model:t,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&l(s.choices[0].delta.content)}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}var lj=e=>{let{accessToken:l,token:t,userRole:s,userID:a}=e,[o,i]=(0,n.useState)(""),[c,d]=(0,n.useState)(""),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)(void 0),[p,j]=(0,n.useState)([]);(0,n.useEffect)(()=>{l&&t&&s&&a&&(async()=>{try{let e=await N(l,a,s);if(console.log("model_info:",e),(null==e?void 0:e.data.length)>0){let l=e.data.map(e=>({value:e.id,label:e.id}));console.log(l),j(l),x(e.data[0].id)}}catch(e){console.error("Error fetching model info:",e)}})()},[l,a,s]);let g=(e,l)=>{u(t=>{let s=t[t.length-1];return s&&s.role===e?[...t.slice(0,t.length-1),{role:e,content:s.content+l}]:[...t,{role:e,content:l}]})},y=async()=>{if(""!==c.trim()&&o&&t&&s&&a){u(e=>[...e,{role:"user",content:c}]);try{h&&await lp(c,e=>g("assistant",e),h,o)}catch(e){console.error("Error fetching model response",e),g("assistant","Error fetching model response")}d("")}};if(s&&"Admin Viewer"==s){let{Title:e,Paragraph:l}=eT.default;return(0,r.jsxs)("div",{children:[(0,r.jsx)(e,{level:1,children:"Access Denied"}),(0,r.jsx)(l,{children:"Ask your proxy admin for access to test models"})]})}return(0,r.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,r.jsx)(W.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,r.jsx)(ep.Z,{children:(0,r.jsxs)(eM.Z,{children:[(0,r.jsx)(eL.Z,{children:(0,r.jsx)(eR.Z,{children:"Chat"})}),(0,r.jsx)(eD.Z,{children:(0,r.jsxs)(eU.Z,{children:[(0,r.jsx)("div",{className:"sm:max-w-2xl",children:(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"API Key"}),(0,r.jsx)(H.Z,{placeholder:"Type API Key here",type:"password",onValueChange:i,value:o})]}),(0,r.jsxs)(Y.Z,{className:"mx-2",children:[(0,r.jsx)(ee.Z,{children:"Select Model:"}),(0,r.jsx)(es.default,{placeholder:"Select a Model",onChange:e=>{console.log("selected ".concat(e)),x(e)},options:p,style:{width:"200px"}})]})]})}),(0,r.jsxs)(eg.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsx)(ew.Z,{children:(0,r.jsx)(ef.Z,{})})}),(0,r.jsx)(ey.Z,{children:m.map((e,l)=>(0,r.jsx)(ew.Z,{children:(0,r.jsx)(ef.Z,{children:"".concat(e.role,": ").concat(e.content)})},l))})]}),(0,r.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,r.jsxs)("div",{className:"flex",children:[(0,r.jsx)(H.Z,{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"Type your message..."}),(0,r.jsx)(J.Z,{onClick:y,className:"ml-2",children:"Send"})]})})]})})]})})})})},lg=t(33509),ly=t(95781);let{Sider:lf}=lg.default;var lZ=e=>{let{setPage:l,userRole:t,defaultSelectedKey:s}=e;return"Admin Viewer"==t?(0,r.jsx)(lg.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,r.jsx)(lf,{width:120,children:(0,r.jsxs)(ly.Z,{mode:"inline",defaultSelectedKeys:s||["4"],style:{height:"100%",borderRight:0},children:[(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api-keys"),children:"API Keys"},"4"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("models"),children:"Models"},"2"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("llm-playground"),children:"Chat UI"},"3"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("usage"),children:"Usage"},"1")]})})}):(0,r.jsx)(lg.default,{style:{minHeight:"100vh",maxWidth:"145px"},children:(0,r.jsx)(lf,{width:145,children:(0,r.jsxs)(ly.Z,{mode:"inline",defaultSelectedKeys:s||["1"],style:{height:"100%",borderRight:0},children:[(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api-keys"),children:(0,r.jsx)(ee.Z,{children:"API Keys"})},"1"),(0,r.jsx)(ly.Z.Item,{onClick:()=>l("llm-playground"),children:(0,r.jsx)(ee.Z,{children:"Test Key"})},"3"),"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("models"),children:(0,r.jsx)(ee.Z,{children:"Models"})},"2"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("usage"),children:(0,r.jsx)(ee.Z,{children:"Usage"})},"4"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("teams"),children:(0,r.jsx)(ee.Z,{children:"Teams"})},"6"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("users"),children:(0,r.jsx)(ee.Z,{children:"Users"})},"5"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("settings"),children:(0,r.jsx)(ee.Z,{children:"Logging & Alerts"})},"8"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("general-settings"),children:(0,r.jsx)(ee.Z,{children:"Router Settings"})},"9"):null,"Admin"==t?(0,r.jsx)(ly.Z.Item,{onClick:()=>l("admin-panel"),children:(0,r.jsx)(ee.Z,{children:"Admin"})},"7"):null,(0,r.jsx)(ly.Z.Item,{onClick:()=>l("api_ref"),children:(0,r.jsx)(ee.Z,{children:"API Reference"})},"11")]})})})},l_=t(67989),lw=e=>{let{accessToken:l,token:t,userRole:s,userID:a,keys:o}=e,i=new Date,[c,d]=(0,n.useState)([]),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)([]),[p,j]=(0,n.useState)([]),[g,y]=(0,n.useState)([]),[f,Z]=(0,n.useState)([]),[_,w]=(0,n.useState)([]),[b,k]=(0,n.useState)([]),[v,S]=(0,n.useState)(""),[N,R]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),M=new Date(i.getFullYear(),i.getMonth(),1),L=new Date(i.getFullYear(),i.getMonth()+1,0),U=z(M),D=z(L);console.log("keys in usage",o);let K=async(e,t,s)=>{if(!e||!t||!l)return;console.log("uiSelectedKey",s);let a=await T(l,s,e.toISOString(),t.toISOString());console.log("End user data updated successfully",a),j(a)},B=async(e,t)=>{e&&t&&l&&(Z((await E(l,e.toISOString(),t.toISOString())).spend_per_tag),console.log("Tag spend data updated successfully"))};function z(e){let l=e.getFullYear(),t=e.getMonth()+1,s=e.getDate();return"".concat(l,"-").concat(t<10?"0"+t:t,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(U)),console.log("End date is ".concat(D)),(0,n.useEffect)(()=>{l&&t&&s&&a&&(async()=>{try{if(console.log("user role: ".concat(s)),"Admin"==s||"Admin Viewer"==s){var e,r;let t=await C(l);d(t);let s=(await P(l)).map(e=>({key:(e.key_name||e.key_alias||e.api_key).substring(0,10),spend:e.total_spend}));u(s);let a=(await O(l)).map(e=>({key:e.model,spend:e.total_spend}));x(a);let n=await A(l);console.log("teamSpend",n),y(n.daily_spend),w(n.teams);let o=n.total_spend_per_team;o=o.map(e=>(e.name=e.team_id||"",e.value=e.total_spend||0,e)),k(o);let i=await E(l,null===(e=N.from)||void 0===e?void 0:e.toISOString(),null===(r=N.to)||void 0===r?void 0:r.toISOString());Z(i.spend_per_tag);let c=await T(l,null,void 0,void 0);j(c),console.log("spend/user result",c)}else"App Owner"==s&&await I(l,t,s,a,U,D).then(async e=>{if(console.log("result from spend logs call",e),"daily_spend"in e){let l=e.daily_spend;console.log("daily spend",l),d(l);let t=e.top_api_keys;u(t)}else{let t=(await F(l,function(e){let l=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[t,s]=e;"spend"!==t&&"startTime"!==t&&"models"!==t&&"users"!==t&&l.push({key:t,spend:s})})}),l.sort((e,l)=>Number(l.spend)-Number(e.spend));let t=l.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(t[0]))),t}(e))).info.map(e=>({key:(e.key_name||e.key_alias).substring(0,10),spend:e.spend}));u(t),d(e)}})}catch(e){console.error("There was an error fetching the data",e)}})()},[l,t,s,a,U,D]),(0,r.jsxs)("div",{style:{width:"100%"},className:"p-8",children:[(0,r.jsx)(eE,{userID:a,userRole:s,accessToken:l,userSpend:null,selectedTeam:null}),(0,r.jsxs)(eM.Z,{children:[(0,r.jsxs)(eL.Z,{className:"mt-2",children:[(0,r.jsx)(eR.Z,{children:"All Up"}),(0,r.jsx)(eR.Z,{children:"Team Based Usage"}),(0,r.jsx)(eR.Z,{children:"End User Usage"}),(0,r.jsx)(eR.Z,{children:"Tag Based Usage"})]}),(0,r.jsxs)(eD.Z,{children:[(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,r.jsx)(Y.Z,{numColSpan:2,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Monthly Spend"}),(0,r.jsx)(eq.Z,{data:c,index:"date",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5})]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Top API Keys"}),(0,r.jsx)(eq.Z,{className:"mt-4 h-40",data:m,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,r.jsx)(Y.Z,{numColSpan:1,children:(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Top Models"}),(0,r.jsx)(eq.Z,{className:"mt-4 h-40",data:h,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,r.jsx)(Y.Z,{numColSpan:1})]})}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,r.jsxs)(Y.Z,{numColSpan:2,children:[(0,r.jsxs)(ep.Z,{className:"mb-2",children:[(0,r.jsx)(el.Z,{children:"Total Spend Per Team"}),(0,r.jsx)(l_.Z,{data:b})]}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Daily Spend Per Team"}),(0,r.jsx)(eq.Z,{className:"h-72",data:g,showLegend:!0,index:"date",categories:_,yAxisWidth:80,colors:["blue","green","yellow","red","purple"],stack:!0})]})]}),(0,r.jsx)(Y.Z,{numColSpan:2})]})}),(0,r.jsxs)(eU.Z,{children:[(0,r.jsxs)("p",{className:"mb-2 text-gray-500 italic text-[12px]",children:["End-Users of your LLM API calls. Tracked when a `user` param is passed in your LLM calls ",(0,r.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/users",target:"_blank",children:"docs here"})]}),(0,r.jsxs)(W.Z,{numItems:2,children:[(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Time Range"}),(0,r.jsx)(eF.Z,{enableSelect:!0,value:N,onValueChange:e=>{R(e),K(e.from,e.to,null)}})]}),(0,r.jsxs)(Y.Z,{children:[(0,r.jsx)(ee.Z,{children:"Select Key"}),(0,r.jsxs)(eb.Z,{defaultValue:"all-keys",children:[(0,r.jsx)(ek.Z,{value:"all-keys",onClick:()=>{K(N.from,N.to,null)},children:"All Keys"},"all-keys"),null==o?void 0:o.map((e,l)=>e&&null!==e.key_alias&&e.key_alias.length>0?(0,r.jsx)(ek.Z,{value:String(l),onClick:()=>{K(N.from,N.to,e.token)},children:e.key_alias},l):null)]})]})]}),(0,r.jsx)(ep.Z,{className:"mt-4",children:(0,r.jsxs)(eg.Z,{className:"max-h-[70vh] min-h-[500px]",children:[(0,r.jsx)(eZ.Z,{children:(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(e_.Z,{children:"End User"}),(0,r.jsx)(e_.Z,{children:"Spend"}),(0,r.jsx)(e_.Z,{children:"Total Events"})]})}),(0,r.jsx)(ey.Z,{children:null==p?void 0:p.map((e,l)=>{var t;return(0,r.jsxs)(ew.Z,{children:[(0,r.jsx)(ef.Z,{children:e.end_user}),(0,r.jsx)(ef.Z,{children:null===(t=e.total_spend)||void 0===t?void 0:t.toFixed(4)}),(0,r.jsx)(ef.Z,{children:e.total_count})]},l)})})]})})]}),(0,r.jsx)(eU.Z,{children:(0,r.jsxs)(W.Z,{numItems:2,className:"gap-2 h-[75vh] w-full mb-4",children:[(0,r.jsxs)(Y.Z,{numColSpan:2,children:[(0,r.jsx)(eF.Z,{className:"mb-4",enableSelect:!0,value:N,onValueChange:e=>{R(e),B(e.from,e.to)}}),(0,r.jsxs)(ep.Z,{children:[(0,r.jsx)(el.Z,{children:"Spend Per Tag"}),(0,r.jsxs)(ee.Z,{children:["Get Started Tracking cost per tag ",(0,r.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags",target:"_blank",children:"here"})]}),(0,r.jsx)(eq.Z,{className:"h-72",data:f,index:"name",categories:["spend"],colors:["blue"]})]})]}),(0,r.jsx)(Y.Z,{numColSpan:2})]})})]})]})]})},lb=()=>{let{Title:e,Paragraph:l}=eT.default,[t,s]=(0,n.useState)(""),[a,i]=(0,n.useState)(null),[c,d]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(!0),j=(0,o.useSearchParams)(),[g,y]=(0,n.useState)({data:[]}),f=j.get("userID"),Z=j.get("token"),[_,w]=(0,n.useState)("api-keys"),[b,k]=(0,n.useState)(null);return(0,n.useEffect)(()=>{if(Z){let e=(0,eP.o)(Z);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),k(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e.toLowerCase())),console.log("Received user role length: ".concat(e.toLowerCase().length)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),s(l),"Admin Viewer"==l&&w("usage")}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e)),e.login_method?p("username_password"==e.login_method):console.log("User Email is not set ".concat(e))}}},[Z]),(0,r.jsx)(n.Suspense,{fallback:(0,r.jsx)("div",{children:"Loading..."}),children:(0,r.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,r.jsx)(m,{userID:f,userRole:t,userEmail:a,showSSOBanner:x}),(0,r.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,r.jsx)("div",{className:"mt-8",children:(0,r.jsx)(lZ,{setPage:w,userRole:t,defaultSelectedKey:null})}),"api-keys"==_?(0,r.jsx)(eO,{userID:f,userRole:t,teams:c,keys:u,setUserRole:s,userEmail:a,setUserEmail:i,setTeams:d,setKeys:h}):"models"==_?(0,r.jsx)(e3,{userID:f,userRole:t,token:Z,accessToken:b,modelData:g,setModelData:y}):"llm-playground"==_?(0,r.jsx)(lj,{userID:f,userRole:t,token:Z,accessToken:b}):"users"==_?(0,r.jsx)(e9,{userID:f,userRole:t,token:Z,keys:u,teams:c,accessToken:b,setKeys:h}):"teams"==_?(0,r.jsx)(le,{teams:c,setTeams:d,searchParams:j,accessToken:b,userID:f,userRole:t}):"admin-panel"==_?(0,r.jsx)(lt,{setTeams:d,searchParams:j,accessToken:b,showSSOBanner:x}):"api_ref"==_?(0,r.jsx)(lx,{}):"settings"==_?(0,r.jsx)(lr,{userID:f,userRole:t,accessToken:b}):"general-settings"==_?(0,r.jsx)(lu,{userID:f,userRole:t,accessToken:b,modelData:g}):(0,r.jsx)(lw,{userID:f,userRole:t,token:Z,accessToken:b,keys:u})]})]})})}}},function(e){e.O(0,[936,884,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/ui/litellm-dashboard/out/_next/static/chunks/app/page-c35c14c9afd091ec.js b/ui/litellm-dashboard/out/_next/static/chunks/app/page-c35c14c9afd091ec.js new file mode 100644 index 0000000000..e8b5c33a1c --- /dev/null +++ b/ui/litellm-dashboard/out/_next/static/chunks/app/page-c35c14c9afd091ec.js @@ -0,0 +1 @@ +(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{20661:function(e,l,t){Promise.resolve().then(t.bind(t,4858))},4858:function(e,l,t){"use strict";t.r(l),t.d(l,{default:function(){return lS}});var s,r,a=t(3827),n=t(64090),o=t(47907),i=t(8792),c=t(40491),d=t(65270),m=e=>{let{userID:l,userRole:t,userEmail:s,showSSOBanner:r}=e;console.log("User ID:",l),console.log("userEmail:",s),console.log("showSSOBanner:",r);let n=[{key:"1",label:(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("p",{children:["Role: ",t]}),(0,a.jsxs)("p",{children:["ID: ",l]})]})}];return(0,a.jsxs)("nav",{className:"left-0 right-0 top-0 flex justify-between items-center h-12 mb-4",children:[(0,a.jsx)("div",{className:"text-left my-2 absolute top-0 left-0",children:(0,a.jsx)("div",{className:"flex flex-col items-center",children:(0,a.jsx)(i.default,{href:"/",children:(0,a.jsx)("button",{className:"text-gray-800 rounded text-center",children:(0,a.jsx)("img",{src:"/get_image",width:160,height:160,alt:"LiteLLM Brand",className:"mr-2"})})})})}),(0,a.jsxs)("div",{className:"text-right mx-4 my-2 absolute top-0 right-0 flex items-center justify-end space-x-2",children:[r?(0,a.jsx)("div",{style:{padding:"6px",borderRadius:"8px"},children:(0,a.jsx)("a",{href:"https://calendly.com/d/4mp-gd3-k5k/litellm-1-1-onboarding-chat",target:"_blank",style:{fontSize:"14px",textDecoration:"underline"},children:"Request hosted proxy"})}):null,(0,a.jsx)("div",{style:{border:"1px solid #391085",padding:"6px",borderRadius:"8px"},children:(0,a.jsx)(c.Z,{menu:{items:n},children:(0,a.jsx)(d.Z,{children:s})})})]})]})},u=t(80588);let h=async()=>{try{let e=await fetch("https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json"),l=await e.json();return console.log("received data: ".concat(l)),l}catch(e){throw console.error("Failed to get model cost map:",e),e}},x=async(e,l)=>{try{let t=await fetch("/model/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model created successfully. Wait 60s and refresh on 'All Models' page"),s}catch(e){throw console.error("Failed to create key:",e),e}},p=async(e,l)=>{console.log("model_id in model delete call: ".concat(l));try{let t=await fetch("/model/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({id:l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),u.ZP.success("Model deleted successfully. Restart server to see this."),s}catch(e){throw console.error("Failed to create key:",e),e}},j=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},g=async(e,l,t)=>{try{if(console.log("Form Values in keyCreateCall:",t),t.description&&(t.metadata||(t.metadata={}),t.metadata.description=t.description,delete t.description,t.metadata=JSON.stringify(t.metadata)),t.metadata){console.log("formValues.metadata:",t.metadata);try{t.metadata=JSON.parse(t.metadata)}catch(e){throw u.ZP.error("Failed to parse metadata: "+e,10),Error("Failed to parse metadata: "+e)}}console.log("Form Values after check:",t);let s=await fetch("/user/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:l,...t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},f=async(e,l)=>{try{console.log("in keyDeleteCall:",l);let t=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},y=async(e,l)=>{try{console.log("in teamDeleteCall:",l);let t=await fetch("/team/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_ids:[l]})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to delete team: "+e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to delete key:",e),e}},Z=async function(e,l,t){let s=arguments.length>3&&void 0!==arguments[3]&&arguments[3],r=arguments.length>4?arguments[4]:void 0,a=arguments.length>5?arguments[5]:void 0;try{let n="/user/info";"App Owner"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),"App User"==t&&l&&(n="".concat(n,"?user_id=").concat(l)),console.log("in userInfoCall viewAll=",s),s&&a&&null!=r&&void 0!=r&&(n="".concat(n,"?view_all=true&page=").concat(r,"&page_size=").concat(a));let o=await fetch(n,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!o.ok){let e=await o.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let i=await o.json();return console.log("API Response:",i),i}catch(e){throw console.error("Failed to create key:",e),e}},_=async(e,l)=>{try{let t="/team/info";l&&(t="".concat(t,"?team_id=").concat(l)),console.log("in teamInfoCall");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},w=async e=>{try{let l=await fetch("/global/spend",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},b=async(e,l,t)=>{try{let l=await fetch("/v2/model/info",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log("modelInfoCall:",t),t}catch(e){throw console.error("Failed to create key:",e),e}},k=async(e,l,t,s,r,a)=>{try{let l="/model/metrics";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},v=async(e,l,t,s,r,a)=>{try{let l="/model/metrics/slow_responses";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},S=async(e,l,t,s,r,a)=>{try{let l="/model/metrics/exceptions";s&&(l="".concat(l,"?_selected_model_group=").concat(s,"&startTime=").concat(r,"&endTime=").concat(a));let t=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to create key:",e),e}},N=async(e,l,t)=>{try{let l=await fetch("/models",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to create key:",e),e}},A=async e=>{try{let l="/global/spend/teams";console.log("in teamSpendLogsCall:",l);let t=await fetch("".concat(l),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},E=async(e,l,t)=>{try{let s="/global/spend/tags";l&&t&&(s="".concat(s,"?start_date=").concat(l,"&end_date=").concat(t)),console.log("in tagsSpendLogsCall:",s);let r=await fetch("".concat(s),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let a=await r.json();return console.log(a),a}catch(e){throw console.error("Failed to create key:",e),e}},I=async(e,l,t,s,r,a)=>{try{console.log("user role in spend logs call: ".concat(t));let l="/spend/logs";l="App Owner"==t?"".concat(l,"?user_id=").concat(s,"&start_date=").concat(r,"&end_date=").concat(a):"".concat(l,"?start_date=").concat(r,"&end_date=").concat(a);let n=await fetch(l,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},C=async e=>{try{let l=await fetch("/global/spend/logs",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},P=async e=>{try{let l=await fetch("/global/spend/keys?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},T=async(e,l,t,s)=>{try{let r="";r=l?JSON.stringify({api_key:l,startTime:t,endTime:s}):JSON.stringify({startTime:t,endTime:s});let a={method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}};a.body=r;let n=await fetch("/global/spend/end_users",a);if(!n.ok){let e=await n.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let o=await n.json();return console.log(o),o}catch(e){throw console.error("Failed to create key:",e),e}},O=async e=>{try{let l=await fetch("/global/spend/models?limit=5",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let t=await l.json();return console.log(t),t}catch(e){throw console.error("Failed to create key:",e),e}},F=async(e,l)=>{try{let t=await fetch("/v2/key/info",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}},R=async(e,l)=>{try{let t="/user/get_users?role=".concat(l);console.log("in userGetAllUsersCall:",t);let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to delete key: "+e,10),Error("Network response was not ok")}let r=await s.json();return console.log(r),r}catch(e){throw console.error("Failed to get requested models:",e),e}},M=async(e,l)=>{try{console.log("Form Values in teamCreateCall:",l);let t=await fetch("/team/new",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},L=async(e,l)=>{try{console.log("Form Values in keyUpdateCall:",l);let t=await fetch("/key/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update key Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},U=async(e,l)=>{try{console.log("Form Values in teamUpateCall:",l);let t=await fetch("/team/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update team: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update Team Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},D=async(e,l)=>{try{console.log("Form Values in modelUpateCall:",l);let t=await fetch("/model/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error("Failed to update model: "+e,10),console.error("Error update from the server:",e),Error("Network response was not ok")}let s=await t.json();return console.log("Update model Response:",s),s}catch(e){throw console.error("Failed to update model:",e),e}},K=async(e,l,t)=>{try{console.log("Form Values in teamMemberAddCall:",t);let s=await fetch("/team/member_add",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({team_id:l,member:t})});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let r=await s.json();return console.log("API Response:",r),r}catch(e){throw console.error("Failed to create key:",e),e}},B=async(e,l,t)=>{try{console.log("Form Values in userUpdateUserCall:",l);let s={...l};null!==t&&(s.user_role=t),s=JSON.stringify(s);let r=await fetch("/user/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:s});if(!r.ok){let e=await r.text();throw u.ZP.error("Failed to create key: "+e,10),console.error("Error response from the server:",e),Error("Network response was not ok")}let a=await r.json();return console.log("API Response:",a),a}catch(e){throw console.error("Failed to create key:",e),e}},z=async(e,l)=>{try{let t="/health/services?service=".concat(l);console.log("Checking Slack Budget Alerts service health");let s=await fetch(t,{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!s.ok){let e=await s.text();throw u.ZP.error("Failed ".concat(l," service health check ")+e),Error(e)}let r=await s.json();return u.ZP.success("Test request to ".concat(l," made - check logs/alerts on ").concat(l," to verify")),r}catch(e){throw console.error("Failed to perform health check:",e),e}},V=async(e,l,t)=>{try{let l=await fetch("/get/config/callbacks",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},q=async e=>{try{let l=await fetch("/config/list?config_type=general_settings",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to get callbacks:",e),e}},G=async(e,l,t)=>{try{let s=await fetch("/config/field/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({field_name:l,field_value:t,config_type:"general_settings"})});if(!s.ok){let e=await s.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let r=await s.json();return u.ZP.success("Successfully updated value!"),r}catch(e){throw console.error("Failed to set callbacks:",e),e}},Y=async(e,l)=>{try{let t=await fetch("/config/field/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({field_name:l,config_type:"general_settings"})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}let s=await t.json();return u.ZP.success("Field reset on proxy"),s}catch(e){throw console.error("Failed to get callbacks:",e),e}},W=async(e,l)=>{try{let t=await fetch("/config/update",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({...l})});if(!t.ok){let e=await t.text();throw u.ZP.error(e,10),Error("Network response was not ok")}return await t.json()}catch(e){throw console.error("Failed to set callbacks:",e),e}},J=async e=>{try{let l=await fetch("/health",{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!l.ok){let e=await l.text();throw u.ZP.error(e),Error("Network response was not ok")}return await l.json()}catch(e){throw console.error("Failed to call /health:",e),e}};var H=t(10384),$=t(46453),X=t(16450),Q=t(52273),ee=t(26780),el=t(15595),et=t(6698),es=t(71801),er=t(42440),ea=t(42308),en=t(50670),eo=t(81583),ei=t(99129),ec=t(44839),ed=t(88707),em=t(1861);let{Option:eu}=en.default;var eh=e=>{let{userID:l,team:t,userRole:s,accessToken:r,data:o,setData:i}=e,[c]=eo.Z.useForm(),[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(null),[p,g]=(0,n.useState)(null),[f,y]=(0,n.useState)([]),[Z,_]=(0,n.useState)([]),w=()=>{m(!1),c.resetFields()},b=()=>{m(!1),x(null),c.resetFields()};(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===s)return;if(null!==r){let e=(await N(r,l,s)).data.map(e=>e.id);console.log("available_model_names:",e),y(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[r,l,s]);let k=async e=>{try{var t,s,a;let n=null!==(t=null==e?void 0:e.key_alias)&&void 0!==t?t:"",d=null!==(s=null==e?void 0:e.team_id)&&void 0!==s?s:null;if((null!==(a=null==o?void 0:o.filter(e=>e.team_id===d).map(e=>e.key_alias))&&void 0!==a?a:[]).includes(n))throw Error("Key alias ".concat(n," already exists for team with ID ").concat(d,", please provide another key alias"));u.ZP.info("Making API Call"),m(!0);let h=await j(r,l,e);console.log("key create Response:",h),i(e=>e?[...e,h]:[h]),x(h.key),g(h.soft_budget),u.ZP.success("API Key Created"),c.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the key:",e),u.ZP.error("Error creating the key: ".concat(e),20)}};return(0,n.useEffect)(()=>{_(t&&t.models.length>0?t.models.includes("all-proxy-models")?f:t.models:f)},[t,f]),(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>m(!0),children:"+ Create New Key"}),(0,a.jsx)(ei.Z,{title:"Create Key",visible:d,width:800,footer:null,onOk:w,onCancel:b,children:(0,a.jsxs)(eo.Z,{form:c,onFinish:k,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"team_id",hidden:!0,initialValue:t?t.team_id:null,valuePropName:"team_id",className:"mt-8",children:(0,a.jsx)(ec.Z,{value:t?t.team_alias:"",disabled:!0})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},onChange:e=>{e.includes("all-team-models")&&c.setFieldsValue({models:["all-team-models"]})},children:[(0,a.jsx)(eu,{value:"all-team-models",children:"All Team Models"},"all-team-models"),Z.map(e=>(0,a.jsx)(eu,{value:e,children:e},e))]})}),(0,a.jsxs)(ee.Z,{className:"mt-20 mb-8",children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)("b",{children:"Optional Settings"})}),(0,a.jsxs)(el.Z,{children:[(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: $".concat((null==t?void 0:t.max_budget)!==null&&(null==t?void 0:t.max_budget)!==void 0?null==t?void 0:t.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.max_budget&&l>t.max_budget)throw Error("Budget cannot exceed team max budget: $".concat(t.max_budget))}}],children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Reset Budget",name:"budget_duration",help:"Team Reset Budget: ".concat((null==t?void 0:t.budget_duration)!==null&&(null==t?void 0:t.budget_duration)!==void 0?null==t?void 0:t.budget_duration:"None"),children:(0,a.jsxs)(en.default,{defaultValue:null,placeholder:"n/a",children:[(0,a.jsx)(en.default.Option,{value:"24h",children:"daily"}),(0,a.jsx)(en.default.Option,{value:"30d",children:"monthly"})]})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Tokens per minute Limit (TPM)",name:"tpm_limit",help:"TPM cannot exceed team TPM limit: ".concat((null==t?void 0:t.tpm_limit)!==null&&(null==t?void 0:t.tpm_limit)!==void 0?null==t?void 0:t.tpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.tpm_limit&&l>t.tpm_limit)throw Error("TPM limit cannot exceed team TPM limit: ".concat(t.tpm_limit))}}],children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Requests per minute Limit (RPM)",name:"rpm_limit",help:"RPM cannot exceed team RPM limit: ".concat((null==t?void 0:t.rpm_limit)!==null&&(null==t?void 0:t.rpm_limit)!==void 0?null==t?void 0:t.rpm_limit:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&t&&null!==t.rpm_limit&&l>t.rpm_limit)throw Error("RPM limit cannot exceed team RPM limit: ".concat(t.rpm_limit))}}],children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Expire Key (eg: 30s, 30h, 30d)",name:"duration",className:"mt-8",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Metadata",name:"metadata",children:(0,a.jsx)(ec.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})})]})]})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create Key"})})]})}),h&&(0,a.jsx)(ei.Z,{visible:d,onOk:w,onCancel:b,footer:null,children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 w-full",children:[(0,a.jsx)(er.Z,{children:"Save your Key"}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,a.jsx)("b",{children:"you will not be able to view it again"})," ","through your LiteLLM account. If you lose this secret key, you will need to generate a new one."]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:null!=h?(0,a.jsxs)("div",{children:[(0,a.jsx)(es.Z,{className:"mt-3",children:"API Key:"}),(0,a.jsx)("div",{style:{background:"#f8f8f8",padding:"10px",borderRadius:"5px",marginBottom:"10px"},children:(0,a.jsx)("pre",{style:{wordWrap:"break-word",whiteSpace:"normal"},children:h})}),(0,a.jsx)(ea.CopyToClipboard,{text:h,onCopy:()=>{u.ZP.success("API Key copied to clipboard")},children:(0,a.jsx)(X.Z,{className:"mt-3",children:"Copy API Key"})})]}):(0,a.jsx)(es.Z,{children:"Key being created, this might take 30s"})})]})})]})},ex=t(9454),ep=t(98941),ej=t(33393),eg=t(5),ef=t(13810),ey=t(61244),eZ=t(10827),e_=t(3851),ew=t(2044),eb=t(64167),ek=t(74480),ev=t(7178),eS=t(95093),eN=t(27166);let{Option:eA}=en.default;var eE=e=>{let{userID:l,userRole:t,accessToken:s,selectedTeam:r,data:o,setData:i,teams:c}=e,[d,m]=(0,n.useState)(!1),[h,x]=(0,n.useState)(!1),[p,j]=(0,n.useState)(null),[g,y]=(0,n.useState)(null),[Z,_]=(0,n.useState)(null),[w,b]=(0,n.useState)(""),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)(!1),[E,I]=(0,n.useState)(null),[C,P]=(0,n.useState)([]),T=new Set,[O,F]=(0,n.useState)(T);(0,n.useEffect)(()=>{(async()=>{try{if(null===l)return;if(null!==s&&null!==t){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),P(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[s,l,t]),(0,n.useEffect)(()=>{if(c){let e=new Set;c.forEach((l,t)=>{let s=l.team_id;e.add(s)}),F(e)}},[c]);let R=e=>{console.log("handleEditClick:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),I(e),v(!0)},M=async e=>{if(null==s)return;let l=e.token;e.key=l,console.log("handleEditSubmit:",e);let t=await L(s,e);console.log("handleEditSubmit: newKeyValues",t),o&&i(o.map(e=>e.token===l?t:e)),u.ZP.success("Key updated successfully"),v(!1),I(null)},U=async e=>{console.log("handleDelete:",e),null==e.token&&null!==e.token_id&&(e.token=e.token_id),null!=o&&(j(e.token),localStorage.removeItem("userData"+l),x(!0))},D=async()=>{if(null!=p&&null!=o){try{await f(s,p);let e=o.filter(e=>e.token!==p);i(e)}catch(e){console.error("Error deleting the key:",e)}x(!1),j(null)}};if(null!=o)return console.log("RERENDER TRIGGERED"),(0,a.jsxs)("div",{children:[(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4 mt-2",children:[(0,a.jsxs)(eZ.Z,{className:"mt-5 max-h-[300px] min-h-[300px]",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Key Alias"}),(0,a.jsx)(ek.Z,{children:"Secret Key"}),(0,a.jsx)(ek.Z,{children:"Spend (USD)"}),(0,a.jsx)(ek.Z,{children:"Budget (USD)"}),(0,a.jsx)(ek.Z,{children:"Models"}),(0,a.jsx)(ek.Z,{children:"TPM / RPM Limits"})]})}),(0,a.jsx)(e_.Z,{children:o.map(e=>{if(console.log(e),"litellm-dashboard"===e.team_id)return null;if(r){if(console.log("item team id: ".concat(e.team_id,", knownTeamIDs.has(item.team_id): ").concat(O.has(e.team_id),", selectedTeam id: ").concat(r.team_id)),(null!=r.team_id||null===e.team_id||O.has(e.team_id))&&e.team_id!=r.team_id)return null;console.log("item team id: ".concat(e.team_id,", is returned"))}return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{style:{maxWidth:"2px",whiteSpace:"pre-wrap",overflow:"hidden"},children:null!=e.key_alias?(0,a.jsx)(es.Z,{children:e.key_alias}):(0,a.jsx)(es.Z,{children:"Not Set"})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:e.key_name})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:(()=>{try{return parseFloat(e.spend).toFixed(4)}catch(l){return e.spend}})()})}),(0,a.jsx)(ew.Z,{children:null!=e.max_budget?(0,a.jsx)(es.Z,{children:e.max_budget}):(0,a.jsx)(es.Z,{children:"Unlimited"})}),(0,a.jsx)(ew.Z,{children:Array.isArray(e.models)?(0,a.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,a.jsx)(a.Fragment,{children:r&&r.models&&r.models.length>0?r.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Team Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l)):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:"all-proxy-models"})})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):"all-team-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Team Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,a.jsx)(ew.Z,{children:(0,a.jsxs)(es.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,a.jsx)("br",{})," RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{onClick:()=>{I(e),A(!0)},icon:ex.Z,size:"sm"}),(0,a.jsx)(ei.Z,{open:S,onCancel:()=>{A(!1),I(null)},footer:null,width:800,children:E&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsxs)("div",{className:"grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-3 mt-8",children:[(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Spend"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:(()=>{try{return parseFloat(E.spend).toFixed(4)}catch(e){return E.spend}})()})})]}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Budget"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor font-semibold text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.max_budget?(0,a.jsx)(a.Fragment,{children:E.max_budget}):(0,a.jsx)(a.Fragment,{children:"Unlimited"})})})]},e.name),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)("p",{className:"text-tremor-default font-medium text-tremor-content dark:text-dark-tremor-content",children:"Expires"}),(0,a.jsx)("div",{className:"mt-2 flex items-baseline space-x-2.5",children:(0,a.jsx)("p",{className:"text-tremor-default font-small text-tremor-content-strong dark:text-dark-tremor-content-strong",children:null!=E.expires?(0,a.jsx)(a.Fragment,{children:new Date(E.expires).toLocaleString(void 0,{day:"numeric",month:"long",year:"numeric",hour:"numeric",minute:"numeric",second:"numeric"})}):(0,a.jsx)(a.Fragment,{children:"Never"})})})]},e.name)]}),(0,a.jsxs)(ef.Z,{className:"my-4",children:[(0,a.jsx)(er.Z,{children:"Token Name"}),(0,a.jsx)(es.Z,{className:"my-1",children:E.key_alias?E.key_alias:E.key_name}),(0,a.jsx)(er.Z,{children:"Token ID"}),(0,a.jsx)(es.Z,{className:"my-1 text-[12px]",children:E.token}),(0,a.jsx)(er.Z,{children:"Metadata"}),(0,a.jsx)(es.Z,{className:"my-1",children:(0,a.jsxs)("pre",{children:[JSON.stringify(E.metadata)," "]})})]}),(0,a.jsx)(X.Z,{className:"mx-auto flex items-center",onClick:()=>{A(!1),I(null)},children:"Close"})]})}),(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>R(e)}),(0,a.jsx)(ey.Z,{onClick:()=>U(e),icon:ej.Z,size:"sm"})]})]},e.token)})})]}),h&&(0,a.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,a.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,a.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,a.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,a.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,a.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,a.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,a.jsx)("div",{className:"sm:flex sm:items-start",children:(0,a.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,a.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Key"}),(0,a.jsx)("div",{className:"mt-2",children:(0,a.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this key ?"})})]})})}),(0,a.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,a.jsx)(X.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,a.jsx)(X.Z,{onClick:()=>{x(!1),j(null)},children:"Cancel"})]})]})]})})]}),E&&(0,a.jsx)(e=>{let{visible:l,onCancel:t,token:s,onSubmit:o}=e,[i]=eo.Z.useForm(),[d,m]=(0,n.useState)(r),[u,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1);return(0,a.jsx)(ei.Z,{title:"Edit Key",visible:l,width:800,footer:null,onOk:()=>{i.validateFields().then(e=>{i.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:i,onFinish:M,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Key Name",name:"key_alias",rules:[{required:!0,message:"Please input a key name"}],help:"required",children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",rules:[{validator:(e,l)=>{let t=l.filter(e=>!d.models.includes(e)&&"all-team-models"!==e&&"all-proxy-models"!==e&&!d.models.includes("all-proxy-models"));return(console.log("errorModels: ".concat(t)),t.length>0)?Promise.reject("Some models are not part of the new team's models - ".concat(t,"Team models: ").concat(d.models)):Promise.resolve()}}],children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(eA,{value:"all-team-models",children:"All Team Models"},"all-team-models"),d&&d.models?d.models.includes("all-proxy-models")?C.filter(e=>"all-proxy-models"!==e).map(e=>(0,a.jsx)(eA,{value:e,children:e},e)):d.models.map(e=>(0,a.jsx)(eA,{value:e,children:e},e)):C.map(e=>(0,a.jsx)(eA,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"Max Budget (USD)",name:"max_budget",help:"Budget cannot exceed team max budget: ".concat((null==d?void 0:d.max_budget)!==null&&(null==d?void 0:d.max_budget)!==void 0?null==d?void 0:d.max_budget:"unlimited"),rules:[{validator:async(e,l)=>{if(l&&d&&null!==d.max_budget&&l>d.max_budget)throw console.log("keyTeam.max_budget: ".concat(d.max_budget)),Error("Budget cannot exceed team max budget: $".concat(d.max_budget))}}],children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"token",name:"token",hidden:!0}),(0,a.jsx)(eo.Z.Item,{label:"Team",name:"team_id",help:"the team this key belongs to",children:(0,a.jsx)(eS.Z,{value:s.team_alias,children:null==c?void 0:c.map((e,l)=>(0,a.jsx)(eN.Z,{value:e.team_id,onClick:()=>m(e),children:e.team_alias},l))})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Edit Key"})})]})})},{visible:k,onCancel:()=>{v(!1),I(null)},token:E,onSubmit:M})]})},eI=t(76032),eC=t(35152),eP=e=>{let{userID:l,userRole:t,accessToken:s,userSpend:r,selectedTeam:o}=e;console.log("userSpend: ".concat(r));let[i,c]=(0,n.useState)(null!==r?r:0),[d,m]=(0,n.useState)(0),[u,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{let e=async()=>{if(s&&l&&t&&"Admin"===t&&null==r)try{let e=await w(s);e&&(e.spend?c(e.spend):c(0),e.max_budget?m(e.max_budget):m(0))}catch(e){console.error("Error fetching global spend data:",e)}};(async()=>{try{if(null===l||null===t)return;if(null!==s){let e=(await N(s,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),h(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[t,s,l]),(0,n.useEffect)(()=>{null!==r&&c(r)},[r]);let x=[];o&&o.models&&(x=o.models),x&&x.includes("all-proxy-models")?(console.log("user models:",u),x=u):x&&x.includes("all-team-models")?x=o.models:x&&0===x.length&&(x=u);let p=void 0!==i?i.toFixed(4):null;return console.log("spend in view user spend: ".concat(i)),(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsxs)("div",{children:[(0,a.jsxs)("p",{className:"text-tremor-default text-tremor-content dark:text-dark-tremor-content",children:["Total Spend"," "]}),(0,a.jsxs)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:["$",p]})]}),(0,a.jsx)("div",{className:"ml-auto",children:(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)(es.Z,{children:"Team Models"})}),(0,a.jsx)(el.Z,{className:"absolute right-0 z-10 bg-white p-2 shadow-lg max-w-xs",children:(0,a.jsx)(eI.Z,{children:x.map(e=>(0,a.jsx)(eC.Z,{children:(0,a.jsx)(es.Z,{children:e})},e))})})]})})]})},eT=e=>{let{userID:l,userRole:t,selectedTeam:s,accessToken:r}=e,[o,i]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{if(null===l||null===t)return;if(null!==r){let e=(await N(r,l,t)).data.map(e=>e.id);console.log("available_model_names:",e),i(e)}}catch(e){console.error("Error fetching user models:",e)}})()},[r,l,t]);let c=[];return s&&s.models&&(c=s.models),c&&c.includes("all-proxy-models")&&(console.log("user models:",o),c=o),(0,a.jsx)(a.Fragment,{children:(0,a.jsx)("div",{className:"mb-5",children:(0,a.jsx)("p",{className:"text-3xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:null==s?void 0:s.team_alias})})})},eO=e=>{let l,{teams:t,setSelectedTeam:s,userRole:r}=e,o={models:[],team_id:null,team_alias:"Default Team"},[i,c]=(0,n.useState)(o);return(l="App User"===r?t:t?[...t,o]:[o],"App User"===r)?null:(0,a.jsxs)("div",{className:"mt-5 mb-5",children:[(0,a.jsx)(er.Z,{children:"Select Team"}),(0,a.jsx)(es.Z,{children:"If you belong to multiple teams, this setting controls which team is used by default when creating new API Keys."}),(0,a.jsxs)(es.Z,{className:"mt-3 mb-3",children:[(0,a.jsx)("b",{children:"Default Team:"})," If no team_id is set for a key, it will be grouped under here."]}),l&&l.length>0?(0,a.jsx)(eS.Z,{defaultValue:"0",children:l.map((e,l)=>(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>s(e),children:e.team_alias},l))}):(0,a.jsxs)(es.Z,{children:["No team created. ",(0,a.jsx)("b",{children:"Defaulting to personal account."})]})]})},eF=t(37963),eR=t(36083);console.log("isLocal:",!1);var eM=e=>{let{userID:l,userRole:t,teams:s,keys:r,setUserRole:i,userEmail:c,setUserEmail:d,setTeams:m,setKeys:u}=e,[h,x]=(0,n.useState)(null),p=(0,o.useSearchParams)();p.get("viewSpend"),(0,o.useRouter)();let j=p.get("token"),[g,f]=(0,n.useState)(null),[y,_]=(0,n.useState)(null),[b,k]=(0,n.useState)([]),v={models:[],team_alias:"Default Team",team_id:null},[S,A]=(0,n.useState)(s?s[0]:v);if(window.addEventListener("beforeunload",function(){sessionStorage.clear()}),(0,n.useEffect)(()=>{if(j){let e=(0,eF.o)(j);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),f(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),i(l)}else console.log("User role not defined");e.user_email?d(e.user_email):console.log("User Email is not set ".concat(e))}}if(l&&g&&t&&!r&&!h){let e=sessionStorage.getItem("userModels"+l);e?k(JSON.parse(e)):(async()=>{try{let e=await Z(g,l,t,!1,null,null);if(console.log("received teams in user dashboard: ".concat(Object.keys(e),"; team values: ").concat(Object.entries(e.teams))),"Admin"==t){let e=await w(g);x(e),console.log("globalSpend:",e)}else x(e.user_info);u(e.keys),m(e.teams);let s=[...e.teams];s.length>0?(console.log("response['teams']: ".concat(s)),A(s[0])):A(v),sessionStorage.setItem("userData"+l,JSON.stringify(e.keys)),sessionStorage.setItem("userSpendData"+l,JSON.stringify(e.user_info));let r=(await N(g,l,t)).data.map(e=>e.id);console.log("available_model_names:",r),k(r),console.log("userModels:",b),sessionStorage.setItem("userModels"+l,JSON.stringify(r))}catch(e){console.error("There was an error fetching the data",e)}})()}},[l,j,g,r,t]),(0,n.useEffect)(()=>{if(null!==r&&null!=S){let e=0;for(let l of r)S.hasOwnProperty("team_id")&&null!==l.team_id&&l.team_id===S.team_id&&(e+=l.spend);_(e)}else if(null!==r){let e=0;for(let l of r)e+=l.spend;_(e)}},[S]),null==l||null==j){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}if(null==g)return null;if(null==t&&i("App Owner"),t&&"Admin Viewer"==t){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to create keys"})]})}return console.log("inside user dashboard, selected team",S),console.log("teamSpend: ".concat(y)),(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsx)($.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(eT,{userID:l,userRole:t,selectedTeam:S||null,accessToken:g}),(0,a.jsx)(eP,{userID:l,userRole:t,accessToken:g,userSpend:y,selectedTeam:S||null}),(0,a.jsx)(eE,{userID:l,userRole:t,accessToken:g,selectedTeam:S||null,data:r,setData:u,teams:s}),(0,a.jsx)(eh,{userID:l,team:S||null,userRole:t,accessToken:g,data:r,setData:u},S?S.team_id:null),(0,a.jsx)(eO,{teams:s,setSelectedTeam:A,userRole:t})]})})})},eL=t(35087),eU=t(92836),eD=t(26734),eK=t(41608),eB=t(32126),ez=t(23682),eV=t(47047),eq=t(76628),eG=t(57750),eY=t(44041),eW=t(38302),eJ=t(28683),eH=t(1460),e$=t(78578),eX=t(63954),eQ=t(90252),e0=t(7905),e1=e=>{let{modelID:l,accessToken:t}=e,[s,r]=(0,n.useState)(!1),o=async()=>{try{u.ZP.info("Making API Call"),r(!0);let e=await p(t,l);console.log("model delete Response:",e),u.ZP.success("Model ".concat(l," deleted successfully")),r(!1)}catch(e){console.error("Error deleting the model:",e)}};return(0,a.jsxs)("div",{children:[(0,a.jsx)(ey.Z,{onClick:()=>r(!0),icon:ej.Z,size:"sm"}),(0,a.jsx)(ei.Z,{open:s,onOk:o,okType:"danger",onCancel:()=>r(!1),children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 w-full",children:[(0,a.jsx)(er.Z,{children:"Delete Model"}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsx)("p",{children:"Are you sure you want to delete this model? This action is irreversible."})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("p",{children:["Model ID: ",(0,a.jsx)("b",{children:l})]})})]})})]})},e2=t(97766),e4=t(46495);let{Title:e8,Link:e5}=eR.default;(s=r||(r={})).OpenAI="OpenAI",s.Azure="Azure",s.Anthropic="Anthropic",s.Google_AI_Studio="Gemini (Google AI Studio)",s.Bedrock="Amazon Bedrock",s.OpenAI_Compatible="OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)",s.Vertex_AI="Vertex AI (Anthropic, Gemini, etc.)";let e3={OpenAI:"openai",Azure:"azure",Anthropic:"anthropic",Google_AI_Studio:"gemini",Bedrock:"bedrock",OpenAI_Compatible:"openai",Vertex_AI:"vertex_ai"},e6={"BadRequestError (400)":"BadRequestErrorRetries","AuthenticationError (401)":"AuthenticationErrorRetries","TimeoutError (408)":"TimeoutErrorRetries","RateLimitError (429)":"RateLimitErrorRetries","ContentPolicyViolationError (400)":"ContentPolicyViolationErrorRetries","InternalServerError (500)":"InternalServerErrorRetries"},e7=async(e,l,t)=>{try{let s=Array.isArray(e.model)?e.model:[e.model];console.log("received deployments: ".concat(s)),console.log("received type of deployments: ".concat(typeof s)),s.forEach(async t=>{console.log("litellm_model: ".concat(t));let s={},r={};s.model=t;let a="";for(let[l,t]of Object.entries(e))if(""!==t){if("model_name"==l)a+=t;else if("custom_llm_provider"==l)continue;else if("model"==l)continue;else if("base_model"===l)r[l]=t;else if("litellm_extra_params"==l){console.log("litellm_extra_params:",t);let e={};if(t&&void 0!=t){try{e=JSON.parse(t)}catch(e){throw u.ZP.error("Failed to parse LiteLLM Extra Params: "+e,10),Error("Failed to parse litellm_extra_params: "+e)}for(let[l,t]of Object.entries(e))s[l]=t}}else s[l]=t}let n={model_name:a,litellm_params:s,model_info:r},o=await x(l,n);console.log("response for model create call: ".concat(o.data))}),t.resetFields()}catch(e){u.ZP.error("Failed to create model: "+e,10)}};var e9=e=>{var l,t,s;let{accessToken:o,token:i,userRole:c,userID:d,modelData:m={data:[]},setModelData:x}=e,[p,j]=(0,n.useState)([]),[g]=eo.Z.useForm(),[f,y]=(0,n.useState)(null),[Z,_]=(0,n.useState)(""),[w,N]=(0,n.useState)([]),A=Object.values(r).filter(e=>isNaN(Number(e))),[E,I]=(0,n.useState)("OpenAI"),[C,P]=(0,n.useState)(""),[T,O]=(0,n.useState)(!1),[F,R]=(0,n.useState)(null),[M,L]=(0,n.useState)([]),[U,K]=(0,n.useState)(null),[B,z]=(0,n.useState)([]),[q,G]=(0,n.useState)([]),[Y,H]=(0,n.useState)([]),[ea,en]=(0,n.useState)([]),[ec,eu]=(0,n.useState)([]),[eh,ex]=(0,n.useState)([]),[ej,eA]=(0,n.useState)([]),[eE,eI]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),[eC,eP]=(0,n.useState)(null),[eT,eO]=(0,n.useState)(0),eF=e=>{R(e),O(!0)},eM=async e=>{if(console.log("handleEditSubmit:",e),null==o)return;let l={},t=null;for(let[s,r]of Object.entries(e))"model_id"!==s?l[s]=r:t=r;let s={litellm_params:l,model_info:{id:t}};console.log("handleEditSubmit payload:",s);try{await D(o,s),u.ZP.success("Model updated successfully, restart server to see updates"),O(!1),R(null)}catch(e){console.log("Error occurred")}},e9=()=>{_(new Date().toLocaleString())},le=async()=>{if(!o){console.error("Access token is missing");return}console.log("new modelGroupRetryPolicy:",eC);try{await W(o,{router_settings:{model_group_retry_policy:eC}}),u.ZP.success("Retry settings saved successfully")}catch(e){console.error("Failed to save retry settings:",e),u.ZP.error("Failed to save retry settings")}};if((0,n.useEffect)(()=>{if(!o||!i||!c||!d)return;let e=async()=>{try{var e,l,t,s,r,a;let n=await b(o,d,c);console.log("Model data response:",n.data),x(n);let i=new Set;for(let e=0;e0&&(u=m[m.length-1],console.log("_initial_model_group:",u),K(u)),console.log("selectedModelGroup:",U);let h=await k(o,d,c,u,null===(e=eE.from)||void 0===e?void 0:e.toISOString(),null===(l=eE.to)||void 0===l?void 0:l.toISOString());console.log("Model metrics response:",h),G(h.data),H(h.all_api_bases);let p=await S(o,d,c,u,null===(t=eE.from)||void 0===t?void 0:t.toISOString(),null===(s=eE.to)||void 0===s?void 0:s.toISOString());console.log("Model exceptions response:",p),en(p.data),eu(p.exception_types);let j=await v(o,d,c,u,null===(r=eE.from)||void 0===r?void 0:r.toISOString(),null===(a=eE.to)||void 0===a?void 0:a.toISOString());console.log("slowResponses:",j),eA(j);let g=(await V(o,d,c)).router_settings;console.log("routerSettingsInfo:",g);let f=g.model_group_retry_policy,y=g.num_retries;console.log("model_group_retry_policy:",f),console.log("default_retries:",y),eP(f),eO(y)}catch(e){console.error("There was an error fetching the model data",e)}};o&&i&&c&&d&&e();let l=async()=>{let e=await h();console.log("received model cost map data: ".concat(Object.keys(e))),y(e)};null==f&&l(),e9()},[o,i,c,d,f,Z]),!m||!o||!i||!c||!d)return(0,a.jsx)("div",{children:"Loading..."});let ll=[];for(let e=0;e(console.log("GET PROVIDER CALLED! - ".concat(f)),null!=f&&"object"==typeof f&&e in f)?f[e].litellm_provider:"openai";if(r){let e=r.split("/"),l=e[0];n=1===e.length?u(r):l}else n="openai";a&&(o=null==a?void 0:a.input_cost_per_token,i=null==a?void 0:a.output_cost_per_token,c=null==a?void 0:a.max_tokens),(null==s?void 0:s.litellm_params)&&(d=Object.fromEntries(Object.entries(null==s?void 0:s.litellm_params).filter(e=>{let[l]=e;return"model"!==l&&"api_base"!==l}))),m.data[e].provider=n,m.data[e].input_cost=o,m.data[e].output_cost=i,m.data[e].max_tokens=c,m.data[e].api_base=null==s?void 0:null===(t=s.litellm_params)||void 0===t?void 0:t.api_base,m.data[e].cleanedLitellmParams=d,ll.push(s.model_name),console.log(m.data[e])}if(c&&"Admin Viewer"==c){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to view all models"})]})}let lt=e=>{console.log("received provider string: ".concat(e));let l=Object.keys(r).find(l=>r[l]===e);if(l){let e=e3[l];console.log("mappingResult: ".concat(e));let t=[];"object"==typeof f&&Object.entries(f).forEach(l=>{let[s,r]=l;null!==r&&"object"==typeof r&&"litellm_provider"in r&&(r.litellm_provider===e||r.litellm_provider.includes(e))&&t.push(s)}),N(t),console.log("providerModels: ".concat(w))}},ls=async()=>{try{u.ZP.info("Running health check..."),P("");let e=await J(o);P(e)}catch(e){console.error("Error running health check:",e),P("Error running health check")}},lr=async(e,l,t)=>{if(console.log("Updating model metrics for group:",e),o&&d&&c&&l&&t){console.log("inside updateModelMetrics - startTime:",l,"endTime:",t),K(e);try{let s=await k(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model metrics response:",s),G(s.data),H(s.all_api_bases);let r=await S(o,d,c,e,l.toISOString(),t.toISOString());console.log("Model exceptions response:",r),en(r.data),eu(r.exception_types);let a=await v(o,d,c,e,l.toISOString(),t.toISOString());console.log("slowResponses:",a),eA(a)}catch(e){console.error("Failed to fetch model metrics",e)}}};return console.log("selectedProvider: ".concat(E)),console.log("providerModels.length: ".concat(w.length)),(0,a.jsx)("div",{style:{width:"100%",height:"100%"},children:(0,a.jsxs)(eD.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(eK.Z,{className:"flex justify-between mt-2 w-full items-center",children:[(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)(eU.Z,{children:"All Models"}),(0,a.jsx)(eU.Z,{children:"Add Model"}),(0,a.jsx)(eU.Z,{children:(0,a.jsx)("pre",{children:"/health Models"})}),(0,a.jsx)(eU.Z,{children:"Model Analytics"}),(0,a.jsx)(eU.Z,{children:"Model Retry Settings"})]}),(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[Z&&(0,a.jsxs)(es.Z,{children:["Last Refreshed: ",Z]}),(0,a.jsx)(ey.Z,{icon:eX.Z,variant:"shadow",size:"xs",className:"self-center",onClick:e9})]})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)($.Z,{children:[(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)(es.Z,{children:"Filter by Public Model Name"}),(0,a.jsxs)(eS.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:"all",onValueChange:e=>K("all"===e?"all":e),children:[(0,a.jsx)(eN.Z,{value:"all",children:"All Models"}),M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>K(e),children:e},l))]})]}),(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{className:"mt-5",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Public Model Name "}),(0,a.jsx)(ek.Z,{children:"Provider"}),"Admin"===c&&(0,a.jsx)(ek.Z,{children:"API Base"}),(0,a.jsx)(ek.Z,{children:"Extra litellm Params"}),(0,a.jsx)(ek.Z,{children:"Input Price per token ($)"}),(0,a.jsx)(ek.Z,{children:"Output Price per token ($)"}),(0,a.jsx)(ek.Z,{children:"Max Tokens"}),(0,a.jsx)(ek.Z,{children:"Status"})]})}),(0,a.jsx)(e_.Z,{children:m.data.filter(e=>"all"===U||e.model_name===U||null==U||""===U).map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:e.model_name})}),(0,a.jsx)(ew.Z,{children:e.provider}),"Admin"===c&&(0,a.jsx)(ew.Z,{children:e.api_base}),(0,a.jsx)(ew.Z,{children:(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{children:(0,a.jsx)(es.Z,{children:"Litellm params"})}),(0,a.jsx)(el.Z,{children:(0,a.jsx)("pre",{children:JSON.stringify(e.cleanedLitellmParams,null,2)})})]})}),(0,a.jsx)(ew.Z,{children:e.input_cost||e.litellm_params.input_cost_per_token||null}),(0,a.jsx)(ew.Z,{children:e.output_cost||e.litellm_params.output_cost_per_token||null}),(0,a.jsx)(ew.Z,{children:e.max_tokens}),(0,a.jsx)(ew.Z,{children:e.model_info.db_model?(0,a.jsx)(eg.Z,{icon:eQ.Z,className:"text-white",children:"DB Model"}):(0,a.jsx)(eg.Z,{icon:e0.Z,className:"text-black",children:"Config Model"})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>eF(e)}),(0,a.jsx)(e1,{modelID:e.model_info.id,accessToken:o})]})]},l))})]})})]}),(0,a.jsx)(e=>{let{visible:l,onCancel:t,model:s,onSubmit:r}=e,[n]=eo.Z.useForm(),o={},i="",c="";if(s){o=s.litellm_params,i=s.model_name;let e=s.model_info;e&&(c=e.id,console.log("model_id: ".concat(c)),o.model_id=c)}return(0,a.jsx)(ei.Z,{title:"Edit Model "+i,visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{r(e),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:n,onFinish:eM,initialValues:o,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{className:"mt-8",label:"api_base",name:"api_base",children:(0,a.jsx)(Q.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"tpm",name:"tpm",tooltip:"int (optional) - Tokens limit for this deployment: in tokens per minute (tpm). Find this information on your model/providers website",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"rpm",name:"rpm",tooltip:"int (optional) - Rate limit for this deployment: in requests per minute (rpm). Find this information on your model/providers website",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"max_retries",name:"max_retries",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"timeout",name:"timeout",tooltip:"int (optional) - Timeout in seconds for LLM requests (Defaults to 600 seconds)",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"stream_timeout",name:"stream_timeout",tooltip:"int (optional) - Timeout for stream requests (seconds)",children:(0,a.jsx)(ed.Z,{min:0,step:1})}),(0,a.jsx)(eo.Z.Item,{label:"input_cost_per_token",name:"input_cost_per_token",tooltip:"float (optional) - Input cost per token",children:(0,a.jsx)(ed.Z,{min:0,step:1e-4})}),(0,a.jsx)(eo.Z.Item,{label:"output_cost_per_token",name:"output_cost_per_token",tooltip:"float (optional) - Output cost per token",children:(0,a.jsx)(ed.Z,{min:0,step:1e-4})}),(0,a.jsx)(eo.Z.Item,{label:"model_id",name:"model_id",hidden:!0})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})})},{visible:T,onCancel:()=>{O(!1),R(null)},model:F,onSubmit:eM})]}),(0,a.jsxs)(eB.Z,{className:"h-full",children:[(0,a.jsx)(e8,{level:2,children:"Add new model"}),(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eo.Z,{form:g,onFinish:()=>{g.validateFields().then(e=>{e7(e,o,g)}).catch(e=>{console.error("Validation failed:",e)})},labelCol:{span:10},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Provider:",name:"custom_llm_provider",tooltip:"E.g. OpenAI, Azure OpenAI, Anthropic, Bedrock, etc.",labelCol:{span:10},labelAlign:"left",children:(0,a.jsx)(eS.Z,{value:E.toString(),children:A.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>{lt(e),I(e)},children:e},l))})}),(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Public Model Name",name:"model_name",tooltip:"Model name your users will pass in. Also used for load-balancing, LiteLLM will load balance between all models with this public name.",className:"mb-0",children:(0,a.jsx)(Q.Z,{placeholder:"Vertex AI (Anthropic, Gemini, etc.)"===(s=E.toString())?"gemini-pro":"Anthropic"==s?"claude-3-opus":"Amazon Bedrock"==s?"claude-3-opus":"Gemini (Google AI Studio)"==s?"gemini-pro":"gpt-3.5-turbo"})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsx)(es.Z,{className:"mb-3 mt-1",children:"Model name your users will pass in."})})]}),(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"LiteLLM Model Name(s)",name:"model",tooltip:"Actual model name used for making litellm.completion() call.",className:"mb-0",children:"Azure"===E?(0,a.jsx)(Q.Z,{placeholder:"Enter model name"}):w.length>0?(0,a.jsx)(eV.Z,{value:w,children:w.map((e,l)=>(0,a.jsx)(eq.Z,{value:e,children:e},l))}):(0,a.jsx)(Q.Z,{placeholder:"gpt-3.5-turbo-0125"})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsxs)(es.Z,{className:"mb-3 mt-1",children:["Actual model name used for making ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/providers",target:"_blank",children:"litellm.completion() call"}),". We'll ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/proxy/reliability#step-1---set-deployments-on-config",target:"_blank",children:"loadbalance"})," models with the same 'public name'"]})})]}),"Amazon Bedrock"!=E&&"Vertex AI (Anthropic, Gemini, etc.)"!=E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Key",name:"api_key",children:(0,a.jsx)(Q.Z,{placeholder:"sk-",type:"password"})}),"OpenAI"==E&&(0,a.jsx)(eo.Z.Item,{label:"Organization ID",name:"organization_id",children:(0,a.jsx)(Q.Z,{placeholder:"[OPTIONAL] my-unique-org"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Project",name:"vertex_project",children:(0,a.jsx)(Q.Z,{placeholder:"adroit-cadet-1234.."})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Location",name:"vertex_location",children:(0,a.jsx)(Q.Z,{placeholder:"us-east-1"})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"Vertex Credentials",name:"vertex_credentials",className:"mb-0",children:(0,a.jsx)(e4.Z,{name:"file",accept:".json",beforeUpload:e=>{if("application/json"===e.type){let l=new FileReader;l.onload=e=>{if(e.target){let l=e.target.result;g.setFieldsValue({vertex_credentials:l})}},l.readAsText(e)}return!1},onChange(e){"uploading"!==e.file.status&&console.log(e.file,e.fileList),"done"===e.file.status?u.ZP.success("".concat(e.file.name," file uploaded successfully")):"error"===e.file.status&&u.ZP.error("".concat(e.file.name," file upload failed."))},children:(0,a.jsx)(em.ZP,{icon:(0,a.jsx)(e2.Z,{}),children:"Click to Upload"})})}),"Vertex AI (Anthropic, Gemini, etc.)"==E&&(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsx)(es.Z,{className:"mb-3 mt-1",children:"Give litellm a gcp service account(.json file), so it can make the relevant calls"})})]}),("Azure"==E||"OpenAI-Compatible Endpoints (Groq, Together AI, Mistral AI, etc.)"==E)&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Base",name:"api_base",children:(0,a.jsx)(Q.Z,{placeholder:"https://..."})}),"Azure"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"API Version",name:"api_version",children:(0,a.jsx)(Q.Z,{placeholder:"2023-07-01-preview"})}),"Azure"==E&&(0,a.jsxs)(eo.Z.Item,{label:"Base Model",name:"base_model",children:[(0,a.jsx)(Q.Z,{placeholder:"azure/gpt-3.5-turbo"}),(0,a.jsxs)(es.Z,{children:["The actual model your azure deployment uses. Used for accurate cost tracking. Select name from ",(0,a.jsx)(e5,{href:"https://github.com/BerriAI/litellm/blob/main/model_prices_and_context_window.json",target:"_blank",children:"here"})]})]}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Access Key ID",name:"aws_access_key_id",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Secret Access Key",name:"aws_secret_access_key",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:""})}),"Amazon Bedrock"==E&&(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"AWS Region Name",name:"aws_region_name",tooltip:"You can provide the raw key or the environment variable (e.g. `os.environ/MY_SECRET_KEY`).",children:(0,a.jsx)(Q.Z,{placeholder:"us-east-1"})}),(0,a.jsx)(eo.Z.Item,{label:"LiteLLM Params",name:"litellm_extra_params",tooltip:"Optional litellm params used for making a litellm.completion() call.",className:"mb-0",children:(0,a.jsx)(e$.Z,{rows:4,placeholder:'{ "rpm": 100, "timeout": 0, "stream_timeout": 0 }'})}),(0,a.jsxs)(eW.Z,{children:[(0,a.jsx)(eJ.Z,{span:10}),(0,a.jsx)(eJ.Z,{span:10,children:(0,a.jsxs)(es.Z,{className:"mb-3 mt-1",children:["Pass JSON of litellm supported params ",(0,a.jsx)(e5,{href:"https://docs.litellm.ai/docs/completion/input",target:"_blank",children:"litellm.completion() call"})]})})]})]}),(0,a.jsx)("div",{style:{textAlign:"center",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add Model"})}),(0,a.jsx)(eH.Z,{title:"Get help on our github",children:(0,a.jsx)(eR.default.Link,{href:"https://github.com/BerriAI/litellm/issues",children:"Need Help?"})})]})})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(es.Z,{children:"`/health` will run a very small request through your models configured on litellm"}),(0,a.jsx)(X.Z,{onClick:ls,children:"Run `/health`"}),C&&(0,a.jsx)("pre",{children:JSON.stringify(C,null,2)})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)($.Z,{numItems:2,className:"mt-2",children:[(0,a.jsxs)(eJ.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Time Range"}),(0,a.jsx)(eL.Z,{enableSelect:!0,value:eE,onValueChange:e=>{eI(e),lr(U,e.from,e.to)}})]}),(0,a.jsxs)(eJ.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Model Group"}),(0,a.jsx)(eS.Z,{className:"mb-4 mt-2",defaultValue:U||M[0],value:U||M[0],children:M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>lr(e,eE.from,eE.to),children:e},l))})]})]}),(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsx)(eJ.Z,{children:(0,a.jsxs)(ef.Z,{className:"mr-2 max-h-[400px] min-h-[400px]",children:[(0,a.jsx)(er.Z,{children:"Avg Latency per Token"}),(0,a.jsx)("p",{className:"text-gray-500 italic",children:" (seconds/token)"}),(0,a.jsx)(es.Z,{className:"text-gray-500 italic mt-1 mb-1",children:"average Latency for successfull requests divided by the total tokens"}),q&&Y&&(0,a.jsx)(eG.Z,{title:"Model Latency",className:"h-72",data:q,showLegend:!1,index:"date",categories:Y,connectNulls:!0,customTooltip:e=>{var l,t;let{payload:s,active:r}=e;if(!r||!s)return null;let n=null===(t=s[0])||void 0===t?void 0:null===(l=t.payload)||void 0===l?void 0:l.date,o=s.sort((e,l)=>l.value-e.value);if(o.length>5){let e=o.length-5;(o=o.slice(0,5)).push({dataKey:"".concat(e," other deployments"),value:s.slice(5).reduce((e,l)=>e+l.value,0),color:"gray"})}return(0,a.jsxs)("div",{className:"w-150 rounded-tremor-default border border-tremor-border bg-tremor-background p-2 text-tremor-default shadow-tremor-dropdown",children:[n&&(0,a.jsxs)("p",{className:"text-tremor-content-emphasis mb-2",children:["Date: ",n]}),o.map((e,l)=>{let t=parseFloat(e.value.toFixed(5)),s=0===t&&e.value>0?"<0.00001":t.toFixed(5);return(0,a.jsxs)("div",{className:"flex justify-between",children:[(0,a.jsxs)("div",{className:"flex items-center space-x-2",children:[(0,a.jsx)("div",{className:"w-2 h-2 mt-1 rounded-full bg-".concat(e.color,"-500")}),(0,a.jsx)("p",{className:"text-tremor-content",children:e.dataKey})]}),(0,a.jsx)("p",{className:"font-medium text-tremor-content-emphasis text-righ ml-2",children:s})]},l)})]})}})]})}),(0,a.jsx)(eJ.Z,{children:(0,a.jsx)(ef.Z,{className:"ml-2 max-h-[400px] min-h-[400px] overflow-y-auto",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Deployment"}),(0,a.jsx)(ek.Z,{children:"Success Responses"}),(0,a.jsxs)(ek.Z,{children:["Slow Responses ",(0,a.jsx)("p",{children:"Success Responses taking 600+s"})]})]})}),(0,a.jsx)(e_.Z,{children:ej.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.api_base}),(0,a.jsx)(ew.Z,{children:e.total_count}),(0,a.jsx)(ew.Z,{children:e.slow_count})]},l))})]})})})]}),(0,a.jsxs)(ef.Z,{className:"mt-4",children:[(0,a.jsx)(er.Z,{children:"Exceptions per Model"}),(0,a.jsx)(eY.Z,{className:"h-72",data:ea,index:"model",categories:ec,stack:!0,colors:["indigo-300","rose-200","#ffcc33"],yAxisWidth:30})]})]}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)(es.Z,{children:"Filter by Public Model Name"}),(0,a.jsx)(eS.Z,{className:"mb-4 mt-2 ml-2 w-50",defaultValue:U||M[0],value:U||M[0],onValueChange:e=>K(e),children:M.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>K(e),children:e},l))})]}),(0,a.jsxs)(er.Z,{children:["Retry Policy for ",U]}),(0,a.jsx)(es.Z,{className:"mb-6",children:"How many retries should be attempted based on the Exception"}),e6&&(0,a.jsx)("table",{children:(0,a.jsx)("tbody",{children:Object.entries(e6).map((e,l)=>{var t;let[s,r]=e,n=null==eC?void 0:null===(t=eC[U])||void 0===t?void 0:t[r];return null==n&&(n=eT),(0,a.jsxs)("tr",{className:"flex justify-between items-center mt-2",children:[(0,a.jsx)("td",{children:(0,a.jsx)(es.Z,{children:s})}),(0,a.jsx)("td",{children:(0,a.jsx)(ed.Z,{className:"ml-5",value:n,min:0,step:1,onChange:e=>{eP(l=>{var t;let s=null!==(t=null==l?void 0:l[U])&&void 0!==t?t:{};return{...null!=l?l:{},[U]:{...s,[r]:e}}})}})})]},l)})})}),(0,a.jsx)(X.Z,{className:"mt-6 mr-8",onClick:le,children:"Save"})]})]})]})})};let{Option:le}=en.default;var ll=e=>{let{userID:l,accessToken:t,teams:s}=e,[r]=eo.Z.useForm(),[o,i]=(0,n.useState)(!1),[c,d]=(0,n.useState)(null),[m,h]=(0,n.useState)([]);(0,n.useEffect)(()=>{(async()=>{try{let e=await N(t,l,"any"),s=[];for(let l=0;l{i(!1),r.resetFields()},p=()=>{i(!1),d(null),r.resetFields()},j=async e=>{try{u.ZP.info("Making API Call"),i(!0),console.log("formValues in create user:",e);let s=await g(t,null,e);console.log("user create Response:",s),d(s.key),u.ZP.success("API user Created"),r.resetFields(),localStorage.removeItem("userData"+l)}catch(e){console.error("Error creating the user:",e)}};return(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>i(!0),children:"+ Invite User"}),(0,a.jsxs)(ei.Z,{title:"Invite User",visible:o,width:800,footer:null,onOk:x,onCancel:p,children:[(0,a.jsx)(es.Z,{className:"mb-1",children:"Invite a user to login to the Admin UI and create Keys"}),(0,a.jsx)(es.Z,{className:"mb-6",children:(0,a.jsx)("b",{children:"Note: SSO Setup Required for this"})}),(0,a.jsxs)(eo.Z,{form:r,onFinish:j,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsx)(eo.Z.Item,{label:"User Email",name:"user_email",children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"team_id",children:(0,a.jsx)(en.default,{placeholder:"Select Team ID",style:{width:"100%"},children:s?s.map(e=>(0,a.jsx)(le,{value:e.team_id,children:e.team_alias},e.team_id)):(0,a.jsx)(le,{value:null,children:"Default Team"},"default")})}),(0,a.jsx)(eo.Z.Item,{label:"Metadata",name:"metadata",children:(0,a.jsx)(ec.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create User"})})]})]}),c&&(0,a.jsxs)(ei.Z,{title:"User Created Successfully",visible:o,onOk:x,onCancel:p,footer:null,children:[(0,a.jsx)("p",{children:"User has been created to access your proxy. Please Ask them to Log In."}),(0,a.jsx)("br",{}),(0,a.jsx)("p",{children:(0,a.jsx)("b",{children:"Note: This Feature is only supported through SSO on the Admin UI"})})]})]})},lt=e=>{let{accessToken:l,token:t,keys:s,userRole:r,userID:o,teams:i,setKeys:c}=e,[d,m]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(0),[j,g]=n.useState(null),[f,y]=(0,n.useState)(null);return((0,n.useEffect)(()=>{if(!l||!t||!r||!o)return;let e=async()=>{try{let e=await Z(l,null,r,!0,x,25);console.log("user data response:",e),m(e)}catch(e){console.error("There was an error fetching the model data",e)}};l&&t&&r&&o&&e()},[l,t,r,o,x]),d&&l&&t&&r&&o)?(0,a.jsx)("div",{style:{width:"100%"},children:(0,a.jsxs)($.Z,{className:"gap-2 p-2 h-[80vh] w-full mt-8",children:[(0,a.jsx)(ll,{userID:o,accessToken:l,teams:i}),(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[80vh] mb-4",children:[(0,a.jsx)("div",{className:"mb-4 mt-1",children:(0,a.jsx)(es.Z,{children:"These are Users on LiteLLM that created API Keys. Automatically tracked by LiteLLM"})}),(0,a.jsx)(eD.Z,{children:(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(eZ.Z,{className:"mt-5",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"User ID"}),(0,a.jsx)(ek.Z,{children:"User Email"}),(0,a.jsx)(ek.Z,{children:"User Models"}),(0,a.jsx)(ek.Z,{children:"User Spend ($ USD)"}),(0,a.jsx)(ek.Z,{children:"User Max Budget ($ USD)"}),(0,a.jsx)(ek.Z,{children:"User API Key Aliases"})]})}),(0,a.jsx)(e_.Z,{children:d.map(e=>{var l;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_id}),(0,a.jsx)(ew.Z,{children:e.user_email}),(0,a.jsx)(ew.Z,{children:e.models&&e.models.length>0?e.models:"All Models"}),(0,a.jsx)(ew.Z,{children:e.spend?null===(l=e.spend)||void 0===l?void 0:l.toFixed(2):0}),(0,a.jsx)(ew.Z,{children:e.max_budget?e.max_budget:"Unlimited"}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)($.Z,{numItems:2,children:e&&e.key_aliases&&e.key_aliases.filter(e=>null!==e).length>0?(0,a.jsx)(eg.Z,{size:"xs",color:"indigo",children:e.key_aliases.filter(e=>null!==e).join(", ")}):(0,a.jsx)(eg.Z,{size:"xs",color:"gray",children:"No Keys"})})})]},e.user_id)})})]})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)("div",{className:"flex items-center",children:[(0,a.jsx)("div",{className:"flex-1"}),(0,a.jsx)("div",{className:"flex-1 flex justify-between items-center"})]})})]})})]}),function(){if(!d)return null;let e=Math.ceil(d.length/25);return(0,a.jsxs)("div",{className:"flex justify-between items-center",children:[(0,a.jsxs)("div",{children:["Showing Page ",x+1," of ",e]}),(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-l focus:outline-none",disabled:0===x,onClick:()=>p(x-1),children:"← Prev"}),(0,a.jsx)("button",{className:"bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded-r focus:outline-none",onClick:()=>{p(x+1)},children:"Next →"})]})]})}()]})}):(0,a.jsx)("div",{children:"Loading..."})},ls=e=>{let{teams:l,searchParams:t,accessToken:s,setTeams:r,userID:o,userRole:i}=e,[c]=eo.Z.useForm(),[d]=eo.Z.useForm(),{Title:m,Paragraph:h}=eR.default,[x,p]=(0,n.useState)(""),[j,g]=(0,n.useState)(!1),[f,Z]=(0,n.useState)(l?l[0]:null),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1),[S,A]=(0,n.useState)([]),[E,I]=(0,n.useState)(!1),[C,P]=(0,n.useState)(null),[T,O]=(0,n.useState)({}),F=e=>{Z(e),g(!0)},R=async e=>{let t=e.team_id;if(console.log("handleEditSubmit:",e),null==s)return;let a=await U(s,e);l&&r(l.map(e=>e.team_id===t?a.data:e)),u.ZP.success("Team updated successfully"),g(!1),Z(null)},L=async e=>{P(e),I(!0)},D=async()=>{if(null!=C&&null!=l&&null!=s){try{await y(s,C);let e=l.filter(e=>e.team_id!==C);r(e)}catch(e){console.error("Error deleting the team:",e)}I(!1),P(null)}};(0,n.useEffect)(()=>{let e=async()=>{try{if(null===o||null===i||null===s||null===l)return;console.log("fetching team info:");let e={};for(let t=0;t<(null==l?void 0:l.length);t++){let r=l[t].team_id,a=await _(s,r);console.log("teamInfo response:",a),null!==a&&(e={...e,[r]:a})}O(e)}catch(e){console.error("Error fetching team info:",e)}};(async()=>{try{if(null===o||null===i)return;if(null!==s){let e=(await N(s,o,i)).data.map(e=>e.id);console.log("available_model_names:",e),A(e)}}catch(e){console.error("Error fetching user models:",e)}})(),e()},[s,o,i,l]);let B=async e=>{try{if(null!=s){var t;let a=null==e?void 0:e.team_alias;if((null!==(t=null==l?void 0:l.map(e=>e.team_alias))&&void 0!==t?t:[]).includes(a))throw Error("Team alias ".concat(a," already exists, please pick another alias"));u.ZP.info("Creating Team");let n=await M(s,e);null!==l?r([...l,n]):r([n]),console.log("response for team create call: ".concat(n)),u.ZP.success("Team created"),b(!1)}}catch(e){console.error("Error creating the team:",e),u.ZP.error("Error creating the team: "+e,20)}},z=async e=>{try{if(null!=s&&null!=l){u.ZP.info("Adding Member");let t={role:"user",user_email:e.user_email,user_id:e.user_id},a=await K(s,f.team_id,t);console.log("response for team create call: ".concat(a.data));let n=l.findIndex(e=>(console.log("team.team_id=".concat(e.team_id,"; response.data.team_id=").concat(a.data.team_id)),e.team_id===a.data.team_id));if(console.log("foundIndex: ".concat(n)),-1!==n){let e=[...l];e[n]=a.data,r(e),Z(a.data)}v(!1)}}catch(e){console.error("Error creating the team:",e)}};return console.log("received teams ".concat(JSON.stringify(l))),(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(m,{level:4,children:"All Teams"}),(0,a.jsxs)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Team Name"}),(0,a.jsx)(ek.Z,{children:"Spend (USD)"}),(0,a.jsx)(ek.Z,{children:"Budget (USD)"}),(0,a.jsx)(ek.Z,{children:"Models"}),(0,a.jsx)(ek.Z,{children:"TPM / RPM Limits"}),(0,a.jsx)(ek.Z,{children:"Info"})]})}),(0,a.jsx)(e_.Z,{children:l&&l.length>0?l.map(e=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.team_alias}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.spend}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:e.max_budget?e.max_budget:"No limit"}),(0,a.jsx)(ew.Z,{style:{maxWidth:"8-x",whiteSpace:"pre-wrap",overflow:"hidden"},children:Array.isArray(e.models)?(0,a.jsx)("div",{style:{display:"flex",flexDirection:"column"},children:0===e.models.length?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})}):e.models.map((e,l)=>"all-proxy-models"===e?(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"red",children:(0,a.jsx)(es.Z,{children:"All Proxy Models"})},l):(0,a.jsx)(eg.Z,{size:"xs",className:"mb-1",color:"blue",children:(0,a.jsx)(es.Z,{children:e.length>30?"".concat(e.slice(0,30),"..."):e})},l))}):null}),(0,a.jsx)(ew.Z,{style:{maxWidth:"4px",whiteSpace:"pre-wrap",overflow:"hidden"},children:(0,a.jsxs)(es.Z,{children:["TPM: ",e.tpm_limit?e.tpm_limit:"Unlimited"," ",(0,a.jsx)("br",{}),"RPM:"," ",e.rpm_limit?e.rpm_limit:"Unlimited"]})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsxs)(es.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].keys&&T[e.team_id].keys.length," ","Keys"]}),(0,a.jsxs)(es.Z,{children:[T&&e.team_id&&T[e.team_id]&&T[e.team_id].team_info&&T[e.team_id].team_info.members_with_roles&&T[e.team_id].team_info.members_with_roles.length," ","Members"]})]}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>F(e)}),(0,a.jsx)(ey.Z,{onClick:()=>L(e.team_id),icon:ej.Z,size:"sm"})]})]},e.team_id)):null})]}),E&&(0,a.jsx)("div",{className:"fixed z-10 inset-0 overflow-y-auto",children:(0,a.jsxs)("div",{className:"flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0",children:[(0,a.jsx)("div",{className:"fixed inset-0 transition-opacity","aria-hidden":"true",children:(0,a.jsx)("div",{className:"absolute inset-0 bg-gray-500 opacity-75"})}),(0,a.jsx)("span",{className:"hidden sm:inline-block sm:align-middle sm:h-screen","aria-hidden":"true",children:"​"}),(0,a.jsxs)("div",{className:"inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full",children:[(0,a.jsx)("div",{className:"bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4",children:(0,a.jsx)("div",{className:"sm:flex sm:items-start",children:(0,a.jsxs)("div",{className:"mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left",children:[(0,a.jsx)("h3",{className:"text-lg leading-6 font-medium text-gray-900",children:"Delete Team"}),(0,a.jsx)("div",{className:"mt-2",children:(0,a.jsx)("p",{className:"text-sm text-gray-500",children:"Are you sure you want to delete this team ?"})})]})})}),(0,a.jsxs)("div",{className:"bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse",children:[(0,a.jsx)(X.Z,{onClick:D,color:"red",className:"ml-2",children:"Delete"}),(0,a.jsx)(X.Z,{onClick:()=>{I(!1),P(null)},children:"Cancel"})]})]})]})})]})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>b(!0),children:"+ Create New Team"}),(0,a.jsx)(ei.Z,{title:"Create Team",visible:w,width:800,footer:null,onOk:()=>{b(!1),c.resetFields()},onCancel:()=>{b(!1),c.resetFields()},children:(0,a.jsxs)(eo.Z,{form:c,onFinish:B,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,a.jsx)(Q.Z,{placeholder:""})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(en.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S.map(e=>(0,a.jsx)(en.default.Option,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Create Team"})})]})})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(m,{level:4,children:"Team Members"}),(0,a.jsx)(h,{children:"If you belong to multiple teams, this setting controls which teams members you see."}),l&&l.length>0?(0,a.jsx)(eS.Z,{defaultValue:"0",children:l.map((e,l)=>(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>{Z(e)},children:e.team_alias},l))}):(0,a.jsxs)(h,{children:["No team created. ",(0,a.jsx)("b",{children:"Defaulting to personal account."})]})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Member Name"}),(0,a.jsx)(ek.Z,{children:"Role"})]})}),(0,a.jsx)(e_.Z,{children:f?f.members_with_roles.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,a.jsx)(ew.Z,{children:e.role})]},l)):null})]})}),f&&(0,a.jsx)(e=>{let{visible:l,onCancel:t,team:s,onSubmit:r}=e,[n]=eo.Z.useForm();return(0,a.jsx)(ei.Z,{title:"Edit Team",visible:l,width:800,footer:null,onOk:()=>{n.validateFields().then(e=>{r({...e,team_id:s.team_id}),n.resetFields()}).catch(e=>{console.error("Validation failed:",e)})},onCancel:t,children:(0,a.jsxs)(eo.Z,{form:n,onFinish:R,initialValues:s,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Team Name",name:"team_alias",rules:[{required:!0,message:"Please input a team name"}],children:(0,a.jsx)(Q.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"Models",name:"models",children:(0,a.jsxs)(en.default,{mode:"multiple",placeholder:"Select models",style:{width:"100%"},children:[(0,a.jsx)(en.default.Option,{value:"all-proxy-models",children:"All Proxy Models"},"all-proxy-models"),S&&S.map(e=>(0,a.jsx)(en.default.Option,{value:e,children:e},e))]})}),(0,a.jsx)(eo.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,a.jsx)(ed.Z,{step:.01,precision:2,width:200})}),(0,a.jsx)(eo.Z.Item,{label:"Tokens per minute Limit (TPM)",name:"tpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"rpm_limit",children:(0,a.jsx)(ed.Z,{step:1,width:400})}),(0,a.jsx)(eo.Z.Item,{label:"Requests per minute Limit (RPM)",name:"team_id",hidden:!0})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Edit Team"})})]})})},{visible:j,onCancel:()=>{g(!1),Z(null)},team:f,onSubmit:R})]}),(0,a.jsxs)(H.Z,{numColSpan:1,children:[(0,a.jsx)(X.Z,{className:"mx-auto mb-5",onClick:()=>v(!0),children:"+ Add member"}),(0,a.jsx)(ei.Z,{title:"Add member",visible:k,width:800,footer:null,onOk:()=>{v(!1),d.resetFields()},onCancel:()=>{v(!1),d.resetFields()},children:(0,a.jsxs)(eo.Z,{form:c,onFinish:z,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,a.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,a.jsx)(eo.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add member"})})]})})]})]})})},lr=t(18190),la=e=>{let l,{searchParams:t,accessToken:s,showSSOBanner:r}=e,[o]=eo.Z.useForm(),[i]=eo.Z.useForm(),{Title:c,Paragraph:d}=eR.default,[m,h]=(0,n.useState)(""),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)(!1),[f,y]=(0,n.useState)(!1),[Z,_]=(0,n.useState)(!1),[w,b]=(0,n.useState)(!1),[k,v]=(0,n.useState)(!1);try{l=window.location.origin}catch(e){l=""}l+="/fallback/login";let S=()=>{v(!1)},N=["proxy_admin","proxy_admin_viewer"];(0,n.useEffect)(()=>{(async()=>{if(null!=s){let e=[],l=await R(s,"proxy_admin_viewer");l.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy viewers: ".concat(l));let t=await R(s,"proxy_admin");t.forEach(l=>{e.push({user_role:l.user_role,user_id:l.user_id,user_email:l.user_email})}),console.log("proxy admins: ".concat(t)),console.log("combinedList: ".concat(e)),p(e)}})()},[s]);let A=()=>{_(!1),i.resetFields()},E=()=>{_(!1),i.resetFields()},I=e=>(0,a.jsxs)(eo.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Email",name:"user_email",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_email",className:"px-3 py-2 border rounded-md w-full"})}),(0,a.jsx)("div",{className:"text-center mb-4",children:"OR"}),(0,a.jsx)(eo.Z.Item,{label:"User ID",name:"user_id",className:"mb-4",children:(0,a.jsx)(ec.Z,{name:"user_id",className:"px-3 py-2 border rounded-md w-full"})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add member"})})]}),C=(e,l,t)=>(0,a.jsxs)(eo.Z,{form:o,onFinish:e,labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{rules:[{required:!0,message:"Required"}],label:"User Role",name:"user_role",labelCol:{span:10},labelAlign:"left",children:(0,a.jsx)(eS.Z,{value:l,children:N.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,children:e},l))})}),(0,a.jsx)(eo.Z.Item,{label:"Team ID",name:"user_id",hidden:!0,initialValue:t,valuePropName:"user_id",className:"mt-8",children:(0,a.jsx)(ec.Z,{value:t,disabled:!0})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Update role"})})]}),P=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,null);console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),u.ZP.success("Refresh tab to see updated user role"),_(!1)}}catch(e){console.error("Error creating the key:",e)}},T=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call");let l=await B(s,e,"proxy_admin_viewer");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),g(!1)}}catch(e){console.error("Error creating the key:",e)}},O=async e=>{try{if(null!=s&&null!=x){u.ZP.info("Making API Call"),e.user_email,e.user_id;let l=await B(s,e,"proxy_admin");console.log("response for team create call: ".concat(l));let t=x.findIndex(e=>(console.log("user.user_id=".concat(e.user_id,"; response.user_id=").concat(l.user_id)),e.user_id===l.user_id));console.log("foundIndex: ".concat(t)),-1==t&&(console.log("updates admin with new user"),x.push(l),p(x)),y(!1)}}catch(e){console.error("Error creating the key:",e)}},F=async e=>{null!=s&&W(s,{environment_variables:{PROXY_BASE_URL:e.proxy_base_url,GOOGLE_CLIENT_ID:e.google_client_id,GOOGLE_CLIENT_SECRET:e.google_client_secret}})};return console.log("admins: ".concat(null==x?void 0:x.length)),(0,a.jsxs)("div",{className:"w-full m-2 mt-2 p-8",children:[(0,a.jsx)(c,{level:4,children:"Admin Access "}),(0,a.jsxs)(d,{children:[r&&(0,a.jsx)("a",{href:"https://docs.litellm.ai/docs/proxy/ui#restrict-ui-access",children:"Requires SSO Setup"}),(0,a.jsx)("br",{}),(0,a.jsx)("b",{children:"Proxy Admin: "})," Can create keys, teams, users, add models, etc. ",(0,a.jsx)("br",{}),(0,a.jsx)("b",{children:"Proxy Admin Viewer: "}),"Can just view spend. They cannot create keys, teams or grant users access to new models."," "]}),(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-2 w-full",children:[(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsx)(ef.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh]",children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Member Name"}),(0,a.jsx)(ek.Z,{children:"Role"})]})}),(0,a.jsx)(e_.Z,{children:x?x.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.user_email?e.user_email:e.user_id?e.user_id:null}),(0,a.jsx)(ew.Z,{children:e.user_role}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(ey.Z,{icon:ep.Z,size:"sm",onClick:()=>_(!0)}),(0,a.jsx)(ei.Z,{title:"Update role",visible:Z,width:800,footer:null,onOk:A,onCancel:E,children:C(P,e.user_role,e.user_id)})]})]},l)):null})]})})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)("div",{className:"flex justify-start",children:[(0,a.jsx)(X.Z,{className:"mr-4 mb-5",onClick:()=>y(!0),children:"+ Add admin"}),(0,a.jsx)(ei.Z,{title:"Add admin",visible:f,width:800,footer:null,onOk:()=>{y(!1),i.resetFields()},onCancel:()=>{y(!1),i.resetFields()},children:I(O)}),(0,a.jsx)(X.Z,{className:"mb-5",onClick:()=>g(!0),children:"+ Add viewer"}),(0,a.jsx)(ei.Z,{title:"Add viewer",visible:j,width:800,footer:null,onOk:()=>{g(!1),i.resetFields()},onCancel:()=>{g(!1),i.resetFields()},children:I(T)})]})})]}),(0,a.jsxs)($.Z,{children:[(0,a.jsx)(c,{level:4,children:"Add SSO"}),(0,a.jsxs)("div",{className:"flex justify-start mb-4",children:[(0,a.jsx)(X.Z,{onClick:()=>b(!0),children:"Add SSO"}),(0,a.jsx)(ei.Z,{title:"Add SSO",visible:w,width:800,footer:null,onOk:()=>{b(!1),o.resetFields()},onCancel:()=>{b(!1),o.resetFields()},children:(0,a.jsxs)(eo.Z,{form:o,onFinish:e=>{O(e),F(e),b(!1),v(!0)},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Admin Email",name:"user_email",rules:[{required:!0,message:"Please enter the email of the proxy admin"}],children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"PROXY BASE URL",name:"proxy_base_url",rules:[{required:!0,message:"Please enter the proxy base url"}],children:(0,a.jsx)(ec.Z,{})}),(0,a.jsx)(eo.Z.Item,{label:"GOOGLE CLIENT ID",name:"google_client_id",rules:[{required:!0,message:"Please enter the google client id"}],children:(0,a.jsx)(ec.Z.Password,{})}),(0,a.jsx)(eo.Z.Item,{label:"GOOGLE CLIENT SECRET",name:"google_client_secret",rules:[{required:!0,message:"Please enter the google client secret"}],children:(0,a.jsx)(ec.Z.Password,{})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})}),(0,a.jsxs)(ei.Z,{title:"SSO Setup Instructions",visible:k,width:800,footer:null,onOk:S,onCancel:()=>{v(!1)},children:[(0,a.jsx)("p",{children:"Follow these steps to complete the SSO setup:"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"1. DO NOT Exit this TAB"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"2. Open a new tab, visit your proxy base url"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"3. Confirm your SSO is configured correctly and you can login on the new Tab"}),(0,a.jsx)(es.Z,{className:"mt-2",children:"4. If Step 3 is successful, you can close this tab"}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{onClick:S,children:"Done"})})]})]}),(0,a.jsxs)(lr.Z,{title:"Login without SSO",color:"teal",children:["If you need to login without sso, you can access ",(0,a.jsxs)("a",{href:l,target:"_blank",children:[(0,a.jsx)("b",{children:l})," "]})]})]})]})},ln=t(42556);let lo=[{name:"slack",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"langfuse",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}},{name:"openmeter",variables:{LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null,SLACK_WEBHOOK_URL:null}}];var li=e=>{let{accessToken:l,userRole:t,userID:s}=e,[r,o]=(0,n.useState)(lo),[i,c]=(0,n.useState)([]),[d,m]=(0,n.useState)(!1),[h]=eo.Z.useForm(),[x,p]=(0,n.useState)(null),[j,g]=(0,n.useState)([]),[f,y]=(0,n.useState)(""),[Z,_]=(0,n.useState)({}),[w,b]=(0,n.useState)([]),k=e=>{w.includes(e)?b(w.filter(l=>l!==e)):b([...w,e])},v={llm_exceptions:"LLM Exceptions",llm_too_slow:"LLM Responses Too Slow",llm_requests_hanging:"LLM Requests Hanging",budget_alerts:"Budget Alerts (API Keys, Users)",db_exceptions:"Database Exceptions (Read/Write)",daily_reports:"Weekly/Monthly Spend Reports"};(0,n.useEffect)(()=>{l&&t&&s&&V(l,s,t).then(e=>{console.log("callbacks",e);let l=lo;o(l=l.map(l=>{let t=e.callbacks.find(e=>e.name===l.name);return t?{...l,variables:{...l.variables,...t.variables}}:l}));let t=e.alerts;if(console.log("alerts_data",t),t&&t.length>0){let e=t[0];console.log("_alert_info",e);let l=e.variables.SLACK_WEBHOOK_URL;console.log("catch_all_webhook",l),b(e.active_alerts),y(l),_(e.alerts_to_webhook)}c(t)})},[l,t,s]);let S=e=>w&&w.includes(e),N=e=>{if(!l)return;let t=Object.fromEntries(Object.entries(e.variables).map(e=>{var l;let[t,s]=e;return[t,(null===(l=document.querySelector('input[name="'.concat(t,'"]')))||void 0===l?void 0:l.value)||s]}));console.log("updatedVariables",t),console.log("updateAlertTypes",j);let s={environment_variables:t,litellm_settings:{success_callback:[e.name]}};try{W(l,s)}catch(e){u.ZP.error("Failed to update callback: "+e,20)}u.ZP.success("Callback updated successfully")},A=()=>{l&&h.validateFields().then(e=>{if(console.log("Form values:",e),"langfuse"===e.callback){W(l,{environment_variables:{LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:e.langfusePublicKey,LANGFUSE_SECRET_KEY:e.langfusePrivateKey,OPENMETER_API_KEY:null}};o(r?[...r,t]:[t])}else if("slack"===e.callback){console.log("values.slackWebhookUrl: ".concat(e.slackWebhookUrl)),W(l,{general_settings:{alerting:["slack"],alerting_threshold:300},environment_variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl}}),console.log("values.callback: ".concat(e.callback));let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:e.slackWebhookUrl,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:null}};o(r?[...r,t]:[t])}else if("openmeter"==e.callback){console.log("values.openMeterApiKey: ".concat(e.openMeterApiKey)),W(l,{environment_variables:{OPENMETER_API_KEY:e.openMeterApiKey},litellm_settings:{success_callback:[e.callback]}});let t={name:e.callback,variables:{SLACK_WEBHOOK_URL:null,LANGFUSE_HOST:null,LANGFUSE_PUBLIC_KEY:null,LANGFUSE_SECRET_KEY:null,OPENMETER_API_KEY:e.openMeterAPIKey}};o(r?[...r,t]:[t])}m(!1),h.resetFields(),p(null)})};return l?(console.log("callbacks: ".concat(r)),(0,a.jsxs)("div",{className:"w-full mx-4",children:[(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,a.jsx)(lr.Z,{title:"[UI] Presidio PII + Guardrails Coming Soon. https://docs.litellm.ai/docs/proxy/pii_masking",color:"sky"}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{variant:"line",defaultValue:"1",children:[(0,a.jsx)(eU.Z,{value:"1",children:"Logging Callbacks"}),(0,a.jsx)(eU.Z,{value:"2",children:"Alerting"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Callback"}),(0,a.jsx)(ek.Z,{children:"Callback Env Vars"})]})}),(0,a.jsx)(e_.Z,{children:r.filter(e=>"slack"!==e.name).map((e,t)=>{var s;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(eg.Z,{color:"emerald",children:e.name})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)("ul",{children:Object.entries(null!==(s=e.variables)&&void 0!==s?s:{}).filter(l=>{let[t,s]=l;return t.toLowerCase().includes(e.name)}).map(e=>{let[l,t]=e;return(0,a.jsxs)("li",{children:[(0,a.jsx)(es.Z,{className:"mt-2",children:l}),"LANGFUSE_HOST"===l?(0,a.jsx)("p",{children:"default value=https://cloud.langfuse.com"}):(0,a.jsx)("div",{}),(0,a.jsx)(Q.Z,{name:l,defaultValue:t,type:"password"})]},l)})}),(0,a.jsx)(X.Z,{className:"mt-2",onClick:()=>N(e),children:"Save Changes"}),(0,a.jsx)(X.Z,{onClick:()=>z(l,e.name),className:"mx-2",children:"Test Callback"})]})]},t)})})]})})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsxs)(es.Z,{className:"my-2",children:["Alerts are only supported for Slack Webhook URLs. Get your webhook urls from ",(0,a.jsx)("a",{href:"https://api.slack.com/messaging/webhooks",target:"_blank",style:{color:"blue"},children:"here"})]}),(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{}),(0,a.jsx)(ek.Z,{}),(0,a.jsx)(ek.Z,{children:"Slack Webhook URL"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(v).map((e,l)=>{let[t,s]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:(0,a.jsx)(ln.Z,{id:"switch",name:"switch",checked:S(t),onChange:()=>k(t)})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(es.Z,{children:s})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(Q.Z,{name:t,type:"password",defaultValue:Z&&Z[t]?Z[t]:f})})]},l)})})]}),(0,a.jsx)(X.Z,{size:"xs",className:"mt-2",onClick:()=>{if(!l)return;let e={};Object.entries(v).forEach(l=>{let[t,s]=l,r=document.querySelector('input[name="'.concat(t,'"]'));console.log("key",t),console.log("webhookInput",r);let a=(null==r?void 0:r.value)||"";console.log("newWebhookValue",a),e[t]=a}),console.log("updatedAlertToWebhooks",e);let t={general_settings:{alert_to_webhook_url:e,alert_types:w}};console.log("payload",t);try{W(l,t)}catch(e){u.ZP.error("Failed to update alerts: "+e,20)}u.ZP.success("Alerts updated successfully")},children:"Save Changes"}),(0,a.jsx)(X.Z,{onClick:()=>z(l,"slack"),className:"mx-2",children:"Test Alerts"})]})})]})]})]}),(0,a.jsx)(ei.Z,{title:"Add Callback",visible:d,onOk:A,width:800,onCancel:()=>{m(!1),h.resetFields(),p(null)},footer:null,children:(0,a.jsxs)(eo.Z,{form:h,layout:"vertical",onFinish:A,children:[(0,a.jsx)(eo.Z.Item,{label:"Callback",name:"callback",rules:[{required:!0,message:"Please select a callback"}],children:(0,a.jsxs)(en.default,{onChange:e=>{p(e)},children:[(0,a.jsx)(en.default.Option,{value:"langfuse",children:"langfuse"}),(0,a.jsx)(en.default.Option,{value:"openmeter",children:"openmeter"})]})}),"langfuse"===x&&(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"LANGFUSE_PUBLIC_KEY",name:"langfusePublicKey",rules:[{required:!0,message:"Please enter the public key"}],children:(0,a.jsx)(Q.Z,{type:"password"})}),(0,a.jsx)(eo.Z.Item,{label:"LANGFUSE_PRIVATE_KEY",name:"langfusePrivateKey",rules:[{required:!0,message:"Please enter the private key"}],children:(0,a.jsx)(Q.Z,{type:"password"})})]}),"openmeter"==x&&(0,a.jsx)(a.Fragment,{children:(0,a.jsx)(eo.Z.Item,{label:"OPENMETER_API_KEY",name:"openMeterApiKey",rules:[{required:!0,message:"Please enter the openmeter api key"}],children:(0,a.jsx)(Q.Z,{type:"password"})})}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Save"})})]})})]})):null};let{Option:lc}=en.default;var ld=e=>{let{models:l,accessToken:t,routerSettings:s,setRouterSettings:r}=e,[o]=eo.Z.useForm(),[i,c]=(0,n.useState)(!1),[d,m]=(0,n.useState)("");return(0,a.jsxs)("div",{children:[(0,a.jsx)(X.Z,{className:"mx-auto",onClick:()=>c(!0),children:"+ Add Fallbacks"}),(0,a.jsx)(ei.Z,{title:"Add Fallbacks",visible:i,width:800,footer:null,onOk:()=>{c(!1),o.resetFields()},onCancel:()=>{c(!1),o.resetFields()},children:(0,a.jsxs)(eo.Z,{form:o,onFinish:e=>{console.log(e);let{model_name:l,models:a}=e,n=[...s.fallbacks||[],{[l]:a}],i={...s,fallbacks:n};console.log(i);try{W(t,{router_settings:i}),r(i)}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully"),c(!1),o.resetFields()},labelCol:{span:8},wrapperCol:{span:16},labelAlign:"left",children:[(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(eo.Z.Item,{label:"Public Model Name",name:"model_name",rules:[{required:!0,message:"Set the model to fallback for"}],help:"required",children:(0,a.jsx)(eS.Z,{defaultValue:d,children:l&&l.map((e,l)=>(0,a.jsx)(eN.Z,{value:e,onClick:()=>m(e),children:e},l))})}),(0,a.jsx)(eo.Z.Item,{label:"Fallback Models",name:"models",rules:[{required:!0,message:"Please select a model"}],help:"required",children:(0,a.jsx)(eV.Z,{value:l,children:l&&l.filter(e=>e!=d).map(e=>(0,a.jsx)(eq.Z,{value:e,children:e},e))})})]}),(0,a.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,a.jsx)(em.ZP,{htmlType:"submit",children:"Add Fallbacks"})})]})})]})},lm=t(12968);async function lu(e,l){console.log("isLocal:",!1);let t=window.location.origin,s=new lm.ZP.OpenAI({apiKey:l,baseURL:t,dangerouslyAllowBrowser:!0});try{let l=await s.chat.completions.create({model:e,messages:[{role:"user",content:"Hi, this is a test message"}],mock_testing_fallbacks:!0});u.ZP.success((0,a.jsxs)("span",{children:["Test model=",(0,a.jsx)("strong",{children:e}),", received model=",(0,a.jsx)("strong",{children:l.model}),". See"," ",(0,a.jsx)("a",{href:"#",onClick:()=>window.open("https://docs.litellm.ai/docs/proxy/reliability","_blank"),style:{textDecoration:"underline",color:"blue"},children:"curl"})]}))}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}let lh={ttl:3600,lowest_latency_buffer:0},lx=e=>{let{selectedStrategy:l,strategyArgs:t,paramExplanation:s}=e;return(0,a.jsxs)(ee.Z,{children:[(0,a.jsx)(et.Z,{className:"text-sm font-medium text-tremor-content-strong dark:text-dark-tremor-content-strong",children:"Routing Strategy Specific Args"}),(0,a.jsx)(el.Z,{children:"latency-based-routing"==l?(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(t).map(e=>{let[l,t]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:l}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:s[l]})]}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(Q.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]})}):(0,a.jsx)(es.Z,{children:"No specific settings"})})]})};var lp=e=>{let{accessToken:l,userRole:t,userID:s,modelData:r}=e,[o,i]=(0,n.useState)({}),[c,d]=(0,n.useState)({}),[m,h]=(0,n.useState)([]),[x,p]=(0,n.useState)(!1),[j]=eo.Z.useForm(),[g,f]=(0,n.useState)(null),[y,Z]=(0,n.useState)(null),[_,w]=(0,n.useState)(null),b={routing_strategy_args:"(dict) Arguments to pass to the routing strategy",routing_strategy:"(string) Routing strategy to use",allowed_fails:"(int) Number of times a deployment can fail before being added to cooldown",cooldown_time:"(int) time in seconds to cooldown a deployment after failure",num_retries:"(int) Number of retries for failed requests. Defaults to 0.",timeout:"(float) Timeout for requests. Defaults to None.",retry_after:"(int) Minimum time to wait before retrying a failed request",ttl:"(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).",lowest_latency_buffer:"(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)."};(0,n.useEffect)(()=>{l&&t&&s&&(V(l,s,t).then(e=>{console.log("callbacks",e),i(e.router_settings)}),q(l).then(e=>{h(e)}))},[l,t,s]);let k=async e=>{if(l){console.log("received key: ".concat(e)),console.log("routerSettings['fallbacks']: ".concat(o.fallbacks)),o.fallbacks.map(l=>(e in l&&delete l[e],l));try{await W(l,{router_settings:o}),i({...o}),Z(o.routing_strategy),u.ZP.success("Router settings updated successfully")}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}}},v=(e,l)=>{h(m.map(t=>t.field_name===e?{...t,field_value:l}:t))},S=(e,t)=>{if(!l)return;let s=m[t].field_value;if(null!=s&&void 0!=s)try{G(l,e,s);let t=m.map(l=>l.field_name===e?{...l,stored_in_db:!0}:l);h(t)}catch(e){}},N=(e,t)=>{if(l)try{Y(l,e);let t=m.map(l=>l.field_name===e?{...l,stored_in_db:null,field_value:null}:l);h(t)}catch(e){}},A=e=>{if(!l)return;console.log("router_settings",e);let t=Object.fromEntries(Object.entries(e).map(e=>{let[l,t]=e;if("routing_strategy_args"!==l&&"routing_strategy"!==l){var s;return[l,(null===(s=document.querySelector('input[name="'.concat(l,'"]')))||void 0===s?void 0:s.value)||t]}if("routing_strategy"==l)return[l,y];if("routing_strategy_args"==l&&"latency-based-routing"==y){let e={},l=document.querySelector('input[name="lowest_latency_buffer"]'),t=document.querySelector('input[name="ttl"]');return(null==l?void 0:l.value)&&(e.lowest_latency_buffer=Number(l.value)),(null==t?void 0:t.value)&&(e.ttl=Number(t.value)),console.log("setRoutingStrategyArgs: ".concat(e)),["routing_strategy_args",e]}return null}).filter(e=>null!=e));console.log("updatedVariables",t);try{W(l,{router_settings:t})}catch(e){u.ZP.error("Failed to update router settings: "+e,20)}u.ZP.success("router settings updated successfully")};return l?(0,a.jsx)("div",{className:"w-full mx-4",children:(0,a.jsxs)(eD.Z,{className:"gap-2 p-8 h-[75vh] w-full mt-2",children:[(0,a.jsxs)(eK.Z,{variant:"line",defaultValue:"1",children:[(0,a.jsx)(eU.Z,{value:"1",children:"Loadbalancing"}),(0,a.jsx)(eU.Z,{value:"2",children:"Fallbacks"}),(0,a.jsx)(eU.Z,{value:"3",children:"General"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:1,className:"gap-2 p-8 w-full mt-2",children:[(0,a.jsx)(er.Z,{children:"Router Settings"}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"})]})}),(0,a.jsx)(e_.Z,{children:Object.entries(o).filter(e=>{let[l,t]=e;return"fallbacks"!=l&&"context_window_fallbacks"!=l&&"routing_strategy_args"!=l}).map(e=>{let[l,t]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:l}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:b[l]})]}),(0,a.jsx)(ew.Z,{children:"routing_strategy"==l?(0,a.jsxs)(eS.Z,{defaultValue:t,className:"w-full max-w-md",onValueChange:Z,children:[(0,a.jsx)(eN.Z,{value:"usage-based-routing",children:"usage-based-routing"}),(0,a.jsx)(eN.Z,{value:"latency-based-routing",children:"latency-based-routing"}),(0,a.jsx)(eN.Z,{value:"simple-shuffle",children:"simple-shuffle"})]}):(0,a.jsx)(Q.Z,{name:l,defaultValue:"object"==typeof t?JSON.stringify(t,null,2):t.toString()})})]},l)})})]}),(0,a.jsx)(lx,{selectedStrategy:y,strategyArgs:o&&o.routing_strategy_args&&Object.keys(o.routing_strategy_args).length>0?o.routing_strategy_args:lh,paramExplanation:b})]}),(0,a.jsx)(H.Z,{children:(0,a.jsx)(X.Z,{className:"mt-2",onClick:()=>A(o),children:"Save Changes"})})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Model Name"}),(0,a.jsx)(ek.Z,{children:"Fallbacks"})]})}),(0,a.jsx)(e_.Z,{children:o.fallbacks&&o.fallbacks.map((e,t)=>Object.entries(e).map(e=>{let[s,r]=e;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:s}),(0,a.jsx)(ew.Z,{children:Array.isArray(r)?r.join(", "):r}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(X.Z,{onClick:()=>lu(s,l),children:"Test Fallback"})}),(0,a.jsx)(ew.Z,{children:(0,a.jsx)(ey.Z,{icon:ej.Z,size:"sm",onClick:()=>k(s)})})]},t.toString()+s)}))})]}),(0,a.jsx)(ld,{models:(null==r?void 0:r.data)?r.data.map(e=>e.model_name):[],accessToken:l,routerSettings:o,setRouterSettings:i})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eZ.Z,{children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"Setting"}),(0,a.jsx)(ek.Z,{children:"Value"}),(0,a.jsx)(ek.Z,{children:"Status"}),(0,a.jsx)(ek.Z,{children:"Action"})]})}),(0,a.jsx)(e_.Z,{children:m.map((e,l)=>(0,a.jsxs)(ev.Z,{children:[(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(es.Z,{children:e.field_name}),(0,a.jsx)("p",{style:{fontSize:"0.65rem",color:"#808080",fontStyle:"italic"},className:"mt-1",children:e.field_description})]}),(0,a.jsx)(ew.Z,{children:"Integer"==e.field_type?(0,a.jsx)(ed.Z,{step:1,value:e.field_value,onChange:l=>v(e.field_name,l)}):null}),(0,a.jsx)(ew.Z,{children:!0==e.stored_in_db?(0,a.jsx)(eg.Z,{icon:eQ.Z,className:"text-white",children:"In DB"}):!1==e.stored_in_db?(0,a.jsx)(eg.Z,{className:"text-gray bg-white outline",children:"In Config"}):(0,a.jsx)(eg.Z,{className:"text-gray bg-white outline",children:"Not Set"})}),(0,a.jsxs)(ew.Z,{children:[(0,a.jsx)(X.Z,{onClick:()=>S(e.field_name,l),children:"Update"}),(0,a.jsx)(ey.Z,{icon:ej.Z,color:"red",onClick:()=>N(e.field_name,l),children:"Reset"})]})]},l))})]})})})]})]})}):null},lj=t(67951),lg=e=>{let{}=e;return(0,a.jsx)(a.Fragment,{children:(0,a.jsx)($.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,a.jsxs)("div",{className:"mb-5",children:[(0,a.jsx)("p",{className:"text-2xl text-tremor-content-strong dark:text-dark-tremor-content-strong font-semibold",children:"OpenAI Compatible Proxy: API Reference"}),(0,a.jsx)(es.Z,{className:"mt-2 mb-2",children:"LiteLLM is OpenAI Compatible. This means your API Key works with the OpenAI SDK. Just replace the base_url to point to your litellm proxy. Example Below "}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{children:[(0,a.jsx)(eU.Z,{children:"OpenAI Python SDK"}),(0,a.jsx)(eU.Z,{children:"LlamaIndex"}),(0,a.jsx)(eU.Z,{children:"Langchain Py"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nimport openai\nclient = openai.OpenAI(\n api_key="your_api_key",\n base_url="http://0.0.0.0:4000" # LiteLLM Proxy is OpenAI compatible, Read More: https://docs.litellm.ai/docs/proxy/user_keys\n)\n\nresponse = client.chat.completions.create(\n model="gpt-3.5-turbo", # model to send to the proxy\n messages = [\n {\n "role": "user",\n "content": "this is a test request, write a short poem"\n }\n ]\n)\n\nprint(response)\n '})}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nimport os, dotenv\n\nfrom llama_index.llms import AzureOpenAI\nfrom llama_index.embeddings import AzureOpenAIEmbedding\nfrom llama_index import VectorStoreIndex, SimpleDirectoryReader, ServiceContext\n\nllm = AzureOpenAI(\n engine="azure-gpt-3.5", # model_name on litellm proxy\n temperature=0.0,\n azure_endpoint="http://0.0.0.0:4000", # litellm proxy endpoint\n api_key="sk-1234", # litellm proxy API Key\n api_version="2023-07-01-preview",\n)\n\nembed_model = AzureOpenAIEmbedding(\n deployment_name="azure-embedding-model",\n azure_endpoint="http://0.0.0.0:4000",\n api_key="sk-1234",\n api_version="2023-07-01-preview",\n)\n\n\ndocuments = SimpleDirectoryReader("llama_index_data").load_data()\nservice_context = ServiceContext.from_defaults(llm=llm, embed_model=embed_model)\nindex = VectorStoreIndex.from_documents(documents, service_context=service_context)\n\nquery_engine = index.as_query_engine()\nresponse = query_engine.query("What did the author do growing up?")\nprint(response)\n\n '})}),(0,a.jsx)(eB.Z,{children:(0,a.jsx)(lj.Z,{language:"python",children:'\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts.chat import (\n ChatPromptTemplate,\n HumanMessagePromptTemplate,\n SystemMessagePromptTemplate,\n)\nfrom langchain.schema import HumanMessage, SystemMessage\n\nchat = ChatOpenAI(\n openai_api_base="http://0.0.0.0:4000",\n model = "gpt-3.5-turbo",\n temperature=0.1\n)\n\nmessages = [\n SystemMessage(\n content="You are a helpful assistant that im using to make a test request to."\n ),\n HumanMessage(\n content="test from litellm. tell me why it\'s amazing in 1 sentence"\n ),\n]\nresponse = chat(messages)\n\nprint(response)\n\n '})})]})]})]})})})};async function lf(e,l,t,s){console.log("isLocal:",!1);let r=window.location.origin,a=new lm.ZP.OpenAI({apiKey:s,baseURL:r,dangerouslyAllowBrowser:!0});try{for await(let s of(await a.chat.completions.create({model:t,stream:!0,messages:[{role:"user",content:e}]})))console.log(s),s.choices[0].delta.content&&l(s.choices[0].delta.content)}catch(e){u.ZP.error("Error occurred while generating model response. Please try again. Error: ".concat(e),20)}}var ly=e=>{let{accessToken:l,token:t,userRole:s,userID:r}=e,[o,i]=(0,n.useState)(""),[c,d]=(0,n.useState)(""),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)(void 0),[p,j]=(0,n.useState)([]);(0,n.useEffect)(()=>{l&&t&&s&&r&&(async()=>{try{let e=await N(l,r,s);if(console.log("model_info:",e),(null==e?void 0:e.data.length)>0){let l=e.data.map(e=>({value:e.id,label:e.id}));console.log(l),j(l),x(e.data[0].id)}}catch(e){console.error("Error fetching model info:",e)}})()},[l,r,s]);let g=(e,l)=>{u(t=>{let s=t[t.length-1];return s&&s.role===e?[...t.slice(0,t.length-1),{role:e,content:s.content+l}]:[...t,{role:e,content:l}]})},f=async()=>{if(""!==c.trim()&&o&&t&&s&&r){u(e=>[...e,{role:"user",content:c}]);try{h&&await lf(c,e=>g("assistant",e),h,o)}catch(e){console.error("Error fetching model response",e),g("assistant","Error fetching model response")}d("")}};if(s&&"Admin Viewer"==s){let{Title:e,Paragraph:l}=eR.default;return(0,a.jsxs)("div",{children:[(0,a.jsx)(e,{level:1,children:"Access Denied"}),(0,a.jsx)(l,{children:"Ask your proxy admin for access to test models"})]})}return(0,a.jsx)("div",{style:{width:"100%",position:"relative"},children:(0,a.jsx)($.Z,{className:"gap-2 p-8 h-[80vh] w-full mt-2",children:(0,a.jsx)(ef.Z,{children:(0,a.jsxs)(eD.Z,{children:[(0,a.jsx)(eK.Z,{children:(0,a.jsx)(eU.Z,{children:"Chat"})}),(0,a.jsx)(ez.Z,{children:(0,a.jsxs)(eB.Z,{children:[(0,a.jsx)("div",{className:"sm:max-w-2xl",children:(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"API Key"}),(0,a.jsx)(Q.Z,{placeholder:"Type API Key here",type:"password",onValueChange:i,value:o})]}),(0,a.jsxs)(H.Z,{className:"mx-2",children:[(0,a.jsx)(es.Z,{children:"Select Model:"}),(0,a.jsx)(en.default,{placeholder:"Select a Model",onChange:e=>{console.log("selected ".concat(e)),x(e)},options:p,style:{width:"200px"}})]})]})}),(0,a.jsxs)(eZ.Z,{className:"mt-5",style:{display:"block",maxHeight:"60vh",overflowY:"auto"},children:[(0,a.jsx)(eb.Z,{children:(0,a.jsx)(ev.Z,{children:(0,a.jsx)(ew.Z,{})})}),(0,a.jsx)(e_.Z,{children:m.map((e,l)=>(0,a.jsx)(ev.Z,{children:(0,a.jsx)(ew.Z,{children:"".concat(e.role,": ").concat(e.content)})},l))})]}),(0,a.jsx)("div",{className:"mt-3",style:{position:"absolute",bottom:5,width:"95%"},children:(0,a.jsxs)("div",{className:"flex",children:[(0,a.jsx)(Q.Z,{type:"text",value:c,onChange:e=>d(e.target.value),placeholder:"Type your message..."}),(0,a.jsx)(X.Z,{onClick:f,className:"ml-2",children:"Send"})]})})]})})]})})})})},lZ=t(33509),l_=t(95781);let{Sider:lw}=lZ.default;var lb=e=>{let{setPage:l,userRole:t,defaultSelectedKey:s}=e;return"Admin Viewer"==t?(0,a.jsx)(lZ.default,{style:{minHeight:"100vh",maxWidth:"120px"},children:(0,a.jsx)(lw,{width:120,children:(0,a.jsxs)(l_.Z,{mode:"inline",defaultSelectedKeys:s||["4"],style:{height:"100%",borderRight:0},children:[(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api-keys"),children:"API Keys"},"4"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("models"),children:"Models"},"2"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("llm-playground"),children:"Chat UI"},"3"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("usage"),children:"Usage"},"1")]})})}):(0,a.jsx)(lZ.default,{style:{minHeight:"100vh",maxWidth:"145px"},children:(0,a.jsx)(lw,{width:145,children:(0,a.jsxs)(l_.Z,{mode:"inline",defaultSelectedKeys:s||["1"],style:{height:"100%",borderRight:0},children:[(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api-keys"),children:(0,a.jsx)(es.Z,{children:"API Keys"})},"1"),(0,a.jsx)(l_.Z.Item,{onClick:()=>l("llm-playground"),children:(0,a.jsx)(es.Z,{children:"Test Key"})},"3"),"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("models"),children:(0,a.jsx)(es.Z,{children:"Models"})},"2"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("usage"),children:(0,a.jsx)(es.Z,{children:"Usage"})},"4"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("teams"),children:(0,a.jsx)(es.Z,{children:"Teams"})},"6"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("users"),children:(0,a.jsx)(es.Z,{children:"Users"})},"5"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("settings"),children:(0,a.jsx)(es.Z,{children:"Logging & Alerts"})},"8"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("general-settings"),children:(0,a.jsx)(es.Z,{children:"Router Settings"})},"9"):null,"Admin"==t?(0,a.jsx)(l_.Z.Item,{onClick:()=>l("admin-panel"),children:(0,a.jsx)(es.Z,{children:"Admin"})},"7"):null,(0,a.jsx)(l_.Z.Item,{onClick:()=>l("api_ref"),children:(0,a.jsx)(es.Z,{children:"API Reference"})},"11")]})})})},lk=t(67989),lv=e=>{let{accessToken:l,token:t,userRole:s,userID:r,keys:o}=e,i=new Date,[c,d]=(0,n.useState)([]),[m,u]=(0,n.useState)([]),[h,x]=(0,n.useState)([]),[p,j]=(0,n.useState)([]),[g,f]=(0,n.useState)([]),[y,Z]=(0,n.useState)([]),[_,w]=(0,n.useState)([]),[b,k]=(0,n.useState)([]),[v,S]=(0,n.useState)(""),[N,R]=(0,n.useState)({from:new Date(Date.now()-6048e5),to:new Date}),M=new Date(i.getFullYear(),i.getMonth(),1),L=new Date(i.getFullYear(),i.getMonth()+1,0),U=z(M),D=z(L);console.log("keys in usage",o);let K=async(e,t,s)=>{if(!e||!t||!l)return;console.log("uiSelectedKey",s);let r=await T(l,s,e.toISOString(),t.toISOString());console.log("End user data updated successfully",r),j(r)},B=async(e,t)=>{e&&t&&l&&(Z((await E(l,e.toISOString(),t.toISOString())).spend_per_tag),console.log("Tag spend data updated successfully"))};function z(e){let l=e.getFullYear(),t=e.getMonth()+1,s=e.getDate();return"".concat(l,"-").concat(t<10?"0"+t:t,"-").concat(s<10?"0"+s:s)}return console.log("Start date is ".concat(U)),console.log("End date is ".concat(D)),(0,n.useEffect)(()=>{l&&t&&s&&r&&(async()=>{try{if(console.log("user role: ".concat(s)),"Admin"==s||"Admin Viewer"==s){var e,a;let t=await C(l);d(t);let s=(await P(l)).map(e=>({key:(e.key_name||e.key_alias||e.api_key).substring(0,10),spend:e.total_spend}));u(s);let r=(await O(l)).map(e=>({key:e.model,spend:e.total_spend}));x(r);let n=await A(l);console.log("teamSpend",n),f(n.daily_spend),w(n.teams);let o=n.total_spend_per_team;o=o.map(e=>(e.name=e.team_id||"",e.value=e.total_spend||0,e)),k(o);let i=await E(l,null===(e=N.from)||void 0===e?void 0:e.toISOString(),null===(a=N.to)||void 0===a?void 0:a.toISOString());Z(i.spend_per_tag);let c=await T(l,null,void 0,void 0);j(c),console.log("spend/user result",c)}else"App Owner"==s&&await I(l,t,s,r,U,D).then(async e=>{if(console.log("result from spend logs call",e),"daily_spend"in e){let l=e.daily_spend;console.log("daily spend",l),d(l);let t=e.top_api_keys;u(t)}else{let t=(await F(l,function(e){let l=[];e.forEach(e=>{Object.entries(e).forEach(e=>{let[t,s]=e;"spend"!==t&&"startTime"!==t&&"models"!==t&&"users"!==t&&l.push({key:t,spend:s})})}),l.sort((e,l)=>Number(l.spend)-Number(e.spend));let t=l.slice(0,5).map(e=>e.key);return console.log("topKeys: ".concat(Object.keys(t[0]))),t}(e))).info.map(e=>({key:(e.key_name||e.key_alias).substring(0,10),spend:e.spend}));u(t),d(e)}})}catch(e){console.error("There was an error fetching the data",e)}})()},[l,t,s,r,U,D]),(0,a.jsxs)("div",{style:{width:"100%"},className:"p-8",children:[(0,a.jsx)(eP,{userID:r,userRole:s,accessToken:l,userSpend:null,selectedTeam:null}),(0,a.jsxs)(eD.Z,{children:[(0,a.jsxs)(eK.Z,{className:"mt-2",children:[(0,a.jsx)(eU.Z,{children:"All Up"}),(0,a.jsx)(eU.Z,{children:"Team Based Usage"}),(0,a.jsx)(eU.Z,{children:"End User Usage"}),(0,a.jsx)(eU.Z,{children:"Tag Based Usage"})]}),(0,a.jsxs)(ez.Z,{children:[(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,a.jsx)(H.Z,{numColSpan:2,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Monthly Spend"}),(0,a.jsx)(eY.Z,{data:c,index:"date",categories:["spend"],colors:["blue"],valueFormatter:e=>"$ ".concat(new Intl.NumberFormat("us").format(e).toString()),yAxisWidth:100,tickGap:5})]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Top API Keys"}),(0,a.jsx)(eY.Z,{className:"mt-4 h-40",data:m,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:80,tickGap:5,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,a.jsx)(H.Z,{numColSpan:1,children:(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Top Models"}),(0,a.jsx)(eY.Z,{className:"mt-4 h-40",data:h,index:"key",categories:["spend"],colors:["blue"],yAxisWidth:200,layout:"vertical",showXAxis:!1,showLegend:!1})]})}),(0,a.jsx)(H.Z,{numColSpan:1})]})}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full",children:[(0,a.jsxs)(H.Z,{numColSpan:2,children:[(0,a.jsxs)(ef.Z,{className:"mb-2",children:[(0,a.jsx)(er.Z,{children:"Total Spend Per Team"}),(0,a.jsx)(lk.Z,{data:b})]}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Daily Spend Per Team"}),(0,a.jsx)(eY.Z,{className:"h-72",data:g,showLegend:!0,index:"date",categories:_,yAxisWidth:80,colors:["blue","green","yellow","red","purple"],stack:!0})]})]}),(0,a.jsx)(H.Z,{numColSpan:2})]})}),(0,a.jsxs)(eB.Z,{children:[(0,a.jsxs)("p",{className:"mb-2 text-gray-500 italic text-[12px]",children:["End-Users of your LLM API calls. Tracked when a `user` param is passed in your LLM calls ",(0,a.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/users",target:"_blank",children:"docs here"})]}),(0,a.jsxs)($.Z,{numItems:2,children:[(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Time Range"}),(0,a.jsx)(eL.Z,{enableSelect:!0,value:N,onValueChange:e=>{R(e),K(e.from,e.to,null)}})]}),(0,a.jsxs)(H.Z,{children:[(0,a.jsx)(es.Z,{children:"Select Key"}),(0,a.jsxs)(eS.Z,{defaultValue:"all-keys",children:[(0,a.jsx)(eN.Z,{value:"all-keys",onClick:()=>{K(N.from,N.to,null)},children:"All Keys"},"all-keys"),null==o?void 0:o.map((e,l)=>e&&null!==e.key_alias&&e.key_alias.length>0?(0,a.jsx)(eN.Z,{value:String(l),onClick:()=>{K(N.from,N.to,e.token)},children:e.key_alias},l):null)]})]})]}),(0,a.jsx)(ef.Z,{className:"mt-4",children:(0,a.jsxs)(eZ.Z,{className:"max-h-[70vh] min-h-[500px]",children:[(0,a.jsx)(eb.Z,{children:(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ek.Z,{children:"End User"}),(0,a.jsx)(ek.Z,{children:"Spend"}),(0,a.jsx)(ek.Z,{children:"Total Events"})]})}),(0,a.jsx)(e_.Z,{children:null==p?void 0:p.map((e,l)=>{var t;return(0,a.jsxs)(ev.Z,{children:[(0,a.jsx)(ew.Z,{children:e.end_user}),(0,a.jsx)(ew.Z,{children:null===(t=e.total_spend)||void 0===t?void 0:t.toFixed(4)}),(0,a.jsx)(ew.Z,{children:e.total_count})]},l)})})]})})]}),(0,a.jsx)(eB.Z,{children:(0,a.jsxs)($.Z,{numItems:2,className:"gap-2 h-[75vh] w-full mb-4",children:[(0,a.jsxs)(H.Z,{numColSpan:2,children:[(0,a.jsx)(eL.Z,{className:"mb-4",enableSelect:!0,value:N,onValueChange:e=>{R(e),B(e.from,e.to)}}),(0,a.jsxs)(ef.Z,{children:[(0,a.jsx)(er.Z,{children:"Spend Per Tag"}),(0,a.jsxs)(es.Z,{children:["Get Started Tracking cost per tag ",(0,a.jsx)("a",{className:"text-blue-500",href:"https://docs.litellm.ai/docs/proxy/enterprise#tracking-spend-for-custom-tags",target:"_blank",children:"here"})]}),(0,a.jsx)(eY.Z,{className:"h-72",data:y,index:"name",categories:["spend"],colors:["blue"]})]})]}),(0,a.jsx)(H.Z,{numColSpan:2})]})})]})]})]})},lS=()=>{let{Title:e,Paragraph:l}=eR.default,[t,s]=(0,n.useState)(""),[r,i]=(0,n.useState)(null),[c,d]=(0,n.useState)(null),[u,h]=(0,n.useState)(null),[x,p]=(0,n.useState)(!0),j=(0,o.useSearchParams)(),[g,f]=(0,n.useState)({data:[]}),y=j.get("userID"),Z=j.get("token"),[_,w]=(0,n.useState)("api-keys"),[b,k]=(0,n.useState)(null);return(0,n.useEffect)(()=>{if(Z){let e=(0,eF.o)(Z);if(e){if(console.log("Decoded token:",e),console.log("Decoded key:",e.key),k(e.key),e.user_role){let l=function(e){if(!e)return"Undefined Role";switch(console.log("Received user role: ".concat(e.toLowerCase())),console.log("Received user role length: ".concat(e.toLowerCase().length)),e.toLowerCase()){case"app_owner":case"demo_app_owner":return"App Owner";case"app_admin":case"proxy_admin":return"Admin";case"proxy_admin_viewer":return"Admin Viewer";case"app_user":return"App User";default:return"Unknown Role"}}(e.user_role);console.log("Decoded user_role:",l),s(l),"Admin Viewer"==l&&w("usage")}else console.log("User role not defined");e.user_email?i(e.user_email):console.log("User Email is not set ".concat(e)),e.login_method?p("username_password"==e.login_method):console.log("User Email is not set ".concat(e))}}},[Z]),(0,a.jsx)(n.Suspense,{fallback:(0,a.jsx)("div",{children:"Loading..."}),children:(0,a.jsxs)("div",{className:"flex flex-col min-h-screen",children:[(0,a.jsx)(m,{userID:y,userRole:t,userEmail:r,showSSOBanner:x}),(0,a.jsxs)("div",{className:"flex flex-1 overflow-auto",children:[(0,a.jsx)("div",{className:"mt-8",children:(0,a.jsx)(lb,{setPage:w,userRole:t,defaultSelectedKey:null})}),"api-keys"==_?(0,a.jsx)(eM,{userID:y,userRole:t,teams:c,keys:u,setUserRole:s,userEmail:r,setUserEmail:i,setTeams:d,setKeys:h}):"models"==_?(0,a.jsx)(e9,{userID:y,userRole:t,token:Z,accessToken:b,modelData:g,setModelData:f}):"llm-playground"==_?(0,a.jsx)(ly,{userID:y,userRole:t,token:Z,accessToken:b}):"users"==_?(0,a.jsx)(lt,{userID:y,userRole:t,token:Z,keys:u,teams:c,accessToken:b,setKeys:h}):"teams"==_?(0,a.jsx)(ls,{teams:c,setTeams:d,searchParams:j,accessToken:b,userID:y,userRole:t}):"admin-panel"==_?(0,a.jsx)(la,{setTeams:d,searchParams:j,accessToken:b,showSSOBanner:x}):"api_ref"==_?(0,a.jsx)(lg,{}):"settings"==_?(0,a.jsx)(li,{userID:y,userRole:t,accessToken:b}):"general-settings"==_?(0,a.jsx)(lp,{userID:y,userRole:t,accessToken:b,modelData:g}):(0,a.jsx)(lv,{userID:y,userRole:t,token:Z,accessToken:b,keys:u})]})]})})}}},function(e){e.O(0,[936,884,971,69,744],function(){return e(e.s=20661)}),_N_E=e.O()}]); \ No newline at end of file diff --git a/ui/litellm-dashboard/out/index.html b/ui/litellm-dashboard/out/index.html index 930018e005..011bb7fc76 100644 --- a/ui/litellm-dashboard/out/index.html +++ b/ui/litellm-dashboard/out/index.html @@ -1 +1 @@ -LiteLLM Dashboard \ No newline at end of file +LiteLLM Dashboard \ No newline at end of file diff --git a/ui/litellm-dashboard/out/index.txt b/ui/litellm-dashboard/out/index.txt index d67a480b37..ce4099b2cd 100644 --- a/ui/litellm-dashboard/out/index.txt +++ b/ui/litellm-dashboard/out/index.txt @@ -1,7 +1,7 @@ 2:I[77831,[],""] -3:I[7926,["936","static/chunks/2f6dbc85-052c4579f80d66ae.js","884","static/chunks/884-7576ee407a2ecbe6.js","931","static/chunks/app/page-6a39771cacf75ea6.js"],""] +3:I[4858,["936","static/chunks/2f6dbc85-052c4579f80d66ae.js","884","static/chunks/884-7576ee407a2ecbe6.js","931","static/chunks/app/page-c35c14c9afd091ec.js"],""] 4:I[5613,[],""] 5:I[31778,[],""] -0:["obp5wqVSVDMiDTC414cR8",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/f04e46b02318b660.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] +0:["2ASoJGxS-D4w-vat00xMy",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$L2",null,{"propsForComponent":{"params":{}},"Component":"$3","isStaticGeneration":true}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L4",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L5",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","title",null,{"children":"404: This page could not be found."}],["$","div",null,{"style":{"fontFamily":"system-ui,\"Segoe UI\",Roboto,Helvetica,Arial,sans-serif,\"Apple Color Emoji\",\"Segoe UI Emoji\"","height":"100vh","textAlign":"center","display":"flex","flexDirection":"column","alignItems":"center","justifyContent":"center"},"children":["$","div",null,{"children":[["$","style",null,{"dangerouslySetInnerHTML":{"__html":"body{color:#000;background:#fff;margin:0}.next-error-h1{border-right:1px solid rgba(0,0,0,.3)}@media (prefers-color-scheme:dark){body{color:#fff;background:#000}.next-error-h1{border-right:1px solid rgba(255,255,255,.3)}}"}}],["$","h1",null,{"className":"next-error-h1","style":{"display":"inline-block","margin":"0 20px 0 0","padding":"0 23px 0 0","fontSize":24,"fontWeight":500,"verticalAlign":"top","lineHeight":"49px"},"children":"404"}],["$","div",null,{"style":{"display":"inline-block"},"children":["$","h2",null,{"style":{"fontSize":14,"fontWeight":400,"lineHeight":"49px","margin":0},"children":"This page could not be found."}]}]]}]}]],"notFoundStyles":[],"styles":null}]}]}],null]],[[["$","link","0",{"rel":"stylesheet","href":"/ui/_next/static/css/f04e46b02318b660.css","precedence":"next","crossOrigin":""}]],"$L6"]]]] 6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"LiteLLM Dashboard"}],["$","meta","3",{"name":"description","content":"LiteLLM Proxy Admin UI"}],["$","link","4",{"rel":"icon","href":"/ui/favicon.ico","type":"image/x-icon","sizes":"16x16"}],["$","meta","5",{"name":"next-size-adjust"}]] 1:null diff --git a/ui/litellm-dashboard/src/components/general_settings.tsx b/ui/litellm-dashboard/src/components/general_settings.tsx index c2013b1578..d16b434b89 100644 --- a/ui/litellm-dashboard/src/components/general_settings.tsx +++ b/ui/litellm-dashboard/src/components/general_settings.tsx @@ -23,12 +23,44 @@ import { AccordionHeader, AccordionList, } from "@tremor/react"; -import { TabPanel, TabPanels, TabGroup, TabList, Tab, Icon } from "@tremor/react"; -import { getCallbacksCall, setCallbacksCall, serviceHealthCheck } from "./networking"; -import { Modal, Form, Input, Select, Button as Button2, message } from "antd"; -import { InformationCircleIcon, PencilAltIcon, PencilIcon, StatusOnlineIcon, TrashIcon, RefreshIcon } from "@heroicons/react/outline"; +import { + TabPanel, + TabPanels, + TabGroup, + TabList, + Tab, + Icon, +} from "@tremor/react"; +import { + getCallbacksCall, + setCallbacksCall, + getGeneralSettingsCall, + serviceHealthCheck, + updateConfigFieldSetting, + deleteConfigFieldSetting, +} from "./networking"; +import { + Modal, + Form, + Input, + Select, + Button as Button2, + message, + InputNumber, +} from "antd"; +import { + InformationCircleIcon, + PencilAltIcon, + PencilIcon, + StatusOnlineIcon, + TrashIcon, + RefreshIcon, + CheckCircleIcon, + XCircleIcon, + QuestionMarkCircleIcon, +} from "@heroicons/react/outline"; import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider"; -import AddFallbacks from "./add_fallbacks" +import AddFallbacks from "./add_fallbacks"; import openai from "openai"; import Paragraph from "antd/es/skeleton/Paragraph"; @@ -36,7 +68,7 @@ interface GeneralSettingsPageProps { accessToken: string | null; userRole: string | null; userID: string | null; - modelData: any + modelData: any; } async function testFallbackModelResponse( @@ -65,43 +97,71 @@ async function testFallbackModelResponse( }, ], // @ts-ignore - mock_testing_fallbacks: true + mock_testing_fallbacks: true, }); message.success( - Test model={selectedModel}, received model={response.model}. - See window.open('https://docs.litellm.ai/docs/proxy/reliability', '_blank')} style={{ textDecoration: 'underline', color: 'blue' }}>curl + Test model={selectedModel}, received model= + {response.model}. See{" "} + + window.open( + "https://docs.litellm.ai/docs/proxy/reliability", + "_blank" + ) + } + style={{ textDecoration: "underline", color: "blue" }} + > + curl + ); } catch (error) { - message.error(`Error occurred while generating model response. Please try again. Error: ${error}`, 20); + message.error( + `Error occurred while generating model response. Please try again. Error: ${error}`, + 20 + ); } } interface AccordionHeroProps { selectedStrategy: string | null; strategyArgs: routingStrategyArgs; - paramExplanation: { [key: string]: string } + paramExplanation: { [key: string]: string }; } interface routingStrategyArgs { - ttl?: number; - lowest_latency_buffer?: number; + ttl?: number; + lowest_latency_buffer?: number; +} + +interface generalSettingsItem { + field_name: string; + field_type: string; + field_value: any; + field_description: string; + stored_in_db: boolean | null; } const defaultLowestLatencyArgs: routingStrategyArgs = { - "ttl": 3600, - "lowest_latency_buffer": 0 -} + ttl: 3600, + lowest_latency_buffer: 0, +}; -export const AccordionHero: React.FC = ({ selectedStrategy, strategyArgs, paramExplanation }) => ( +export const AccordionHero: React.FC = ({ + selectedStrategy, + strategyArgs, + paramExplanation, +}) => ( - Routing Strategy Specific Args - - { - selectedStrategy == "latency-based-routing" ? - + + Routing Strategy Specific Args + + + {selectedStrategy == "latency-based-routing" ? ( + @@ -114,51 +174,75 @@ export const AccordionHero: React.FC = ({ selectedStrategy, {param} -

{paramExplanation[param]}

+

+ {paramExplanation[param]} +

+ name={param} + defaultValue={ + typeof value === "object" + ? JSON.stringify(value, null, 2) + : value.toString() + } + />
))}
-
- : No specific settings - } -
-
+ + ) : ( + No specific settings + )} + + ); const GeneralSettings: React.FC = ({ accessToken, userRole, userID, - modelData + modelData, }) => { - const [routerSettings, setRouterSettings] = useState<{ [key: string]: any }>({}); + const [routerSettings, setRouterSettings] = useState<{ [key: string]: any }>( + {} + ); + const [generalSettingsDict, setGeneralSettingsDict] = useState<{ + [key: string]: any; + }>({}); + const [generalSettings, setGeneralSettings] = useState( + [] + ); const [isModalVisible, setIsModalVisible] = useState(false); const [form] = Form.useForm(); const [selectedCallback, setSelectedCallback] = useState(null); - const [selectedStrategy, setSelectedStrategy] = useState(null) - const [strategySettings, setStrategySettings] = useState(null); + const [selectedStrategy, setSelectedStrategy] = useState(null); + const [strategySettings, setStrategySettings] = + useState(null); let paramExplanation: { [key: string]: string } = { - "routing_strategy_args": "(dict) Arguments to pass to the routing strategy", - "routing_strategy": "(string) Routing strategy to use", - "allowed_fails": "(int) Number of times a deployment can fail before being added to cooldown", - "cooldown_time": "(int) time in seconds to cooldown a deployment after failure", - "num_retries": "(int) Number of retries for failed requests. Defaults to 0.", - "timeout": "(float) Timeout for requests. Defaults to None.", - "retry_after": "(int) Minimum time to wait before retrying a failed request", - "ttl": "(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).", - "lowest_latency_buffer": "(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency)." - } + routing_strategy_args: "(dict) Arguments to pass to the routing strategy", + routing_strategy: "(string) Routing strategy to use", + allowed_fails: + "(int) Number of times a deployment can fail before being added to cooldown", + cooldown_time: + "(int) time in seconds to cooldown a deployment after failure", + num_retries: "(int) Number of retries for failed requests. Defaults to 0.", + timeout: "(float) Timeout for requests. Defaults to None.", + retry_after: "(int) Minimum time to wait before retrying a failed request", + ttl: "(int) Sliding window to look back over when calculating the average latency of a deployment. Default - 1 hour (in seconds).", + lowest_latency_buffer: + "(float) Shuffle between deployments within this % of the lowest latency. Default - 0 (i.e. always pick lowest latency).", + }; useEffect(() => { if (!accessToken || !userRole || !userID) { @@ -169,6 +253,10 @@ const GeneralSettings: React.FC = ({ let router_settings = data.router_settings; setRouterSettings(router_settings); }); + getGeneralSettingsCall(accessToken).then((data) => { + let general_settings = data; + setGeneralSettings(general_settings); + }); }, [accessToken, userRole, userID]); const handleAddCallback = () => { @@ -190,8 +278,8 @@ const GeneralSettings: React.FC = ({ return; } - console.log(`received key: ${key}`) - console.log(`routerSettings['fallbacks']: ${routerSettings['fallbacks']}`) + console.log(`received key: ${key}`); + console.log(`routerSettings['fallbacks']: ${routerSettings["fallbacks"]}`); routerSettings["fallbacks"].map((dict: { [key: string]: any }) => { // Check if the dictionary has the specified key and delete it if present @@ -202,18 +290,73 @@ const GeneralSettings: React.FC = ({ }); const payload = { - router_settings: routerSettings + router_settings: routerSettings, }; try { await setCallbacksCall(accessToken, payload); setRouterSettings({ ...routerSettings }); - setSelectedStrategy(routerSettings["routing_strategy"]) + setSelectedStrategy(routerSettings["routing_strategy"]); message.success("Router settings updated successfully"); } catch (error) { message.error("Failed to update router settings: " + error, 20); } - } + }; + + const handleInputChange = (fieldName: string, newValue: any) => { + // Update the value in the state + const updatedSettings = generalSettings.map((setting) => + setting.field_name === fieldName + ? { ...setting, field_value: newValue } + : setting + ); + setGeneralSettings(updatedSettings); + }; + + const handleUpdateField = (fieldName: string, idx: number) => { + if (!accessToken) { + return; + } + + let fieldValue = generalSettings[idx].field_value; + + if (fieldValue == null || fieldValue == undefined) { + return; + } + try { + updateConfigFieldSetting(accessToken, fieldName, fieldValue); + // update value in state + + const updatedSettings = generalSettings.map((setting) => + setting.field_name === fieldName + ? { ...setting, stored_in_db: true } + : setting + ); + setGeneralSettings(updatedSettings); + } catch (error) { + // do something + } + }; + + const handleResetField = (fieldName: string, idx: number) => { + if (!accessToken) { + return; + } + + try { + deleteConfigFieldSetting(accessToken, fieldName); + // update value in state + + const updatedSettings = generalSettings.map((setting) => + setting.field_name === fieldName + ? { ...setting, stored_in_db: null, field_value: null } + : setting + ); + setGeneralSettings(updatedSettings); + } catch (error) { + // do something + } + }; const handleSaveChanges = (router_settings: any) => { if (!accessToken) { @@ -223,39 +366,55 @@ const GeneralSettings: React.FC = ({ console.log("router_settings", router_settings); const updatedVariables = Object.fromEntries( - Object.entries(router_settings).map(([key, value]) => { - if (key !== 'routing_strategy_args' && key !== "routing_strategy") { - return [key, (document.querySelector(`input[name="${key}"]`) as HTMLInputElement)?.value || value]; - } - else if (key == "routing_strategy") { - return [key, selectedStrategy] - } - else if (key == "routing_strategy_args" && selectedStrategy == "latency-based-routing") { - let setRoutingStrategyArgs: routingStrategyArgs = {} + Object.entries(router_settings) + .map(([key, value]) => { + if (key !== "routing_strategy_args" && key !== "routing_strategy") { + return [ + key, + ( + document.querySelector( + `input[name="${key}"]` + ) as HTMLInputElement + )?.value || value, + ]; + } else if (key == "routing_strategy") { + return [key, selectedStrategy]; + } else if ( + key == "routing_strategy_args" && + selectedStrategy == "latency-based-routing" + ) { + let setRoutingStrategyArgs: routingStrategyArgs = {}; - const lowestLatencyBufferElement = document.querySelector(`input[name="lowest_latency_buffer"]`) as HTMLInputElement; - const ttlElement = document.querySelector(`input[name="ttl"]`) as HTMLInputElement; + const lowestLatencyBufferElement = document.querySelector( + `input[name="lowest_latency_buffer"]` + ) as HTMLInputElement; + const ttlElement = document.querySelector( + `input[name="ttl"]` + ) as HTMLInputElement; - if (lowestLatencyBufferElement?.value) { - setRoutingStrategyArgs["lowest_latency_buffer"] = Number(lowestLatencyBufferElement.value) + if (lowestLatencyBufferElement?.value) { + setRoutingStrategyArgs["lowest_latency_buffer"] = Number( + lowestLatencyBufferElement.value + ); + } + + if (ttlElement?.value) { + setRoutingStrategyArgs["ttl"] = Number(ttlElement.value); + } + + console.log(`setRoutingStrategyArgs: ${setRoutingStrategyArgs}`); + return ["routing_strategy_args", setRoutingStrategyArgs]; } - - if (ttlElement?.value) { - setRoutingStrategyArgs["ttl"] = Number(ttlElement.value) - } - - console.log(`setRoutingStrategyArgs: ${setRoutingStrategyArgs}`) - return [ - "routing_strategy_args", setRoutingStrategyArgs - ] - } - return null; - }).filter(entry => entry !== null && entry !== undefined) as Iterable<[string, unknown]> + return null; + }) + .filter((entry) => entry !== null && entry !== undefined) as Iterable< + [string, unknown] + > ); console.log("updatedVariables", updatedVariables); const payload = { - router_settings: updatedVariables + router_settings: updatedVariables, }; try { @@ -267,117 +426,240 @@ const GeneralSettings: React.FC = ({ message.success("router settings updated successfully"); }; - - if (!accessToken) { return null; } - return (
- General Settings + Loadbalancing Fallbacks + General - - Router Settings - - - - - Setting - Value - - - - {Object.entries(routerSettings).filter(([param, value]) => param != "fallbacks" && param != "context_window_fallbacks" && param != "routing_strategy_args").map(([param, value]) => ( - - - {param} -

{paramExplanation[param]}

-
- - { - param == "routing_strategy" ? - - usage-based-routing - latency-based-routing - simple-shuffle - : - - } - + + Router Settings + +
+ + + Setting + Value + + + + {Object.entries(routerSettings) + .filter( + ([param, value]) => + param != "fallbacks" && + param != "context_window_fallbacks" && + param != "routing_strategy_args" + ) + .map(([param, value]) => ( + + + {param} +

+ {paramExplanation[param]} +

+
+ + {param == "routing_strategy" ? ( + + + usage-based-routing + + + latency-based-routing + + + simple-shuffle + + + ) : ( + + )} + +
+ ))} +
+
+ 0 + ? routerSettings["routing_strategy_args"] + : defaultLowestLatencyArgs // default value when keys length is 0 + } + paramExplanation={paramExplanation} + /> +
+ + + +
+
+ + + + + Model Name + Fallbacks - ))} - -
- 0 - ? routerSettings['routing_strategy_args'] - : defaultLowestLatencyArgs // default value when keys length is 0 - } - paramExplanation={paramExplanation} - /> - - - - - -
- - - - - Model Name - Fallbacks - - + - - { - routerSettings["fallbacks"] && - routerSettings["fallbacks"].map((item: Object, index: number) => - Object.entries(item).map(([key, value]) => ( - - {key} - {Array.isArray(value) ? value.join(', ') : value} - - - - - deleteFallbacks(key)} - /> - - - )) - ) - } - -
- data.model_name) : []} accessToken={accessToken} routerSettings={routerSettings} setRouterSettings={setRouterSettings}/> -
-
-
+ + {routerSettings["fallbacks"] && + routerSettings["fallbacks"].map( + (item: Object, index: number) => + Object.entries(item).map(([key, value]) => ( + + {key} + + {Array.isArray(value) ? value.join(", ") : value} + + + + + + deleteFallbacks(key)} + /> + + + )) + )} + + + data.model_name) + : [] + } + accessToken={accessToken} + routerSettings={routerSettings} + setRouterSettings={setRouterSettings} + /> + + + + + + + Setting + Value + Status + Action + + + + {generalSettings.map((value, index) => ( + + + {value.field_name} +

+ {value.field_description} +

+
+ + {value.field_type == "Integer" ? ( + + handleInputChange(value.field_name, newValue) + } // Handle value change + /> + ) : null} + + + {value.stored_in_db == true ? ( + + In DB + + ) : value.stored_in_db == false ? ( + + In Config + + ) : ( + + Not Set + + )} + + + + + handleResetField(value.field_name, index) + } + > + Reset + + +
+ ))} +
+
+
+
+ +
); }; -export default GeneralSettings; \ No newline at end of file +export default GeneralSettings; diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 1ec131f726..a405d4440b 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -14,15 +14,17 @@ export interface Model { export const modelCostMap = async () => { try { - const response = await fetch('https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json'); + const response = await fetch( + "https://raw.githubusercontent.com/BerriAI/litellm/main/model_prices_and_context_window.json" + ); const jsonData = await response.json(); - console.log(`received data: ${jsonData}`) - return jsonData + console.log(`received data: ${jsonData}`); + return jsonData; } catch (error) { console.error("Failed to get model cost map:", error); throw error; } -} +}; export const modelCreateCall = async ( accessToken: string, @@ -50,19 +52,21 @@ export const modelCreateCall = async ( const data = await response.json(); console.log("API Response:", data); - message.success("Model created successfully. Wait 60s and refresh on 'All Models' page"); + message.success( + "Model created successfully. Wait 60s and refresh on 'All Models' page" + ); return data; } catch (error) { console.error("Failed to create key:", error); throw error; } -} +}; -export const modelDeleteCall = async ( +export const modelDeleteCall = async ( accessToken: string, - model_id: string, + model_id: string ) => { - console.log(`model_id in model delete call: ${model_id}`) + console.log(`model_id in model delete call: ${model_id}`); try { const url = proxyBaseUrl ? `${proxyBaseUrl}/model/delete` : `/model/delete`; const response = await fetch(url, { @@ -72,7 +76,7 @@ export const modelDeleteCall = async ( "Content-Type": "application/json", }, body: JSON.stringify({ - "id": model_id, + id: model_id, }), }); @@ -91,7 +95,7 @@ export const modelDeleteCall = async ( console.error("Failed to create key:", error); throw error; } -} +}; export const keyCreateCall = async ( accessToken: string, @@ -280,15 +284,14 @@ export const teamDeleteCall = async (accessToken: String, teamID: String) => { console.error("Failed to delete key:", error); throw error; } - -} +}; export const userInfoCall = async ( accessToken: String, userID: String | null, userRole: String, viewAll: Boolean = false, - page: number | null, + page: number | null, page_size: number | null ) => { try { @@ -300,7 +303,7 @@ export const userInfoCall = async ( url = `${url}?user_id=${userID}`; } console.log("in userInfoCall viewAll=", viewAll); - if (viewAll && page_size && (page != null) && (page != undefined)) { + if (viewAll && page_size && page != null && page != undefined) { url = `${url}?view_all=true&page=${page}&page_size=${page_size}`; } //message.info("Requesting user data"); @@ -329,10 +332,9 @@ export const userInfoCall = async ( } }; - export const teamInfoCall = async ( accessToken: String, - teamID: String | null, + teamID: String | null ) => { try { let url = proxyBaseUrl ? `${proxyBaseUrl}/team/info` : `/team/info`; @@ -364,10 +366,7 @@ export const teamInfoCall = async ( } }; - -export const getTotalSpendCall = async ( - accessToken: String, -) => { +export const getTotalSpendCall = async (accessToken: String) => { /** * Get all models on proxy */ @@ -435,11 +434,10 @@ export const modelInfoCall = async ( } }; - export const modelMetricsCall = async ( accessToken: String, userID: String, - userRole: String, + userRole: String, modelGroup: String | null, startTime: String | undefined, endTime: String | undefined @@ -450,7 +448,7 @@ export const modelMetricsCall = async ( try { let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics` : `/model/metrics`; if (modelGroup) { - url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}` + url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`; } // message.info("Requesting model data"); const response = await fetch(url, { @@ -476,12 +474,10 @@ export const modelMetricsCall = async ( } }; - - export const modelMetricsSlowResponsesCall = async ( accessToken: String, userID: String, - userRole: String, + userRole: String, modelGroup: String | null, startTime: String | undefined, endTime: String | undefined @@ -490,11 +486,13 @@ export const modelMetricsSlowResponsesCall = async ( * Get all models on proxy */ try { - let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/slow_responses` : `/model/metrics/slow_responses`; + let url = proxyBaseUrl + ? `${proxyBaseUrl}/model/metrics/slow_responses` + : `/model/metrics/slow_responses`; if (modelGroup) { - url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}` + url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`; } - + // message.info("Requesting model data"); const response = await fetch(url, { method: "GET", @@ -519,11 +517,10 @@ export const modelMetricsSlowResponsesCall = async ( } }; - export const modelExceptionsCall = async ( accessToken: String, userID: String, - userRole: String, + userRole: String, modelGroup: String | null, startTime: String | undefined, endTime: String | undefined @@ -532,10 +529,12 @@ export const modelExceptionsCall = async ( * Get all models on proxy */ try { - let url = proxyBaseUrl ? `${proxyBaseUrl}/model/metrics/exceptions` : `/model/metrics/exceptions`; + let url = proxyBaseUrl + ? `${proxyBaseUrl}/model/metrics/exceptions` + : `/model/metrics/exceptions`; if (modelGroup) { - url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}` + url = `${url}?_selected_model_group=${modelGroup}&startTime=${startTime}&endTime=${endTime}`; } const response = await fetch(url, { method: "GET", @@ -560,7 +559,6 @@ export const modelExceptionsCall = async ( } }; - export const modelAvailableCall = async ( accessToken: String, userID: String, @@ -625,7 +623,6 @@ export const keySpendLogsCall = async (accessToken: String, token: String) => { } }; - export const teamSpendLogsCall = async (accessToken: String) => { try { const url = proxyBaseUrl @@ -654,19 +651,18 @@ export const teamSpendLogsCall = async (accessToken: String) => { } }; - export const tagsSpendLogsCall = async ( - accessToken: String, - startTime: String | undefined, - endTime: String | undefined - ) => { + accessToken: String, + startTime: String | undefined, + endTime: String | undefined +) => { try { let url = proxyBaseUrl ? `${proxyBaseUrl}/global/spend/tags` : `/global/spend/tags`; - + if (startTime && endTime) { - url = `${url}?start_date=${startTime}&end_date=${endTime}` + url = `${url}?start_date=${startTime}&end_date=${endTime}`; } console.log("in tagsSpendLogsCall:", url); @@ -692,7 +688,6 @@ export const tagsSpendLogsCall = async ( } }; - export const userSpendLogsCall = async ( accessToken: String, token: String, @@ -806,11 +801,15 @@ export const adminTopEndUsersCall = async ( let body = ""; if (keyToken) { - body = JSON.stringify({ api_key: keyToken, startTime: startTime, endTime: endTime }); + body = JSON.stringify({ + api_key: keyToken, + startTime: startTime, + endTime: endTime, + }); } else { body = JSON.stringify({ startTime: startTime, endTime: endTime }); } - + //message.info("Making top end users request"); // Define requestOptions with body as an optional property @@ -1079,7 +1078,6 @@ export const teamCreateCall = async ( } }; - export const keyUpdateCall = async ( accessToken: string, formValues: Record // Assuming formValues is an object @@ -1240,7 +1238,7 @@ export const userUpdateUserCall = async ( console.log("Form Values in userUpdateUserCall:", formValues); // Log the form values before making the API call const url = proxyBaseUrl ? `${proxyBaseUrl}/user/update` : `/user/update`; - let response_body = {...formValues}; + let response_body = { ...formValues }; if (userRole !== null) { response_body["user_role"] = userRole; } @@ -1333,7 +1331,7 @@ export const slackBudgetAlertsHealthCheck = async (accessToken: String) => { // throw error with message throw new Error(errorData); } - + const data = await response.json(); message.success("Test Slack Alert worked - check your Slack!"); console.log("Service Health Response:", data); @@ -1347,9 +1345,10 @@ export const slackBudgetAlertsHealthCheck = async (accessToken: String) => { } }; - - -export const serviceHealthCheck= async (accessToken: String, service: String) => { +export const serviceHealthCheck = async ( + accessToken: String, + service: String +) => { try { let url = proxyBaseUrl ? `${proxyBaseUrl}/health/services?service=${service}` @@ -1371,9 +1370,11 @@ export const serviceHealthCheck= async (accessToken: String, service: String) => // throw error with message throw new Error(errorData); } - + const data = await response.json(); - message.success(`Test request to ${service} made - check logs/alerts on ${service} to verify`); + message.success( + `Test request to ${service} made - check logs/alerts on ${service} to verify` + ); // You can add additional logic here based on the response if needed return data; } catch (error) { @@ -1382,9 +1383,6 @@ export const serviceHealthCheck= async (accessToken: String, service: String) => } }; - - - export const getCallbacksCall = async ( accessToken: String, userID: String, @@ -1394,7 +1392,9 @@ export const getCallbacksCall = async ( * Get all the models user has access to */ try { - let url = proxyBaseUrl ? `${proxyBaseUrl}/get/config/callbacks` : `/get/config/callbacks`; + let url = proxyBaseUrl + ? `${proxyBaseUrl}/get/config/callbacks` + : `/get/config/callbacks`; //message.info("Requesting model data"); const response = await fetch(url, { @@ -1421,11 +1421,117 @@ export const getCallbacksCall = async ( } }; +export const getGeneralSettingsCall = async (accessToken: String) => { + try { + let url = proxyBaseUrl + ? `${proxyBaseUrl}/config/list?config_type=general_settings` + : `/config/list?config_type=general_settings`; + //message.info("Requesting model data"); + const response = await fetch(url, { + method: "GET", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + }); + if (!response.ok) { + const errorData = await response.text(); + message.error(errorData, 10); + throw new Error("Network response was not ok"); + } + const data = await response.json(); + //message.info("Received model data"); + return data; + // Handle success - you might want to update some state or UI based on the created key + } catch (error) { + console.error("Failed to get callbacks:", error); + throw error; + } +}; +export const updateConfigFieldSetting = async ( + accessToken: String, + fieldName: string, + fieldValue: any +) => { + try { + let url = proxyBaseUrl + ? `${proxyBaseUrl}/config/field/update` + : `/config/field/update`; + let formData = { + field_name: fieldName, + field_value: fieldValue, + config_type: "general_settings", + }; + //message.info("Requesting model data"); + const response = await fetch(url, { + method: "POST", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + + if (!response.ok) { + const errorData = await response.text(); + message.error(errorData, 10); + throw new Error("Network response was not ok"); + } + + const data = await response.json(); + //message.info("Received model data"); + message.success("Successfully updated value!"); + return data; + // Handle success - you might want to update some state or UI based on the created key + } catch (error) { + console.error("Failed to set callbacks:", error); + throw error; + } +}; + +export const deleteConfigFieldSetting = async ( + accessToken: String, + fieldName: String +) => { + try { + let url = proxyBaseUrl + ? `${proxyBaseUrl}/config/field/delete` + : `/config/field/delete`; + + let formData = { + field_name: fieldName, + config_type: "general_settings", + }; + //message.info("Requesting model data"); + const response = await fetch(url, { + method: "POST", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(formData), + }); + + if (!response.ok) { + const errorData = await response.text(); + message.error(errorData, 10); + throw new Error("Network response was not ok"); + } + + const data = await response.json(); + message.success("Field reset on proxy"); + return data; + // Handle success - you might want to update some state or UI based on the created key + } catch (error) { + console.error("Failed to get callbacks:", error); + throw error; + } +}; export const setCallbacksCall = async ( accessToken: String, formValues: Record @@ -1464,9 +1570,7 @@ export const setCallbacksCall = async ( } }; -export const healthCheckCall = async ( - accessToken: String, -) => { +export const healthCheckCall = async (accessToken: String) => { /** * Get all the models user has access to */ @@ -1497,6 +1601,3 @@ export const healthCheckCall = async ( throw error; } }; - - -