forked from phoenix/litellm-mirror
fix: stability fixes for ui
This commit is contained in:
parent
034ca95a94
commit
524cdb74a4
16 changed files with 248 additions and 120 deletions
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-a85b2c176012d8e5.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-e1b183dda365ec86.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>🚅 LiteLLM</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[30280,[\"303\",\"static/chunks/303-d80f23087a9e6aec.js\",\"931\",\"static/chunks/app/page-f5480eede36fdcd5.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"HOfpn9FdKIMCOfG_am2z2\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",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]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"🚅 LiteLLM\"}],[\"$\",\"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\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-a85b2c176012d8e5.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-e1b183dda365ec86.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>🚅 LiteLLM</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[30280,[\"303\",\"static/chunks/303-d80f23087a9e6aec.js\",\"931\",\"static/chunks/app/page-f9c7d1158cda8c5f.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"Au9NvM222ys66B_S9303T\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",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]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"🚅 LiteLLM\"}],[\"$\",\"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\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
|
@ -1,7 +1,7 @@
|
||||||
2:I[77831,[],""]
|
2:I[77831,[],""]
|
||||||
3:I[30280,["303","static/chunks/303-d80f23087a9e6aec.js","931","static/chunks/app/page-f5480eede36fdcd5.js"],""]
|
3:I[30280,["303","static/chunks/303-d80f23087a9e6aec.js","931","static/chunks/app/page-f9c7d1158cda8c5f.js"],""]
|
||||||
4:I[5613,[],""]
|
4:I[5613,[],""]
|
||||||
5:I[31778,[],""]
|
5:I[31778,[],""]
|
||||||
0:["HOfpn9FdKIMCOfG_am2z2",[[["",{"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/a40ad0909dd7838e.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
0:["Au9NvM222ys66B_S9303T",[[["",{"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/a40ad0909dd7838e.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"}],["$","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"}]]
|
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"🚅 LiteLLM"}],["$","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
|
1:null
|
||||||
|
|
|
@ -785,6 +785,7 @@ async def user_api_key_auth(
|
||||||
"/v1/models",
|
"/v1/models",
|
||||||
"/global/spend/logs",
|
"/global/spend/logs",
|
||||||
"/global/spend/keys",
|
"/global/spend/keys",
|
||||||
|
"/global/spend/models",
|
||||||
]
|
]
|
||||||
# check if the current route startswith any of the allowed routes
|
# check if the current route startswith any of the allowed routes
|
||||||
if (
|
if (
|
||||||
|
|
File diff suppressed because one or more lines are too long
|
@ -1 +1 @@
|
||||||
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-a85b2c176012d8e5.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-e1b183dda365ec86.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>🚅 LiteLLM</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[30280,[\"303\",\"static/chunks/303-d80f23087a9e6aec.js\",\"931\",\"static/chunks/app/page-f5480eede36fdcd5.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"HOfpn9FdKIMCOfG_am2z2\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",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]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"🚅 LiteLLM\"}],[\"$\",\"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\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
<!DOCTYPE html><html id="__next_error__"><head><meta charSet="utf-8"/><meta name="viewport" content="width=device-width, initial-scale=1"/><link rel="preload" as="script" fetchPriority="low" href="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin=""/><script src="/ui/_next/static/chunks/fd9d1056-a85b2c176012d8e5.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/69-e1b183dda365ec86.js" async="" crossorigin=""></script><script src="/ui/_next/static/chunks/main-app-096338c8e1915716.js" async="" crossorigin=""></script><title>🚅 LiteLLM</title><meta name="description" content="LiteLLM Proxy Admin UI"/><link rel="icon" href="/ui/favicon.ico" type="image/x-icon" sizes="16x16"/><meta name="next-size-adjust"/><script src="/ui/_next/static/chunks/polyfills-c67a75d1b6f99dc8.js" crossorigin="" noModule=""></script></head><body><script src="/ui/_next/static/chunks/webpack-12184ee6a95c1363.js" crossorigin="" async=""></script><script>(self.__next_f=self.__next_f||[]).push([0]);self.__next_f.push([2,null])</script><script>self.__next_f.push([1,"1:HL[\"/ui/_next/static/media/c9a5bc6a7c948fb0-s.p.woff2\",\"font\",{\"crossOrigin\":\"\",\"type\":\"font/woff2\"}]\n2:HL[\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"style\",{\"crossOrigin\":\"\"}]\n0:\"$L3\"\n"])</script><script>self.__next_f.push([1,"4:I[47690,[],\"\"]\n6:I[77831,[],\"\"]\n7:I[30280,[\"303\",\"static/chunks/303-d80f23087a9e6aec.js\",\"931\",\"static/chunks/app/page-f9c7d1158cda8c5f.js\"],\"\"]\n8:I[5613,[],\"\"]\n9:I[31778,[],\"\"]\nb:I[48955,[],\"\"]\nc:[]\n"])</script><script>self.__next_f.push([1,"3:[[[\"$\",\"link\",\"0\",{\"rel\":\"stylesheet\",\"href\":\"/ui/_next/static/css/a40ad0909dd7838e.css\",\"precedence\":\"next\",\"crossOrigin\":\"\"}]],[\"$\",\"$L4\",null,{\"buildId\":\"Au9NvM222ys66B_S9303T\",\"assetPrefix\":\"/ui\",\"initialCanonicalUrl\":\"/\",\"initialTree\":[\"\",{\"children\":[\"__PAGE__\",{}]},\"$undefined\",\"$undefined\",true],\"initialSeedData\":[\"\",{\"children\":[\"__PAGE__\",{},[\"$L5\",[\"$\",\"$L6\",null,{\"propsForComponent\":{\"params\":{}},\"Component\":\"$7\",\"isStaticGeneration\":true}],null]]},[null,[\"$\",\"html\",null,{\"lang\":\"en\",\"children\":[\"$\",\"body\",null,{\"className\":\"__className_c23dc8\",\"children\":[\"$\",\"$L8\",null,{\"parallelRouterKey\":\"children\",\"segmentPath\":[\"children\"],\"loading\":\"$undefined\",\"loadingStyles\":\"$undefined\",\"loadingScripts\":\"$undefined\",\"hasLoading\":false,\"error\":\"$undefined\",\"errorStyles\":\"$undefined\",\"errorScripts\":\"$undefined\",\"template\":[\"$\",\"$L9\",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]],\"initialHead\":[false,\"$La\"],\"globalErrorComponent\":\"$b\",\"missingSlots\":\"$Wc\"}]]\n"])</script><script>self.__next_f.push([1,"a:[[\"$\",\"meta\",\"0\",{\"name\":\"viewport\",\"content\":\"width=device-width, initial-scale=1\"}],[\"$\",\"meta\",\"1\",{\"charSet\":\"utf-8\"}],[\"$\",\"title\",\"2\",{\"children\":\"🚅 LiteLLM\"}],[\"$\",\"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\"}]]\n5:null\n"])</script><script>self.__next_f.push([1,""])</script></body></html>
|
|
@ -1,7 +1,7 @@
|
||||||
2:I[77831,[],""]
|
2:I[77831,[],""]
|
||||||
3:I[30280,["303","static/chunks/303-d80f23087a9e6aec.js","931","static/chunks/app/page-f5480eede36fdcd5.js"],""]
|
3:I[30280,["303","static/chunks/303-d80f23087a9e6aec.js","931","static/chunks/app/page-f9c7d1158cda8c5f.js"],""]
|
||||||
4:I[5613,[],""]
|
4:I[5613,[],""]
|
||||||
5:I[31778,[],""]
|
5:I[31778,[],""]
|
||||||
0:["HOfpn9FdKIMCOfG_am2z2",[[["",{"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/a40ad0909dd7838e.css","precedence":"next","crossOrigin":""}]],"$L6"]]]]
|
0:["Au9NvM222ys66B_S9303T",[[["",{"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/a40ad0909dd7838e.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"}],["$","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"}]]
|
6:[["$","meta","0",{"name":"viewport","content":"width=device-width, initial-scale=1"}],["$","meta","1",{"charSet":"utf-8"}],["$","title","2",{"children":"🚅 LiteLLM"}],["$","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
|
1:null
|
||||||
|
|
|
@ -11,8 +11,10 @@ import ChatUI from "@/components/chat_ui";
|
||||||
import Sidebar from "../components/leftnav";
|
import Sidebar from "../components/leftnav";
|
||||||
import Usage from "../components/usage";
|
import Usage from "../components/usage";
|
||||||
import { jwtDecode } from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
|
import { Typography } from "antd";
|
||||||
|
|
||||||
const CreateKeyPage = () => {
|
const CreateKeyPage = () => {
|
||||||
|
const { Title, Paragraph } = Typography;
|
||||||
const [userRole, setUserRole] = useState("");
|
const [userRole, setUserRole] = useState("");
|
||||||
const [userEmail, setUserEmail] = useState<null | string>(null);
|
const [userEmail, setUserEmail] = useState<null | string>(null);
|
||||||
const [teams, setTeams] = useState<null | any[]>(null);
|
const [teams, setTeams] = useState<null | any[]>(null);
|
||||||
|
|
|
@ -21,6 +21,7 @@ import {
|
||||||
import { modelAvailableCall } from "./networking";
|
import { modelAvailableCall } from "./networking";
|
||||||
import openai from "openai";
|
import openai from "openai";
|
||||||
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
import { Prism as SyntaxHighlighter } from "react-syntax-highlighter";
|
||||||
|
import { Typography } from "antd";
|
||||||
|
|
||||||
interface ChatUIProps {
|
interface ChatUIProps {
|
||||||
accessToken: string | null;
|
accessToken: string | null;
|
||||||
|
@ -145,6 +146,16 @@ const ChatUI: React.FC<ChatUIProps> = ({
|
||||||
setInputMessage("");
|
setInputMessage("");
|
||||||
};
|
};
|
||||||
|
|
||||||
|
if (userRole && userRole == "Admin Viewer") {
|
||||||
|
const { Title, Paragraph } = Typography;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Title level={1}>Access Denied</Title>
|
||||||
|
<Paragraph>Ask your proxy admin for access to test models</Paragraph>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "100%", position: "relative" }}>
|
<div style={{ width: "100%", position: "relative" }}>
|
||||||
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
||||||
|
|
|
@ -23,10 +23,19 @@ const Sidebar: React.FC<SidebarProps> = ({
|
||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
defaultSelectedKeys={
|
defaultSelectedKeys={
|
||||||
defaultSelectedKey ? defaultSelectedKey : ["1"]
|
defaultSelectedKey ? defaultSelectedKey : ["4"]
|
||||||
}
|
}
|
||||||
style={{ height: "100%", borderRight: 0 }}
|
style={{ height: "100%", borderRight: 0 }}
|
||||||
>
|
>
|
||||||
|
<Menu.Item key="4" onClick={() => setPage("api-keys")}>
|
||||||
|
API Keys
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="2" onClick={() => setPage("models")}>
|
||||||
|
Models
|
||||||
|
</Menu.Item>
|
||||||
|
<Menu.Item key="3" onClick={() => setPage("llm-playground")}>
|
||||||
|
Chat UI
|
||||||
|
</Menu.Item>
|
||||||
<Menu.Item key="1" onClick={() => setPage("usage")}>
|
<Menu.Item key="1" onClick={() => setPage("usage")}>
|
||||||
Usage
|
Usage
|
||||||
</Menu.Item>
|
</Menu.Item>
|
||||||
|
|
|
@ -1,8 +1,20 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Card, Title, Subtitle, Table, TableHead, TableRow, TableCell, TableBody, Metric, Grid } from "@tremor/react";
|
import {
|
||||||
|
Card,
|
||||||
|
Title,
|
||||||
|
Subtitle,
|
||||||
|
Table,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableBody,
|
||||||
|
Metric,
|
||||||
|
Grid,
|
||||||
|
} from "@tremor/react";
|
||||||
import { modelInfoCall, userGetRequesedtModelsCall } from "./networking";
|
import { modelInfoCall, userGetRequesedtModelsCall } from "./networking";
|
||||||
import { Badge, BadgeDelta, Button } from '@tremor/react';
|
import { Badge, BadgeDelta, Button } from "@tremor/react";
|
||||||
import RequestAccess from "./request_model_access";
|
import RequestAccess from "./request_model_access";
|
||||||
|
import { Typography } from "antd";
|
||||||
|
|
||||||
interface ModelDashboardProps {
|
interface ModelDashboardProps {
|
||||||
accessToken: string | null;
|
accessToken: string | null;
|
||||||
|
@ -20,7 +32,6 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
const [modelData, setModelData] = useState<any>({ data: [] });
|
const [modelData, setModelData] = useState<any>({ data: [] });
|
||||||
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accessToken || !token || !userRole || !userID) {
|
if (!accessToken || !token || !userRole || !userID) {
|
||||||
return;
|
return;
|
||||||
|
@ -28,7 +39,11 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
// Replace with your actual API call for model data
|
// Replace with your actual API call for model data
|
||||||
const modelDataResponse = await modelInfoCall(accessToken, userID, userRole);
|
const modelDataResponse = await modelInfoCall(
|
||||||
|
accessToken,
|
||||||
|
userID,
|
||||||
|
userRole
|
||||||
|
);
|
||||||
console.log("Model data response:", modelDataResponse.data);
|
console.log("Model data response:", modelDataResponse.data);
|
||||||
setModelData(modelDataResponse);
|
setModelData(modelDataResponse);
|
||||||
|
|
||||||
|
@ -38,7 +53,6 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
console.log("Pending Requests:", pendingRequests);
|
console.log("Pending Requests:", pendingRequests);
|
||||||
setPendingRequests(user_requests.requests || []);
|
setPendingRequests(user_requests.requests || []);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("There was an error fetching the model data", error);
|
console.error("There was an error fetching the model data", error);
|
||||||
}
|
}
|
||||||
|
@ -67,110 +81,155 @@ const ModelDashboard: React.FC<ModelDashboardProps> = ({
|
||||||
|
|
||||||
let defaultProvider = "openai";
|
let defaultProvider = "openai";
|
||||||
let provider = "";
|
let provider = "";
|
||||||
let input_cost = "Undefined"
|
let input_cost = "Undefined";
|
||||||
let output_cost = "Undefined"
|
let output_cost = "Undefined";
|
||||||
let max_tokens = "Undefined"
|
let max_tokens = "Undefined";
|
||||||
|
|
||||||
// Check if litellm_model_name is null or undefined
|
// Check if litellm_model_name is null or undefined
|
||||||
if (litellm_model_name) {
|
if (litellm_model_name) {
|
||||||
// Split litellm_model_name based on "/"
|
// Split litellm_model_name based on "/"
|
||||||
let splitModel = litellm_model_name.split("/");
|
let splitModel = litellm_model_name.split("/");
|
||||||
|
|
||||||
// Get the first element in the split
|
// Get the first element in the split
|
||||||
let firstElement = splitModel[0];
|
let firstElement = splitModel[0];
|
||||||
|
|
||||||
// If there is only one element, default provider to openai
|
|
||||||
provider = splitModel.length === 1 ? defaultProvider : firstElement;
|
|
||||||
|
|
||||||
|
// If there is only one element, default provider to openai
|
||||||
|
provider = splitModel.length === 1 ? defaultProvider : firstElement;
|
||||||
} else {
|
} else {
|
||||||
// litellm_model_name is null or undefined, default provider to openai
|
// litellm_model_name is null or undefined, default provider to openai
|
||||||
provider = defaultProvider;
|
provider = defaultProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (model_info) {
|
if (model_info) {
|
||||||
input_cost = model_info?.input_cost_per_token;
|
input_cost = model_info?.input_cost_per_token;
|
||||||
output_cost = model_info?.output_cost_per_token;
|
output_cost = model_info?.output_cost_per_token;
|
||||||
max_tokens = model_info?.max_tokens;
|
max_tokens = model_info?.max_tokens;
|
||||||
|
|
||||||
}
|
}
|
||||||
modelData.data[i].provider = provider
|
modelData.data[i].provider = provider;
|
||||||
modelData.data[i].input_cost = input_cost
|
modelData.data[i].input_cost = input_cost;
|
||||||
modelData.data[i].output_cost = output_cost
|
modelData.data[i].output_cost = output_cost;
|
||||||
modelData.data[i].max_tokens = max_tokens
|
modelData.data[i].max_tokens = max_tokens;
|
||||||
|
|
||||||
all_models_on_proxy.push(curr_model.model_name);
|
all_models_on_proxy.push(curr_model.model_name);
|
||||||
|
|
||||||
console.log(modelData.data[i]);
|
console.log(modelData.data[i]);
|
||||||
|
|
||||||
}
|
}
|
||||||
// when users click request access show pop up to allow them to request access
|
// when users click request access show pop up to allow them to request access
|
||||||
|
|
||||||
|
if (userRole && userRole == "Admin Viewer") {
|
||||||
|
const { Title, Paragraph } = Typography;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Title level={1}>Access Denied</Title>
|
||||||
|
<Paragraph>
|
||||||
|
Ask your proxy admin for access to view all models
|
||||||
|
</Paragraph>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "100%" }}>
|
<div style={{ width: "100%" }}>
|
||||||
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
||||||
<Card>
|
<Card>
|
||||||
<Table className="mt-5">
|
<Table className="mt-5">
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell><Title>Model Name </Title></TableCell>
|
|
||||||
<TableCell><Title>Provider</Title></TableCell>
|
|
||||||
<TableCell><Title>Access</Title></TableCell>
|
|
||||||
<TableCell><Title>Input Price per token ($)</Title></TableCell>
|
|
||||||
<TableCell><Title>Output Price per token ($)</Title></TableCell>
|
|
||||||
<TableCell><Title>Max Tokens</Title></TableCell>
|
|
||||||
</TableRow>
|
|
||||||
</TableHead>
|
|
||||||
<TableBody>
|
|
||||||
{modelData.data.map((model: any) => (
|
|
||||||
<TableRow key={model.model_name}>
|
|
||||||
|
|
||||||
<TableCell><Title>{model.model_name}</Title></TableCell>
|
|
||||||
<TableCell>{model.provider}</TableCell>
|
|
||||||
|
|
||||||
<TableCell>
|
<TableCell>
|
||||||
{model.user_access ? <Badge color={"green"}>Yes</Badge> : <RequestAccess userModels={all_models_on_proxy} accessToken={accessToken} userID={userID}></RequestAccess>}
|
<Title>Model Name </Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Provider</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Access</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Input Price per token ($)</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Output Price per token ($)</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Max Tokens</Title>
|
||||||
</TableCell>
|
</TableCell>
|
||||||
|
|
||||||
<TableCell>{model.input_cost}</TableCell>
|
|
||||||
<TableCell>{model.output_cost}</TableCell>
|
|
||||||
<TableCell>{model.max_tokens}</TableCell>
|
|
||||||
|
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
</TableHead>
|
||||||
</TableBody>
|
<TableBody>
|
||||||
</Table>
|
{modelData.data.map((model: any) => (
|
||||||
</Card>
|
<TableRow key={model.model_name}>
|
||||||
{
|
<TableCell>
|
||||||
userRole === "Admin" && pendingRequests && pendingRequests.length > 0 ? (
|
<Title>{model.model_name}</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>{model.provider}</TableCell>
|
||||||
|
|
||||||
|
<TableCell>
|
||||||
|
{model.user_access ? (
|
||||||
|
<Badge color={"green"}>Yes</Badge>
|
||||||
|
) : (
|
||||||
|
<RequestAccess
|
||||||
|
userModels={all_models_on_proxy}
|
||||||
|
accessToken={accessToken}
|
||||||
|
userID={userID}
|
||||||
|
></RequestAccess>
|
||||||
|
)}
|
||||||
|
</TableCell>
|
||||||
|
|
||||||
|
<TableCell>{model.input_cost}</TableCell>
|
||||||
|
<TableCell>{model.output_cost}</TableCell>
|
||||||
|
<TableCell>{model.max_tokens}</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Card>
|
||||||
|
{userRole === "Admin" &&
|
||||||
|
pendingRequests &&
|
||||||
|
pendingRequests.length > 0 ? (
|
||||||
<Card>
|
<Card>
|
||||||
<Table>
|
<Table>
|
||||||
<TableHead>
|
<TableHead>
|
||||||
<Title>Pending Requests</Title>
|
<Title>Pending Requests</Title>
|
||||||
<TableRow>
|
<TableRow>
|
||||||
<TableCell><Title>User ID</Title></TableCell>
|
<TableCell>
|
||||||
<TableCell><Title>Requested Models</Title></TableCell>
|
<Title>User ID</Title>
|
||||||
<TableCell><Title>Justification</Title></TableCell>
|
</TableCell>
|
||||||
<TableCell><Title>Justification</Title></TableCell>
|
<TableCell>
|
||||||
|
<Title>Requested Models</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Justification</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>Justification</Title>
|
||||||
|
</TableCell>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
</TableHead>
|
</TableHead>
|
||||||
<TableBody>
|
<TableBody>
|
||||||
{pendingRequests.map((request: any) => (
|
{pendingRequests.map((request: any) => (
|
||||||
<TableRow key={request.request_id}>
|
<TableRow key={request.request_id}>
|
||||||
<TableCell><p>{request.user_id}</p></TableCell>
|
<TableCell>
|
||||||
<TableCell><p>{request.models[0]}</p></TableCell>
|
<p>{request.user_id}</p>
|
||||||
<TableCell><p>{request.justification}</p></TableCell>
|
</TableCell>
|
||||||
<TableCell><p>{request.user_id}</p></TableCell>
|
<TableCell>
|
||||||
|
<p>{request.models[0]}</p>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<p>{request.justification}</p>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<p>{request.user_id}</p>
|
||||||
|
</TableCell>
|
||||||
<Button>Approve</Button>
|
<Button>Approve</Button>
|
||||||
<Button variant="secondary" className="ml-2">Deny</Button>
|
<Button variant="secondary" className="ml-2">
|
||||||
|
Deny
|
||||||
|
</Button>
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
))}
|
||||||
</TableBody>
|
</TableBody>
|
||||||
</Table>
|
</Table>
|
||||||
</Card>
|
</Card>
|
||||||
) : null
|
) : null}
|
||||||
}
|
|
||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
|
@ -8,7 +8,7 @@ import ViewUserSpend from "./view_user_spend";
|
||||||
import DashboardTeam from "./dashboard_default_team";
|
import DashboardTeam from "./dashboard_default_team";
|
||||||
import { useSearchParams, useRouter } from "next/navigation";
|
import { useSearchParams, useRouter } from "next/navigation";
|
||||||
import { jwtDecode } from "jwt-decode";
|
import { jwtDecode } from "jwt-decode";
|
||||||
|
import { Typography } from "antd";
|
||||||
const isLocal = process.env.NODE_ENV === "development";
|
const isLocal = process.env.NODE_ENV === "development";
|
||||||
console.log("isLocal:", isLocal);
|
console.log("isLocal:", isLocal);
|
||||||
const proxyBaseUrl = isLocal ? "http://localhost:4000" : null;
|
const proxyBaseUrl = isLocal ? "http://localhost:4000" : null;
|
||||||
|
@ -184,6 +184,16 @@ const UserDashboard: React.FC<UserDashboardProps> = ({
|
||||||
setUserRole("App Owner");
|
setUserRole("App Owner");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (userRole && userRole == "Admin Viewer") {
|
||||||
|
const { Title, Paragraph } = Typography;
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Title level={1}>Access Denied</Title>
|
||||||
|
<Paragraph>Ask your proxy admin for access to create keys</Paragraph>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div>
|
<div>
|
||||||
<Grid numItems={1} className="gap-0 p-10 h-[75vh] w-full">
|
<Grid numItems={1} className="gap-0 p-10 h-[75vh] w-full">
|
||||||
|
|
|
@ -1,7 +1,18 @@
|
||||||
import React, { useState, useEffect } from "react";
|
import React, { useState, useEffect } from "react";
|
||||||
import { Card, Title, Subtitle, Table, TableHead, TableRow, TableCell, TableBody, Metric, Grid } from "@tremor/react";
|
import {
|
||||||
|
Card,
|
||||||
|
Title,
|
||||||
|
Subtitle,
|
||||||
|
Table,
|
||||||
|
TableHead,
|
||||||
|
TableRow,
|
||||||
|
TableCell,
|
||||||
|
TableBody,
|
||||||
|
Metric,
|
||||||
|
Grid,
|
||||||
|
} from "@tremor/react";
|
||||||
import { userInfoCall } from "./networking";
|
import { userInfoCall } from "./networking";
|
||||||
import { Badge, BadgeDelta, Button } from '@tremor/react';
|
import { Badge, BadgeDelta, Button } from "@tremor/react";
|
||||||
import RequestAccess from "./request_model_access";
|
import RequestAccess from "./request_model_access";
|
||||||
import CreateUser from "./create_user_button";
|
import CreateUser from "./create_user_button";
|
||||||
|
|
||||||
|
@ -21,7 +32,6 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
const [userData, setuserData] = useState<null | any[]>(null);
|
const [userData, setuserData] = useState<null | any[]>(null);
|
||||||
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
const [pendingRequests, setPendingRequests] = useState<any[]>([]);
|
||||||
|
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!accessToken || !token || !userRole || !userID) {
|
if (!accessToken || !token || !userRole || !userID) {
|
||||||
return;
|
return;
|
||||||
|
@ -29,10 +39,14 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
const fetchData = async () => {
|
const fetchData = async () => {
|
||||||
try {
|
try {
|
||||||
// Replace with your actual API call for model data
|
// Replace with your actual API call for model data
|
||||||
const userDataResponse = await userInfoCall(accessToken, null, userRole, true);
|
const userDataResponse = await userInfoCall(
|
||||||
|
accessToken,
|
||||||
|
null,
|
||||||
|
userRole,
|
||||||
|
true
|
||||||
|
);
|
||||||
console.log("user data response:", userDataResponse);
|
console.log("user data response:", userDataResponse);
|
||||||
setuserData(userDataResponse);
|
setuserData(userDataResponse);
|
||||||
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error("There was an error fetching the model data", error);
|
console.error("There was an error fetching the model data", error);
|
||||||
}
|
}
|
||||||
|
@ -51,40 +65,62 @@ const ViewUserDashboard: React.FC<ViewUserDashboardProps> = ({
|
||||||
return <div>Loading...</div>;
|
return <div>Loading...</div>;
|
||||||
}
|
}
|
||||||
|
|
||||||
// when users click request access show pop up to allow them to request access
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div style={{ width: "100%" }}>
|
<div style={{ width: "100%" }}>
|
||||||
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
<Grid className="gap-2 p-10 h-[75vh] w-full">
|
||||||
<CreateUser
|
<CreateUser userID={userID} accessToken={accessToken} />
|
||||||
userID={userID}
|
<Card>
|
||||||
accessToken={accessToken}
|
<Table className="mt-5">
|
||||||
/>
|
<TableHead>
|
||||||
<Card>
|
<TableRow>
|
||||||
<Table className="mt-5">
|
<TableCell>
|
||||||
<TableHead>
|
<Title>User ID </Title>
|
||||||
<TableRow>
|
</TableCell>
|
||||||
<TableCell><Title>User ID </Title></TableCell>
|
<TableCell>
|
||||||
<TableCell><Title>User Role</Title></TableCell>
|
<Title>User Role</Title>
|
||||||
<TableCell><Title>User Models</Title></TableCell>
|
</TableCell>
|
||||||
<TableCell><Title>User Spend ($ USD)</Title></TableCell>
|
<TableCell>
|
||||||
<TableCell><Title>User Max Budget ($ USD)</Title></TableCell>
|
<Title>User Models</Title>
|
||||||
</TableRow>
|
</TableCell>
|
||||||
</TableHead>
|
<TableCell>
|
||||||
<TableBody>
|
<Title>User Spend ($ USD)</Title>
|
||||||
{userData.map((user: any) => (
|
</TableCell>
|
||||||
<TableRow key={user.user_id}>
|
<TableCell>
|
||||||
<TableCell><Title>{user.user_id}</Title></TableCell>
|
<Title>User Max Budget ($ USD)</Title>
|
||||||
<TableCell><Title>{user.user_role ? user.user_role : "app_user"}</Title></TableCell>
|
</TableCell>
|
||||||
<TableCell><Title>{user.models && user.models.length > 0 ? user.models : "All Models"}</Title></TableCell>
|
|
||||||
<TableCell><Title>{user.spend ? user.spend : 0}</Title></TableCell>
|
|
||||||
<TableCell><Title>{user.max_budget ? user.max_budget : "Unlimited"}</Title></TableCell>
|
|
||||||
|
|
||||||
</TableRow>
|
</TableRow>
|
||||||
))}
|
</TableHead>
|
||||||
</TableBody>
|
<TableBody>
|
||||||
</Table>
|
{userData.map((user: any) => (
|
||||||
</Card>
|
<TableRow key={user.user_id}>
|
||||||
|
<TableCell>
|
||||||
|
<Title>{user.user_id}</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>
|
||||||
|
{user.user_role ? user.user_role : "app_user"}
|
||||||
|
</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>
|
||||||
|
{user.models && user.models.length > 0
|
||||||
|
? user.models
|
||||||
|
: "All Models"}
|
||||||
|
</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>{user.spend ? user.spend : 0}</Title>
|
||||||
|
</TableCell>
|
||||||
|
<TableCell>
|
||||||
|
<Title>
|
||||||
|
{user.max_budget ? user.max_budget : "Unlimited"}
|
||||||
|
</Title>
|
||||||
|
</TableCell>
|
||||||
|
</TableRow>
|
||||||
|
))}
|
||||||
|
</TableBody>
|
||||||
|
</Table>
|
||||||
|
</Card>
|
||||||
</Grid>
|
</Grid>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue