Ver código fonte

refac: tools valves

Timothy Jaeryang Baek 1 semana atrás
pai
commit
27d61307cd

+ 2 - 0
backend/open_webui/models/tools.py

@@ -95,6 +95,8 @@ class ToolResponse(BaseModel):
 class ToolUserResponse(ToolResponse):
     user: Optional[UserResponse] = None
 
+    model_config = ConfigDict(extra="allow")
+
 
 class ToolForm(BaseModel):
     id: str

+ 9 - 1
backend/open_webui/routers/tools.py

@@ -41,7 +41,15 @@ router = APIRouter()
 
 @router.get("/", response_model=list[ToolUserResponse])
 async def get_tools(request: Request, user=Depends(get_verified_user)):
-    tools = Tools.get_tools()
+    tools = [
+        ToolUserResponse(
+            **{
+                **tool.model_dump(),
+                "has_user_valves": "class UserValves(BaseModel):" in tool.content,
+            }
+        )
+        for tool in Tools.get_tools()
+    ]
 
     # OpenAPI Tool Servers
     for server in await get_tool_servers(request):

+ 56 - 1
src/lib/components/chat/MessageInput/IntegrationsMenu.svelte

@@ -19,6 +19,7 @@
 	import Terminal from '$lib/components/icons/Terminal.svelte';
 	import ChevronRight from '$lib/components/icons/ChevronRight.svelte';
 	import ChevronLeft from '$lib/components/icons/ChevronLeft.svelte';
+	import ValvesModal from '$lib/components/workspace/common/ValvesModal.svelte';
 
 	const i18n = getContext('i18n');
 
@@ -43,6 +44,11 @@
 	let show = false;
 	let tab = '';
 
+	let showValvesModal = false;
+
+	let selectedValvesType = 'tool';
+	let selectedValvesItemId = null;
+
 	let tools = null;
 
 	$: if (show) {
@@ -64,7 +70,8 @@
 				a[tool.id] = {
 					name: tool.name,
 					description: tool.meta.description,
-					enabled: selectedToolIds.includes(tool.id)
+					enabled: selectedToolIds.includes(tool.id),
+					...tool
 				};
 				return a;
 			}, {});
@@ -87,6 +94,16 @@
 	};
 </script>
 
+<ValvesModal
+	bind:show={showValvesModal}
+	userValves={true}
+	type={selectedValvesType}
+	id={selectedValvesItemId ?? null}
+	on:save={async () => {
+		await tick();
+	}}
+/>
+
 <Dropdown
 	bind:show
 	on:change={(e) => {
@@ -322,6 +339,44 @@
 								</div>
 							</div>
 
+							{#if tools[toolId]?.has_user_valves}
+								<div class=" shrink-0">
+									<Tooltip content={$i18n.t('Valves')}>
+										<button
+											class="self-center w-fit text-sm text-gray-600 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-300 transition rounded-full"
+											type="button"
+											on:click={(e) => {
+												e.stopPropagation();
+												e.preventDefault();
+												selectedValvesType = 'tool';
+												selectedValvesItemId = toolId;
+												showValvesModal = true;
+											}}
+										>
+											<svg
+												xmlns="http://www.w3.org/2000/svg"
+												fill="none"
+												viewBox="0 0 24 24"
+												stroke-width="1.5"
+												stroke="currentColor"
+												class="size-4"
+											>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="M9.594 3.94c.09-.542.56-.94 1.11-.94h2.593c.55 0 1.02.398 1.11.94l.213 1.281c.063.374.313.686.645.87.074.04.147.083.22.127.325.196.72.257 1.075.124l1.217-.456a1.125 1.125 0 0 1 1.37.49l1.296 2.247a1.125 1.125 0 0 1-.26 1.431l-1.003.827c-.293.241-.438.613-.43.992a7.723 7.723 0 0 1 0 .255c-.008.378.137.75.43.991l1.004.827c.424.35.534.955.26 1.43l-1.298 2.247a1.125 1.125 0 0 1-1.369.491l-1.217-.456c-.355-.133-.75-.072-1.076.124a6.47 6.47 0 0 1-.22.128c-.331.183-.581.495-.644.869l-.213 1.281c-.09.543-.56.94-1.11.94h-2.594c-.55 0-1.019-.398-1.11-.94l-.213-1.281c-.062-.374-.312-.686-.644-.87a6.52 6.52 0 0 1-.22-.127c-.325-.196-.72-.257-1.076-.124l-1.217.456a1.125 1.125 0 0 1-1.369-.49l-1.297-2.247a1.125 1.125 0 0 1 .26-1.431l1.004-.827c.292-.24.437-.613.43-.991a6.932 6.932 0 0 1 0-.255c.007-.38-.138-.751-.43-.992l-1.004-.827a1.125 1.125 0 0 1-.26-1.43l1.297-2.247a1.125 1.125 0 0 1 1.37-.491l1.216.456c.356.133.751.072 1.076-.124.072-.044.146-.086.22-.128.332-.183.582-.495.644-.869l.214-1.28Z"
+												/>
+												<path
+													stroke-linecap="round"
+													stroke-linejoin="round"
+													d="M15 12a3 3 0 1 1-6 0 3 3 0 0 1 6 0Z"
+												/>
+											</svg>
+										</button>
+									</Tooltip>
+								</div>
+							{/if}
+
 							<div class=" shrink-0">
 								<Switch
 									state={tools[toolId].enabled}

+ 69 - 25
src/lib/components/workspace/common/ValvesModal.svelte

@@ -11,6 +11,20 @@
 		updateFunctionValvesById
 	} from '$lib/apis/functions';
 	import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools';
+
+	import {
+		getUserValvesSpecById as getToolUserValvesSpecById,
+		getUserValvesById as getToolUserValvesById,
+		updateUserValvesById as updateToolUserValvesById,
+		getTools
+	} from '$lib/apis/tools';
+	import {
+		getUserValvesSpecById as getFunctionUserValvesSpecById,
+		getUserValvesById as getFunctionUserValvesById,
+		updateUserValvesById as updateFunctionUserValvesById,
+		getFunctions
+	} from '$lib/apis/functions';
+
 	import Spinner from '../../common/Spinner.svelte';
 	import Switch from '$lib/components/common/Switch.svelte';
 	import Valves from '$lib/components/common/Valves.svelte';
@@ -23,6 +37,7 @@
 
 	export let type = 'tool';
 	export let id = null;
+	export let userValves = false;
 
 	let saving = false;
 	let loading = false;
@@ -43,14 +58,28 @@
 
 			let res = null;
 
-			if (type === 'tool') {
-				res = await updateToolValvesById(localStorage.token, id, valves).catch((error) => {
-					toast.error(`${error}`);
-				});
-			} else if (type === 'function') {
-				res = await updateFunctionValvesById(localStorage.token, id, valves).catch((error) => {
-					toast.error(`${error}`);
-				});
+			if (userValves) {
+				if (type === 'tool') {
+					res = await updateToolUserValvesById(localStorage.token, id, valves).catch((error) => {
+						toast.error(`${error}`);
+					});
+				} else if (type === 'function') {
+					res = await updateFunctionUserValvesById(localStorage.token, id, valves).catch(
+						(error) => {
+							toast.error(`${error}`);
+						}
+					);
+				}
+			} else {
+				if (type === 'tool') {
+					res = await updateToolValvesById(localStorage.token, id, valves).catch((error) => {
+						toast.error(`${error}`);
+					});
+				} else if (type === 'function') {
+					res = await updateFunctionValvesById(localStorage.token, id, valves).catch((error) => {
+						toast.error(`${error}`);
+					});
+				}
 			}
 
 			if (res) {
@@ -67,28 +96,43 @@
 		valves = {};
 		valvesSpec = null;
 
-		if (type === 'tool') {
-			valves = await getToolValvesById(localStorage.token, id);
-			valvesSpec = await getToolValvesSpecById(localStorage.token, id);
-		} else if (type === 'function') {
-			valves = await getFunctionValvesById(localStorage.token, id);
-			valvesSpec = await getFunctionValvesSpecById(localStorage.token, id);
-		}
+		try {
+			if (userValves) {
+				if (type === 'tool') {
+					valves = await getToolUserValvesById(localStorage.token, id);
+					valvesSpec = await getToolUserValvesSpecById(localStorage.token, id);
+				} else if (type === 'function') {
+					valves = await getFunctionUserValvesById(localStorage.token, id);
+					valvesSpec = await getFunctionUserValvesSpecById(localStorage.token, id);
+				}
+			} else {
+				if (type === 'tool') {
+					valves = await getToolValvesById(localStorage.token, id);
+					valvesSpec = await getToolValvesSpecById(localStorage.token, id);
+				} else if (type === 'function') {
+					valves = await getFunctionValvesById(localStorage.token, id);
+					valvesSpec = await getFunctionValvesSpecById(localStorage.token, id);
+				}
+			}
 
-		if (!valves) {
-			valves = {};
-		}
+			if (!valves) {
+				valves = {};
+			}
 
-		if (valvesSpec) {
-			// Convert array to string
-			for (const property in valvesSpec.properties) {
-				if (valvesSpec.properties[property]?.type === 'array') {
-					valves[property] = (valves[property] ?? []).join(',');
+			if (valvesSpec) {
+				// Convert array to string
+				for (const property in valvesSpec.properties) {
+					if (valvesSpec.properties[property]?.type === 'array') {
+						valves[property] = (valves[property] ?? []).join(',');
+					}
 				}
 			}
-		}
 
-		loading = false;
+			loading = false;
+		} catch (e) {
+			toast.error(`Error fetching valves`);
+			show = false;
+		}
 	};
 
 	$: if (show) {