diff --git a/litellm/proxy/proxy_server.py b/litellm/proxy/proxy_server.py index ee620697a..d597dde8c 100644 --- a/litellm/proxy/proxy_server.py +++ b/litellm/proxy/proxy_server.py @@ -554,9 +554,6 @@ async def user_api_key_auth( ) return _user_api_key_obj - elif route.startswith("/config/"): - raise Exception(f"Only admin can modify config") - if isinstance( api_key, str ): # if generated token, make sure it starts with sk-. @@ -1077,6 +1074,7 @@ async def user_api_key_auth( "/sso", "/login", "/key", + "/config", "/spend", "/user", "/model/info", @@ -8025,13 +8023,8 @@ async def get_config(): try: config_data = await proxy_config.get_config() - _environment_variables = config_data.get("environment_variables", {}) - config_data = config_data["litellm_settings"] + config_data = config_data.get("litellm_settings", {}) - # only store the keys and return the values as sk...*** - for key, value in _environment_variables.items(): - _environment_variables[key] = value[:5] + "*****" - config_data["environment_variables"] = _environment_variables return {"data": config_data, "status": "success"} except Exception as e: traceback.print_exc() diff --git a/ui/litellm-dashboard/src/components/networking.tsx b/ui/litellm-dashboard/src/components/networking.tsx index 9bdc3b496..5a096031a 100644 --- a/ui/litellm-dashboard/src/components/networking.tsx +++ b/ui/litellm-dashboard/src/components/networking.tsx @@ -1159,3 +1159,46 @@ export const getCallbacksCall = async ( }; + + + + +export const setCallbacksCall = async ( + accessToken: String, + formValues: Record +) => { + /** + * Set callbacks on proxy + */ + try { + let url = proxyBaseUrl ? `${proxyBaseUrl}/config/update` : `/config/update`; + + //message.info("Requesting model data"); + const response = await fetch(url, { + method: "POST", + headers: { + Authorization: `Bearer ${accessToken}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + ...formValues, // Include formValues in the request body + }), + }); + + if (!response.ok) { + const errorData = await response.text(); + message.error(errorData); + throw new Error("Network response was not ok"); + } + + const data = await response.json(); + //message.info("Received model data"); + return data; + // Handle success - you might want to update some state or UI based on the created key + } catch (error) { + console.error("Failed to set callbacks:", error); + throw error; + } +}; + + diff --git a/ui/litellm-dashboard/src/components/settings.tsx b/ui/litellm-dashboard/src/components/settings.tsx index e9718e0c8..eddede50e 100644 --- a/ui/litellm-dashboard/src/components/settings.tsx +++ b/ui/litellm-dashboard/src/components/settings.tsx @@ -16,8 +16,9 @@ import { Button, Col, } from "@tremor/react"; -import { getCallbacksCall } from "./networking"; +import { getCallbacksCall, setCallbacksCall } from "./networking"; import { Modal, Form, Input, Select, Button as Button2 } from "antd"; +import StaticGenerationSearchParamsBailoutProvider from "next/dist/client/components/static-generation-searchparams-bailout-provider"; interface SettingsPageProps { accessToken: string | null; @@ -30,7 +31,7 @@ const Settings: React.FC = ({ userRole, userID, }) => { - const [callbacks, setCallbacks] = useState(["None"]); + const [callbacks, setCallbacks] = useState([]); const [isModalVisible, setIsModalVisible] = useState(false); const [form] = Form.useForm(); @@ -57,10 +58,36 @@ const Settings: React.FC = ({ }; const handleOk = () => { + if (!accessToken) { + return; + } // Handle form submission form.validateFields().then((values) => { // Call API to add the callback + let payload; console.log("Callback values:", values); + if (values.callback === 'langfuse') { + payload = { + environment_variables: { + LANGFUSE_PUBLIC_KEY: values.langfusePublicKey, + LANGFUSE_SECRET_KEY: values.langfusePrivateKey, + LANGFUSE_HOST: values.langfuseCloudUrl , + }, + litellm_settings: { + success_callback: [values.callback] + } + }; + setCallbacksCall(accessToken, payload); + + // add langfuse to callbacks + setCallbacks(callbacks ? [...callbacks, values.callback] : [values.callback]); + + + } else { + payload = { + error: 'Invalid callback value' + }; + } setIsModalVisible(false); form.resetFields(); }); @@ -75,17 +102,19 @@ const Settings: React.FC = ({ Logging Callbacks -
- {callbacks.length === 0 ? ( - None +
+ {!callbacks ? ( + None + ) : callbacks.length === 0 ? ( + None ) : ( - callbacks.map((callback, index) => ( + callbacks.map((callback, index) => ( - {callback} + {callback} - )) + )) )} -
+
@@ -104,7 +133,7 @@ const Settings: React.FC = ({ onCancel={handleCancel} footer={null} > -
+