From 627705a347bcddb6893b3a1b23cda6636d22d24e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:02:27 -0700 Subject: [PATCH] feat: valves --- backend/apps/webui/routers/functions.py | 68 +++++-- backend/apps/webui/routers/tools.py | 63 +++++- src/lib/apis/functions/index.ts | 32 +++ src/lib/apis/tools/index.ts | 99 ++++++++++ src/lib/components/workspace/Functions.svelte | 10 + src/lib/components/workspace/Tools.svelte | 10 + .../components/workspace/ValvesModal.svelte | 187 +++++++++++------- 7 files changed, 377 insertions(+), 92 deletions(-) diff --git a/backend/apps/webui/routers/functions.py b/backend/apps/webui/routers/functions.py index 8c6454eac..4da68a052 100644 --- a/backend/apps/webui/routers/functions.py +++ b/backend/apps/webui/routers/functions.py @@ -127,8 +127,8 @@ async def get_function_valves_by_id(id: str, user=Depends(get_admin_user)): function = Functions.get_function_by_id(id) if function: try: - valves = Functions.get_function_valves_by_id(id) - return valves + function_valves = Functions.get_function_valves_by_id(id) + return function_valves.valves except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -142,24 +142,70 @@ async def get_function_valves_by_id(id: str, user=Depends(get_admin_user)): ############################ -# UpdateToolValves +# GetFunctionValvesSpec +############################ + + +@router.get("/id/{id}/valves/spec", response_model=Optional[dict]) +async def get_function_valves_spec_by_id( + request: Request, id: str, user=Depends(get_admin_user) +): + function = Functions.get_function_by_id(id) + if function: + if id in request.app.state.FUNCTIONS: + function_module = request.app.state.FUNCTIONS[id] + else: + function_module, function_type = load_function_module_by_id(id) + request.app.state.FUNCTIONS[id] = function_module + + if hasattr(function_module, "Valves"): + Valves = function_module.Valves + return Valves.schema() + return None + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + +############################ +# UpdateFunctionValves ############################ @router.post("/id/{id}/valves/update", response_model=Optional[dict]) -async def update_toolkit_valves_by_id( - id: str, form_data: dict, user=Depends(get_admin_user) +async def update_function_valves_by_id( + request: Request, id: str, form_data: dict, user=Depends(get_admin_user) ): function = Functions.get_function_by_id(id) if function: - try: - valves = Functions.update_function_valves_by_id(id, form_data) - return valves - except Exception as e: + + if id in request.app.state.FUNCTIONS: + function_module = request.app.state.FUNCTIONS[id] + else: + function_module, function_type = load_function_module_by_id(id) + request.app.state.FUNCTIONS[id] = function_module + + if hasattr(function_module, "Valves"): + Valves = function_module.Valves + + try: + valves = Valves(**form_data) + Functions.update_function_valves_by_id(id, valves.model_dump()) + return valves.model_dump() + except Exception as e: + print(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, ) + else: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, diff --git a/backend/apps/webui/routers/tools.py b/backend/apps/webui/routers/tools.py index 7988acc86..7ddcf3ed9 100644 --- a/backend/apps/webui/routers/tools.py +++ b/backend/apps/webui/routers/tools.py @@ -133,8 +133,8 @@ async def get_toolkit_valves_by_id(id: str, user=Depends(get_admin_user)): toolkit = Tools.get_tool_by_id(id) if toolkit: try: - valves = Tools.get_tool_valves_by_id(id) - return valves + tool_valves = Tools.get_tool_valves_by_id(id) + return tool_valves.valves except Exception as e: raise HTTPException( status_code=status.HTTP_400_BAD_REQUEST, @@ -147,6 +147,34 @@ async def get_toolkit_valves_by_id(id: str, user=Depends(get_admin_user)): ) +############################ +# GetToolValvesSpec +############################ + + +@router.get("/id/{id}/valves/spec", response_model=Optional[dict]) +async def get_toolkit_valves_spec_by_id( + request: Request, id: str, user=Depends(get_admin_user) +): + toolkit = Tools.get_tool_by_id(id) + if toolkit: + if id in request.app.state.TOOLS: + toolkit_module = request.app.state.TOOLS[id] + else: + toolkit_module = load_toolkit_module_by_id(id) + request.app.state.TOOLS[id] = toolkit_module + + if hasattr(toolkit_module, "UserValves"): + UserValves = toolkit_module.UserValves + return UserValves.schema() + return None + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + ############################ # UpdateToolValves ############################ @@ -154,18 +182,35 @@ async def get_toolkit_valves_by_id(id: str, user=Depends(get_admin_user)): @router.post("/id/{id}/valves/update", response_model=Optional[dict]) async def update_toolkit_valves_by_id( - id: str, form_data: dict, user=Depends(get_admin_user) + request: Request, id: str, form_data: dict, user=Depends(get_admin_user) ): toolkit = Tools.get_tool_by_id(id) if toolkit: - try: - valves = Tools.update_tool_valves_by_id(id, form_data) - return valves - except Exception as e: + if id in request.app.state.TOOLS: + toolkit_module = request.app.state.TOOLS[id] + else: + toolkit_module = load_toolkit_module_by_id(id) + request.app.state.TOOLS[id] = toolkit_module + + if hasattr(toolkit_module, "Valves"): + Valves = toolkit_module.Valves + + try: + valves = Valves(**form_data) + Tools.update_tool_valves_by_id(id, valves.model_dump()) + return valves.model_dump() + except Exception as e: + print(e) + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, ) + else: raise HTTPException( status_code=status.HTTP_401_UNAUTHORIZED, diff --git a/src/lib/apis/functions/index.ts b/src/lib/apis/functions/index.ts index c8607b091..2d5ad16b7 100644 --- a/src/lib/apis/functions/index.ts +++ b/src/lib/apis/functions/index.ts @@ -256,6 +256,38 @@ export const getFunctionValvesById = async (token: string, id: string) => { return res; }; +export const getFunctionValvesSpecById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/valves/spec`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const updateFunctionValvesById = async (token: string, id: string, valves: object) => { let error = null; diff --git a/src/lib/apis/tools/index.ts b/src/lib/apis/tools/index.ts index 25d543feb..28e8dde86 100644 --- a/src/lib/apis/tools/index.ts +++ b/src/lib/apis/tools/index.ts @@ -192,6 +192,105 @@ export const deleteToolById = async (token: string, id: string) => { return res; }; +export const getToolValvesById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const getToolValvesSpecById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves/spec`, { + method: 'GET', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + } + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + +export const updateToolValvesById = async (token: string, id: string, valves: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves/update`, { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + ...valves + }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .then((json) => { + return json; + }) + .catch((err) => { + error = err.detail; + + console.log(err); + return null; + }); + + if (error) { + throw error; + } + + return res; +}; + export const getUserValvesById = async (token: string, id: string) => { let error = null; diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index 75e0ce4ff..fb92cc32d 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -24,6 +24,7 @@ import FunctionMenu from './Functions/FunctionMenu.svelte'; import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; import Switch from '../common/Switch.svelte'; + import ValvesModal from './ValvesModal.svelte'; const i18n = getContext('i18n'); @@ -33,6 +34,9 @@ let showConfirm = false; let query = ''; + let showValvesModal = false; + let selectedFunction = null; + const shareHandler = async (tool) => { console.log(tool); }; @@ -175,6 +179,10 @@ + -
- -
- + {#if (valves[property] ?? null) !== null} +
+
+ +
+
+ {/if} -
- -
-
{$i18n.t('Email')}
- -
- -
-
- -
-
{$i18n.t('Password')}
- -
- -
-
+ {#if (valvesSpec.properties[property]?.description ?? null) !== null} +
+ {valvesSpec.properties[property].description} +
+ {/if} + + {/each} + {:else} +
No valves
+ {/if} + {:else} + + {/if}