diff --git a/litellm/caching.py b/litellm/caching.py
index 38174c2abbc..257bb1ca549 100644
--- a/litellm/caching.py
+++ b/litellm/caching.py
@@ -61,6 +61,10 @@ class InMemoryCache(BaseCache):
self.cache_dict.clear()
self.ttl_dict.clear()
+ def delete_cache(self, key):
+ self.cache_dict.pop(key, None)
+ self.ttl_dict.pop(key, None)
+
class RedisCache(BaseCache):
def __init__(self, host=None, port=None, password=None, **kwargs):
@@ -117,6 +121,9 @@ class RedisCache(BaseCache):
def flush_cache(self):
self.redis_client.flushall()
+ def delete_cache(self, key):
+ self.redis_client.delete(key)
+
class S3Cache(BaseCache):
def __init__(
@@ -304,6 +311,12 @@ class DualCache(BaseCache):
if self.redis_cache is not None:
self.redis_cache.flush_cache()
+ def delete_cache(self, key):
+ if self.in_memory_cache is not None:
+ self.in_memory_cache.delete_cache(key)
+ if self.redis_cache is not None:
+ self.redis_cache.delete_cache(key)
+
#### LiteLLM.Completion / Embedding Cache ####
class Cache:
diff --git a/litellm/proxy/_experimental/out/404.html b/litellm/proxy/_experimental/out/404.html
index adedbe62c65..56852eeb12e 100644
--- a/litellm/proxy/_experimental/out/404.html
+++ b/litellm/proxy/_experimental/out/404.html
@@ -1 +1 @@
-
404: This page could not be found.Create Next App
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found.Create Next App
404
This page could not be found.
\ No newline at end of file
diff --git a/litellm/proxy/_experimental/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_buildManifest.js b/litellm/proxy/_experimental/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_buildManifest.js
similarity index 100%
rename from litellm/proxy/_experimental/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_buildManifest.js
rename to litellm/proxy/_experimental/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_buildManifest.js
diff --git a/litellm/proxy/_experimental/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_ssgManifest.js b/litellm/proxy/_experimental/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_ssgManifest.js
similarity index 100%
rename from litellm/proxy/_experimental/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_ssgManifest.js
rename to litellm/proxy/_experimental/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_ssgManifest.js
diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-cf0440186224a114.js b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-cf0440186224a114.js
deleted file mode 100644
index da9b6b57020..00000000000
--- a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-cf0440186224a114.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{8598:function(e,t,r){Promise.resolve().then(r.t.bind(r,5250,23)),Promise.resolve().then(r.bind(r,3239))},3239:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return F}});var l=r(3827),s=r(4090),a=r(588);let n=async(e,t,r)=>{try{if(console.log("Form Values in keyCreateCall:",r),r.metadata)try{r.metadata=JSON.parse(r.metadata)}catch(e){a.ZP.error("Failed to parse metadata: "+e)}let l=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...r})});if(!l.ok){let e=await l.text();throw a.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await l.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},o=async(e,t)=>{try{let r=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!r.ok)throw Error("Network response was not ok");let l=await r.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},i=async(e,t)=>{try{let r=await fetch("/user/info?user_id=".concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok)throw Error("Network response was not ok");let l=await r.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}};var c=r(384),d=r(6453),h=r(2179),u=r(1801),x=r(6776),m=r(2902),j=r(7171),y=r(9714),Z=r(8707),p=r(1861);let{Option:k}=x.default;var g=e=>{let{userID:t,accessToken:r,data:o,setData:i}=e,[x]=m.Z.useForm(),[k,g]=(0,s.useState)(!1),[f,w]=(0,s.useState)(null),b=()=>{g(!1),x.resetFields()},C=()=>{g(!1),w(null),x.resetFields()},S=async e=>{try{a.ZP.info("Making API Call"),e.models&&""!==e.models.trim()?e.models=e.models.split(",").map(e=>e.trim()):e.models=[],g(!0);let l=await n(r,t,e);i(e=>e?[...e,l]:[l]),w(l.key),a.ZP.success("API Key Created"),x.resetFields()}catch(e){console.error("Error creating the key:",e)}};return(0,l.jsxs)("div",{children:[(0,l.jsx)(h.Z,{className:"mx-auto",onClick:()=>g(!0),children:"+ Create New Key"}),(0,l.jsx)(j.Z,{title:"Create Key",visible:k,width:800,footer:null,onOk:b,onCancel:C,children:(0,l.jsxs)(m.Z,{form:x,onFinish:S,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:[(0,l.jsx)(m.Z.Item,{label:"Key Name",name:"key_alias",children:(0,l.jsx)(y.Z,{})}),(0,l.jsx)(m.Z.Item,{label:"Models (Comma Separated). Eg: gpt-3.5-turbo,gpt-4",name:"models",children:(0,l.jsx)(y.Z,{placeholder:"gpt-4,gpt-3.5-turbo"})}),(0,l.jsx)(m.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,l.jsx)(Z.Z,{step:.01,precision:2,width:200})}),(0,l.jsx)(m.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,l.jsx)(y.Z,{})}),(0,l.jsx)(m.Z.Item,{label:"Team ID",name:"team_id",children:(0,l.jsx)(y.Z,{placeholder:"ai_team"})}),(0,l.jsx)(m.Z.Item,{label:"Metadata",name:"metadata",children:(0,l.jsx)(y.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,l.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,l.jsx)(p.ZP,{htmlType:"submit",children:"Create Key"})})]})}),f&&(0,l.jsx)(j.Z,{title:"Save your key",visible:k,onOk:b,onCancel:C,footer:null,children:(0,l.jsxs)(d.Z,{numItems:1,className:"gap-2 w-full",children:[(0,l.jsx)(c.Z,{numColSpan:1,children:(0,l.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,l.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,l.jsx)(c.Z,{numColSpan:1,children:null!=f?(0,l.jsxs)(u.Z,{children:["API Key: ",f]}):(0,l.jsx)(u.Z,{children:"Key being created, this might take 30s"})})]})})]})},f=r(3393),w=r(3810),b=r(1244),C=r(827),S=r(3851),I=r(2044),N=r(4167),E=r(4480),v=r(2287),_=r(2440),P=e=>{let{userID:t,accessToken:r,data:s,setData:a}=e,n=async e=>{if(null!=s)try{await o(r,e);let t=s.filter(t=>t.token!==e);a(t)}catch(e){console.error("Error deleting the key:",e)}};if(null!=s)return console.log("RERENDER TRIGGERED"),(0,l.jsxs)(w.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,l.jsx)(_.Z,{children:"API Keys"}),(0,l.jsxs)(C.Z,{className:"mt-5",children:[(0,l.jsx)(N.Z,{children:(0,l.jsxs)(v.Z,{children:[(0,l.jsx)(E.Z,{children:"Secret Key"}),(0,l.jsx)(E.Z,{children:"Spend (USD)"}),(0,l.jsx)(E.Z,{children:"Key Budget (USD)"}),(0,l.jsx)(E.Z,{children:"Team ID"}),(0,l.jsx)(E.Z,{children:"Metadata"}),(0,l.jsx)(E.Z,{children:"Expires"})]})}),(0,l.jsx)(S.Z,{children:s.map(e=>(console.log(e),(0,l.jsxs)(v.Z,{children:[(0,l.jsx)(I.Z,{children:null!=e.key_alias?(0,l.jsx)(u.Z,{children:e.key_alias}):(0,l.jsx)(u.Z,{children:e.token})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:e.spend})}),(0,l.jsx)(I.Z,{children:null!=e.max_budget?(0,l.jsx)(u.Z,{children:e.max_budget}):(0,l.jsx)(u.Z,{children:"Unlimited Budget"})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:e.team_id})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:JSON.stringify(e.metadata)})}),(0,l.jsx)(I.Z,{children:null!=e.expires?(0,l.jsx)(u.Z,{children:e.expires}):(0,l.jsx)(u.Z,{children:"Never expires"})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(b.Z,{onClick:()=>n(e.token),icon:f.Z,size:"xs"})})]},e.token)))})]})]})},D=r(7907),T=r(7963),F=()=>{let[e,t]=(0,s.useState)(null),r=(0,D.useSearchParams)(),a=r.get("userID"),n=r.get("token"),[o,h]=(0,s.useState)(null);return((0,s.useEffect)(()=>{if(n){let e=(0,T.o)(n);e&&(console.log("Decoded token:",e),console.log("Decoded key:",e.key),h(e.key))}a&&o&&!e&&(async()=>{try{let e=await i(o,a);t(e.keys)}catch(e){console.error("There was an error fetching the data",e)}})()},[a,n,o,e]),null==a||null==n)?(window.location.href="/sso/key/generate",null):null==o?null:(0,l.jsx)(d.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,l.jsxs)(c.Z,{numColSpan:1,children:[(0,l.jsx)(P,{userID:a,accessToken:o,data:e,setData:t}),(0,l.jsx)(g,{userID:a,accessToken:o,data:e,setData:t})]})})}}},function(e){e.O(0,[448,971,69,744],function(){return e(e.s=8598)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/litellm/proxy/_experimental/out/_next/static/chunks/app/page-e5227a95293777d5.js b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-e5227a95293777d5.js
new file mode 100644
index 00000000000..d5999b73b85
--- /dev/null
+++ b/litellm/proxy/_experimental/out/_next/static/chunks/app/page-e5227a95293777d5.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{8598:function(e,t,l){Promise.resolve().then(l.t.bind(l,5250,23)),Promise.resolve().then(l.bind(l,3239))},3239:function(e,t,l){"use strict";l.r(t),l.d(t,{default:function(){return F}});var r=l(3827),s=l(4090),a=l(588);let n=async(e,t,l)=>{try{if(console.log("Form Values in keyCreateCall:",l),l.metadata)try{l.metadata=JSON.parse(l.metadata)}catch(e){a.ZP.error("Failed to parse metadata: "+e)}let r=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...l})});if(!r.ok){let e=await r.text();throw a.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await r.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},o=async(e,t)=>{try{console.log("in keyDeleteCall:",t);let l=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!l.ok){let e=await l.text();throw a.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let r=await l.json();return console.log(r),a.ZP.success("API Key Deleted"),r}catch(e){throw console.error("Failed to create key:",e),e}},i=async(e,t)=>{try{let l="/user/info";console.log("in userInfoCall:",l);let r=await fetch("".concat(l,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw a.ZP.error(e),Error("Network response was not ok")}let s=await r.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}};var c=l(384),d=l(6453),h=l(2179),u=l(1801),x=l(6776),m=l(2902),j=l(7171),y=l(9714),Z=l(8707),p=l(1861);let{Option:k}=x.default;var g=e=>{let{userID:t,accessToken:l,data:o,setData:i}=e,[x]=m.Z.useForm(),[k,g]=(0,s.useState)(!1),[f,w]=(0,s.useState)(null),b=()=>{g(!1),x.resetFields()},C=()=>{g(!1),w(null),x.resetFields()},S=async e=>{try{a.ZP.info("Making API Call"),e.models&&""!==e.models.trim()?e.models=e.models.split(",").map(e=>e.trim()):e.models=[],g(!0);let r=await n(l,t,e);i(e=>e?[...e,r]:[r]),w(r.key),a.ZP.success("API Key Created"),x.resetFields()}catch(e){console.error("Error creating the key:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(h.Z,{className:"mx-auto",onClick:()=>g(!0),children:"+ Create New Key"}),(0,r.jsx)(j.Z,{title:"Create Key",visible:k,width:800,footer:null,onOk:b,onCancel:C,children:(0,r.jsxs)(m.Z,{form:x,onFinish:S,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsx)(m.Z.Item,{label:"Key Name",name:"key_alias",children:(0,r.jsx)(y.Z,{})}),(0,r.jsx)(m.Z.Item,{label:"Models (Comma Separated). Eg: gpt-3.5-turbo,gpt-4",name:"models",children:(0,r.jsx)(y.Z,{placeholder:"gpt-4,gpt-3.5-turbo"})}),(0,r.jsx)(m.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(Z.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(m.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,r.jsx)(y.Z,{})}),(0,r.jsx)(m.Z.Item,{label:"Team ID",name:"team_id",children:(0,r.jsx)(y.Z,{placeholder:"ai_team"})}),(0,r.jsx)(m.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(y.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(p.ZP,{htmlType:"submit",children:"Create Key"})})]})}),f&&(0,r.jsx)(j.Z,{title:"Save your key",visible:k,onOk:b,onCancel:C,footer:null,children:(0,r.jsxs)(d.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(c.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)(c.Z,{numColSpan:1,children:null!=f?(0,r.jsxs)(u.Z,{children:["API Key: ",f]}):(0,r.jsx)(u.Z,{children:"Key being created, this might take 30s"})})]})})]})},f=l(3393),w=l(3810),b=l(1244),C=l(827),S=l(3851),I=l(2044),N=l(4167),P=l(4480),E=l(2287),_=l(2440),v=e=>{let{userID:t,accessToken:l,data:s,setData:a}=e,n=async e=>{if(null!=s)try{await o(l,e);let t=s.filter(t=>t.token!==e);a(t)}catch(e){console.error("Error deleting the key:",e)}};if(null!=s)return console.log("RERENDER TRIGGERED"),(0,r.jsxs)(w.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,r.jsx)(_.Z,{children:"API Keys"}),(0,r.jsxs)(C.Z,{className:"mt-5",children:[(0,r.jsx)(N.Z,{children:(0,r.jsxs)(E.Z,{children:[(0,r.jsx)(P.Z,{children:"Key Alias"}),(0,r.jsx)(P.Z,{children:"Secret Key"}),(0,r.jsx)(P.Z,{children:"Spend (USD)"}),(0,r.jsx)(P.Z,{children:"Key Budget (USD)"}),(0,r.jsx)(P.Z,{children:"Team ID"}),(0,r.jsx)(P.Z,{children:"Metadata"}),(0,r.jsx)(P.Z,{children:"Expires"})]})}),(0,r.jsx)(S.Z,{children:s.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,r.jsxs)(E.Z,{children:[(0,r.jsx)(I.Z,{children:null!=e.key_alias?(0,r.jsx)(u.Z,{children:e.key_alias}):(0,r.jsx)(u.Z,{children:"Not Set"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.key_name})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.spend})}),(0,r.jsx)(I.Z,{children:null!=e.max_budget?(0,r.jsx)(u.Z,{children:e.max_budget}):(0,r.jsx)(u.Z,{children:"Unlimited Budget"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.team_id})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:JSON.stringify(e.metadata)})}),(0,r.jsx)(I.Z,{children:null!=e.expires?(0,r.jsx)(u.Z,{children:e.expires}):(0,r.jsx)(u.Z,{children:"Never expires"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(b.Z,{onClick:()=>n(e.token),icon:f.Z,size:"xs"})})]},e.token))})]})]})},D=l(7907),T=l(7963),F=()=>{let[e,t]=(0,s.useState)(null),l=(0,D.useSearchParams)(),a=l.get("userID"),n=l.get("token"),[o,h]=(0,s.useState)(null);if((0,s.useEffect)(()=>{if(n){let e=(0,T.o)(n);e&&(console.log("Decoded token:",e),console.log("Decoded key:",e.key),h(e.key))}a&&o&&!e&&(async()=>{try{let e=await i(o,a);t(e.keys)}catch(e){console.error("There was an error fetching the data",e)}})()},[a,n,o,e]),null==a||null==n){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==o?null:(0,r.jsx)(d.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,r.jsxs)(c.Z,{numColSpan:1,children:[(0,r.jsx)(v,{userID:a,accessToken:o,data:e,setData:t}),(0,r.jsx)(g,{userID:a,accessToken:o,data:e,setData:t})]})})}}},function(e){e.O(0,[448,971,69,744],function(){return e(e.s=8598)}),_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 fe26a9f0ba4..7ad6dd2c0b6 100644
--- a/litellm/proxy/_experimental/out/index.html
+++ b/litellm/proxy/_experimental/out/index.html
@@ -1 +1 @@
-Create Next App
Loading...
\ No newline at end of file
+Create Next App
Loading...
\ No newline at end of file
diff --git a/litellm/proxy/_experimental/out/index.txt b/litellm/proxy/_experimental/out/index.txt
index 1cec7f58a76..d31c7af9252 100644
--- a/litellm/proxy/_experimental/out/index.txt
+++ b/litellm/proxy/_experimental/out/index.txt
@@ -1,8 +1,8 @@
2:"$Sreact.suspense"
-3:I[5250,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-cf0440186224a114.js"],""]
-4:I[3239,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-cf0440186224a114.js"],""]
+3:I[5250,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-e5227a95293777d5.js"],""]
+4:I[3239,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-e5227a95293777d5.js"],""]
5:I[5613,[],""]
6:I[1778,[],""]
-0:["9KvKBLd4AqpwRy9Epc-98",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$2",null,{"fallback":["$","div",null,{"children":"Loading..."}],"children":["$","div",null,{"className":"flex min-h-screen flex-col items-center","children":[["$","nav",null,{"className":"left-0 right-0 top-0 flex justify-between items-center h-12","children":[["$","div",null,{"className":"text-left mx-4 my-2 absolute top-0 left-0","children":["$","div",null,{"className":"flex flex-col items-center","children":["$","$L3",null,{"href":"/","children":["$","button",null,{"className":"text-gray-800 text-2xl px-4 py-1 rounded text-center","children":"🚅 LiteLLM"}]}]}]}],["$","div",null,{"className":"text-right mx-4 my-2 absolute top-0 right-0","children":[["$","a",null,{"href":"https://docs.litellm.ai/docs/","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 mr-2 text-center","children":"Docs"}]}],["$","a",null,{"href":"https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 text-center","children":"Schedule Demo"}]}]]}]]}],["$","$L4",null,{}]]}]}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",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/7384ba6288e79f81.css","precedence":"next","crossOrigin":""}]],"$L7"]]]]
+0:["B4oAVsVV35eL3Y1bPepKW",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$2",null,{"fallback":["$","div",null,{"children":"Loading..."}],"children":["$","div",null,{"className":"flex min-h-screen flex-col items-center","children":[["$","nav",null,{"className":"left-0 right-0 top-0 flex justify-between items-center h-12","children":[["$","div",null,{"className":"text-left mx-4 my-2 absolute top-0 left-0","children":["$","div",null,{"className":"flex flex-col items-center","children":["$","$L3",null,{"href":"/","children":["$","button",null,{"className":"text-gray-800 text-2xl px-4 py-1 rounded text-center","children":"🚅 LiteLLM"}]}]}]}],["$","div",null,{"className":"text-right mx-4 my-2 absolute top-0 right-0","children":[["$","a",null,{"href":"https://docs.litellm.ai/docs/","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 mr-2 text-center","children":"Docs"}]}],["$","a",null,{"href":"https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 text-center","children":"Schedule Demo"}]}]]}]]}],["$","$L4",null,{}]]}]}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",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/7384ba6288e79f81.css","precedence":"next","crossOrigin":""}]],"$L7"]]]]
7:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"Create Next App"}],["$","meta","3",{"name":"description","content":"Generated by create next app"}],["$","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/proxy_server.py b/litellm/proxy/proxy_server.py
index dd8124285c0..9170305dff4 100644
--- a/litellm/proxy/proxy_server.py
+++ b/litellm/proxy/proxy_server.py
@@ -1452,11 +1452,14 @@ async def generate_key_helper_fn(
saved_token["expires"], datetime
):
saved_token["expires"] = saved_token["expires"].isoformat()
- user_api_key_cache.set_cache(
- key=key_data["token"],
- value=LiteLLM_VerificationToken(**saved_token), # type: ignore
- ttl=60,
- )
+ if key_data["token"] is not None and isinstance(key_data["token"], str):
+ hashed_token = hash_token(key_data["token"])
+ saved_token["token"] = hashed_token
+ user_api_key_cache.set_cache(
+ key=hashed_token,
+ value=LiteLLM_VerificationToken(**saved_token), # type: ignore
+ ttl=60,
+ )
if prisma_client is not None:
## CREATE USER (If necessary)
verbose_proxy_logger.debug(f"prisma_client: Creating User={user_data}")
@@ -2672,13 +2675,32 @@ async def delete_key_fn(data: DeleteKeyRequest):
HTTPException: If an error occurs during key deletion.
"""
try:
+ global user_api_key_cache
keys = data.keys
+ if len(keys) == 0:
+ raise ProxyException(
+ message=f"No keys provided, passed in: keys={keys}",
+ type="auth_error",
+ param="keys",
+ code=status.HTTP_400_BAD_REQUEST,
+ )
result = await delete_verification_token(tokens=keys)
verbose_proxy_logger.debug("/key/delete - deleted_keys=", result)
number_deleted_keys = len(result["deleted_keys"])
assert len(keys) == number_deleted_keys
+
+ for key in keys:
+ user_api_key_cache.delete_cache(key)
+ # remove hash token from cache
+ hashed_token = hash_token(key)
+ user_api_key_cache.delete_cache(hashed_token)
+
+ verbose_proxy_logger.debug(
+ f"/keys/delete - cache after delete: {user_api_key_cache.in_memory_cache.cache_dict}"
+ )
+
return {"deleted_keys": keys}
except Exception as e:
if isinstance(e, HTTPException):
@@ -3165,9 +3187,16 @@ async def login(request: Request):
):
user_id = username
# User is Authe'd in - generate key for the UI to access Proxy
- response = await generate_key_helper_fn(
- **{"duration": "1hr", "key_max_budget": 0, "models": [], "aliases": {}, "config": {}, "spend": 0, "user_id": user_id, "team_id": "litellm-dashboard"} # type: ignore
- )
+
+ if os.getenv("DATABASE_URL") is not None:
+ response = await generate_key_helper_fn(
+ **{"duration": "1hr", "key_max_budget": 0, "models": [], "aliases": {}, "config": {}, "spend": 0, "user_id": user_id, "team_id": "litellm-dashboard"} # type: ignore
+ )
+ else:
+ response = {
+ "token": "sk-gm",
+ "user_id": "litellm-dashboard",
+ }
key = response["token"] # type: ignore
user_id = response["user_id"] # type: ignore
diff --git a/litellm/tests/test_key_generate_prisma.py b/litellm/tests/test_key_generate_prisma.py
index 55bc3cec82b..140d638e880 100644
--- a/litellm/tests/test_key_generate_prisma.py
+++ b/litellm/tests/test_key_generate_prisma.py
@@ -104,6 +104,8 @@ def test_generate_and_call_with_valid_key(prisma_client):
async def test():
await litellm.proxy.proxy_server.prisma_client.connect()
+ from litellm.proxy.proxy_server import user_api_key_cache
+
request = NewUserRequest()
key = await new_user(request)
print(key)
@@ -111,6 +113,26 @@ def test_generate_and_call_with_valid_key(prisma_client):
generated_key = key.key
bearer_token = "Bearer " + generated_key
+ assert generated_key not in user_api_key_cache.in_memory_cache.cache_dict
+ assert (
+ hash_token(generated_key)
+ in user_api_key_cache.in_memory_cache.cache_dict
+ )
+
+ cached_value = user_api_key_cache.in_memory_cache.cache_dict[
+ hash_token(generated_key)
+ ]
+
+ print("cached value=", cached_value)
+ print("cached token", cached_value.token)
+
+ value_from_prisma = valid_token = await prisma_client.get_data(
+ token=generated_key,
+ )
+ print("token from prisma", value_from_prisma)
+
+ assert value_from_prisma.token == cached_value.token
+
request = Request(scope={"type": "http"})
request._url = URL(url="/chat/completions")
@@ -618,6 +640,8 @@ def test_delete_key(prisma_client):
async def test():
await litellm.proxy.proxy_server.prisma_client.connect()
+ from litellm.proxy.proxy_server import user_api_key_cache
+
request = NewUserRequest()
key = await new_user(request)
print(key)
@@ -632,6 +656,12 @@ def test_delete_key(prisma_client):
print("result from delete key", result_delete_key)
assert result_delete_key == {"deleted_keys": [generated_key]}
+ assert generated_key not in user_api_key_cache.in_memory_cache.cache_dict
+ assert (
+ hash_token(generated_key)
+ not in user_api_key_cache.in_memory_cache.cache_dict
+ )
+
asyncio.run(test())
except Exception as e:
pytest.fail(f"An exception occurred - {str(e)}")
@@ -648,6 +678,8 @@ def test_delete_key_auth(prisma_client):
async def test():
await litellm.proxy.proxy_server.prisma_client.connect()
+ from litellm.proxy.proxy_server import user_api_key_cache
+
request = NewUserRequest()
key = await new_user(request)
print(key)
@@ -666,6 +698,12 @@ def test_delete_key_auth(prisma_client):
request = Request(scope={"type": "http"}, receive=None)
request._url = URL(url="/chat/completions")
+ assert generated_key not in user_api_key_cache.in_memory_cache.cache_dict
+ assert (
+ hash_token(generated_key)
+ not in user_api_key_cache.in_memory_cache.cache_dict
+ )
+
# use generated key to auth in
result = await user_api_key_auth(request=request, api_key=bearer_token)
print("got result", result)
diff --git a/tests/test_keys.py b/tests/test_keys.py
index 75baf966eba..9cbcc25e16b 100644
--- a/tests/test_keys.py
+++ b/tests/test_keys.py
@@ -234,7 +234,9 @@ async def get_key_info(session, call_key, get_key=None):
return status
else:
print(f"call_key: {call_key}; get_key: {get_key}")
- raise Exception(f"Request did not return a 200 status code: {status}")
+ raise Exception(
+ f"Request did not return a 200 status code: {status}. Responses {response_text}"
+ )
return await response.json()
@@ -282,7 +284,7 @@ async def get_spend_logs(session, request_id):
@pytest.mark.asyncio
async def test_key_info_spend_values():
"""
- Test to ensure spend is correctly calculated.
+ Test to ensure spend is correctly calculated
- create key
- make completion call
- assert cost is expected value
diff --git a/ui/litellm-dashboard/out/404.html b/ui/litellm-dashboard/out/404.html
index adedbe62c65..56852eeb12e 100644
--- a/ui/litellm-dashboard/out/404.html
+++ b/ui/litellm-dashboard/out/404.html
@@ -1 +1 @@
-404: This page could not be found.Create Next App
404
This page could not be found.
\ No newline at end of file
+404: This page could not be found.Create Next App
404
This page could not be found.
\ No newline at end of file
diff --git a/ui/litellm-dashboard/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_buildManifest.js b/ui/litellm-dashboard/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_buildManifest.js
similarity index 100%
rename from ui/litellm-dashboard/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_buildManifest.js
rename to ui/litellm-dashboard/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_buildManifest.js
diff --git a/ui/litellm-dashboard/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_ssgManifest.js b/ui/litellm-dashboard/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_ssgManifest.js
similarity index 100%
rename from ui/litellm-dashboard/out/_next/static/9KvKBLd4AqpwRy9Epc-98/_ssgManifest.js
rename to ui/litellm-dashboard/out/_next/static/B4oAVsVV35eL3Y1bPepKW/_ssgManifest.js
diff --git a/ui/litellm-dashboard/out/_next/static/chunks/app/page-cf0440186224a114.js b/ui/litellm-dashboard/out/_next/static/chunks/app/page-cf0440186224a114.js
deleted file mode 100644
index da9b6b57020..00000000000
--- a/ui/litellm-dashboard/out/_next/static/chunks/app/page-cf0440186224a114.js
+++ /dev/null
@@ -1 +0,0 @@
-(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{8598:function(e,t,r){Promise.resolve().then(r.t.bind(r,5250,23)),Promise.resolve().then(r.bind(r,3239))},3239:function(e,t,r){"use strict";r.r(t),r.d(t,{default:function(){return F}});var l=r(3827),s=r(4090),a=r(588);let n=async(e,t,r)=>{try{if(console.log("Form Values in keyCreateCall:",r),r.metadata)try{r.metadata=JSON.parse(r.metadata)}catch(e){a.ZP.error("Failed to parse metadata: "+e)}let l=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...r})});if(!l.ok){let e=await l.text();throw a.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await l.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},o=async(e,t)=>{try{let r=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!r.ok)throw Error("Network response was not ok");let l=await r.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}},i=async(e,t)=>{try{let r=await fetch("/user/info?user_id=".concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok)throw Error("Network response was not ok");let l=await r.json();return console.log(l),l}catch(e){throw console.error("Failed to create key:",e),e}};var c=r(384),d=r(6453),h=r(2179),u=r(1801),x=r(6776),m=r(2902),j=r(7171),y=r(9714),Z=r(8707),p=r(1861);let{Option:k}=x.default;var g=e=>{let{userID:t,accessToken:r,data:o,setData:i}=e,[x]=m.Z.useForm(),[k,g]=(0,s.useState)(!1),[f,w]=(0,s.useState)(null),b=()=>{g(!1),x.resetFields()},C=()=>{g(!1),w(null),x.resetFields()},S=async e=>{try{a.ZP.info("Making API Call"),e.models&&""!==e.models.trim()?e.models=e.models.split(",").map(e=>e.trim()):e.models=[],g(!0);let l=await n(r,t,e);i(e=>e?[...e,l]:[l]),w(l.key),a.ZP.success("API Key Created"),x.resetFields()}catch(e){console.error("Error creating the key:",e)}};return(0,l.jsxs)("div",{children:[(0,l.jsx)(h.Z,{className:"mx-auto",onClick:()=>g(!0),children:"+ Create New Key"}),(0,l.jsx)(j.Z,{title:"Create Key",visible:k,width:800,footer:null,onOk:b,onCancel:C,children:(0,l.jsxs)(m.Z,{form:x,onFinish:S,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:[(0,l.jsx)(m.Z.Item,{label:"Key Name",name:"key_alias",children:(0,l.jsx)(y.Z,{})}),(0,l.jsx)(m.Z.Item,{label:"Models (Comma Separated). Eg: gpt-3.5-turbo,gpt-4",name:"models",children:(0,l.jsx)(y.Z,{placeholder:"gpt-4,gpt-3.5-turbo"})}),(0,l.jsx)(m.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,l.jsx)(Z.Z,{step:.01,precision:2,width:200})}),(0,l.jsx)(m.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,l.jsx)(y.Z,{})}),(0,l.jsx)(m.Z.Item,{label:"Team ID",name:"team_id",children:(0,l.jsx)(y.Z,{placeholder:"ai_team"})}),(0,l.jsx)(m.Z.Item,{label:"Metadata",name:"metadata",children:(0,l.jsx)(y.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,l.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,l.jsx)(p.ZP,{htmlType:"submit",children:"Create Key"})})]})}),f&&(0,l.jsx)(j.Z,{title:"Save your key",visible:k,onOk:b,onCancel:C,footer:null,children:(0,l.jsxs)(d.Z,{numItems:1,className:"gap-2 w-full",children:[(0,l.jsx)(c.Z,{numColSpan:1,children:(0,l.jsxs)("p",{children:["Please save this secret key somewhere safe and accessible. For security reasons, ",(0,l.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,l.jsx)(c.Z,{numColSpan:1,children:null!=f?(0,l.jsxs)(u.Z,{children:["API Key: ",f]}):(0,l.jsx)(u.Z,{children:"Key being created, this might take 30s"})})]})})]})},f=r(3393),w=r(3810),b=r(1244),C=r(827),S=r(3851),I=r(2044),N=r(4167),E=r(4480),v=r(2287),_=r(2440),P=e=>{let{userID:t,accessToken:r,data:s,setData:a}=e,n=async e=>{if(null!=s)try{await o(r,e);let t=s.filter(t=>t.token!==e);a(t)}catch(e){console.error("Error deleting the key:",e)}};if(null!=s)return console.log("RERENDER TRIGGERED"),(0,l.jsxs)(w.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,l.jsx)(_.Z,{children:"API Keys"}),(0,l.jsxs)(C.Z,{className:"mt-5",children:[(0,l.jsx)(N.Z,{children:(0,l.jsxs)(v.Z,{children:[(0,l.jsx)(E.Z,{children:"Secret Key"}),(0,l.jsx)(E.Z,{children:"Spend (USD)"}),(0,l.jsx)(E.Z,{children:"Key Budget (USD)"}),(0,l.jsx)(E.Z,{children:"Team ID"}),(0,l.jsx)(E.Z,{children:"Metadata"}),(0,l.jsx)(E.Z,{children:"Expires"})]})}),(0,l.jsx)(S.Z,{children:s.map(e=>(console.log(e),(0,l.jsxs)(v.Z,{children:[(0,l.jsx)(I.Z,{children:null!=e.key_alias?(0,l.jsx)(u.Z,{children:e.key_alias}):(0,l.jsx)(u.Z,{children:e.token})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:e.spend})}),(0,l.jsx)(I.Z,{children:null!=e.max_budget?(0,l.jsx)(u.Z,{children:e.max_budget}):(0,l.jsx)(u.Z,{children:"Unlimited Budget"})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:e.team_id})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(u.Z,{children:JSON.stringify(e.metadata)})}),(0,l.jsx)(I.Z,{children:null!=e.expires?(0,l.jsx)(u.Z,{children:e.expires}):(0,l.jsx)(u.Z,{children:"Never expires"})}),(0,l.jsx)(I.Z,{children:(0,l.jsx)(b.Z,{onClick:()=>n(e.token),icon:f.Z,size:"xs"})})]},e.token)))})]})]})},D=r(7907),T=r(7963),F=()=>{let[e,t]=(0,s.useState)(null),r=(0,D.useSearchParams)(),a=r.get("userID"),n=r.get("token"),[o,h]=(0,s.useState)(null);return((0,s.useEffect)(()=>{if(n){let e=(0,T.o)(n);e&&(console.log("Decoded token:",e),console.log("Decoded key:",e.key),h(e.key))}a&&o&&!e&&(async()=>{try{let e=await i(o,a);t(e.keys)}catch(e){console.error("There was an error fetching the data",e)}})()},[a,n,o,e]),null==a||null==n)?(window.location.href="/sso/key/generate",null):null==o?null:(0,l.jsx)(d.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,l.jsxs)(c.Z,{numColSpan:1,children:[(0,l.jsx)(P,{userID:a,accessToken:o,data:e,setData:t}),(0,l.jsx)(g,{userID:a,accessToken:o,data:e,setData:t})]})})}}},function(e){e.O(0,[448,971,69,744],function(){return e(e.s=8598)}),_N_E=e.O()}]);
\ No newline at end of file
diff --git a/ui/litellm-dashboard/out/_next/static/chunks/app/page-e5227a95293777d5.js b/ui/litellm-dashboard/out/_next/static/chunks/app/page-e5227a95293777d5.js
new file mode 100644
index 00000000000..d5999b73b85
--- /dev/null
+++ b/ui/litellm-dashboard/out/_next/static/chunks/app/page-e5227a95293777d5.js
@@ -0,0 +1 @@
+(self.webpackChunk_N_E=self.webpackChunk_N_E||[]).push([[931],{8598:function(e,t,l){Promise.resolve().then(l.t.bind(l,5250,23)),Promise.resolve().then(l.bind(l,3239))},3239:function(e,t,l){"use strict";l.r(t),l.d(t,{default:function(){return F}});var r=l(3827),s=l(4090),a=l(588);let n=async(e,t,l)=>{try{if(console.log("Form Values in keyCreateCall:",l),l.metadata)try{l.metadata=JSON.parse(l.metadata)}catch(e){a.ZP.error("Failed to parse metadata: "+e)}let r=await fetch("/key/generate",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({user_id:t,...l})});if(!r.ok){let e=await r.text();throw a.ZP.error("Failed to create key: "+e),console.error("Error response from the server:",e),Error("Network response was not ok")}let s=await r.json();return console.log("API Response:",s),s}catch(e){throw console.error("Failed to create key:",e),e}},o=async(e,t)=>{try{console.log("in keyDeleteCall:",t);let l=await fetch("/key/delete",{method:"POST",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"},body:JSON.stringify({keys:[t]})});if(!l.ok){let e=await l.text();throw a.ZP.error("Failed to delete key: "+e),Error("Network response was not ok")}let r=await l.json();return console.log(r),a.ZP.success("API Key Deleted"),r}catch(e){throw console.error("Failed to create key:",e),e}},i=async(e,t)=>{try{let l="/user/info";console.log("in userInfoCall:",l);let r=await fetch("".concat(l,"/?user_id=").concat(t),{method:"GET",headers:{Authorization:"Bearer ".concat(e),"Content-Type":"application/json"}});if(!r.ok){let e=await r.text();throw a.ZP.error(e),Error("Network response was not ok")}let s=await r.json();return console.log(s),s}catch(e){throw console.error("Failed to create key:",e),e}};var c=l(384),d=l(6453),h=l(2179),u=l(1801),x=l(6776),m=l(2902),j=l(7171),y=l(9714),Z=l(8707),p=l(1861);let{Option:k}=x.default;var g=e=>{let{userID:t,accessToken:l,data:o,setData:i}=e,[x]=m.Z.useForm(),[k,g]=(0,s.useState)(!1),[f,w]=(0,s.useState)(null),b=()=>{g(!1),x.resetFields()},C=()=>{g(!1),w(null),x.resetFields()},S=async e=>{try{a.ZP.info("Making API Call"),e.models&&""!==e.models.trim()?e.models=e.models.split(",").map(e=>e.trim()):e.models=[],g(!0);let r=await n(l,t,e);i(e=>e?[...e,r]:[r]),w(r.key),a.ZP.success("API Key Created"),x.resetFields()}catch(e){console.error("Error creating the key:",e)}};return(0,r.jsxs)("div",{children:[(0,r.jsx)(h.Z,{className:"mx-auto",onClick:()=>g(!0),children:"+ Create New Key"}),(0,r.jsx)(j.Z,{title:"Create Key",visible:k,width:800,footer:null,onOk:b,onCancel:C,children:(0,r.jsxs)(m.Z,{form:x,onFinish:S,labelCol:{span:6},wrapperCol:{span:16},labelAlign:"left",children:[(0,r.jsx)(m.Z.Item,{label:"Key Name",name:"key_alias",children:(0,r.jsx)(y.Z,{})}),(0,r.jsx)(m.Z.Item,{label:"Models (Comma Separated). Eg: gpt-3.5-turbo,gpt-4",name:"models",children:(0,r.jsx)(y.Z,{placeholder:"gpt-4,gpt-3.5-turbo"})}),(0,r.jsx)(m.Z.Item,{label:"Max Budget (USD)",name:"max_budget",children:(0,r.jsx)(Z.Z,{step:.01,precision:2,width:200})}),(0,r.jsx)(m.Z.Item,{label:"Duration (eg: 30s, 30h, 30d)",name:"duration",children:(0,r.jsx)(y.Z,{})}),(0,r.jsx)(m.Z.Item,{label:"Team ID",name:"team_id",children:(0,r.jsx)(y.Z,{placeholder:"ai_team"})}),(0,r.jsx)(m.Z.Item,{label:"Metadata",name:"metadata",children:(0,r.jsx)(y.Z.TextArea,{rows:4,placeholder:"Enter metadata as JSON"})}),(0,r.jsx)("div",{style:{textAlign:"right",marginTop:"10px"},children:(0,r.jsx)(p.ZP,{htmlType:"submit",children:"Create Key"})})]})}),f&&(0,r.jsx)(j.Z,{title:"Save your key",visible:k,onOk:b,onCancel:C,footer:null,children:(0,r.jsxs)(d.Z,{numItems:1,className:"gap-2 w-full",children:[(0,r.jsx)(c.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)(c.Z,{numColSpan:1,children:null!=f?(0,r.jsxs)(u.Z,{children:["API Key: ",f]}):(0,r.jsx)(u.Z,{children:"Key being created, this might take 30s"})})]})})]})},f=l(3393),w=l(3810),b=l(1244),C=l(827),S=l(3851),I=l(2044),N=l(4167),P=l(4480),E=l(2287),_=l(2440),v=e=>{let{userID:t,accessToken:l,data:s,setData:a}=e,n=async e=>{if(null!=s)try{await o(l,e);let t=s.filter(t=>t.token!==e);a(t)}catch(e){console.error("Error deleting the key:",e)}};if(null!=s)return console.log("RERENDER TRIGGERED"),(0,r.jsxs)(w.Z,{className:"w-full mx-auto flex-auto overflow-y-auto max-h-[50vh] mb-4",children:[(0,r.jsx)(_.Z,{children:"API Keys"}),(0,r.jsxs)(C.Z,{className:"mt-5",children:[(0,r.jsx)(N.Z,{children:(0,r.jsxs)(E.Z,{children:[(0,r.jsx)(P.Z,{children:"Key Alias"}),(0,r.jsx)(P.Z,{children:"Secret Key"}),(0,r.jsx)(P.Z,{children:"Spend (USD)"}),(0,r.jsx)(P.Z,{children:"Key Budget (USD)"}),(0,r.jsx)(P.Z,{children:"Team ID"}),(0,r.jsx)(P.Z,{children:"Metadata"}),(0,r.jsx)(P.Z,{children:"Expires"})]})}),(0,r.jsx)(S.Z,{children:s.map(e=>(console.log(e),"litellm-dashboard"===e.team_id)?null:(0,r.jsxs)(E.Z,{children:[(0,r.jsx)(I.Z,{children:null!=e.key_alias?(0,r.jsx)(u.Z,{children:e.key_alias}):(0,r.jsx)(u.Z,{children:"Not Set"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.key_name})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.spend})}),(0,r.jsx)(I.Z,{children:null!=e.max_budget?(0,r.jsx)(u.Z,{children:e.max_budget}):(0,r.jsx)(u.Z,{children:"Unlimited Budget"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:e.team_id})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(u.Z,{children:JSON.stringify(e.metadata)})}),(0,r.jsx)(I.Z,{children:null!=e.expires?(0,r.jsx)(u.Z,{children:e.expires}):(0,r.jsx)(u.Z,{children:"Never expires"})}),(0,r.jsx)(I.Z,{children:(0,r.jsx)(b.Z,{onClick:()=>n(e.token),icon:f.Z,size:"xs"})})]},e.token))})]})]})},D=l(7907),T=l(7963),F=()=>{let[e,t]=(0,s.useState)(null),l=(0,D.useSearchParams)(),a=l.get("userID"),n=l.get("token"),[o,h]=(0,s.useState)(null);if((0,s.useEffect)(()=>{if(n){let e=(0,T.o)(n);e&&(console.log("Decoded token:",e),console.log("Decoded key:",e.key),h(e.key))}a&&o&&!e&&(async()=>{try{let e=await i(o,a);t(e.keys)}catch(e){console.error("There was an error fetching the data",e)}})()},[a,n,o,e]),null==a||null==n){let e="/sso/key/generate";return console.log("Full URL:",e),window.location.href=e,null}return null==o?null:(0,r.jsx)(d.Z,{numItems:1,className:"gap-0 p-10 h-[75vh] w-full",children:(0,r.jsxs)(c.Z,{numColSpan:1,children:[(0,r.jsx)(v,{userID:a,accessToken:o,data:e,setData:t}),(0,r.jsx)(g,{userID:a,accessToken:o,data:e,setData:t})]})})}}},function(e){e.O(0,[448,971,69,744],function(){return e(e.s=8598)}),_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 fe26a9f0ba4..7ad6dd2c0b6 100644
--- a/ui/litellm-dashboard/out/index.html
+++ b/ui/litellm-dashboard/out/index.html
@@ -1 +1 @@
-Create Next App
Loading...
\ No newline at end of file
+Create Next App
Loading...
\ No newline at end of file
diff --git a/ui/litellm-dashboard/out/index.txt b/ui/litellm-dashboard/out/index.txt
index 1cec7f58a76..d31c7af9252 100644
--- a/ui/litellm-dashboard/out/index.txt
+++ b/ui/litellm-dashboard/out/index.txt
@@ -1,8 +1,8 @@
2:"$Sreact.suspense"
-3:I[5250,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-cf0440186224a114.js"],""]
-4:I[3239,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-cf0440186224a114.js"],""]
+3:I[5250,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-e5227a95293777d5.js"],""]
+4:I[3239,["448","static/chunks/448-cd38799829cf7b57.js","931","static/chunks/app/page-e5227a95293777d5.js"],""]
5:I[5613,[],""]
6:I[1778,[],""]
-0:["9KvKBLd4AqpwRy9Epc-98",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$2",null,{"fallback":["$","div",null,{"children":"Loading..."}],"children":["$","div",null,{"className":"flex min-h-screen flex-col items-center","children":[["$","nav",null,{"className":"left-0 right-0 top-0 flex justify-between items-center h-12","children":[["$","div",null,{"className":"text-left mx-4 my-2 absolute top-0 left-0","children":["$","div",null,{"className":"flex flex-col items-center","children":["$","$L3",null,{"href":"/","children":["$","button",null,{"className":"text-gray-800 text-2xl px-4 py-1 rounded text-center","children":"🚅 LiteLLM"}]}]}]}],["$","div",null,{"className":"text-right mx-4 my-2 absolute top-0 right-0","children":[["$","a",null,{"href":"https://docs.litellm.ai/docs/","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 mr-2 text-center","children":"Docs"}]}],["$","a",null,{"href":"https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 text-center","children":"Schedule Demo"}]}]]}]]}],["$","$L4",null,{}]]}]}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",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/7384ba6288e79f81.css","precedence":"next","crossOrigin":""}]],"$L7"]]]]
+0:["B4oAVsVV35eL3Y1bPepKW",[[["",{"children":["__PAGE__",{}]},"$undefined","$undefined",true],["",{"children":["__PAGE__",{},["$L1",["$","$2",null,{"fallback":["$","div",null,{"children":"Loading..."}],"children":["$","div",null,{"className":"flex min-h-screen flex-col items-center","children":[["$","nav",null,{"className":"left-0 right-0 top-0 flex justify-between items-center h-12","children":[["$","div",null,{"className":"text-left mx-4 my-2 absolute top-0 left-0","children":["$","div",null,{"className":"flex flex-col items-center","children":["$","$L3",null,{"href":"/","children":["$","button",null,{"className":"text-gray-800 text-2xl px-4 py-1 rounded text-center","children":"🚅 LiteLLM"}]}]}]}],["$","div",null,{"className":"text-right mx-4 my-2 absolute top-0 right-0","children":[["$","a",null,{"href":"https://docs.litellm.ai/docs/","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 mr-2 text-center","children":"Docs"}]}],["$","a",null,{"href":"https://calendly.com/d/4mp-gd3-k5k/berriai-1-1-onboarding-litellm-hosted-version","target":"_blank","rel":"noopener noreferrer","children":["$","button",null,{"className":"border border-gray-800 rounded-lg text-gray-800 text-xl px-4 py-1 rounded p-1 text-center","children":"Schedule Demo"}]}]]}]]}],["$","$L4",null,{}]]}]}],null]]},[null,["$","html",null,{"lang":"en","children":["$","body",null,{"className":"__className_c23dc8","children":["$","$L5",null,{"parallelRouterKey":"children","segmentPath":["children"],"loading":"$undefined","loadingStyles":"$undefined","loadingScripts":"$undefined","hasLoading":false,"error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L6",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/7384ba6288e79f81.css","precedence":"next","crossOrigin":""}]],"$L7"]]]]
7:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"Create Next App"}],["$","meta","3",{"name":"description","content":"Generated by create next app"}],["$","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/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx
index dcc48de380a..6384005c1af 100644
--- a/ui/litellm-dashboard/src/components/networking.tsx
+++ b/ui/litellm-dashboard/src/components/networking.tsx
@@ -3,10 +3,12 @@
*/
import { message } from 'antd';
+const proxyBaseUrl = null
+
export const keyCreateCall = async (
accessToken: string,
userID: string,
- formValues: Record // Assuming formValues is an object
+ formValues: Record, // Assuming formValues is an object
) => {
try {
console.log("Form Values in keyCreateCall:", formValues); // Log the form values before making the API call
@@ -20,8 +22,8 @@ export const keyCreateCall = async (
message.error("Failed to parse metadata: " + error);
}
}
-
- const response = await fetch(`/key/generate`, {
+ const url = proxyBaseUrl ? `${proxyBaseUrl}/key/generate` : `/key/generate`;
+ const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
@@ -56,7 +58,10 @@ export const keyDeleteCall = async (
user_key: String
) => {
try {
- const response = await fetch(`/key/delete`, {
+ const url = proxyBaseUrl ? `${proxyBaseUrl}/key/delete` : `/key/delete`;
+ console.log("in keyDeleteCall:", user_key)
+
+ const response = await fetch(url, {
method: "POST",
headers: {
Authorization: `Bearer ${accessToken}`,
@@ -68,11 +73,14 @@ export const keyDeleteCall = async (
});
if (!response.ok) {
+ const errorData = await response.text();
+ message.error("Failed to delete key: " + errorData);
throw new Error("Network response was not ok");
}
const data = await response.json();
console.log(data);
+ message.success("API Key Deleted");
return data;
// Handle success - you might want to update some state or UI based on the created key
} catch (error) {
@@ -86,8 +94,10 @@ export const userInfoCall = async (
userID: String
) => {
try {
+ const url = proxyBaseUrl ? `${proxyBaseUrl}/user/info` : `/user/info`;
+ console.log("in userInfoCall:", url)
const response = await fetch(
- `/user/info?user_id=${userID}`,
+ `${url}/?user_id=${userID}`,
{
method: "GET",
headers: {
@@ -98,6 +108,8 @@ export const userInfoCall = async (
);
if (!response.ok) {
+ const errorData = await response.text();
+ message.error(errorData);
throw new Error("Network response was not ok");
}
diff --git a/ui/litellm-dashboard/src/components/user_dashboard.tsx b/ui/litellm-dashboard/src/components/user_dashboard.tsx
index dccbd21dbfd..4a0a72e189d 100644
--- a/ui/litellm-dashboard/src/components/user_dashboard.tsx
+++ b/ui/litellm-dashboard/src/components/user_dashboard.tsx
@@ -8,6 +8,8 @@ import EnterProxyUrl from "./enter_proxy_url";
import { useSearchParams } from "next/navigation";
import { jwtDecode } from "jwt-decode";
+const proxyBaseUrl = null
+
const UserDashboard = () => {
const [data, setData] = useState(null); // Keep the initialization of state here
// Assuming useSearchParams() hook exists and works in your setup
@@ -53,8 +55,8 @@ const UserDashboard = () => {
// Now you can construct the full URL
- const url = `/sso/key/generate`;
-
+ const url = proxyBaseUrl ? `${proxyBaseUrl}/sso/key/generate` : `/sso/key/generate`;
+ console.log("Full URL:", url);
window.location.href = url;
return null;
diff --git a/ui/litellm-dashboard/src/components/view_key_table.tsx b/ui/litellm-dashboard/src/components/view_key_table.tsx
index bcfa8a23e6f..e7e2cc967b4 100644
--- a/ui/litellm-dashboard/src/components/view_key_table.tsx
+++ b/ui/litellm-dashboard/src/components/view_key_table.tsx
@@ -67,6 +67,10 @@ const ViewKeyTable: React.FC = ({
{data.map((item) => {
console.log(item);
+ // skip item if item.team_id == "litellm-dashboard"
+ if (item.team_id === "litellm-dashboard") {
+ return null;
+ }
return (