| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | import logging | 
					
						
							| 
									
										
										
										
											2024-08-28 06:10:27 +08:00
										 |  |  | import time | 
					
						
							|  |  |  | from typing import Optional | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-12-10 16:54:13 +08:00
										 |  |  | from open_webui.internal.db import Base, JSONField, get_db | 
					
						
							|  |  |  | from open_webui.models.users import Users, UserResponse | 
					
						
							| 
									
										
										
										
											2024-09-04 22:54:48 +08:00
										 |  |  | from open_webui.env import SRC_LOG_LEVELS | 
					
						
							| 
									
										
										
										
											2024-08-28 06:10:27 +08:00
										 |  |  | from pydantic import BaseModel, ConfigDict | 
					
						
							| 
									
										
										
										
											2024-11-15 10:57:25 +08:00
										 |  |  | from sqlalchemy import BigInteger, Column, String, Text, JSON | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 09:09:15 +08:00
										 |  |  | from open_webui.utils.access_control import has_access | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | log = logging.getLogger(__name__) | 
					
						
							|  |  |  | log.setLevel(SRC_LOG_LEVELS["MODELS"]) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #################### | 
					
						
							|  |  |  | # Tools DB Schema | 
					
						
							|  |  |  | #################### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  | class Tool(Base): | 
					
						
							|  |  |  |     __tablename__ = "tool" | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  |     id = Column(String, primary_key=True) | 
					
						
							|  |  |  |     user_id = Column(String) | 
					
						
							| 
									
										
										
										
											2024-06-24 19:21:51 +08:00
										 |  |  |     name = Column(Text) | 
					
						
							|  |  |  |     content = Column(Text) | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  |     specs = Column(JSONField) | 
					
						
							|  |  |  |     meta = Column(JSONField) | 
					
						
							|  |  |  |     valves = Column(JSONField) | 
					
						
							| 
									
										
										
										
											2024-11-15 10:57:25 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     access_control = Column(JSON, nullable=True)  # Controls data access levels. | 
					
						
							| 
									
										
										
										
											2024-11-15 12:13:43 +08:00
										 |  |  |     # Defines access control rules for this entry. | 
					
						
							|  |  |  |     # - `None`: Public access, available to all users with the "user" role. | 
					
						
							|  |  |  |     # - `{}`: Private access, restricted exclusively to the owner. | 
					
						
							|  |  |  |     # - Custom permissions: Specific access control for reading and writing; | 
					
						
							|  |  |  |     #   Can specify group or user-level restrictions: | 
					
						
							|  |  |  |     #   { | 
					
						
							|  |  |  |     #      "read": { | 
					
						
							|  |  |  |     #          "group_ids": ["group_id1", "group_id2"], | 
					
						
							|  |  |  |     #          "user_ids":  ["user_id1", "user_id2"] | 
					
						
							|  |  |  |     #      }, | 
					
						
							|  |  |  |     #      "write": { | 
					
						
							|  |  |  |     #          "group_ids": ["group_id1", "group_id2"], | 
					
						
							|  |  |  |     #          "user_ids":  ["user_id1", "user_id2"] | 
					
						
							|  |  |  |     #      } | 
					
						
							|  |  |  |     #   } | 
					
						
							| 
									
										
										
										
											2024-11-15 10:57:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  |     updated_at = Column(BigInteger) | 
					
						
							|  |  |  |     created_at = Column(BigInteger) | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ToolMeta(BaseModel): | 
					
						
							|  |  |  |     description: Optional[str] = None | 
					
						
							| 
									
										
										
										
											2024-06-24 11:31:40 +08:00
										 |  |  |     manifest: Optional[dict] = {} | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class ToolModel(BaseModel): | 
					
						
							|  |  |  |     id: str | 
					
						
							|  |  |  |     user_id: str | 
					
						
							|  |  |  |     name: str | 
					
						
							|  |  |  |     content: str | 
					
						
							| 
									
										
										
										
											2024-08-14 20:46:31 +08:00
										 |  |  |     specs: list[dict] | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |     meta: ToolMeta | 
					
						
							| 
									
										
										
										
											2024-11-15 12:13:43 +08:00
										 |  |  |     access_control: Optional[dict] = None | 
					
						
							| 
									
										
										
										
											2024-11-15 10:57:25 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |     updated_at: int  # timestamp in epoch | 
					
						
							|  |  |  |     created_at: int  # timestamp in epoch | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  |     model_config = ConfigDict(from_attributes=True) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | #################### | 
					
						
							|  |  |  | # Forms | 
					
						
							|  |  |  | #################### | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-28 10:11:50 +08:00
										 |  |  | class ToolUserModel(ToolModel): | 
					
						
							|  |  |  |     user: Optional[UserResponse] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | class ToolResponse(BaseModel): | 
					
						
							|  |  |  |     id: str | 
					
						
							|  |  |  |     user_id: str | 
					
						
							|  |  |  |     name: str | 
					
						
							|  |  |  |     meta: ToolMeta | 
					
						
							| 
									
										
										
										
											2024-11-17 12:47:45 +08:00
										 |  |  |     access_control: Optional[dict] = None | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |     updated_at: int  # timestamp in epoch | 
					
						
							|  |  |  |     created_at: int  # timestamp in epoch | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-18 22:19:34 +08:00
										 |  |  | class ToolUserResponse(ToolResponse): | 
					
						
							|  |  |  |     user: Optional[UserResponse] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | class ToolForm(BaseModel): | 
					
						
							|  |  |  |     id: str | 
					
						
							|  |  |  |     name: str | 
					
						
							|  |  |  |     content: str | 
					
						
							|  |  |  |     meta: ToolMeta | 
					
						
							| 
									
										
										
										
											2024-11-17 12:47:45 +08:00
										 |  |  |     access_control: Optional[dict] = None | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-24 09:05:33 +08:00
										 |  |  | class ToolValves(BaseModel): | 
					
						
							|  |  |  |     valves: Optional[dict] = None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | class ToolsTable: | 
					
						
							|  |  |  |     def insert_new_tool( | 
					
						
							| 
									
										
										
										
											2024-08-14 20:46:31 +08:00
										 |  |  |         self, user_id: str, form_data: ToolForm, specs: list[dict] | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |     ) -> Optional[ToolModel]: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |         with get_db() as db: | 
					
						
							|  |  |  |             tool = ToolModel( | 
					
						
							|  |  |  |                 **{ | 
					
						
							|  |  |  |                     **form_data.model_dump(), | 
					
						
							|  |  |  |                     "specs": specs, | 
					
						
							|  |  |  |                     "user_id": user_id, | 
					
						
							|  |  |  |                     "updated_at": int(time.time()), | 
					
						
							|  |  |  |                     "created_at": int(time.time()), | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |             try: | 
					
						
							|  |  |  |                 result = Tool(**tool.model_dump()) | 
					
						
							|  |  |  |                 db.add(result) | 
					
						
							|  |  |  |                 db.commit() | 
					
						
							|  |  |  |                 db.refresh(result) | 
					
						
							|  |  |  |                 if result: | 
					
						
							|  |  |  |                     return ToolModel.model_validate(result) | 
					
						
							|  |  |  |                 else: | 
					
						
							|  |  |  |                     return None | 
					
						
							|  |  |  |             except Exception as e: | 
					
						
							| 
									
										
										
										
											2025-02-25 22:36:25 +08:00
										 |  |  |                 log.exception(f"Error creating a new tool: {e}") | 
					
						
							| 
									
										
										
										
											2024-06-24 19:06:15 +08:00
										 |  |  |                 return None | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 20:58:57 +08:00
										 |  |  |     def get_tool_by_id(self, id: str) -> Optional[ToolModel]: | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |             with get_db() as db: | 
					
						
							|  |  |  |                 tool = db.get(Tool, id) | 
					
						
							|  |  |  |                 return ToolModel.model_validate(tool) | 
					
						
							| 
									
										
										
										
											2024-08-14 20:38:19 +08:00
										 |  |  |         except Exception: | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-28 10:11:50 +08:00
										 |  |  |     def get_tools(self) -> list[ToolUserModel]: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:39:16 +08:00
										 |  |  |         with get_db() as db: | 
					
						
							| 
									
										
										
										
											2024-11-20 08:47:35 +08:00
										 |  |  |             tools = [] | 
					
						
							|  |  |  |             for tool in db.query(Tool).order_by(Tool.updated_at.desc()).all(): | 
					
						
							|  |  |  |                 user = Users.get_user_by_id(tool.user_id) | 
					
						
							|  |  |  |                 tools.append( | 
					
						
							| 
									
										
										
										
											2024-11-28 10:11:50 +08:00
										 |  |  |                     ToolUserModel.model_validate( | 
					
						
							| 
									
										
										
										
											2024-11-20 08:47:35 +08:00
										 |  |  |                         { | 
					
						
							|  |  |  |                             **ToolModel.model_validate(tool).model_dump(), | 
					
						
							|  |  |  |                             "user": user.model_dump() if user else None, | 
					
						
							|  |  |  |                         } | 
					
						
							|  |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2024-11-18 22:19:34 +08:00
										 |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-11-20 08:47:35 +08:00
										 |  |  |             return tools | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-11-17 09:09:15 +08:00
										 |  |  |     def get_tools_by_user_id( | 
					
						
							|  |  |  |         self, user_id: str, permission: str = "write" | 
					
						
							| 
									
										
										
										
											2024-11-28 10:11:50 +08:00
										 |  |  |     ) -> list[ToolUserModel]: | 
					
						
							| 
									
										
										
										
											2024-11-17 09:09:15 +08:00
										 |  |  |         tools = self.get_tools() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             tool | 
					
						
							|  |  |  |             for tool in tools | 
					
						
							|  |  |  |             if tool.user_id == user_id | 
					
						
							| 
									
										
										
										
											2024-11-17 09:17:18 +08:00
										 |  |  |             or has_access(user_id, permission, tool.access_control) | 
					
						
							| 
									
										
										
										
											2024-11-17 09:09:15 +08:00
										 |  |  |         ] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-24 10:18:13 +08:00
										 |  |  |     def get_tool_valves_by_id(self, id: str) -> Optional[dict]: | 
					
						
							| 
									
										
										
										
											2024-06-24 09:05:33 +08:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |             with get_db() as db: | 
					
						
							|  |  |  |                 tool = db.get(Tool, id) | 
					
						
							|  |  |  |                 return tool.valves if tool.valves else {} | 
					
						
							| 
									
										
										
										
											2024-06-24 09:05:33 +08:00
										 |  |  |         except Exception as e: | 
					
						
							| 
									
										
										
										
											2025-02-25 22:36:25 +08:00
										 |  |  |             log.exception(f"Error getting tool valves by id {id}: {e}") | 
					
						
							| 
									
										
										
										
											2024-06-24 09:05:33 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update_tool_valves_by_id(self, id: str, valves: dict) -> Optional[ToolValves]: | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |             with get_db() as db: | 
					
						
							|  |  |  |                 db.query(Tool).filter_by(id=id).update( | 
					
						
							|  |  |  |                     {"valves": valves, "updated_at": int(time.time())} | 
					
						
							|  |  |  |                 ) | 
					
						
							|  |  |  |                 db.commit() | 
					
						
							|  |  |  |                 return self.get_tool_by_id(id) | 
					
						
							| 
									
										
										
										
											2024-08-14 20:38:19 +08:00
										 |  |  |         except Exception: | 
					
						
							| 
									
										
										
										
											2024-06-24 09:05:33 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  |     def get_user_valves_by_id_and_user_id( | 
					
						
							|  |  |  |         self, id: str, user_id: str | 
					
						
							|  |  |  |     ) -> Optional[dict]: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             user = Users.get_user_by_id(user_id) | 
					
						
							| 
									
										
										
										
											2024-07-04 15:37:05 +08:00
										 |  |  |             user_settings = user.settings.model_dump() if user.settings else {} | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Check if user has "tools" and "valves" settings | 
					
						
							| 
									
										
										
										
											2024-06-23 03:08:32 +08:00
										 |  |  |             if "tools" not in user_settings: | 
					
						
							|  |  |  |                 user_settings["tools"] = {} | 
					
						
							|  |  |  |             if "valves" not in user_settings["tools"]: | 
					
						
							|  |  |  |                 user_settings["tools"]["valves"] = {} | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-23 03:08:32 +08:00
										 |  |  |             return user_settings["tools"]["valves"].get(id, {}) | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  |         except Exception as e: | 
					
						
							| 
									
										
										
										
											2025-02-27 14:18:18 +08:00
										 |  |  |             log.exception( | 
					
						
							|  |  |  |                 f"Error getting user values by id {id} and user_id {user_id}: {e}" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     def update_user_valves_by_id_and_user_id( | 
					
						
							|  |  |  |         self, id: str, user_id: str, valves: dict | 
					
						
							|  |  |  |     ) -> Optional[dict]: | 
					
						
							|  |  |  |         try: | 
					
						
							|  |  |  |             user = Users.get_user_by_id(user_id) | 
					
						
							| 
									
										
										
										
											2024-07-04 15:37:05 +08:00
										 |  |  |             user_settings = user.settings.model_dump() if user.settings else {} | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Check if user has "tools" and "valves" settings | 
					
						
							| 
									
										
										
										
											2024-06-23 03:08:32 +08:00
										 |  |  |             if "tools" not in user_settings: | 
					
						
							|  |  |  |                 user_settings["tools"] = {} | 
					
						
							|  |  |  |             if "valves" not in user_settings["tools"]: | 
					
						
							|  |  |  |                 user_settings["tools"]["valves"] = {} | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-23 03:08:32 +08:00
										 |  |  |             user_settings["tools"]["valves"][id] = valves | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |             # Update the user settings in the database | 
					
						
							| 
									
										
										
										
											2024-06-21 20:58:57 +08:00
										 |  |  |             Users.update_user_by_id(user_id, {"settings": user_settings}) | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-23 03:08:32 +08:00
										 |  |  |             return user_settings["tools"]["valves"][id] | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  |         except Exception as e: | 
					
						
							| 
									
										
										
										
											2025-02-27 14:18:18 +08:00
										 |  |  |             log.exception( | 
					
						
							|  |  |  |                 f"Error updating user valves by id {id} and user_id {user_id}: {e}" | 
					
						
							|  |  |  |             ) | 
					
						
							| 
									
										
										
										
											2024-06-23 02:26:33 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |     def update_tool_by_id(self, id: str, updated: dict) -> Optional[ToolModel]: | 
					
						
							|  |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |             with get_db() as db: | 
					
						
							| 
									
										
										
										
											2024-07-09 02:46:37 +08:00
										 |  |  |                 db.query(Tool).filter_by(id=id).update( | 
					
						
							|  |  |  |                     {**updated, "updated_at": int(time.time())} | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |                 db.commit() | 
					
						
							| 
									
										
										
										
											2024-07-09 02:46:37 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |                 tool = db.query(Tool).get(id) | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |                 db.refresh(tool) | 
					
						
							|  |  |  |                 return ToolModel.model_validate(tool) | 
					
						
							| 
									
										
										
										
											2024-08-14 20:38:19 +08:00
										 |  |  |         except Exception: | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |             return None | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-21 20:58:57 +08:00
										 |  |  |     def delete_tool_by_id(self, id: str) -> bool: | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |         try: | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |             with get_db() as db: | 
					
						
							|  |  |  |                 db.query(Tool).filter_by(id=id).delete() | 
					
						
							| 
									
										
										
										
											2024-07-06 23:10:58 +08:00
										 |  |  |                 db.commit() | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-07-04 14:32:39 +08:00
										 |  |  |                 return True | 
					
						
							| 
									
										
										
										
											2024-08-14 20:38:19 +08:00
										 |  |  |         except Exception: | 
					
						
							| 
									
										
										
										
											2024-06-11 11:39:55 +08:00
										 |  |  |             return False | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-18 21:03:31 +08:00
										 |  |  | Tools = ToolsTable() |