From 4d66e39402c0b7229733afcbc5614b34d6661953 Mon Sep 17 00:00:00 2001 From: Karl Lee <61072264+KarlLee830@users.noreply.github.com> Date: Fri, 21 Jun 2024 11:45:57 +0800 Subject: [PATCH 01/71] i18n: Update Chinese translation --- src/lib/i18n/locales/zh-CN/translation.json | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 71f3efb5fc..95775333ab 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -99,7 +99,7 @@ "Clear memory": "清除记忆", "Click here for help.": "点击这里获取帮助。", "Click here to": "单击", - "Click here to download user import template file.": "", + "Click here to download user import template file.": "单击此处下载用户导入所需的模板文件。", "Click here to select": "点击这里选择", "Click here to select a csv file.": "单击此处选择 csv 文件。", "Click here to select a py file.": "单击此处选择 py 文件。", @@ -134,8 +134,8 @@ "Create new secret key": "创建新安全密钥", "Created at": "创建于", "Created At": "创建于", - "Created by": "", - "CSV Import": "", + "Created by": "作者", + "CSV Import": "通过 CSV 文件导入", "Current Model": "当前模型", "Current Password": "当前密码", "Custom": "自定义", @@ -249,7 +249,7 @@ "Fluidly stream large external response chunks": "流畅地传输外部大型响应块数据", "Focus chat input": "聚焦对话输入", "Followed instructions perfectly": "完全按照指示执行", - "Form": "", + "Form": "手动创建", "Format your variables using square brackets like this:": "使用这样的方括号格式化你的变量:", "Frequency Penalty": "频率惩罚", "Functions": "功能", From f0b5008fc83f9774002e174d45da9f0756faa8c3 Mon Sep 17 00:00:00 2001 From: Karl Lee <61072264+KarlLee830@users.noreply.github.com> Date: Fri, 21 Jun 2024 15:44:06 +0800 Subject: [PATCH 02/71] i18n: Update Chinese translation --- src/lib/i18n/locales/zh-CN/translation.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 95775333ab..0e982c3517 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -266,7 +266,7 @@ "Hello, {{name}}": "您好,{{name}}", "Help": "帮助", "Hide": "隐藏", - "Hide Model": "隐藏模型", + "Hide Model": "隐藏", "How can I help you today?": "有什么我能帮您的吗?", "Hybrid Search": "混合搜索", "Image Generation (Experimental)": "图像生成(实验性)", @@ -490,7 +490,7 @@ "short-summary": "简短总结", "Show": "显示", "Show Admin Details in Account Pending Overlay": "在用户待激活界面中显示管理员邮箱等详细信息", - "Show Model": "显示模型", + "Show Model": "显示", "Show shortcuts": "显示快捷方式", "Showcased creativity": "很有创意", "sidebar": "侧边栏", From 0c7df2cde224f02086e355e66ff7413aec3bcc44 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sat, 22 Jun 2024 00:17:34 +0800 Subject: [PATCH 03/71] Improve Traditional Chinese(zh-TW) locale --- src/lib/i18n/locales/zh-TW/translation.json | 480 ++++++++++---------- 1 file changed, 240 insertions(+), 240 deletions(-) diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index a99ba68ffe..b5f2a022df 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -4,36 +4,36 @@ "(e.g. `sh webui.sh --api`)": "(例如 `sh webui.sh --api`)", "(latest)": "(最新版)", "{{ models }}": "{{ models }}", - "{{ owner }}: You cannot delete a base model": "{{ owner }}:你無法刪除基本模型", + "{{ owner }}: You cannot delete a base model": "{{ owner }}:您無法刪除基礎模型", "{{modelName}} is thinking...": "{{modelName}} 正在思考...", "{{user}}'s Chats": "{{user}} 的聊天", - "{{webUIName}} Backend Required": "需要 {{webUIName}} 後台", - "A task model is used when performing tasks such as generating titles for chats and web search queries": "在執行任務時使用任務模型,例如為聊天和網絡搜索查詢生成標題", + "{{webUIName}} Backend Required": "需要 {{webUIName}} 後端", + "A task model is used when performing tasks such as generating titles for chats and web search queries": "在執行任務時使用任務模型,例如為聊天和網頁搜尋查詢生成標題", "a user": "使用者", "About": "關於", "Account": "帳號", - "Account Activation Pending": "", - "Accurate information": "準確信息", - "Active Users": "", + "Account Activation Pending": "帳號啟用中", + "Accurate information": "準確資訊", + "Active Users": "活躍使用者", "Add": "新增", "Add a model id": "新增模型 ID", - "Add a short description about what this model does": "為這個模型添加一個簡短描述", - "Add a short title for this prompt": "為這個提示詞添加一個簡短的標題", + "Add a short description about what this model does": "為這個模型新增一個簡短描述", + "Add a short title for this prompt": "為這個提示詞新增一個簡短的標題", "Add a tag": "新增標籤", - "Add custom prompt": "新增自定義提示詞", + "Add custom prompt": "新增自訂提示詞", "Add Docs": "新增文件", "Add Files": "新增檔案", "Add Memory": "新增記憶", "Add message": "新增訊息", "Add Model": "新增模型", "Add Tags": "新增標籤", - "Add User": "新增用户", + "Add User": "新增使用者", "Adjusting these settings will apply changes universally to all users.": "調整這些設定將對所有使用者進行更改。", "admin": "管理員", - "Admin": "", + "Admin": "管理員", "Admin Panel": "管理員控制台", "Admin Settings": "管理設定", - "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", + "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "管理員隨時可以使用所有工具;使用者需要在工作區中為每個模型分配工具。", "Advanced Parameters": "進階參數", "Advanced Params": "進階參數", "all": "所有", @@ -41,43 +41,43 @@ "All Users": "所有使用者", "Allow": "允許", "Allow Chat Deletion": "允許刪除聊天紀錄", - "Allow non-local voices": "", - "Allow User Location": "", - "alphanumeric characters and hyphens": "英文字母、數字(0~9)和連字符(-)", + "Allow non-local voices": "允許非本機語音", + "Allow User Location": "允許使用者位置", + "alphanumeric characters and hyphens": "英文字母、數字(0~9)和連字元(-)", "Already have an account?": "已經有帳號了嗎?", "an assistant": "助手", "and": "和", - "and create a new shared link.": "創建一個新的共享連結。", + "and create a new shared link.": "並建立一個新的共享連結。", "API Base URL": "API 基本 URL", - "API Key": "API Key", - "API Key created.": "API Key", - "API keys": "API Keys", - "April": "4月", - "Archive": "存檔", - "Archive All Chats": "存檔所有聊天紀錄", - "Archived Chats": "聊天記錄存檔", + "API Key": "API 金鑰", + "API Key created.": "API 金鑰已建立。", + "API keys": "API 金鑰", + "April": "4 月", + "Archive": "封存", + "Archive All Chats": "封存所有聊天紀錄", + "Archived Chats": "已封存的聊天紀錄", "are allowed - Activate this command by typing": "是允許的 - 透過輸入", - "Are you sure?": "你確定嗎?", + "Are you sure?": "您確定嗎?", "Attach file": "附加檔案", "Attention to detail": "細節精確", "Audio": "音訊", - "August": "8月", + "August": "8 月", "Auto-playback response": "自動播放回答", "AUTOMATIC1111 Base URL": "AUTOMATIC1111 基本 URL", "AUTOMATIC1111 Base URL is required.": "需要 AUTOMATIC1111 基本 URL", - "available!": "可以使用!", + "available!": "可用!", "Back": "返回", "Bad Response": "錯誤回應", "Banners": "橫幅", - "Base Model (From)": "基本模型(來自)", - "Batch Size (num_batch)": "", + "Base Model (From)": "基礎模型(來自)", + "Batch Size (num_batch)": "批次大小(num_batch)", "before": "前", "Being lazy": "懶人模式", - "Brave Search API Key": "搜尋 API Key", - "Bypass SSL verification for Websites": "跳過 SSL 驗證", - "Call": "", - "Call feature is not supported when using Web STT engine": "", - "Camera": "", + "Brave Search API Key": "Brave 搜尋 API 金鑰", + "Bypass SSL verification for Websites": "跳過網站的 SSL 驗證", + "Call": "呼叫", + "Call feature is not supported when using Web STT engine": "使用 Web STT 引擎時不支援呼叫功能", + "Camera": "相機", "Cancel": "取消", "Capabilities": "功能", "Change Password": "修改密碼", @@ -85,27 +85,27 @@ "Chat Background Image": "", "Chat Bubble UI": "聊天氣泡介面", "Chat direction": "聊天方向", - "Chat History": "聊天紀錄功能", - "Chat History is off for this browser.": "此瀏覽器已關閉聊天紀錄功能。", + "Chat History": "聊天紀錄", + "Chat History is off for this browser.": "此瀏覽器已關閉聊天紀錄。", "Chats": "聊天", "Check Again": "重新檢查", "Check for updates": "檢查更新", "Checking for updates...": "正在檢查更新...", "Choose a model before saving...": "儲存前選擇一個模型...", - "Chunk Overlap": "Chunk Overlap", - "Chunk Params": "Chunk 參數", - "Chunk Size": "Chunk 大小", + "Chunk Overlap": "區塊重疊", + "Chunk Params": "區塊參數", + "Chunk Size": "區塊大小", "Citation": "引文", - "Clear memory": "", - "Click here for help.": "點擊這裡尋找幫助。", - "Click here to": "點擊這裡", - "Click here to download user import template file.": "", - "Click here to select": "點擊這裡選擇", - "Click here to select a csv file.": "點擊這裡選擇 csv 檔案。", - "Click here to select a py file.": "", - "Click here to select documents.": "點擊這裡選擇文件。", - "click here.": "點擊這裡。", - "Click on the user role button to change a user's role.": "點擊使用者 Role 按鈕以更改使用者的 Role。", + "Clear memory": "清除記憶", + "Click here for help.": "點選這裡尋求幫助。", + "Click here to": "點選這裡", + "Click here to download user import template file.": "點選這裡下載使用者匯入的範本", + "Click here to select": "點選這裡選擇", + "Click here to select a csv file.": "點選這裡選擇 csv 檔案。", + "Click here to select a py file.": "點選這裡選擇 py 檔案。", + "Click here to select documents.": "點選這裡選擇文件。", + "click here.": "點選這裡。", + "Click on the user role button to change a user's role.": "點選使用者角色按鈕以更改使用者的角色。", "Clone": "複製", "Close": "關閉", "Collection": "收藏", @@ -118,7 +118,7 @@ "Confirm Password": "確認密碼", "Confirm your action": "", "Connections": "連線", - "Contact Admin for WebUI Access": "", + "Contact Admin for WebUI Access": "聯絡管理員以取得 WebUI 存取權", "Content": "內容", "Context Length": "上下文長度", "Continue Response": "繼續回答", @@ -130,8 +130,8 @@ "Copying to clipboard was successful!": "成功複製到剪貼簿!", "Create a model": "建立模型", "Create Account": "建立帳號", - "Create new key": "建立新密鑰", - "Create new secret key": "建立新密鑰", + "Create new key": "建立新金鑰", + "Create new secret key": "建立新金鑰", "Created at": "建立於", "Created At": "建立於", "Created by": "", @@ -139,18 +139,18 @@ "Current Model": "目前模型", "Current Password": "目前密碼", "Custom": "自訂", - "Customize models for a specific purpose": "為特定目的自定義模型", + "Customize models for a specific purpose": "為特定目的自訂模型", "Dark": "暗色", - "Dashboard": "", + "Dashboard": "儀表板", "Database": "資料庫", - "December": "12月", + "December": "12 月", "Default": "預設", "Default (Automatic1111)": "預設(Automatic1111)", "Default (SentenceTransformers)": "預設(SentenceTransformers)", "Default Model": "預設模型", "Default model updated": "預設模型已更新", "Default Prompt Suggestions": "預設提示詞建議", - "Default User Role": "預設用戶 Role", + "Default User Role": "預設使用者角色", "delete": "刪除", "Delete": "刪除", "Delete a model": "刪除一個模型", @@ -159,178 +159,178 @@ "Delete Chat": "刪除聊天紀錄", "Delete chat?": "", "delete this link": "刪除此連結", - "Delete User": "刪除用戶", + "Delete User": "刪除使用者", "Deleted {{deleteModelTag}}": "已刪除 {{deleteModelTag}}", "Deleted {{name}}": "已刪除 {{name}}", "Description": "描述", - "Didn't fully follow instructions": "無法完全遵循指示", + "Didn't fully follow instructions": "未完全遵循指示", "Discover a model": "發現新模型", "Discover a prompt": "發現新提示詞", - "Discover, download, and explore custom prompts": "發現、下載並探索他人設置的提示詞", - "Discover, download, and explore model presets": "發現、下載並探索他人設置的模型", - "Dismissible": "", - "Display Emoji in Call": "", - "Display the username instead of You in the Chat": "在聊天中顯示使用者名稱而不是「你」", + "Discover, download, and explore custom prompts": "發現、下載並探索自訂提示詞", + "Discover, download, and explore model presets": "發現、下載並探索模型預設值", + "Dismissible": "可忽略", + "Display Emoji in Call": "在呼叫中顯示表情符號", + "Display the username instead of You in the Chat": "在聊天中顯示使用者名稱而不是「您」", "Document": "文件", "Document Settings": "文件設定", - "Documentation": "", + "Documentation": "文件", "Documents": "文件", - "does not make any external connections, and your data stays securely on your locally hosted server.": "不會與外部溝通,你的數據會安全地留在你的本機伺服器上。", + "does not make any external connections, and your data stays securely on your locally hosted server.": "不會與外部連線,您的資料會安全地留在您的本機伺服器上。", "Don't Allow": "不允許", "Don't have an account?": "還沒有註冊帳號?", "Don't like the style": "不喜歡這個樣式?", "Download": "下載", "Download canceled": "下載已取消", "Download Database": "下載資料庫", - "Drop any files here to add to the conversation": "拖拽文件到此處以新增至對話", + "Drop any files here to add to the conversation": "拖拽任意檔案到此處以新增至對話", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "例如 '30s', '10m'。有效的時間單位為 's', 'm', 'h'。", "Edit": "編輯", "Edit Doc": "編輯文件", - "Edit Memory": "", + "Edit Memory": "編輯記憶", "Edit User": "編輯使用者", "Email": "電子郵件", - "Embedding Batch Size": "", + "Embedding Batch Size": "嵌入批次大小", "Embedding Model": "嵌入模型", "Embedding Model Engine": "嵌入模型引擎", "Embedding model set to \"{{embedding_model}}\"": "嵌入模型已設定為 \"{{embedding_model}}\"", - "Enable Chat History": "啟用聊天歷史", - "Enable Community Sharing": "啟用社區分享", + "Enable Chat History": "啟用聊天紀錄", + "Enable Community Sharing": "啟用社群分享", "Enable New Sign Ups": "允許註冊新帳號", - "Enable Web Search": "啟用網絡搜索", - "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "請確保你的 CSV 檔案包含這四個欄位,並按照此順序:名稱、電子郵件、密碼、角色。", + "Enable Web Search": "啟用網頁搜尋", + "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "請確保您的 CSV 檔案包含這四個欄位,並按照此順序:名稱、電子郵件、密碼、角色。", "Enter {{role}} message here": "在這裡輸入 {{role}} 訊息", "Enter a detail about yourself for your LLMs to recall": "輸入 LLM 記憶的詳細內容", - "Enter Brave Search API Key": "輸入 Brave Search API Key", - "Enter Chunk Overlap": "輸入 Chunk Overlap", - "Enter Chunk Size": "輸入 Chunk 大小", + "Enter Brave Search API Key": "輸入 Brave 搜尋 API 金鑰", + "Enter Chunk Overlap": "輸入區塊重疊", + "Enter Chunk Size": "輸入區塊大小", "Enter Github Raw URL": "輸入 Github Raw URL", - "Enter Google PSE API Key": "輸入 Google PSE API Key", - "Enter Google PSE Engine Id": "輸入 Google PSE Engine Id", + "Enter Google PSE API Key": "輸入 Google PSE API 金鑰", + "Enter Google PSE Engine Id": "輸入 Google PSE 引擎 ID", "Enter Image Size (e.g. 512x512)": "輸入圖片大小(例如 512x512)", "Enter language codes": "輸入語言代碼", "Enter model tag (e.g. {{modelTag}})": "輸入模型標籤(例如 {{modelTag}})", "Enter Number of Steps (e.g. 50)": "輸入步數(例如 50)", "Enter Score": "輸入分數", "Enter Searxng Query URL": "輸入 Searxng 查詢 URL", - "Enter Serper API Key": "輸入 Serper API Key", - "Enter Serply API Key": "", - "Enter Serpstack API Key": "輸入 Serpstack API Key", + "Enter Serper API Key": "輸入 Serper API 金鑰", + "Enter Serply API Key": "輸入 Serply API 金鑰", + "Enter Serpstack API Key": "輸入 Serpstack API 金鑰", "Enter stop sequence": "輸入停止序列", - "Enter Tavily API Key": "", + "Enter Tavily API Key": "輸入 Tavily API 金鑰", "Enter Top K": "輸入 Top K", "Enter URL (e.g. http://127.0.0.1:7860/)": "輸入 URL(例如 http://127.0.0.1:7860/)", "Enter URL (e.g. http://localhost:11434)": "輸入 URL(例如 http://localhost:11434)", - "Enter Your Email": "輸入你的電子郵件", - "Enter Your Full Name": "輸入你的全名", - "Enter Your Password": "輸入你的密碼", - "Enter Your Role": "輸入你的角色", + "Enter Your Email": "輸入您的電子郵件", + "Enter Your Full Name": "輸入您的全名", + "Enter Your Password": "輸入您的密碼", + "Enter Your Role": "輸入您的角色", "Error": "錯誤", - "Experimental": "實驗功能", - "Export": "出口", + "Experimental": "實驗性功能", + "Export": "匯出", "Export All Chats (All Users)": "匯出所有聊天紀錄(所有使用者)", - "Export chat (.json)": "", + "Export chat (.json)": "匯出聊天紀錄(.json)", "Export Chats": "匯出聊天紀錄", - "Export Documents Mapping": "匯出文件映射", - "Export Functions": "", + "Export Documents Mapping": "匯出文件對映", + "Export Functions": "匯出功能", "Export Models": "匯出模型", "Export Prompts": "匯出提示詞", - "Export Tools": "", - "External Models": "", - "Failed to create API Key.": "無法創建 API 金鑰。", + "Export Tools": "匯出工具", + "External Models": "外部模型", + "Failed to create API Key.": "無法建立 API 金鑰。", "Failed to read clipboard contents": "無法讀取剪貼簿內容", - "Failed to update settings": "", - "February": "2月", - "Feel free to add specific details": "請自由添加詳細內容。", - "File": "", + "Failed to update settings": "無法更新設定", + "February": "2 月", + "Feel free to add specific details": "請隨意新增詳細內容。", + "File": "檔案", "File Mode": "檔案模式", "File not found.": "找不到檔案。", - "Filters": "", - "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "偽裝偽裝檢測:無法使用頭像作為頭像。預設為預設頭像。", - "Fluidly stream large external response chunks": "流暢地傳輸大型外部響應區塊", + "Filters": "篩選器", + "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "偽造偵測:無法使用初始頭像。預設為預設個人影象。", + "Fluidly stream large external response chunks": "流暢地傳輸大型外部回應區塊", "Focus chat input": "聚焦聊天輸入框", "Followed instructions perfectly": "完全遵循指示", - "Form": "", - "Format your variables using square brackets like this:": "像這樣使用方括號來格式化你的變數:", + "Form": "表單", + "Format your variables using square brackets like this:": "像這樣使用方括號來格式化您的變數:", "Frequency Penalty": "頻率懲罰", - "Functions": "", + "Functions": "功能", "General": "常用", "General Settings": "常用設定", - "Generate Image": "", - "Generating search query": "生成搜索查詢", - "Generation Info": "生成信息", + "Generate Image": "生成圖片", + "Generating search query": "生成搜尋查詢", + "Generation Info": "生成資訊", "Good Response": "優秀的回應", - "Google PSE API Key": "Google PSE API Key", - "Google PSE Engine Id": "Google PSE Engine Id", + "Google PSE API Key": "Google PSE API 金鑰", + "Google PSE Engine Id": "Google PSE 引擎 ID", "h:mm a": "h:mm a", "has no conversations.": "沒有對話", - "Hello, {{name}}": "你好,{{name}}", + "Hello, {{name}}": "您好,{{name}}", "Help": "幫助", "Hide": "隱藏", - "Hide Model": "", - "How can I help you today?": "今天能為你做什麼?", - "Hybrid Search": "混合搜索", - "Image Generation (Experimental)": "圖像生成(實驗功能)", - "Image Generation Engine": "圖像生成引擎", + "Hide Model": "隱藏模型", + "How can I help you today?": "今天能為您做些什麼?", + "Hybrid Search": "混合搜尋", + "Image Generation (Experimental)": "影像生成(實驗性功能)", + "Image Generation Engine": "影像生成引擎", "Image Settings": "圖片設定", "Images": "圖片", "Import Chats": "匯入聊天紀錄", - "Import Documents Mapping": "匯入文件映射", - "Import Functions": "", + "Import Documents Mapping": "匯入文件對映", + "Import Functions": "匯入功能", "Import Models": "匯入模型", "Import Prompts": "匯入提示詞", - "Import Tools": "", - "Include `--api` flag when running stable-diffusion-webui": "在運行 stable-diffusion-webui 時加上 `--api` 標誌", + "Import Tools": "匯入工具", + "Include `--api` flag when running stable-diffusion-webui": "在執行 stable-diffusion-webui 時加上 `--api` 標誌", "Info": "資訊", "Input commands": "輸入命令", "Install from Github URL": "從 Github URL 安裝", - "Instant Auto-Send After Voice Transcription": "", + "Instant Auto-Send After Voice Transcription": "語音轉錄後立即自動傳送", "Interface": "介面", "Invalid Tag": "無效標籤", - "January": "1月", - "join our Discord for help.": "加入我們的 Discord 尋找幫助。", + "January": "1 月", + "join our Discord for help.": "加入我們的 Discord 尋求幫助。", "JSON": "JSON", "JSON Preview": "JSON 預覽", - "July": "7月", - "June": "6月", + "July": "7 月", + "June": "6 月", "JWT Expiration": "JWT 過期時間", "JWT Token": "JWT Token", "Keep Alive": "保持活躍", "Keyboard shortcuts": "鍵盤快速鍵", - "Knowledge": "", + "Knowledge": "知識", "Language": "語言", "Last Active": "最後活動", - "Last Modified": "", + "Last Modified": "最後修改", "Light": "亮色", - "Listening...": "", + "Listening...": "正在聆聽...", "LLMs can make mistakes. Verify important information.": "LLM 可能會產生錯誤。請驗證重要資訊。", - "Local Models": "", + "Local Models": "本機模型", "LTR": "LTR", - "Made by OpenWebUI Community": "由 OpenWebUI 社區製作", + "Made by OpenWebUI Community": "由 OpenWebUI 社群製作", "Make sure to enclose them with": "請確保變數有被以下符號框住:", - "Manage": "", - "Manage Models": "管理模組", + "Manage": "管理", + "Manage Models": "管理模型", "Manage Ollama Models": "管理 Ollama 模型", - "Manage Pipelines": "管理管道", - "March": "3月", + "Manage Pipelines": "管理管線", + "March": "3 月", "Max Tokens (num_predict)": "最大 Token(num_predict)", "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "最多可以同時下載 3 個模型。請稍後再試。", - "May": "5月", + "May": "5 月", "Memories accessible by LLMs will be shown here.": "LLM 記憶將會顯示在此處。", "Memory": "記憶", - "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "創建連結後發送的訊息將不會被共享。具有 URL 的用戶將會能夠檢視共享的聊天。", - "Minimum Score": "最小分數", + "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "建立連結後傳送的訊息將不會被共享。具有 URL 的使用者將會能夠檢視共享的聊天。", + "Minimum Score": "最低分數", "Mirostat": "Mirostat", "Mirostat Eta": "Mirostat Eta", "Mirostat Tau": "Mirostat Tau", "MMMM DD, YYYY": "MMMM DD, YYYY", "MMMM DD, YYYY HH:mm": "MMMM DD, YYYY HH:mm", - "MMMM DD, YYYY hh:mm:ss A": "", + "MMMM DD, YYYY hh:mm:ss A": "MMMM DD, YYYY hh:mm:ss A", "Model '{{modelName}}' has been successfully downloaded.": "'{{modelName}}' 模型已成功下載。", "Model '{{modelTag}}' is already in queue for downloading.": "'{{modelTag}}' 模型已經在下載佇列中。", "Model {{modelId}} not found": "找不到 {{modelId}} 模型", "Model {{modelName}} is not vision capable": "{{modelName}} 模型不適用於視覺", "Model {{name}} is now {{status}}": "{{name}} 模型現在是 {{status}}", - "Model filesystem path detected. Model shortname is required for update, cannot continue.": "模型文件系統路徑已檢測。需要更新模型短名,無法繼續。", + "Model filesystem path detected. Model shortname is required for update, cannot continue.": "已偵測到模型檔案系統路徑。需要更新模型簡稱,無法繼續。", "Model ID": "模型 ID", "Model not selected": "未選擇模型", "Model Params": "模型參數", @@ -344,32 +344,32 @@ "Name your model": "請輸入模型名稱", "New Chat": "新增聊天", "New Password": "新密碼", - "No documents found": "", + "No documents found": "找不到文件", "No results found": "沒有找到結果", - "No search query generated": "沒有生成搜索查詢", + "No search query generated": "沒有生成搜尋查詢", "No source available": "沒有可用的來源", "None": "無", - "Not factually correct": "與真實資訊不相符", - "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "註:如果設置最低分數,則搜索將只返回分數大於或等於最低分數的文檔。", - "Notifications": "桌面通知", - "November": "11月", - "num_thread (Ollama)": "num_thread(奧拉馬)", + "Not factually correct": "與真實資訊不符", + "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "註:如果設定最低分數,則搜尋將只返回分數大於或等於最低分數的文件。", + "Notifications": "通知", + "November": "11 月", + "num_thread (Ollama)": "num_thread(Ollama)", "October": "10 月", "Off": "關閉", "Okay, Let's Go!": "好的,啟動吧!", - "OLED Dark": "`", + "OLED Dark": "OLED 深色", "Ollama": "Ollama", "Ollama API": "Ollama API", - "Ollama API disabled": "Ollama API 已禁用", - "Ollama API is disabled": "", + "Ollama API disabled": "Ollama API 已停用", + "Ollama API is disabled": "Ollama API 已停用", "Ollama Version": "Ollama 版本", "On": "開啟", "Only": "僅有", - "Only alphanumeric characters and hyphens are allowed in the command string.": "命令字串中只能包含英文字母、數字(0~9)和連字符(-)。", - "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "哎呀!請稍等!你的文件還在處理中。我們正最佳化文件,請耐心等待,一旦準備好,我們會通知你。", + "Only alphanumeric characters and hyphens are allowed in the command string.": "命令字串中只能包含英文字母、數字(0~9)和連字元(-)。", + "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "哎呀!請稍等!您的文件還在處理中。我們正最佳化文件,請耐心等待,一旦準備好,我們會通知您。", "Oops! Looks like the URL is invalid. Please double-check and try again.": "哎呀!看起來 URL 無效。請仔細檢查後再試一次。", - "Oops! There was an error in the previous response. Please try again or contact admin.": "", - "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "哎呀!你正在使用不支援的方法(僅有前台)。請從後台提供 WebUI。", + "Oops! There was an error in the previous response. Please try again or contact admin.": "哎呀!先前的回應發生錯誤。請重試或聯絡管理員", + "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "哎呀!您正在使用不支援的方法(僅有前端)。請從後端提供 WebUI。", "Open": "開啟", "Open AI": "Open AI", "Open AI (Dall-E)": "Open AI (Dall-E)", @@ -383,22 +383,22 @@ "Other": "其他", "Password": "密碼", "PDF document (.pdf)": "PDF 文件 (.pdf)", - "PDF Extract Images (OCR)": "PDF 圖像擷取(OCR 光學文字辨識)", + "PDF Extract Images (OCR)": "PDF 影像擷取(OCR 光學文字辨識)", "pending": "待審查", - "Permission denied when accessing media devices": "", - "Permission denied when accessing microphone": "", + "Permission denied when accessing media devices": "存取媒體裝置時被拒絕權限", + "Permission denied when accessing microphone": "存取麥克風時被拒絕權限", "Permission denied when accessing microphone: {{error}}": "存取麥克風時被拒絕權限:{{error}}", "Personalization": "個人化", "Pipelines": "管線", - "Pipelines Valves": "管線阀门", + "Pipelines Valves": "管線閥門", "Plain text (.txt)": "純文字 (.txt)", "Playground": "AI 對話遊樂場", "Positive attitude": "積極態度", "Previous 30 days": "前 30 天", "Previous 7 days": "前 7 天", - "Profile Image": "個人圖像", + "Profile Image": "個人影像", "Prompt": "提示詞", - "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "提示詞(例如:告訴我關於羅馬帝國的趣味事)", + "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "提示詞(例如:告訴我關於羅馬帝國的一些趣事)", "Prompt Content": "提示詞內容", "Prompt suggestions": "提示詞建議", "Prompts": "提示詞", @@ -408,32 +408,32 @@ "RAG Template": "RAG 範例", "Read Aloud": "讀出", "Record voice": "錄音", - "Redirecting you to OpenWebUI Community": "將你重新導向到 OpenWebUI 社群", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", - "Refused when it shouldn't have": "拒絕時不該拒絕", + "Redirecting you to OpenWebUI Community": "將您重新導向到 OpenWebUI 社群", + "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "將自己稱為「使用者」(例如,「使用者正在學習西班牙語」)", + "Refused when it shouldn't have": "不該拒絕時拒絕了", "Regenerate": "重新生成", "Release Notes": "發布說明", "Remove": "移除", "Remove Model": "移除模型", - "Rename": "重命名", + "Rename": "重新命名", "Repeat Last N": "重複最後 N 次", "Request Mode": "請求模式", "Reranking Model": "重新排序模型", - "Reranking model disabled": "重新排序模型已禁用", + "Reranking model disabled": "重新排序模型已停用", "Reranking model set to \"{{reranking_model}}\"": "重新排序模型設定為 \"{{reranking_model}}\"", - "Reset": "", - "Reset Upload Directory": "", - "Reset Vector Storage": "重置向量儲存空間", + "Reset": "重設", + "Reset Upload Directory": "重設上傳目錄", + "Reset Vector Storage": "重設向量儲存空間", "Response AutoCopy to Clipboard": "自動複製回答到剪貼簿", - "Role": "Role", + "Role": "角色", "Rosé Pine": "玫瑰松", "Rosé Pine Dawn": "黎明玫瑰松", "RTL": "RTL", - "Running": "", + "Running": "運作中", "Save": "儲存", "Save & Create": "儲存並建立", "Save & Update": "儲存並更新", - "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "現已不支援將聊天紀錄儲存到瀏覽器儲存空間中。請點擊下面的按鈕下載並刪除你的聊天記錄。別擔心,你可以通過以下方式輕鬆地重新匯入你的聊天記錄到後台", + "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "現已不支援將聊天紀錄儲存到瀏覽器儲存空間中。請點選下面的按鈕下載並刪除您的聊天記錄。別擔心,您可以透過以下方式輕鬆地重新匯入您的聊天記錄到後端", "Scan": "掃描", "Scan complete!": "掃描完成!", "Scan for documents from {{path}}": "從 {{path}} 掃描文件", @@ -441,37 +441,37 @@ "Search a model": "搜尋模型", "Search Chats": "搜尋聊天", "Search Documents": "搜尋文件", - "Search Functions": "", + "Search Functions": "搜尋功能", "Search Models": "搜尋模型", "Search Prompts": "搜尋提示詞", - "Search Query Generation Prompt": "", - "Search Query Generation Prompt Length Threshold": "", + "Search Query Generation Prompt": "搜尋查詢生成提示詞", + "Search Query Generation Prompt Length Threshold": "搜尋查詢生成提示詞長度閾值", "Search Result Count": "搜尋結果數量", - "Search Tools": "", - "Searched {{count}} sites_other": "掃描 {{count}} 個網站_其他", - "Searching \"{{searchQuery}}\"": "", + "Search Tools": "搜尋工具", + "Searched {{count}} sites_other": "搜尋了 {{count}} 個網站", + "Searching \"{{searchQuery}}\"": "正在搜尋 \"{{searchQuery}}\"", "Searxng Query URL": "Searxng 查詢 URL", - "See readme.md for instructions": "查看 readme.md 獲取指南", - "See what's new": "查看最新內容", + "See readme.md for instructions": "檢視 readme.md 取得指南", + "See what's new": "檢視最新內容", "Seed": "種子", "Select a base model": "選擇基礎模型", - "Select a engine": "", + "Select a engine": "選擇引擎", "Select a mode": "選擇模式", "Select a model": "選擇一個模型", - "Select a pipeline": "選擇管道", - "Select a pipeline url": "選擇管道 URL", - "Select an Ollama instance": "選擇 Ollama 實例", - "Select Documents": "", + "Select a pipeline": "選擇管線", + "Select a pipeline url": "選擇管線 URL", + "Select an Ollama instance": "選擇 Ollama 執行個體", + "Select Documents": "選擇文件", "Select model": "選擇模型", - "Select only one model to call": "", - "Selected model(s) do not support image inputs": "已選擇模型不支持圖像輸入", + "Select only one model to call": "僅選擇一個模型來呼叫", + "Selected model(s) do not support image inputs": "已選擇模型不支援影像輸入", "Send": "傳送", "Send a Message": "傳送訊息", "Send message": "傳送訊息", - "September": "九月", - "Serper API Key": "Serper API Key", - "Serply API Key": "", - "Serpstack API Key": "Serpstack API Key", + "September": "9 月", + "Serper API Key": "Serper API 金鑰", + "Serply API Key": "Serply API 金鑰", + "Serpstack API Key": "Serpstack API 金鑰", "Server connection verified": "已驗證伺服器連線", "Set as default": "設為預設", "Set Default Model": "設定預設模型", @@ -483,14 +483,14 @@ "Set Voice": "設定語音", "Settings": "設定", "Settings saved successfully!": "成功儲存設定", - "Settings updated successfully": "", + "Settings updated successfully": "設定更新成功", "Share": "分享", "Share Chat": "分享聊天", "Share to OpenWebUI Community": "分享到 OpenWebUI 社群", "short-summary": "簡短摘要", "Show": "顯示", - "Show Admin Details in Account Pending Overlay": "", - "Show Model": "", + "Show Admin Details in Account Pending Overlay": "在帳號待審覆蓋層中顯示管理員詳細資訊", + "Show Model": "顯示模型", "Show shortcuts": "顯示快速鍵", "Showcased creativity": "展示創造性", "sidebar": "側邊欄", @@ -502,79 +502,79 @@ "Speech recognition error: {{error}}": "語音識別錯誤:{{error}}", "Speech-to-Text Engine": "語音轉文字引擎", "Stop Sequence": "停止序列", - "STT Model": "", + "STT Model": "STT 模型", "STT Settings": "語音轉文字設定", "Submit": "提交", - "Subtitle (e.g. about the Roman Empire)": "標題(例如:關於羅馬帝國)", + "Subtitle (e.g. about the Roman Empire)": "副標題(例如:關於羅馬帝國)", "Success": "成功", "Successfully updated.": "更新成功。", "Suggested": "建議", "System": "系統", "System Prompt": "系統提示詞", "Tags": "標籤", - "Tap to interrupt": "", - "Tavily API Key": "", + "Tap to interrupt": "點選以中斷", + "Tavily API Key": "Tavily API 金鑰", "Tell us more:": "告訴我們更多:", "Temperature": "溫度", - "Template": "模板", - "Text Completion": "文本補全(Text Completion)", + "Template": "範本", + "Text Completion": "文字補全", "Text-to-Speech Engine": "文字轉語音引擎", "Tfs Z": "Tfs Z", - "Thanks for your feedback!": "感謝你的回饋!", + "Thanks for your feedback!": "感謝您的回饋!", "The score should be a value between 0.0 (0%) and 1.0 (100%).": "分數應該介於 0.0(0%)和 1.0(100%)之間。", "Theme": "主題", - "Thinking...": "", - "This action cannot be undone. Do you wish to continue?": "", - "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "這確保你寶貴的對話安全地儲存到你的後台資料庫。謝謝!", - "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "Thinking...": "正在思考...", + "This action cannot be undone. Do you wish to continue?": "此動作無法被復原。您想要繼續進行嗎?", + "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "這確保您寶貴的對話安全地儲存到您的後端資料庫。謝謝!", + "This is an experimental feature, it may not function as expected and is subject to change at any time.": "這是一個實驗性功能,可能無法如預期運作,並且隨時可能更改。", "This setting does not sync across browsers or devices.": "此設定不會在瀏覽器或裝置間同步。", "This will delete": "", "Thorough explanation": "詳細說明", "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "提示:透過在每次替換後在聊天輸入框中按 Tab 鍵連續更新多個變數。", "Title": "標題", "Title (e.g. Tell me a fun fact)": "標題(例如:告訴我一個有趣的事)", - "Title Auto-Generation": "自動生成標題", + "Title Auto-Generation": "自動產生標題", "Title cannot be an empty string.": "標題不能為空字串", - "Title Generation Prompt": "自動生成標題的提示詞", + "Title Generation Prompt": "自動產生標題的提示詞", "to": "到", - "To access the available model names for downloading,": "若想查看可供下載的模型名稱,", - "To access the GGUF models available for downloading,": "若想查看可供下載的 GGUF 模型名稱,", - "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "", - "To add documents here, upload them to the \"Documents\" workspace first.": "", + "To access the available model names for downloading,": "若想檢視可供下載的模型名稱,", + "To access the GGUF models available for downloading,": "若想檢視可供下載的 GGUF 模型名稱,", + "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "若要存取 WebUI,請聯絡管理員。管理員可以從管理面板管理使用者狀態。", + "To add documents here, upload them to the \"Documents\" workspace first.": "若要在此新增文件,請先將它們上傳到「文件」工作區。", "to chat input.": "到聊天輸入框來啟動此命令。", - "To select filters here, add them to the \"Functions\" workspace first.": "", - "To select toolkits here, add them to the \"Tools\" workspace first.": "", + "To select filters here, add them to the \"Functions\" workspace first.": "若要在此選擇篩選器,請先將它們新增到「功能」工作區。", + "To select toolkits here, add them to the \"Tools\" workspace first.": "若要在此選擇工具包,請先將它們新增到「工具」工作區。", "Today": "今天", "Toggle settings": "切換設定", "Toggle sidebar": "切換側邊欄", - "Tokens To Keep On Context Refresh (num_keep)": "", - "Tools": "", + "Tokens To Keep On Context Refresh (num_keep)": "上下文重新整理時保留的 Token 數量(num_keep)", + "Tools": "工具", "Top K": "Top K", "Top P": "Top P", "Trouble accessing Ollama?": "存取 Ollama 時遇到問題?", - "TTS Model": "", - "TTS Settings": "文字轉語音設定", - "TTS Voice": "", + "TTS Model": "文字轉語音(TTS)模型", + "TTS Settings": "文字轉語音(TTS)設定", + "TTS Voice": "文字轉語音(TTS)聲調", "Type": "類型", "Type Hugging Face Resolve (Download) URL": "輸入 Hugging Face 解析後的(下載)URL", "Uh-oh! There was an issue connecting to {{provider}}.": "哎呀!連線到 {{provider}} 時出現問題。", - "UI": "", - "Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "", - "Update": "", + "UI": "使用者界面", + "Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "未知的檔案類型 '{{file_type}}'。但仍會繼續上傳。", + "Update": "更新", "Update and Copy Link": "更新並複製連結", "Update password": "更新密碼", - "Updated at": "", - "Upload": "", + "Updated at": "更新於", + "Upload": "上傳", "Upload a GGUF model": "上傳一個 GGUF 模型", - "Upload Files": "上傳文件", - "Upload Pipeline": "", + "Upload Files": "上傳檔案", + "Upload Pipeline": "上傳管線", "Upload Progress": "上傳進度", "URL Mode": "URL 模式", - "Use '#' in the prompt input to load and select your documents.": "在輸入框中輸入 '#' 以載入並選擇你的文件。", + "Use '#' in the prompt input to load and select your documents.": "在輸入框中輸入 '#' 以載入並選擇您的文件。", "Use Gravatar": "使用 Gravatar", - "Use Initials": "使用初始头像", - "use_mlock (Ollama)": "use_mlock(奧拉馬)", - "use_mmap (Ollama)": "use_mmap (Ollama)", + "Use Initials": "使用初始頭像", + "use_mlock (Ollama)": "use_mlock(Ollama)", + "use_mmap (Ollama)": "use_mmap(Ollama)", "user": "使用者", "User Permissions": "使用者權限", "Users": "使用者", @@ -585,32 +585,32 @@ "Version": "版本", "Voice": "", "Warning": "警告", - "Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告:如果更新或更改你的嵌入模型,則需要重新導入所有文件", + "Warning: If you update or change your embedding model, you will need to re-import all documents.": "警告:如果更新或更改您的嵌入模型,則需要重新匯入所有文件", "Web": "網頁", - "Web API": "", - "Web Loader Settings": "Web 載入器設定", - "Web Params": "Web 參數", - "Web Search": "Web 搜尋", - "Web Search Engine": "Web 搜尋引擎", + "Web API": "網頁 API", + "Web Loader Settings": "網頁載入器設定", + "Web Params": "網頁參數", + "Web Search": "網頁搜尋", + "Web Search Engine": "網頁搜尋引擎", "Webhook URL": "Webhook URL", "WebUI Settings": "WebUI 設定", "WebUI will make requests to": "WebUI 將會存取", "What’s New in": "全新內容", "When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "當歷史被關閉時,這個瀏覽器上的新聊天將不會出現在任何裝置的歷史記錄中", - "Whisper (Local)": "", - "Widescreen Mode": "", + "Whisper (Local)": "Whisper(本地)", + "Widescreen Mode": "寬螢幕模式", "Workspace": "工作區", - "Write a prompt suggestion (e.g. Who are you?)": "寫一個提示詞建議(例如:你是誰?)", + "Write a prompt suggestion (e.g. Who are you?)": "寫一個提示詞建議(例如:您是誰?)", "Write a summary in 50 words that summarizes [topic or keyword].": "寫一個 50 字的摘要來概括 [主題或關鍵詞]。", "Yesterday": "昨天", - "You": "你", - "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "", - "You cannot clone a base model": "你不能複製基礎模型", - "You have no archived conversations.": "你沒有任何已封存的對話", - "You have shared this chat": "你已分享此聊天", - "You're a helpful assistant.": "你是一位善於協助他人的助手。", + "You": "您", + "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "您可以透過下方的「管理」按鈕新增記憶,個人化您的 LLM 互動,使其更有幫助並更符合您的需求。", + "You cannot clone a base model": "您不能複製基礎模型", + "You have no archived conversations.": "您沒有任何已封存的對話", + "You have shared this chat": "您已分享此聊天", + "You're a helpful assistant.": "您是一位善於協助他人的助手。", "You're now logged in.": "已登入。", - "Your account status is currently pending activation.": "", + "Your account status is currently pending activation.": "您的帳號狀態目前待啟用。", "Youtube": "Youtube", "Youtube Loader Settings": "Youtube 載入器設定" } From 14fd3a8acabc306edfd509c363f9a243c992f704 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Fri, 21 Jun 2024 11:05:55 -0700 Subject: [PATCH 04/71] refac --- backend/main.py | 1 - 1 file changed, 1 deletion(-) diff --git a/backend/main.py b/backend/main.py index 744c84b6d7..737641e2d4 100644 --- a/backend/main.py +++ b/backend/main.py @@ -1817,7 +1817,6 @@ async def get_manifest_json(): "start_url": "/", "display": "standalone", "background_color": "#343541", - "theme_color": "#343541", "orientation": "portrait-primary", "icons": [{"src": "/static/logo.png", "type": "image/png", "sizes": "500x500"}], } From b06d7dd56a4b1fbae064209394e1bbd09518d383 Mon Sep 17 00:00:00 2001 From: aleix Date: Fri, 21 Jun 2024 20:52:25 +0200 Subject: [PATCH 05/71] i18n: Update Catalan Translation --- src/lib/i18n/locales/ca-ES/translation.json | 786 ++++++++++---------- 1 file changed, 393 insertions(+), 393 deletions(-) diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index a7757749e1..2652add5bd 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -1,618 +1,618 @@ { - "'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' or '-1' per no caduca mai.", + "'s', 'm', 'h', 'd', 'w' or '-1' for no expiration.": "'s', 'm', 'h', 'd', 'w' o '-1' perquè no caduqui mai.", "(Beta)": "(Beta)", "(e.g. `sh webui.sh --api`)": "(p. ex. `sh webui.sh --api`)", "(latest)": "(últim)", "{{ models }}": "{{ models }}", - "{{ owner }}: You cannot delete a base model": "{{ propietari }}: No es pot suprimir un model base", + "{{ owner }}: You cannot delete a base model": "{{ owner }}: No es pot eliminar un model base", "{{modelName}} is thinking...": "{{modelName}} està pensant...", - "{{user}}'s Chats": "{{user}}'s Chats", - "{{webUIName}} Backend Required": "Es requereix Backend de {{webUIName}}", - "A task model is used when performing tasks such as generating titles for chats and web search queries": "Un model de tasca s'utilitza quan es realitzen tasques com ara generar títols per a xats i consultes de cerca web", + "{{user}}'s Chats": "Els xats de {{user}}", + "{{webUIName}} Backend Required": "El Backend de {{webUIName}} és necessari", + "A task model is used when performing tasks such as generating titles for chats and web search queries": "Un model de tasca s'utilitza quan es realitzen tasques com ara generar títols per a xats i consultes de cerca per a la web", "a user": "un usuari", "About": "Sobre", "Account": "Compte", - "Account Activation Pending": "", + "Account Activation Pending": "Activació del compte pendent", "Accurate information": "Informació precisa", - "Active Users": "", + "Active Users": "Usuaris actius", "Add": "Afegir", - "Add a model id": "Afegir un identificador de model", - "Add a short description about what this model does": "Afegiu una breu descripció sobre què fa aquest model", - "Add a short title for this prompt": "Afegeix un títol curt per aquest prompt", + "Add a model id": "Afegeix un identificador de model", + "Add a short description about what this model does": "Afegeix una breu descripció sobre què fa aquest model", + "Add a short title for this prompt": "Afegeix un títol curt per a aquesta indicació", "Add a tag": "Afegeix una etiqueta", - "Add custom prompt": "Afegir un prompt personalitzat", - "Add Docs": "Afegeix Documents", - "Add Files": "Afegeix Arxius", - "Add Memory": "Afegir Memòria", - "Add message": "Afegeix missatge", - "Add Model": "Afegir Model", - "Add Tags": "afegeix etiquetes", - "Add User": "Afegir Usuari", - "Adjusting these settings will apply changes universally to all users.": "Ajustar aquests paràmetres aplicarà canvis de manera universal a tots els usuaris.", + "Add custom prompt": "Afegir una indicació personalitzada", + "Add Docs": "Afegir documents", + "Add Files": "Afegir arxius", + "Add Memory": "Afegir memòria", + "Add message": "Afegir un missatge", + "Add Model": "Afegir un model", + "Add Tags": "Afegir etiquetes", + "Add User": "Afegir un usuari", + "Adjusting these settings will apply changes universally to all users.": "Si ajustes aquesta configuració, els canvis s'aplicaran de manera universal a tots els usuaris.", "admin": "administrador", - "Admin": "", - "Admin Panel": "Panell d'Administració", - "Admin Settings": "Configuració d'Administració", - "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "", - "Advanced Parameters": "Paràmetres Avançats", + "Admin": "Administrador", + "Admin Panel": "Panell d'administració", + "Admin Settings": "Configuració d'administració", + "Admins have access to all tools at all times; users need tools assigned per model in the workspace.": "Els administradors tenen accés a totes les eines en tot moment; els usuaris necessiten eines assignades per model a l'espai de treball.", + "Advanced Parameters": "Paràmetres avançats", "Advanced Params": "Paràmetres avançats", "all": "tots", - "All Documents": "Tots els Documents", - "All Users": "Tots els Usuaris", - "Allow": "Permet", - "Allow Chat Deletion": "Permet la Supressió del Xat", - "Allow non-local voices": "", - "Allow User Location": "", + "All Documents": "Tots els documents", + "All Users": "Tots els usuaris", + "Allow": "Permetre", + "Allow Chat Deletion": "Permetre la supressió del xat", + "Allow non-local voices": "Permetre veus no locals", + "Allow User Location": "Permetre la ubicació de l'usuari", "alphanumeric characters and hyphens": "caràcters alfanumèrics i guions", "Already have an account?": "Ja tens un compte?", "an assistant": "un assistent", "and": "i", "and create a new shared link.": "i crear un nou enllaç compartit.", "API Base URL": "URL Base de l'API", - "API Key": "Clau de l'API", - "API Key created.": "Clau de l'API creada.", + "API Key": "clau API", + "API Key created.": "clau API creada.", "API keys": "Claus de l'API", "April": "Abril", "Archive": "Arxiu", "Archive All Chats": "Arxiva tots els xats", - "Archived Chats": "Arxiu d'historial de xat", + "Archived Chats": "Xats arxivats", "are allowed - Activate this command by typing": "estan permesos - Activa aquesta comanda escrivint", "Are you sure?": "Estàs segur?", "Attach file": "Adjuntar arxiu", - "Attention to detail": "Detall atent", + "Attention to detail": "Atenció al detall", "Audio": "Àudio", "August": "Agost", - "Auto-playback response": "Resposta de reproducció automàtica", - "AUTOMATIC1111 Base URL": "URL Base AUTOMATIC1111", - "AUTOMATIC1111 Base URL is required.": "Es requereix l'URL Base AUTOMATIC1111.", + "Auto-playback response": "Reproduir la resposta automàticament", + "AUTOMATIC1111 Base URL": "URL Base d'AUTOMATIC1111", + "AUTOMATIC1111 Base URL is required.": "Es requereix l'URL Base d'AUTOMATIC1111.", "available!": "disponible!", "Back": "Enrere", - "Bad Response": "Resposta Erroni", + "Bad Response": "Resposta errònia", "Banners": "Banners", "Base Model (From)": "Model base (des de)", - "Batch Size (num_batch)": "", + "Batch Size (num_batch)": "Mida del lot (num_batch)", "before": "abans", - "Being lazy": "Ser l'estupidez", - "Brave Search API Key": "Clau API Brave Search", - "Bypass SSL verification for Websites": "Desactivar la verificació SSL per a l'accés a l'Internet", - "Call": "", - "Call feature is not supported when using Web STT engine": "", - "Camera": "", - "Cancel": "Cancel·la", + "Being lazy": "Essent mandrós", + "Brave Search API Key": "Clau API de Brave Search", + "Bypass SSL verification for Websites": "Desactivar la verificació SSL per a l'accés a Internet", + "Call": "Trucada", + "Call feature is not supported when using Web STT engine": "La funció de trucada no s'admet quan s'utilitza el motor Web STT", + "Camera": "Càmera", + "Cancel": "Cancel·lar", "Capabilities": "Capacitats", - "Change Password": "Canvia la Contrasenya", + "Change Password": "Canviar la contrasenya", "Chat": "Xat", - "Chat Background Image": "", + "Chat Background Image": "Imatge de fons del xat", "Chat Bubble UI": "Chat Bubble UI", - "Chat direction": "Direcció del Xat", - "Chat History": "Històric del Xat", - "Chat History is off for this browser.": "L'historial de xat està desactivat per a aquest navegador.", + "Chat direction": "Direcció del xat", + "Chat History": "Històric del xat", + "Chat History is off for this browser.": "L'historic del xat està desactivat per a aquest navegador.", "Chats": "Xats", - "Check Again": "Comprova-ho de Nou", - "Check for updates": "Comprova si hi ha actualitzacions", + "Check Again": "Comprovar-ho de nou", + "Check for updates": "Comprovar si hi ha actualitzacions", "Checking for updates...": "Comprovant actualitzacions...", - "Choose a model before saving...": "Tria un model abans de guardar...", - "Chunk Overlap": "Solapament de Blocs", - "Chunk Params": "Paràmetres de Blocs", - "Chunk Size": "Mida del Bloc", - "Citation": "Citació", - "Clear memory": "", - "Click here for help.": "Fes clic aquí per ajuda.", - "Click here to": "Fes clic aquí per", - "Click here to download user import template file.": "", - "Click here to select": "Fes clic aquí per seleccionar", - "Click here to select a csv file.": "Fes clic aquí per seleccionar un fitxer csv.", - "Click here to select a py file.": "", - "Click here to select documents.": "Fes clic aquí per seleccionar documents.", - "click here.": "fes clic aquí.", - "Click on the user role button to change a user's role.": "Fes clic al botó de rol d'usuari per canviar el rol d'un usuari.", - "Clone": "Clon", - "Close": "Tanca", + "Choose a model before saving...": "Triar un model abans de desar...", + "Chunk Overlap": "Solapament de blocs", + "Chunk Params": "Paràmetres dels blocs", + "Chunk Size": "Mida del bloc", + "Citation": "Cita", + "Clear memory": "Esborrar la memòria", + "Click here for help.": "Clica aquí per obtenir ajuda.", + "Click here to": "Clic aquí per", + "Click here to download user import template file.": "Fes clic aquí per descarregar l'arxiu de plantilla d'importació d'usuaris", + "Click here to select": "Clica aquí per seleccionar", + "Click here to select a csv file.": "Clica aquí per seleccionar un fitxer csv.", + "Click here to select a py file.": "Clica aquí per seleccionar un fitxer py.", + "Click here to select documents.": "Clica aquí per seleccionar documents.", + "click here.": "clica aquí.", + "Click on the user role button to change a user's role.": "Clica sobre el botó de rol d'usuari per canviar el rol d'un usuari.", + "Clone": "Clonar", + "Close": "Tancar", "Collection": "Col·lecció", "ComfyUI": "ComfyUI", "ComfyUI Base URL": "URL base de ComfyUI", - "ComfyUI Base URL is required.": "URL base de ComfyUI és obligatòria.", + "ComfyUI Base URL is required.": "L'URL base de ComfyUI és obligatòria.", "Command": "Comanda", - "Concurrent Requests": "Sol·licituds simultànies", - "Confirm": "", - "Confirm Password": "Confirma la Contrasenya", - "Confirm your action": "", + "Concurrent Requests": "Peticions simultànies", + "Confirm": "Confirmar", + "Confirm Password": "Confirmar la contrasenya", + "Confirm your action": "Confirma la teva acció", "Connections": "Connexions", - "Contact Admin for WebUI Access": "", + "Contact Admin for WebUI Access": "Posat en contacte amb l'administrador per accedir a WebUI", "Content": "Contingut", - "Context Length": "Longitud del Context", - "Continue Response": "Continua la Resposta", + "Context Length": "Mida del context", + "Continue Response": "Continuar la resposta", "Copied shared chat URL to clipboard!": "S'ha copiat l'URL compartida al porta-retalls!", "Copy": "Copiar", - "Copy last code block": "Copia l'últim bloc de codi", - "Copy last response": "Copia l'última resposta", + "Copy last code block": "Copiar l'últim bloc de codi", + "Copy last response": "Copiar l'última resposta", "Copy Link": "Copiar l'enllaç", - "Copying to clipboard was successful!": "La còpia al porta-retalls ha estat exitosa!", + "Copying to clipboard was successful!": "La còpia al porta-retalls s'ha realitzat amb èxit!", "Create a model": "Crear un model", - "Create Account": "Crea un Compte", - "Create new key": "Crea una nova clau", - "Create new secret key": "Crea una nova clau secreta", + "Create Account": "Crear un compte", + "Create new key": "Crear una nova clau", + "Create new secret key": "Crear una nova clau secreta", "Created at": "Creat el", "Created At": "Creat el", - "Created by": "", - "CSV Import": "", - "Current Model": "Model Actual", - "Current Password": "Contrasenya Actual", + "Created by": "Creat per", + "CSV Import": "Importar CSV", + "Current Model": "Model actual", + "Current Password": "Contrasenya actual", "Custom": "Personalitzat", "Customize models for a specific purpose": "Personalitzar models per a un propòsit específic", "Dark": "Fosc", - "Dashboard": "", - "Database": "Base de Dades", + "Dashboard": "Tauler", + "Database": "Base de dades", "December": "Desembre", "Default": "Per defecte", "Default (Automatic1111)": "Per defecte (Automatic1111)", "Default (SentenceTransformers)": "Per defecte (SentenceTransformers)", "Default Model": "Model per defecte", "Default model updated": "Model per defecte actualitzat", - "Default Prompt Suggestions": "Suggeriments de Prompt Per Defecte", - "Default User Role": "Rol d'Usuari Per Defecte", - "delete": "esborra", - "Delete": "Esborra", - "Delete a model": "Esborra un model", - "Delete All Chats": "Suprimir tots els xats", - "Delete chat": "Esborra xat", - "Delete Chat": "Esborra Xat", - "Delete chat?": "", - "delete this link": "Esborra aquest enllaç", - "Delete User": "Esborra Usuari", - "Deleted {{deleteModelTag}}": "Esborrat {{deleteModelTag}}", - "Deleted {{name}}": "Suprimit {{nom}}", + "Default Prompt Suggestions": "Suggeriments d'indicació per defecte", + "Default User Role": "Rol d'usuari per defecte", + "delete": "eliminar", + "Delete": "Eliminar", + "Delete a model": "Eliminar un model", + "Delete All Chats": "Eliminar tots els xats", + "Delete chat": "Eliminar xat", + "Delete Chat": "Eliminar xat", + "Delete chat?": "Eliminar el xat?", + "delete this link": "Eliminar aquest enllaç", + "Delete User": "Eliminar usuari", + "Deleted {{deleteModelTag}}": "S'ha eliminat {{deleteModelTag}}", + "Deleted {{name}}": "S'ha eliminat {{name}}", "Description": "Descripció", - "Didn't fully follow instructions": "No s'ha completat els instruccions", - "Discover a model": "Descobreix un model", - "Discover a prompt": "Descobreix un prompt", - "Discover, download, and explore custom prompts": "Descobreix, descarrega i explora prompts personalitzats", - "Discover, download, and explore model presets": "Descobreix, descarrega i explora presets de models", - "Dismissible": "", - "Display Emoji in Call": "", - "Display the username instead of You in the Chat": "Mostra el nom d'usuari en lloc de 'Tu' al Xat", + "Didn't fully follow instructions": "No s'han seguit les instruccions completament", + "Discover a model": "Descobrir un model", + "Discover a prompt": "Descobrir una indicació", + "Discover, download, and explore custom prompts": "Descobrir, descarregar i explorar indicacions personalitzades", + "Discover, download, and explore model presets": "Descobrir, descarregar i explorar models preconfigurats", + "Dismissible": "Descartable", + "Display Emoji in Call": "Mostrar emojis a la trucada", + "Display the username instead of You in the Chat": "Mostrar el nom d'usuari en lloc de 'Tu' al xat", "Document": "Document", - "Document Settings": "Configuració de Documents", - "Documentation": "", + "Document Settings": "Configuració de documents", + "Documentation": "Documentació", "Documents": "Documents", "does not make any external connections, and your data stays securely on your locally hosted server.": "no realitza connexions externes, i les teves dades romanen segures al teu servidor allotjat localment.", - "Don't Allow": "No Permetre", + "Don't Allow": "No permetre", "Don't have an account?": "No tens un compte?", "Don't like the style": "No t'agrada l'estil?", "Download": "Descarregar", "Download canceled": "Descàrrega cancel·lada", - "Download Database": "Descarrega Base de Dades", + "Download Database": "Descarregar la base de dades", "Drop any files here to add to the conversation": "Deixa qualsevol arxiu aquí per afegir-lo a la conversa", "e.g. '30s','10m'. Valid time units are 's', 'm', 'h'.": "p. ex. '30s','10m'. Les unitats de temps vàlides són 's', 'm', 'h'.", "Edit": "Editar", - "Edit Doc": "Edita Document", - "Edit Memory": "", - "Edit User": "Edita Usuari", + "Edit Doc": "Editar el document", + "Edit Memory": "Editar la memòria", + "Edit User": "Editar l'usuari", "Email": "Correu electrònic", - "Embedding Batch Size": "", - "Embedding Model": "Model d'embutiment", - "Embedding Model Engine": "Motor de model d'embutiment", - "Embedding model set to \"{{embedding_model}}\"": "Model d'embutiment configurat a \"{{embedding_model}}\"", - "Enable Chat History": "Activa Historial de Xat", - "Enable Community Sharing": "Activar l'ús compartit de la comunitat", - "Enable New Sign Ups": "Permet Noves Inscripcions", - "Enable Web Search": "Activa la cerca web", - "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que el fitxer CSV inclou 4 columnes en aquest ordre: Nom, Correu Electrònic, Contrasenya, Rol.", + "Embedding Batch Size": "Mida del lot d'incrustació", + "Embedding Model": "Model d'incrustació", + "Embedding Model Engine": "Motor de model d'incrustació", + "Embedding model set to \"{{embedding_model}}\"": "Model d'incrustació configurat a \"{{embedding_model}}\"", + "Enable Chat History": "Activar l'historial de xats", + "Enable Community Sharing": "Activar l'ús compartit amb la comunitat", + "Enable New Sign Ups": "Permetre nous registres", + "Enable Web Search": "Activar la cerca web", + "Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.": "Assegura't que els teus fitxers CSV inclouen 4 columnes en aquest ordre: Nom, Correu electrònic, Contrasenya, Rol.", "Enter {{role}} message here": "Introdueix aquí el missatge de {{role}}", - "Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu per que els LLMs puguin recordar-te", - "Enter Brave Search API Key": "Introduïu la clau de l'API Brave Search", - "Enter Chunk Overlap": "Introdueix el Solapament de Blocs", - "Enter Chunk Size": "Introdueix la Mida del Bloc", - "Enter Github Raw URL": "Introduïu l'URL en brut de Github", - "Enter Google PSE API Key": "Introduïu la clau de l'API de Google PSE", - "Enter Google PSE Engine Id": "Introduïu l'identificador del motor PSE de Google", - "Enter Image Size (e.g. 512x512)": "Introdueix la Mida de la Imatge (p. ex. 512x512)", + "Enter a detail about yourself for your LLMs to recall": "Introdueix un detall sobre tu què els teus models de llenguatge puguin recordar", + "Enter Brave Search API Key": "Introdueix la clau API de Brave Search", + "Enter Chunk Overlap": "Introdueix la mida de solapament de blocs", + "Enter Chunk Size": "Introdueix la mida del bloc", + "Enter Github Raw URL": "Introdueix l'URL en brut de Github", + "Enter Google PSE API Key": "Introdueix la clau API de Google PSE", + "Enter Google PSE Engine Id": "Introdueix l'identificador del motor PSE de Google", + "Enter Image Size (e.g. 512x512)": "Introdueix la mida de la imatge (p. ex. 512x512)", "Enter language codes": "Introdueix els codis de llenguatge", "Enter model tag (e.g. {{modelTag}})": "Introdueix l'etiqueta del model (p. ex. {{modelTag}})", - "Enter Number of Steps (e.g. 50)": "Introdueix el Nombre de Passos (p. ex. 50)", - "Enter Score": "Introdueix el Puntuació", - "Enter Searxng Query URL": "Introduïu l'URL de consulta de Searxng", - "Enter Serper API Key": "Introduïu la clau de l'API Serper", - "Enter Serply API Key": "", - "Enter Serpstack API Key": "Introduïu la clau de l'API Serpstack", + "Enter Number of Steps (e.g. 50)": "Introdueix el nombre de passos (p. ex. 50)", + "Enter Score": "Introdueix la puntuació", + "Enter Searxng Query URL": "Introdueix l'URL de consulta de Searxng", + "Enter Serper API Key": "Introdueix la clau API Serper", + "Enter Serply API Key": "Introdueix la clau API Serply", + "Enter Serpstack API Key": "Introdueix la clau API Serpstack", "Enter stop sequence": "Introdueix la seqüència de parada", - "Enter Tavily API Key": "", + "Enter Tavily API Key": "Introdueix la clau API de Tavily", "Enter Top K": "Introdueix Top K", "Enter URL (e.g. http://127.0.0.1:7860/)": "Introdueix l'URL (p. ex. http://127.0.0.1:7860/)", "Enter URL (e.g. http://localhost:11434)": "Introdueix l'URL (p. ex. http://localhost:11434)", - "Enter Your Email": "Introdueix el Teu Correu Electrònic", - "Enter Your Full Name": "Introdueix el Teu Nom Complet", - "Enter Your Password": "Introdueix la Teva Contrasenya", - "Enter Your Role": "Introdueix el Teu Ròl", + "Enter Your Email": "Introdueix el teu correu electrònic", + "Enter Your Full Name": "Introdueix el teu nom complet", + "Enter Your Password": "Introdueix la teva contrasenya", + "Enter Your Role": "Introdueix el teu rol", "Error": "Error", "Experimental": "Experimental", "Export": "Exportar", - "Export All Chats (All Users)": "Exporta Tots els Xats (Tots els Usuaris)", - "Export chat (.json)": "", - "Export Chats": "Exporta Xats", - "Export Documents Mapping": "Exporta el Mapatge de Documents", - "Export Functions": "", - "Export Models": "Models d'exportació", - "Export Prompts": "Exporta Prompts", - "Export Tools": "", - "External Models": "", - "Failed to create API Key.": "No s'ha pogut crear la clau d'API.", + "Export All Chats (All Users)": "Exportar tots els xats (Tots els usuaris)", + "Export chat (.json)": "Exportar el xat (.json)", + "Export Chats": "Exportar els xats", + "Export Documents Mapping": "Exportar el mapatge de documents", + "Export Functions": "Exportar funcions", + "Export Models": "Exportar els models", + "Export Prompts": "Exportar les indicacions", + "Export Tools": "Exportar les eines", + "External Models": "Models externs", + "Failed to create API Key.": "No s'ha pogut crear la clau API.", "Failed to read clipboard contents": "No s'ha pogut llegir el contingut del porta-retalls", - "Failed to update settings": "", + "Failed to update settings": "No s'ha pogut actualitzar la configuració", "February": "Febrer", - "Feel free to add specific details": "Siusplau, afegeix detalls específics", - "File": "", - "File Mode": "Mode Arxiu", - "File not found.": "Arxiu no trobat.", - "Filters": "", - "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "S'ha detectat la suplantació d'identitat d'empremtes digitals: no es poden utilitzar les inicials com a avatar. Per defecte a la imatge de perfil predeterminada.", - "Fluidly stream large external response chunks": "Transmita con fluidez grandes fragmentos de respuesta externa", - "Focus chat input": "Enfoca l'entrada del xat", - "Followed instructions perfectly": "Siguiu les instruccions perfeicte", - "Form": "", + "Feel free to add specific details": "Sent-te lliure d'afegir detalls específics", + "File": "Arxiu", + "File Mode": "Mode d'arxiu", + "File not found.": "No s'ha trobat l'arxiu.", + "Filters": "Filtres", + "Fingerprint spoofing detected: Unable to use initials as avatar. Defaulting to default profile image.": "S'ha detectat la suplantació d'identitat de l'empremta digital: no es poden utilitzar les inicials com a avatar. S'estableix la imatge de perfil predeterminada.", + "Fluidly stream large external response chunks": "Transmetre amb fluïdesa grans trossos de resposta externa", + "Focus chat input": "Estableix el focus a l'entrada del xat", + "Followed instructions perfectly": "S'han seguit les instruccions perfectament", + "Form": "Formulari", "Format your variables using square brackets like this:": "Formata les teves variables utilitzant claudàtors així:", - "Frequency Penalty": "Pena de freqüència", - "Functions": "", + "Frequency Penalty": "Penalització per freqüència", + "Functions": "Funcions", "General": "General", - "General Settings": "Configuració General", - "Generate Image": "", - "Generating search query": "Generació de consultes de cerca", - "Generation Info": "Informació de Generació", - "Good Response": "Resposta bona", - "Google PSE API Key": "Clau de l'API PSE de Google", + "General Settings": "Configuració general", + "Generate Image": "Generar imatge", + "Generating search query": "Generant consulta", + "Generation Info": "Informació sobre la generació", + "Good Response": "Bona resposta", + "Google PSE API Key": "Clau API PSE de Google", "Google PSE Engine Id": "Identificador del motor PSE de Google", "h:mm a": "h:mm a", "has no conversations.": "no té converses.", "Hello, {{name}}": "Hola, {{name}}", "Help": "Ajuda", "Hide": "Amaga", - "Hide Model": "", + "Hide Model": "Amagar el model", "How can I help you today?": "Com et puc ajudar avui?", - "Hybrid Search": "Cerca Hibrida", - "Image Generation (Experimental)": "Generació d'Imatges (Experimental)", - "Image Generation Engine": "Motor de Generació d'Imatges", - "Image Settings": "Configuració d'Imatges", + "Hybrid Search": "Cerca híbrida", + "Image Generation (Experimental)": "Generació d'imatges (Experimental)", + "Image Generation Engine": "Motor de generació d'imatges", + "Image Settings": "Configuració d'imatges", "Images": "Imatges", - "Import Chats": "Importa Xats", - "Import Documents Mapping": "Importa el Mapa de Documents", - "Import Functions": "", - "Import Models": "Models d'importació", - "Import Prompts": "Importa Prompts", - "Import Tools": "", - "Include `--api` flag when running stable-diffusion-webui": "Inclou la bandera `--api` quan executis stable-diffusion-webui", + "Import Chats": "Importar xats", + "Import Documents Mapping": "Importar el mapatge de documents", + "Import Functions": "Importar funcions", + "Import Models": "Importar models", + "Import Prompts": "Importar indicacions", + "Import Tools": "Importar eines", + "Include `--api` flag when running stable-diffusion-webui": "Inclou `--api` quan executis stable-diffusion-webui", "Info": "Informació", - "Input commands": "Entra ordres", - "Install from Github URL": "Instal·leu des de l'URL de Github", - "Instant Auto-Send After Voice Transcription": "", + "Input commands": "Entra comandes", + "Install from Github URL": "Instal·lar des de l'URL de Github", + "Instant Auto-Send After Voice Transcription": "Enviament automàtic després de la transcripció de veu", "Interface": "Interfície", - "Invalid Tag": "Etiqueta Inválida", + "Invalid Tag": "Etiqueta no vàlida", "January": "Gener", - "join our Discord for help.": "uneix-te al nostre Discord per ajuda.", + "join our Discord for help.": "uneix-te al nostre Discord per obtenir ajuda.", "JSON": "JSON", - "JSON Preview": "Vista prèvia de JSON", + "JSON Preview": "Vista prèvia del document JSON", "July": "Juliol", "June": "Juny", - "JWT Expiration": "Expiració de JWT", + "JWT Expiration": "Caducitat del JWT", "JWT Token": "Token JWT", - "Keep Alive": "Mantén Actiu", - "Keyboard shortcuts": "Dreceres de Teclat", - "Knowledge": "", + "Keep Alive": "Manté actiu", + "Keyboard shortcuts": "Dreceres de teclat", + "Knowledge": "Coneixement", "Language": "Idioma", - "Last Active": "Últim Actiu", - "Last Modified": "", + "Last Active": "Activitat recent", + "Last Modified": "Modificació", "Light": "Clar", - "Listening...": "", - "LLMs can make mistakes. Verify important information.": "Els LLMs poden cometre errors. Verifica la informació important.", - "Local Models": "", + "Listening...": "Escoltant...", + "LLMs can make mistakes. Verify important information.": "Els models de llenguatge poden cometre errors. Verifica la informació important.", + "Local Models": "Models locals", "LTR": "LTR", "Made by OpenWebUI Community": "Creat per la Comunitat OpenWebUI", "Make sure to enclose them with": "Assegura't d'envoltar-los amb", - "Manage": "", - "Manage Models": "Gestiona Models", - "Manage Ollama Models": "Gestiona Models Ollama", - "Manage Pipelines": "Gestionar canonades", + "Manage": "Gestionar", + "Manage Models": "Gestionar els models", + "Manage Ollama Models": "Gestionar els models Ollama", + "Manage Pipelines": "Gestionar les Pipelines", "March": "Març", - "Max Tokens (num_predict)": "Max Fitxes (num_predict)", + "Max Tokens (num_predict)": "Nombre màxim de Tokens (num_predict)", "Maximum of 3 models can be downloaded simultaneously. Please try again later.": "Es poden descarregar un màxim de 3 models simultàniament. Si us plau, prova-ho més tard.", "May": "Maig", - "Memories accessible by LLMs will be shown here.": "Els memòries accessible per a LLMs es mostraran aquí.", + "Memories accessible by LLMs will be shown here.": "Les memòries accessibles pels models de llenguatge es mostraran aquí.", "Memory": "Memòria", - "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Els missatges que envieu després de crear el vostre enllaç no es compartiran. Els usuaris amb l'URL podran veure el xat compartit.", + "Messages you send after creating your link won't be shared. Users with the URL will be able to view the shared chat.": "Els missatges enviats després de crear el teu enllaç no es compartiran. Els usuaris amb l'URL podran veure el xat compartit.", "Minimum Score": "Puntuació mínima", "Mirostat": "Mirostat", "Mirostat Eta": "Eta de Mirostat", "Mirostat Tau": "Tau de Mirostat", "MMMM DD, YYYY": "DD de MMMM, YYYY", "MMMM DD, YYYY HH:mm": "DD de MMMM, YYYY HH:mm", - "MMMM DD, YYYY hh:mm:ss A": "", + "MMMM DD, YYYY hh:mm:ss A": "DD de MMMM, YYYY HH:mm:ss, A", "Model '{{modelName}}' has been successfully downloaded.": "El model '{{modelName}}' s'ha descarregat amb èxit.", "Model '{{modelTag}}' is already in queue for downloading.": "El model '{{modelTag}}' ja està en cua per ser descarregat.", - "Model {{modelId}} not found": "Model {{modelId}} no trobat", + "Model {{modelId}} not found": "No s'ha trobat el model {{modelId}}", "Model {{modelName}} is not vision capable": "El model {{modelName}} no és capaç de visió", - "Model {{name}} is now {{status}}": "El model {{nom}} ara és {{estat}}", - "Model filesystem path detected. Model shortname is required for update, cannot continue.": "S'ha detectat el camí del sistema de fitxers del model. És necessari un nom curt del model per a actualitzar, no es pot continuar.", + "Model {{name}} is now {{status}}": "El model {{name}} ara és {{status}}", + "Model filesystem path detected. Model shortname is required for update, cannot continue.": "S'ha detectat el camí del sistema de fitxers del model. És necessari un nom curt del model per actualitzar, no es pot continuar.", "Model ID": "Identificador del model", "Model not selected": "Model no seleccionat", "Model Params": "Paràmetres del model", - "Model Whitelisting": "Llista Blanca de Models", - "Model(s) Whitelisted": "Model(s) a la Llista Blanca", - "Modelfile Content": "Contingut del Fitxer de Model", + "Model Whitelisting": "Llista blanca de models", + "Model(s) Whitelisted": "Model(s) a la llista blanca", + "Modelfile Content": "Contingut del Modelfile", "Models": "Models", "More": "Més", "Name": "Nom", - "Name Tag": "Etiqueta de Nom", - "Name your model": "Posa un nom al model", - "New Chat": "Xat Nou", - "New Password": "Nova Contrasenya", - "No documents found": "", + "Name Tag": "Etiqueta de nom", + "Name your model": "Posa un nom al teu model", + "New Chat": "Nou xat", + "New Password": "Nova contrasenya", + "No documents found": "No s'han trobat documents", "No results found": "No s'han trobat resultats", - "No search query generated": "No es genera cap consulta de cerca", + "No search query generated": "No s'ha generat cap consulta", "No source available": "Sense font disponible", "None": "Cap", - "Not factually correct": "No està clarament correcte", - "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Si establiscs una puntuació mínima, la cerca només retornarà documents amb una puntuació major o igual a la puntuació mínima.", - "Notifications": "Notificacions d'Escriptori", + "Not factually correct": "No és clarament correcte", + "Note: If you set a minimum score, the search will only return documents with a score greater than or equal to the minimum score.": "Nota: Si s'estableix una puntuació mínima, la cerca només retornarà documents amb una puntuació major o igual a la puntuació mínima.", + "Notifications": "Notificacions", "November": "Novembre", "num_thread (Ollama)": "num_thread (Ollama)", "October": "Octubre", "Off": "Desactivat", - "Okay, Let's Go!": "D'acord, Anem!", + "Okay, Let's Go!": "D'acord, som-hi!", "OLED Dark": "OLED Fosc", "Ollama": "Ollama", "Ollama API": "API d'Ollama", - "Ollama API disabled": "L'API d'Ollama desactivada", - "Ollama API is disabled": "", + "Ollama API disabled": "API d'Ollama desactivada", + "Ollama API is disabled": "L'API d'Ollama està desactivada", "Ollama Version": "Versió d'Ollama", "On": "Activat", "Only": "Només", - "Only alphanumeric characters and hyphens are allowed in the command string.": "Només es permeten caràcters alfanumèrics i guions en la cadena de comandes.", - "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ui! Aguanta! Els teus fitxers encara estan en el forn de processament. Els estem cuinant a la perfecció. Si us plau, tingues paciència i t'avisarem quan estiguin llestos.", - "Oops! Looks like the URL is invalid. Please double-check and try again.": "Ui! Sembla que l'URL és invàlida. Si us plau, revisa-ho i prova de nou.", - "Oops! There was an error in the previous response. Please try again or contact admin.": "", + "Only alphanumeric characters and hyphens are allowed in the command string.": "Només es permeten caràcters alfanumèrics i guions en la comanda.", + "Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.": "Ep! Un moment! Els teus fitxers encara s'estan processant. Els estem cuinant a la perfecció. Si us plau, tingues paciència i t'avisarem quan estiguin preparats.", + "Oops! Looks like the URL is invalid. Please double-check and try again.": "Ui! Sembla que l'URL no és vàlida. Si us plau, revisa-la i torna-ho a provar.", + "Oops! There was an error in the previous response. Please try again or contact admin.": "Ui! Hi ha hagut un error en la resposta anterior. Torna a provar-ho o contacta amb un administrador", "Oops! You're using an unsupported method (frontend only). Please serve the WebUI from the backend.": "Ui! Estàs utilitzant un mètode no suportat (només frontend). Si us plau, serveix la WebUI des del backend.", "Open": "Obre", "Open AI": "Open AI", "Open AI (Dall-E)": "Open AI (Dall-E)", - "Open new chat": "Obre un nou xat", + "Open new chat": "Obre un xat nou", "OpenAI": "OpenAI", "OpenAI API": "API d'OpenAI", "OpenAI API Config": "Configuració de l'API d'OpenAI", - "OpenAI API Key is required.": "Es requereix la Clau API d'OpenAI.", + "OpenAI API Key is required.": "Es requereix la clau API d'OpenAI.", "OpenAI URL/Key required.": "URL/Clau d'OpenAI requerides.", "or": "o", "Other": "Altres", "Password": "Contrasenya", "PDF document (.pdf)": "Document PDF (.pdf)", - "PDF Extract Images (OCR)": "Extreu Imatges de PDF (OCR)", + "PDF Extract Images (OCR)": "Extreu imatges del PDF (OCR)", "pending": "pendent", - "Permission denied when accessing media devices": "", - "Permission denied when accessing microphone": "", + "Permission denied when accessing media devices": "Permís denegat en accedir a dispositius multimèdia", + "Permission denied when accessing microphone": "Permís denegat en accedir al micròfon", "Permission denied when accessing microphone: {{error}}": "Permís denegat en accedir al micròfon: {{error}}", "Personalization": "Personalització", - "Pipelines": "Canonades", - "Pipelines Valves": "Vàlvules de canonades", + "Pipelines": "Pipelines", + "Pipelines Valves": "Vàlvules de les Pipelines", "Plain text (.txt)": "Text pla (.txt)", - "Playground": "Zona de Jocs", - "Positive attitude": "Attitudin positiva", + "Playground": "Zona de jocs", + "Positive attitude": "Actitud positiva", "Previous 30 days": "30 dies anteriors", "Previous 7 days": "7 dies anteriors", "Profile Image": "Imatge de perfil", - "Prompt": "Prompt", - "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Prompt (p.ex. diu-me un fàcte divertit sobre l'Imperi Roman)", - "Prompt Content": "Contingut del Prompt", - "Prompt suggestions": "Suggeriments de Prompt", - "Prompts": "Prompts", - "Pull \"{{searchValue}}\" from Ollama.com": "Treu \"{{searchValue}}\" de Ollama.com", - "Pull a model from Ollama.com": "Treu un model d'Ollama.com", - "Query Params": "Paràmetres de Consulta", + "Prompt": "Indicació", + "Prompt (e.g. Tell me a fun fact about the Roman Empire)": "Indicació (p.ex. Digues-me quelcom divertit sobre l'Imperi Romà)", + "Prompt Content": "Contingut de la indicació", + "Prompt suggestions": "Suggeriments d'indicacions", + "Prompts": "Indicacions", + "Pull \"{{searchValue}}\" from Ollama.com": "Obtenir \"{{searchValue}}\" de Ollama.com", + "Pull a model from Ollama.com": "Obtenir un model d'Ollama.com", + "Query Params": "Paràmetres de consulta", "RAG Template": "Plantilla RAG", - "Read Aloud": "Llegiu al voltant", - "Record voice": "Enregistra veu", - "Redirecting you to OpenWebUI Community": "Redirigint-te a la Comunitat OpenWebUI", - "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "", - "Refused when it shouldn't have": "Refusat quan no hauria d'haver-ho", + "Read Aloud": "Llegir en veu alta", + "Record voice": "Enregistrar la veu", + "Redirecting you to OpenWebUI Community": "Redirigint-te a la comunitat OpenWebUI", + "Refer to yourself as \"User\" (e.g., \"User is learning Spanish\")": "Fes referència a tu mateix com a \"Usuari\" (p. ex., \"L'usuari està aprenent espanyol\")", + "Refused when it shouldn't have": "Refusat quan no hauria d'haver estat", "Regenerate": "Regenerar", - "Release Notes": "Notes de la Versió", - "Remove": "Elimina", - "Remove Model": "Elimina Model", - "Rename": "Canvia el nom", - "Repeat Last N": "Repeteix Últim N", - "Request Mode": "Mode de Sol·licitud", - "Reranking Model": "Model de Reranking desactivat", - "Reranking model disabled": "Model de Reranking desactivat", - "Reranking model set to \"{{reranking_model}}\"": "Model de Reranking establert a \"{{reranking_model}}\"", - "Reset": "", - "Reset Upload Directory": "", - "Reset Vector Storage": "Reinicia l'Emmagatzematge de Vectors", - "Response AutoCopy to Clipboard": "Resposta AutoCopiar al Portapapers", + "Release Notes": "Notes de la versió", + "Remove": "Eliminar", + "Remove Model": "Eliminar el model", + "Rename": "Canviar el nom", + "Repeat Last N": "Repeteix els darrers N", + "Request Mode": "Mode de sol·licitud", + "Reranking Model": "Model de reavaluació", + "Reranking model disabled": "Model de reavaluació desactivat", + "Reranking model set to \"{{reranking_model}}\"": "Model de reavaluació establert a \"{{reranking_model}}\"", + "Reset": "Restableix", + "Reset Upload Directory": "Restableix el directori de pujades", + "Reset Vector Storage": "Restableix l'emmagatzematge de vectors", + "Response AutoCopy to Clipboard": "Copiar la resposta automàticament al porta-retalls", "Role": "Rol", "Rosé Pine": "Rosé Pine", "Rosé Pine Dawn": "Albada Rosé Pine", "RTL": "RTL", - "Running": "", - "Save": "Guarda", - "Save & Create": "Guarda i Crea", - "Save & Update": "Guarda i Actualitza", - "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Guardar registres de xat directament a l'emmagatzematge del teu navegador ja no és suportat. Si us plau, pren un moment per descarregar i eliminar els teus registres de xat fent clic al botó de sota. No et preocupis, pots reimportar fàcilment els teus registres de xat al backend a través de", - "Scan": "Escaneja", - "Scan complete!": "Escaneig completat!", - "Scan for documents from {{path}}": "Escaneja documents des de {{path}}", - "Search": "Cerca", - "Search a model": "Cerca un model", + "Running": "S'està executant", + "Save": "Desar", + "Save & Create": "Desar i crear", + "Save & Update": "Desar i actualitzar", + "Saving chat logs directly to your browser's storage is no longer supported. Please take a moment to download and delete your chat logs by clicking the button below. Don't worry, you can easily re-import your chat logs to the backend through": "Desar els registres de xat directament a l'emmagatzematge del teu navegador ja no està suportat. Si us plau, descarregr i elimina els registres de xat fent clic al botó de sota. No et preocupis, pots tornar a importar fàcilment els teus registres de xat al backend a través de", + "Scan": "Escanejar", + "Scan complete!": "Escaneigr completat!", + "Scan for documents from {{path}}": "Escanejar documents des de {{path}}", + "Search": "Cercar", + "Search a model": "Cercar un model", "Search Chats": "Cercar xats", - "Search Documents": "Cerca Documents", - "Search Functions": "", - "Search Models": "Models de cerca", - "Search Prompts": "Cerca Prompts", - "Search Query Generation Prompt": "", - "Search Query Generation Prompt Length Threshold": "", + "Search Documents": "Cercar documents", + "Search Functions": "Cercar funcions", + "Search Models": "Cercar models", + "Search Prompts": "Cercar indicacions", + "Search Query Generation Prompt": "Indicació de cerca de generació de consultes", + "Search Query Generation Prompt Length Threshold": "Mida màxima de la indicació de cerca de generació de consultes", "Search Result Count": "Recompte de resultats de cerca", - "Search Tools": "", - "Searched {{count}} sites_one": "Cercat {{count}} sites_one", - "Searched {{count}} sites_many": "Cercat {{recompte}} sites_many", - "Searched {{count}} sites_other": "Cercat {{recompte}} sites_other", - "Searching \"{{searchQuery}}\"": "", - "Searxng Query URL": "Searxng URL de consulta", - "See readme.md for instructions": "Consulta el readme.md per a instruccions", - "See what's new": "Veure novetats", + "Search Tools": "Cercar eines", + "Searched {{count}} sites_one": "S'ha cercat {{count}} una pàgina", + "Searched {{count}} sites_many": "S'han cercat {{count}} pàgines", + "Searched {{count}} sites_other": "S'han cercat {{count}} pàgines", + "Searching \"{{searchQuery}}\"": "Cercant \"{{searchQuery}}\"", + "Searxng Query URL": "URL de consulta de Searxng", + "See readme.md for instructions": "Consulta l'arxiu readme.md per obtenir instruccions", + "See what's new": "Veure què hi ha de nou", "Seed": "Llavor", "Select a base model": "Seleccionar un model base", - "Select a engine": "", - "Select a mode": "Selecciona un mode", - "Select a model": "Selecciona un model", - "Select a pipeline": "Seleccioneu una canonada", - "Select a pipeline url": "Seleccionar un URL de canonada", - "Select an Ollama instance": "Selecciona una instància d'Ollama", - "Select Documents": "", - "Select model": "Selecciona un model", - "Select only one model to call": "", - "Selected model(s) do not support image inputs": "Els models seleccionats no admeten l'entrada d'imatges", - "Send": "Envia", - "Send a Message": "Envia un Missatge", - "Send message": "Envia missatge", + "Select a engine": "Seleccionar un motor", + "Select a mode": "Seleccionar un mode", + "Select a model": "Seleccionar un model", + "Select a pipeline": "Seleccionar una Pipeline", + "Select a pipeline url": "Seleccionar l'URL d'una Pipeline", + "Select an Ollama instance": "Seleccionar una instància d'Ollama", + "Select Documents": "Seleccionar documents", + "Select model": "Seleccionar un model", + "Select only one model to call": "Seleccionar només un model per trucar", + "Selected model(s) do not support image inputs": "El(s) model(s) seleccionats no admeten l'entrada d'imatges", + "Send": "Enviar", + "Send a Message": "Enviar un missatge", + "Send message": "Enviar missatge", "September": "Setembre", - "Serper API Key": "Clau API Serper", - "Serply API Key": "", - "Serpstack API Key": "Serpstack API Key", + "Serper API Key": "Clau API de Serper", + "Serply API Key": "Clau API de Serply", + "Serpstack API Key": "Clau API de Serpstack", "Server connection verified": "Connexió al servidor verificada", - "Set as default": "Estableix com a predeterminat", - "Set Default Model": "Estableix Model Predeterminat", - "Set embedding model (e.g. {{model}})": "Estableix el model d'emboscada (p.ex. {{model}})", - "Set Image Size": "Estableix Mida de la Imatge", - "Set reranking model (e.g. {{model}})": "Estableix el model de reranking (p.ex. {{model}})", - "Set Steps": "Estableix Passos", - "Set Task Model": "Defineix el model de tasca", - "Set Voice": "Estableix Veu", + "Set as default": "Establir com a predeterminat", + "Set Default Model": "Establir el model predeterminat", + "Set embedding model (e.g. {{model}})": "Establir el model d'incrustació (p.ex. {{model}})", + "Set Image Size": "Establir la mida de la image", + "Set reranking model (e.g. {{model}})": "Establir el model de reavaluació (p.ex. {{model}})", + "Set Steps": "Establir el nombre de passos", + "Set Task Model": "Establir el model de tasca", + "Set Voice": "Establir la veu", "Settings": "Configuracions", - "Settings saved successfully!": "Configuracions guardades amb èxit!", - "Settings updated successfully": "", + "Settings saved successfully!": "Les configuracions s'han desat amb èxit!", + "Settings updated successfully": "Les configuracions s'han actualitzat amb èxit", "Share": "Compartir", - "Share Chat": "Compartir el Chat", - "Share to OpenWebUI Community": "Comparteix amb la Comunitat OpenWebUI", - "short-summary": "resum curt", - "Show": "Mostra", - "Show Admin Details in Account Pending Overlay": "", - "Show Model": "", - "Show shortcuts": "Mostra dreceres", - "Showcased creativity": "Mostra la creativitat", + "Share Chat": "Compartir el xat", + "Share to OpenWebUI Community": "Compartir amb la comunitat OpenWebUI", + "short-summary": "resum breu", + "Show": "Mostrar", + "Show Admin Details in Account Pending Overlay": "Mostrar els detalls de l'administrador a la superposició del compte pendent", + "Show Model": "Mostrar el model", + "Show shortcuts": "Mostrar dreceres", + "Showcased creativity": "Creativitat mostrada", "sidebar": "barra lateral", - "Sign in": "Inicia sessió", - "Sign Out": "Tanca sessió", - "Sign up": "Registra't", + "Sign in": "Iniciar sessió", + "Sign Out": "Tancar sessió", + "Sign up": "Registrar-se", "Signing in": "Iniciant sessió", "Source": "Font", "Speech recognition error: {{error}}": "Error de reconeixement de veu: {{error}}", - "Speech-to-Text Engine": "Motor de Veu a Text", - "Stop Sequence": "Atura Seqüència", - "STT Model": "", - "STT Settings": "Configuracions STT", - "Submit": "Envia", + "Speech-to-Text Engine": "Motor de veu a text", + "Stop Sequence": "Atura la seqüència", + "STT Model": "Model SST", + "STT Settings": "Configuracions de STT", + "Submit": "Enviar", "Subtitle (e.g. about the Roman Empire)": "Subtítol (per exemple, sobre l'Imperi Romà)", "Success": "Èxit", "Successfully updated.": "Actualitzat amb èxit.", "Suggested": "Suggerit", "System": "Sistema", - "System Prompt": "Prompt del Sistema", + "System Prompt": "Indicació del Sistema", "Tags": "Etiquetes", - "Tap to interrupt": "", - "Tavily API Key": "", - "Tell us more:": "Dóna'ns més informació:", + "Tap to interrupt": "Prem per interrompre", + "Tavily API Key": "Clau API de Tavily", + "Tell us more:": "Dona'ns més informació:", "Temperature": "Temperatura", "Template": "Plantilla", - "Text Completion": "Completació de Text", - "Text-to-Speech Engine": "Motor de Text a Veu", + "Text Completion": "Completament de text", + "Text-to-Speech Engine": "Motor de text a veu", "Tfs Z": "Tfs Z", "Thanks for your feedback!": "Gràcies pel teu comentari!", - "The score should be a value between 0.0 (0%) and 1.0 (100%).": "El puntuatge ha de ser un valor entre 0.0 (0%) i 1.0 (100%).", + "The score should be a value between 0.0 (0%) and 1.0 (100%).": "El valor de puntuació hauria de ser entre 0.0 (0%) i 1.0 (100%).", "Theme": "Tema", - "Thinking...": "", - "This action cannot be undone. Do you wish to continue?": "", - "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Això assegura que les teves converses valuoses queden segurament guardades a la teva base de dades backend. Gràcies!", - "This is an experimental feature, it may not function as expected and is subject to change at any time.": "", + "Thinking...": "Pensant...", + "This action cannot be undone. Do you wish to continue?": "Aquesta acció no es pot desfer. Vols continuar?", + "This ensures that your valuable conversations are securely saved to your backend database. Thank you!": "Això assegura que les teves converses valuoses queden desades de manera segura a la teva base de dades. Gràcies!", + "This is an experimental feature, it may not function as expected and is subject to change at any time.": "Aquesta és una funció experimental, és possible que no funcioni com s'espera i està subjecta a canvis en qualsevol moment.", "This setting does not sync across browsers or devices.": "Aquesta configuració no es sincronitza entre navegadors ni dispositius.", - "This will delete": "", - "Thorough explanation": "Explacació exhaustiva", - "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza diversos espais de variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.", + "This will delete": "Això eliminarà", + "Thorough explanation": "Explicació en detall", + "Tip: Update multiple variable slots consecutively by pressing the tab key in the chat input after each replacement.": "Consell: Actualitza les diverses variables consecutivament prement la tecla de tabulació en l'entrada del xat després de cada reemplaçament.", "Title": "Títol", - "Title (e.g. Tell me a fun fact)": "Títol (p. ex. diu-me un fet divertit)", - "Title Auto-Generation": "Auto-Generació de Títol", + "Title (e.g. Tell me a fun fact)": "Títol (p. ex. Digues-me quelcom divertit)", + "Title Auto-Generation": "Generació automàtica de títol", "Title cannot be an empty string.": "El títol no pot ser una cadena buida.", - "Title Generation Prompt": "Prompt de Generació de Títol", + "Title Generation Prompt": "Indicació de generació de títol", "to": "a", "To access the available model names for downloading,": "Per accedir als noms dels models disponibles per descarregar,", "To access the GGUF models available for downloading,": "Per accedir als models GGUF disponibles per descarregar,", - "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "", - "To add documents here, upload them to the \"Documents\" workspace first.": "", + "To access the WebUI, please reach out to the administrator. Admins can manage user statuses from the Admin Panel.": "Per accedir a la WebUI, poseu-vos en contacte amb l'administrador. Els administradors poden gestionar els estats dels usuaris des del tauler d'administració.", + "To add documents here, upload them to the \"Documents\" workspace first.": "Per afegir documents aquí, puja-ls primer a l'espai de treball \"Documents\".", "to chat input.": "a l'entrada del xat.", - "To select filters here, add them to the \"Functions\" workspace first.": "", - "To select toolkits here, add them to the \"Tools\" workspace first.": "", + "To select filters here, add them to the \"Functions\" workspace first.": "Per seleccionar filtres aquí, afegeix-los primer a l'espai de treball \"Funcions\".", + "To select toolkits here, add them to the \"Tools\" workspace first.": "Per seleccionar kits d'eines aquí, afegeix-los primer a l'espai de treball \"Eines\".", "Today": "Avui", - "Toggle settings": "Commuta configuracions", - "Toggle sidebar": "Commuta barra lateral", - "Tokens To Keep On Context Refresh (num_keep)": "", - "Tools": "", + "Toggle settings": "Alterna configuracions", + "Toggle sidebar": "Alterna la barra lateral", + "Tokens To Keep On Context Refresh (num_keep)": "Tokens a mantenir en l'actualització del context (num_keep)", + "Tools": "Eines", "Top K": "Top K", "Top P": "Top P", - "Trouble accessing Ollama?": "Problemes accedint a Ollama?", - "TTS Model": "", + "Trouble accessing Ollama?": "Problemes en accedir a Ollama?", + "TTS Model": "Model TTS", "TTS Settings": "Configuracions TTS", - "TTS Voice": "", + "TTS Voice": "Veu TTS", "Type": "Tipus", - "Type Hugging Face Resolve (Download) URL": "Escriu URL de Resolució (Descàrrega) de Hugging Face", - "Uh-oh! There was an issue connecting to {{provider}}.": "Uf! Hi va haver un problema connectant-se a {{provider}}.", - "UI": "", - "Unknown file type '{{file_type}}'. Proceeding with the file upload anyway.": "", - "Update": "", - "Update and Copy Link": "Actualitza i Copia enllaç", - "Update password": "Actualitza contrasenya", - "Updated at": "", - "Upload": "", - "Upload a GGUF model": "Puja un model GGUF", + "Type Hugging Face Resolve (Download) URL": "Escriu l'URL de Resolució (Descàrrega) de Hugging Face", + "Uh-oh! There was an issue connecting to {{provider}}.": "Oh! Hi ha hagut un problema connectant a {{provider}}.", + "UI": "UI", + "Unknown File Type '{{file_type}}', but accepting and treating as plain text": "Tipus d'arxiu desconegut '{{file_type}}', però s'accepta i es tracta com a text pla", + "Update": "Actualitzar", + "Update and Copy Link": "Actualitzar i copiar l'enllaç", + "Update password": "Actualitzar la contrasenya", + "Updated at": "Actualitzat", + "Upload": "Pujar", + "Upload a GGUF model": "Pujar un model GGUF", "Upload Files": "Pujar fitxers", - "Upload Pipeline": "", - "Upload Progress": "Progrés de Càrrega", + "Upload Pipeline": "Pujar una Pipeline", + "Upload Progress": "Progrés de càrrega", "URL Mode": "Mode URL", - "Use '#' in the prompt input to load and select your documents.": "Utilitza '#' a l'entrada del prompt per carregar i seleccionar els teus documents.", - "Use Gravatar": "Utilitza Gravatar", - "Use Initials": "Utilitza Inicials", + "Use '#' in the prompt input to load and select your documents.": "Utilitza '#' a l'entrada de la indicació per carregar i seleccionar els teus documents.", + "Use Gravatar": "Utilitzar Gravatar", + "Use Initials": "Utilitzar inicials", "use_mlock (Ollama)": "use_mlock (Ollama)", "use_mmap (Ollama)": "use_mmap (Ollama)", "user": "usuari", - "User Permissions": "Permisos d'Usuari", + "User Permissions": "Permisos d'usuari", "Users": "Usuaris", - "Utilize": "Utilitza", + "Utilize": "Utilitzar", "Valid time units:": "Unitats de temps vàlides:", "variable": "variable", "variable to have them replaced with clipboard content.": "variable per tenir-les reemplaçades amb el contingut del porta-retalls.", "Version": "Versió", - "Voice": "", - "Warning": "Advertiment", - "Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avís: Si actualitzeu o canvieu el model d'incrustació, haureu de tornar a importar tots els documents.", + "Voice": "Veu", + "Warning": "Avís", + "Warning: If you update or change your embedding model, you will need to re-import all documents.": "Avís: Si s'actualitza o es canvia el model d'incrustació, s'hauran de tornar a importar tots els documents.", "Web": "Web", - "Web API": "", + "Web API": "Web API", "Web Loader Settings": "Configuració del carregador web", "Web Params": "Paràmetres web", - "Web Search": "Cercador web", - "Web Search Engine": "Cercador web", + "Web Search": "Cerca la web", + "Web Search Engine": "Motor de cerca de la web", "Webhook URL": "URL del webhook", - "WebUI Settings": "Configuració de WebUI", + "WebUI Settings": "Configuracions de WebUI", "WebUI will make requests to": "WebUI farà peticions a", - "What’s New in": "Què hi ha de Nou en", + "What’s New in": "Què hi ha de nou a", "When history is turned off, new chats on this browser won't appear in your history on any of your devices.": "Quan l'historial està desactivat, els nous xats en aquest navegador no apareixeran en el teu historial en cap dels teus dispositius.", - "Whisper (Local)": "", - "Widescreen Mode": "", - "Workspace": "Treball", - "Write a prompt suggestion (e.g. Who are you?)": "Escriu una suggerència de prompt (p. ex. Qui ets tu?)", + "Whisper (Local)": "Whisper (local)", + "Widescreen Mode": "Mode de pantalla ampla", + "Workspace": "Espai de treball", + "Write a prompt suggestion (e.g. Who are you?)": "Escriu una suggerència d'indicació (p. ex. Qui ets?)", "Write a summary in 50 words that summarizes [topic or keyword].": "Escriu un resum en 50 paraules que resumeixi [tema o paraula clau].", - "Yesterday": "Ayer", + "Yesterday": "Ahir", "You": "Tu", - "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "", + "You can personalize your interactions with LLMs by adding memories through the 'Manage' button below, making them more helpful and tailored to you.": "Pots personalitzar les teves interaccions amb els models de llenguatge afegint memòries mitjançant el botó 'Gestiona' que hi ha a continuació, fent-les més útils i adaptades a tu.", "You cannot clone a base model": "No es pot clonar un model base", "You have no archived conversations.": "No tens converses arxivades.", "You have shared this chat": "Has compartit aquest xat", "You're a helpful assistant.": "Ets un assistent útil.", "You're now logged in.": "Ara estàs connectat.", - "Your account status is currently pending activation.": "", + "Your account status is currently pending activation.": "El compte està actualment pendent d'activació", "Youtube": "Youtube", "Youtube Loader Settings": "Configuració del carregador de Youtube" } From ae567796ee304a114f5ec97966b947b19d9b5ac4 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 01:39:53 -0700 Subject: [PATCH 06/71] refac --- backend/apps/webui/main.py | 4 +- backend/main.py | 83 +++++++++++++++++++++----------------- 2 files changed, 50 insertions(+), 37 deletions(-) diff --git a/backend/apps/webui/main.py b/backend/apps/webui/main.py index ce58047ed6..a9f7fb2866 100644 --- a/backend/apps/webui/main.py +++ b/backend/apps/webui/main.py @@ -130,7 +130,9 @@ async def get_pipe_models(): manifold_pipe_name = p["name"] if hasattr(function_module, "name"): - manifold_pipe_name = f"{pipe.name}{manifold_pipe_name}" + manifold_pipe_name = ( + f"{function_module.name}{manifold_pipe_name}" + ) pipe_models.append( { diff --git a/backend/main.py b/backend/main.py index 737641e2d4..9eb7d20711 100644 --- a/backend/main.py +++ b/backend/main.py @@ -389,26 +389,31 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): if hasattr(function_module, "inlet"): inlet = function_module.inlet + # Get the signature of the function + sig = inspect.signature(inlet) + param = {"body": data} + + if "__user__" in sig.parameters: + param = { + **param, + "__user__": { + "id": user.id, + "email": user.email, + "name": user.name, + "role": user.role, + }, + } + + if "__id__" in sig.parameters: + param = { + **param, + "__id__": filter_id, + } + if inspect.iscoroutinefunction(inlet): - data = await inlet( - data, - { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - }, - ) + data = await inlet(**param) else: - data = inlet( - data, - { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - }, - ) + data = inlet(**param) except Exception as e: print(f"Error: {e}") @@ -1031,26 +1036,32 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): try: if hasattr(function_module, "outlet"): outlet = function_module.outlet + + # Get the signature of the function + sig = inspect.signature(outlet) + param = {"body": data} + + if "__user__" in sig.parameters: + param = { + **param, + "__user__": { + "id": user.id, + "email": user.email, + "name": user.name, + "role": user.role, + }, + } + + if "__id__" in sig.parameters: + param = { + **param, + "__id__": filter_id, + } + if inspect.iscoroutinefunction(outlet): - data = await outlet( - data, - { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - }, - ) + data = await outlet(**param) else: - data = outlet( - data, - { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - }, - ) + data = outlet(**param) except Exception as e: print(f"Error: {e}") From a8a451344cd5970c939a1744aff571db57b74e6d Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 01:42:28 -0700 Subject: [PATCH 07/71] refac --- backend/main.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/backend/main.py b/backend/main.py index 9eb7d20711..0b7f23bde8 100644 --- a/backend/main.py +++ b/backend/main.py @@ -858,13 +858,28 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u print(pipe_id) pipe = webui_app.state.FUNCTIONS[pipe_id].pipe - if form_data["stream"]: + # Get the signature of the function + sig = inspect.signature(pipe) + param = {"body": form_data} + + if "__user__" in sig.parameters: + param = { + **param, + "__user__": { + "id": user.id, + "email": user.email, + "name": user.name, + "role": user.role, + }, + } + + if form_data["stream"]: async def stream_content(): if inspect.iscoroutinefunction(pipe): - res = await pipe(body=form_data) + res = await pipe(**param) else: - res = pipe(body=form_data) + res = pipe(**param) if isinstance(res, str): message = stream_message_template(form_data["model"], res) @@ -910,9 +925,9 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u ) else: if inspect.iscoroutinefunction(pipe): - res = await pipe(body=form_data) + res = await pipe(**param) else: - res = pipe(body=form_data) + res = pipe(**param) if isinstance(res, dict): return res From 0ac8e97447539a1e4b6a8174f88f321a1b701d8b Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 01:43:40 -0700 Subject: [PATCH 08/71] refac: styling --- src/lib/components/workspace/Functions.svelte | 2 +- src/lib/components/workspace/Tools.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index 35e3082208..5ecfd19f98 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -113,7 +113,7 @@
-
{func.id}
+
{func.id}
{func.meta.description} diff --git a/src/lib/components/workspace/Tools.svelte b/src/lib/components/workspace/Tools.svelte index d2b04ad022..f39d2d3918 100644 --- a/src/lib/components/workspace/Tools.svelte +++ b/src/lib/components/workspace/Tools.svelte @@ -111,7 +111,7 @@
-
{tool.id}
+
{tool.id}
{tool.meta.description} From e4af3852f7101c38411ce7e10c5ff838b9f309d9 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 02:29:22 -0700 Subject: [PATCH 09/71] refac: allow class in tools --- backend/utils/tools.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/utils/tools.py b/backend/utils/tools.py index 5fef2a2b68..5846ed4bdb 100644 --- a/backend/utils/tools.py +++ b/backend/utils/tools.py @@ -20,7 +20,9 @@ def get_tools_specs(tools) -> List[dict]: function_list = [ {"name": func, "function": getattr(tools, func)} for func in dir(tools) - if callable(getattr(tools, func)) and not func.startswith("__") + if callable(getattr(tools, func)) + and not func.startswith("__") + and not inspect.isclass(getattr(tools, func)) ] specs = [] From 8345bb55d4f0266b504bcd1c014f448b82d94527 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 02:29:33 -0700 Subject: [PATCH 10/71] refac: styling --- .../chat/Settings/Personalization.svelte | 4 +- .../components/chat/Settings/Valves.svelte | 85 +++++++++++++++++++ src/lib/components/chat/SettingsModal.svelte | 64 ++++++++++---- 3 files changed, 135 insertions(+), 18 deletions(-) create mode 100644 src/lib/components/chat/Settings/Valves.svelte diff --git a/src/lib/components/chat/Settings/Personalization.svelte b/src/lib/components/chat/Settings/Personalization.svelte index 6450344d75..5d86c1fbda 100644 --- a/src/lib/components/chat/Settings/Personalization.svelte +++ b/src/lib/components/chat/Settings/Personalization.svelte @@ -31,7 +31,7 @@ dispatch('save'); }} > -
+
-
+
{ diff --git a/src/lib/components/chat/Settings/Valves.svelte b/src/lib/components/chat/Settings/Valves.svelte new file mode 100644 index 0000000000..159688ee96 --- /dev/null +++ b/src/lib/components/chat/Settings/Valves.svelte @@ -0,0 +1,85 @@ + + +
{ + dispatch('save'); + }} +> +
+
+ + + +
+ +
+
+
+ +
+
+
+ +
+
+
+
+ +
+ +
+ diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte index 7160910073..75d656f6b9 100644 --- a/src/lib/components/chat/SettingsModal.svelte +++ b/src/lib/components/chat/SettingsModal.svelte @@ -16,6 +16,7 @@ import Personalization from './Settings/Personalization.svelte'; import { updateUserSettings } from '$lib/apis/users'; import { goto } from '$app/navigation'; + import Valves from './Settings/Valves.svelte'; const i18n = getContext('i18n'); @@ -65,8 +66,8 @@ + + +
+
+ +
+ {$i18n.t('Manage Valves')} +
+
- +
+ +
+
-
+
+
+
diff --git a/src/routes/(app)/+layout.svelte b/src/routes/(app)/+layout.svelte index 8973b9eb72..875ebf4eb9 100644 --- a/src/routes/(app)/+layout.svelte +++ b/src/routes/(app)/+layout.svelte @@ -29,13 +29,15 @@ showChangelog, config, showCallOverlay, - tools + tools, + functions } from '$lib/stores'; import SettingsModal from '$lib/components/chat/SettingsModal.svelte'; import Sidebar from '$lib/components/layout/Sidebar.svelte'; import ChangelogModal from '$lib/components/ChangelogModal.svelte'; import AccountPending from '$lib/components/layout/Overlay/AccountPending.svelte'; + import { getFunctions } from '$lib/apis/functions'; const i18n = getContext('i18n'); @@ -93,6 +95,9 @@ (async () => { tools.set(await getTools(localStorage.token)); })(), + (async () => { + functions.set(await getFunctions(localStorage.token)); + })(), (async () => { banners.set(await getBanners(localStorage.token)); })(), From d362fd027e5873271dbb4f50acde1202ee7465d2 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:08:32 -0700 Subject: [PATCH 13/71] feat: user valves integration --- backend/apps/webui/models/functions.py | 28 ++-- backend/apps/webui/models/tools.py | 28 ++-- backend/apps/webui/routers/functions.py | 7 +- src/lib/apis/functions/index.ts | 99 ++++++++++++ src/lib/apis/tools/index.ts | 99 ++++++++++++ .../components/chat/Settings/Valves.svelte | 151 ++++++++++++++++-- 6 files changed, 375 insertions(+), 37 deletions(-) diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index c1e0dc5dda..cd6320f953 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -8,6 +8,8 @@ from apps.webui.internal.db import DB, JSONField from apps.webui.models.users import Users import json +import copy + from config import SRC_LOG_LEVELS @@ -121,14 +123,15 @@ class FunctionsTable: ) -> Optional[dict]: try: user = Users.get_user_by_id(user_id) + user_settings = user.settings.model_dump() # Check if user has "functions" and "valves" settings - if "functions" not in user.settings: - user.settings["functions"] = {} - if "valves" not in user.settings["functions"]: - user.settings["functions"]["valves"] = {} + if "functions" not in user_settings: + user_settings["functions"] = {} + if "valves" not in user_settings["functions"]: + user_settings["functions"]["valves"] = {} - return user.settings["functions"]["valves"].get(id, {}) + return user_settings["functions"]["valves"].get(id, {}) except Exception as e: print(f"An error occurred: {e}") return None @@ -138,20 +141,21 @@ class FunctionsTable: ) -> Optional[dict]: try: user = Users.get_user_by_id(user_id) + user_settings = user.settings.model_dump() # Check if user has "functions" and "valves" settings - if "functions" not in user.settings: - user.settings["functions"] = {} - if "valves" not in user.settings["functions"]: - user.settings["functions"]["valves"] = {} + if "functions" not in user_settings: + user_settings["functions"] = {} + if "valves" not in user_settings["functions"]: + user_settings["functions"]["valves"] = {} - user.settings["functions"]["valves"][id] = valves + user_settings["functions"]["valves"][id] = valves # Update the user settings in the database - query = Users.update_user_by_id(user_id, {"settings": user.settings}) + query = Users.update_user_by_id(user_id, {"settings": user_settings}) query.execute() - return user.settings["functions"]["valves"][id] + return user_settings["functions"]["valves"][id] except Exception as e: print(f"An error occurred: {e}") return None diff --git a/backend/apps/webui/models/tools.py b/backend/apps/webui/models/tools.py index 1592c228fe..ab322ac14a 100644 --- a/backend/apps/webui/models/tools.py +++ b/backend/apps/webui/models/tools.py @@ -8,6 +8,8 @@ from apps.webui.internal.db import DB, JSONField from apps.webui.models.users import Users import json +import copy + from config import SRC_LOG_LEVELS @@ -112,14 +114,15 @@ class ToolsTable: ) -> Optional[dict]: try: user = Users.get_user_by_id(user_id) + user_settings = user.settings.model_dump() # Check if user has "tools" and "valves" settings - if "tools" not in user.settings: - user.settings["tools"] = {} - if "valves" not in user.settings["tools"]: - user.settings["tools"]["valves"] = {} + if "tools" not in user_settings: + user_settings["tools"] = {} + if "valves" not in user_settings["tools"]: + user_settings["tools"]["valves"] = {} - return user.settings["tools"]["valves"].get(id, {}) + return user_settings["tools"]["valves"].get(id, {}) except Exception as e: print(f"An error occurred: {e}") return None @@ -129,20 +132,21 @@ class ToolsTable: ) -> Optional[dict]: try: user = Users.get_user_by_id(user_id) + user_settings = user.settings.model_dump() # Check if user has "tools" and "valves" settings - if "tools" not in user.settings: - user.settings["tools"] = {} - if "valves" not in user.settings["tools"]: - user.settings["tools"]["valves"] = {} + if "tools" not in user_settings: + user_settings["tools"] = {} + if "valves" not in user_settings["tools"]: + user_settings["tools"]["valves"] = {} - user.settings["tools"]["valves"][id] = valves + user_settings["tools"]["valves"][id] = valves # Update the user settings in the database - query = Users.update_user_by_id(user_id, {"settings": user.settings}) + query = Users.update_user_by_id(user_id, {"settings": user_settings}) query.execute() - return user.settings["tools"]["valves"][id] + return user_settings["tools"]["valves"][id] except Exception as e: print(f"An error occurred: {e}") return None diff --git a/backend/apps/webui/routers/functions.py b/backend/apps/webui/routers/functions.py index 53b9ab130e..acf1894fdb 100644 --- a/backend/apps/webui/routers/functions.py +++ b/backend/apps/webui/routers/functions.py @@ -145,7 +145,7 @@ async def get_function_user_valves_by_id(id: str, user=Depends(get_verified_user async def get_function_user_valves_spec_by_id( request: Request, id: str, user=Depends(get_verified_user) ): - function = Functions.get_tool_by_id(id) + function = Functions.get_function_by_id(id) if function: if id in request.app.state.FUNCTIONS: function_module = request.app.state.FUNCTIONS[id] @@ -168,8 +168,7 @@ async def get_function_user_valves_spec_by_id( async def update_function_user_valves_by_id( request: Request, id: str, form_data: dict, user=Depends(get_verified_user) ): - - function = Functions.get_tool_by_id(id) + function = Functions.get_function_by_id(id) if function: if id in request.app.state.FUNCTIONS: @@ -211,7 +210,7 @@ async def update_function_user_valves_by_id( @router.post("/id/{id}/update", response_model=Optional[FunctionModel]) -async def update_toolkit_by_id( +async def update_function_by_id( request: Request, id: str, form_data: FunctionForm, user=Depends(get_admin_user) ): function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py") diff --git a/src/lib/apis/functions/index.ts b/src/lib/apis/functions/index.ts index e035ef1c17..530702a3e1 100644 --- a/src/lib/apis/functions/index.ts +++ b/src/lib/apis/functions/index.ts @@ -191,3 +191,102 @@ export const deleteFunctionById = async (token: string, id: string) => { return res; }; + +export const getUserValvesById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/valves/user`, { + 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 getUserValvesSpecById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/valves/user/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 updateUserValvesById = async (token: string, id: string, valves: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/valves/user/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; +}; diff --git a/src/lib/apis/tools/index.ts b/src/lib/apis/tools/index.ts index 9c620e7b50..25d543febb 100644 --- a/src/lib/apis/tools/index.ts +++ b/src/lib/apis/tools/index.ts @@ -191,3 +191,102 @@ export const deleteToolById = async (token: string, id: string) => { return res; }; + +export const getUserValvesById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves/user`, { + 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 getUserValvesSpecById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves/user/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 updateUserValvesById = async (token: string, id: string, valves: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/tools/id/${id}/valves/user/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; +}; diff --git a/src/lib/components/chat/Settings/Valves.svelte b/src/lib/components/chat/Settings/Valves.svelte index cfa03d907d..f41d0e672c 100644 --- a/src/lib/components/chat/Settings/Valves.svelte +++ b/src/lib/components/chat/Settings/Valves.svelte @@ -1,12 +1,24 @@
{ + submitHandler(); dispatch('save'); }} > @@ -82,11 +164,62 @@
-
+ {#if selectedId} +
-
-
-
+
+ {#if !loading} + {#if valvesSpec} + {#each Object.keys(valvesSpec.properties) as property, idx} +
+
+
+ {valvesSpec.properties[property].title} + + {#if (valvesSpec?.required ?? []).includes(property)} + *required + {/if} +
+ + +
+ + {#if (valves[property] ?? null) !== null} +
+
+ +
+
+ {/if} +
+ {/each} + {:else} +
No valves
+ {/if} + {:else} + + {/if} +
+ {/if}
From 6ccb5e8f67e0ae26ebc82960dc0b2ef148d2078c Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:14:12 -0700 Subject: [PATCH 14/71] feat: user valves support --- backend/main.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/backend/main.py b/backend/main.py index 0b7f23bde8..6135d59a38 100644 --- a/backend/main.py +++ b/backend/main.py @@ -278,6 +278,9 @@ async def get_function_call_response( "email": user.email, "name": user.name, "role": user.role, + "valves": Tools.get_user_valves_by_id_and_user_id( + tool_id, user.id + ), }, } @@ -401,6 +404,9 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): "email": user.email, "name": user.name, "role": user.role, + "valves": Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id + ), }, } @@ -871,10 +877,14 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u "email": user.email, "name": user.name, "role": user.role, + "valves": Functions.get_user_valves_by_id_and_user_id( + pipe_id, user.id + ), }, } if form_data["stream"]: + async def stream_content(): if inspect.iscoroutinefunction(pipe): res = await pipe(**param) @@ -1010,7 +1020,12 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): f"{url}/{filter['id']}/filter/outlet", headers=headers, json={ - "user": {"id": user.id, "name": user.name, "role": user.role}, + "user": { + "id": user.id, + "name": user.name, + "email": user.email, + "role": user.role, + }, "body": data, }, ) @@ -1064,6 +1079,9 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): "email": user.email, "name": user.name, "role": user.role, + "valves": Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id + ), }, } From 646832ba8c98febcaa328b270c6fbd9c2b22067c Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:23:37 -0700 Subject: [PATCH 15/71] refac --- backend/main.py | 65 +++++++++++++++++++++++++++++++++++++------------ 1 file changed, 50 insertions(+), 15 deletions(-) diff --git a/backend/main.py b/backend/main.py index 6135d59a38..732ef96aa4 100644 --- a/backend/main.py +++ b/backend/main.py @@ -278,8 +278,16 @@ async def get_function_call_response( "email": user.email, "name": user.name, "role": user.role, - "valves": Tools.get_user_valves_by_id_and_user_id( - tool_id, user.id + **( + { + "valves": toolkit_module.UserValves( + Tools.get_user_valves_by_id_and_user_id( + tool_id, user.id + ) + ) + } + if hasattr(toolkit_module, "UserValves") + else {} ), }, } @@ -404,8 +412,18 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): "email": user.email, "name": user.name, "role": user.role, - "valves": Functions.get_user_valves_by_id_and_user_id( - filter_id, user.id + **( + { + "valves": function_module.UserValves( + Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id + ) + ) + } + if hasattr( + function_module, "UserValves" + ) + else {} ), }, } @@ -850,12 +868,6 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u pipe = model.get("pipe") if pipe: - form_data["user"] = { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - } async def job(): pipe_id = form_data["model"] @@ -863,7 +875,14 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u pipe_id, sub_pipe_id = pipe_id.split(".", 1) print(pipe_id) - pipe = webui_app.state.FUNCTIONS[pipe_id].pipe + # Check if function is already loaded + if pipe_id not in app.state.FUNCTIONS: + function_module, function_type = load_function_module_by_id(pipe_id) + app.state.FUNCTIONS[pipe_id] = function_module + else: + function_module = app.state.FUNCTIONS[pipe_id] + + pipe = function_module.pipe # Get the signature of the function sig = inspect.signature(pipe) @@ -877,8 +896,16 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u "email": user.email, "name": user.name, "role": user.role, - "valves": Functions.get_user_valves_by_id_and_user_id( - pipe_id, user.id + **( + { + "valves": pipe.UserValves( + Functions.get_user_valves_by_id_and_user_id( + pipe_id, user.id + ) + ) + } + if hasattr(function_module, "UserValves") + else {} ), }, } @@ -1079,8 +1106,16 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): "email": user.email, "name": user.name, "role": user.role, - "valves": Functions.get_user_valves_by_id_and_user_id( - filter_id, user.id + **( + { + "valves": function_module.UserValves( + Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id + ) + ) + } + if hasattr(function_module, "UserValves") + else {} ), }, } From f524238910b5b01cdf22ebb881b9cd9358b78ff2 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:24:46 -0700 Subject: [PATCH 16/71] fix --- backend/main.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/backend/main.py b/backend/main.py index 732ef96aa4..704f22bfcc 100644 --- a/backend/main.py +++ b/backend/main.py @@ -876,11 +876,11 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u print(pipe_id) # Check if function is already loaded - if pipe_id not in app.state.FUNCTIONS: + if pipe_id not in webui_app.state.FUNCTIONS: function_module, function_type = load_function_module_by_id(pipe_id) - app.state.FUNCTIONS[pipe_id] = function_module + webui_app.state.FUNCTIONS[pipe_id] = function_module else: - function_module = app.state.FUNCTIONS[pipe_id] + function_module = webui_app.state.FUNCTIONS[pipe_id] pipe = function_module.pipe From 6ce91de7e0a7226ec51c433289383ff337e136c9 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:25:02 -0700 Subject: [PATCH 17/71] fix --- backend/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/main.py b/backend/main.py index 704f22bfcc..b223931c9c 100644 --- a/backend/main.py +++ b/backend/main.py @@ -898,7 +898,7 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u "role": user.role, **( { - "valves": pipe.UserValves( + "valves": function_module.UserValves( Functions.get_user_valves_by_id_and_user_id( pipe_id, user.id ) From 9205b90af6cb6d4c5f42ca59525c39585fb5973c Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:26:03 -0700 Subject: [PATCH 18/71] fix --- backend/main.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/backend/main.py b/backend/main.py index b223931c9c..993f775d7d 100644 --- a/backend/main.py +++ b/backend/main.py @@ -281,7 +281,7 @@ async def get_function_call_response( **( { "valves": toolkit_module.UserValves( - Tools.get_user_valves_by_id_and_user_id( + **Tools.get_user_valves_by_id_and_user_id( tool_id, user.id ) ) @@ -415,7 +415,7 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): **( { "valves": function_module.UserValves( - Functions.get_user_valves_by_id_and_user_id( + **Functions.get_user_valves_by_id_and_user_id( filter_id, user.id ) ) @@ -899,7 +899,7 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u **( { "valves": function_module.UserValves( - Functions.get_user_valves_by_id_and_user_id( + **Functions.get_user_valves_by_id_and_user_id( pipe_id, user.id ) ) @@ -1109,7 +1109,7 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): **( { "valves": function_module.UserValves( - Functions.get_user_valves_by_id_and_user_id( + **Functions.get_user_valves_by_id_and_user_id( filter_id, user.id ) ) From cf6447eb2a68c7c8da3605d395fabb5ac186569f Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 12:43:30 -0700 Subject: [PATCH 19/71] feat: function exception handler --- backend/main.py | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) diff --git a/backend/main.py b/backend/main.py index 993f775d7d..81a882bb5e 100644 --- a/backend/main.py +++ b/backend/main.py @@ -913,10 +913,15 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u if form_data["stream"]: async def stream_content(): - if inspect.iscoroutinefunction(pipe): - res = await pipe(**param) - else: - res = pipe(**param) + try: + if inspect.iscoroutinefunction(pipe): + res = await pipe(**param) + else: + res = pipe(**param) + except Exception as e: + print(f"Error: {e}") + yield f"data: {json.dumps({'error': {'detail':str(e)}})}\n\n" + return if isinstance(res, str): message = stream_message_template(form_data["model"], res) @@ -961,6 +966,16 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u stream_content(), media_type="text/event-stream" ) else: + + try: + if inspect.iscoroutinefunction(pipe): + res = await pipe(**param) + else: + res = pipe(**param) + except Exception as e: + print(f"Error: {e}") + return {"error": {"detail":str(e)}} + if inspect.iscoroutinefunction(pipe): res = await pipe(**param) else: From c1971fd8d7143313bfce3c82a7eb5208ae47bde3 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 13:01:26 -0700 Subject: [PATCH 20/71] refac: show default instead of none --- src/lib/components/chat/Settings/Valves.svelte | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/Settings/Valves.svelte b/src/lib/components/chat/Settings/Valves.svelte index f41d0e672c..115dd3bd15 100644 --- a/src/lib/components/chat/Settings/Valves.svelte +++ b/src/lib/components/chat/Settings/Valves.svelte @@ -189,7 +189,13 @@ }} > {#if (valves[property] ?? null) === null} - {$i18n.t('None')} + + {#if (valvesSpec?.required ?? []).includes(property)} + {$i18n.t('None')} + {:else} + {$i18n.t('Default')} + {/if} + {:else} {$i18n.t('Custom')} {/if} From 98c18b3032863406008cd2a98149a286d27b89f5 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 13:13:46 -0700 Subject: [PATCH 21/71] fix: web search --- src/lib/components/chat/Chat.svelte | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index d83eb3cb2f..8f84488477 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -600,10 +600,14 @@ files = model.info.meta.knowledge; } const lastUserMessage = messages.filter((message) => message.role === 'user').at(-1); + files = [ ...files, ...(lastUserMessage?.files?.filter((item) => ['doc', 'file', 'collection', 'web_search_results'].includes(item.type) + ) ?? []), + ...(responseMessage?.files?.filter((item) => + ['doc', 'file', 'collection', 'web_search_results'].includes(item.type) ) ?? []) ].filter( // Remove duplicates @@ -844,6 +848,9 @@ ...files, ...(lastUserMessage?.files?.filter((item) => ['doc', 'file', 'collection', 'web_search_results'].includes(item.type) + ) ?? []), + ...(responseMessage?.files?.filter((item) => + ['doc', 'file', 'collection', 'web_search_results'].includes(item.type) ) ?? []) ].filter( // Remove duplicates @@ -1213,6 +1220,7 @@ const getWebSearchResults = async (model: string, parentId: string, responseId: string) => { const responseMessage = history.messages[responseId]; + const userMessage = history.messages[parentId]; responseMessage.statusHistory = [ { @@ -1223,7 +1231,7 @@ ]; messages = messages; - const prompt = history.messages[parentId].content; + const prompt = userMessage.content; let searchQuery = await generateSearchQuery(localStorage.token, model, messages, prompt).catch( (error) => { console.log(error); From d0f34baaa3c9ca899013834cf71cc97ae57c8e75 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 13:21:36 -0700 Subject: [PATCH 22/71] feat: voice interruption toggle --- .../chat/MessageInput/CallOverlay.svelte | 2 +- .../components/chat/Settings/Interface.svelte | 27 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/MessageInput/CallOverlay.svelte b/src/lib/components/chat/MessageInput/CallOverlay.svelte index a9e96783bf..bca31f6101 100644 --- a/src/lib/components/chat/MessageInput/CallOverlay.svelte +++ b/src/lib/components/chat/MessageInput/CallOverlay.svelte @@ -271,7 +271,7 @@ return; } - if (assistantSpeaking) { + if (assistantSpeaking && !($settings?.voiceInterruption ?? false)) { // Mute the audio if the assistant is speaking analyser.maxDecibels = 0; analyser.minDecibels = -1; diff --git a/src/lib/components/chat/Settings/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index a5db91a7b2..f8a7019fbe 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -32,6 +32,7 @@ let chatDirection: 'LTR' | 'RTL' = 'LTR'; let showEmojiInCall = false; + let voiceInterruption = false; const toggleSplitLargeChunks = async () => { splitLargeChunks = !splitLargeChunks; @@ -58,6 +59,11 @@ saveSettings({ showEmojiInCall: showEmojiInCall }); }; + const toggleVoiceInterruption = async () => { + voiceInterruption = !voiceInterruption; + saveSettings({ voiceInterruption: voiceInterruption }); + }; + const toggleUserLocation = async () => { userLocation = !userLocation; @@ -128,6 +134,7 @@ showUsername = $settings.showUsername ?? false; showEmojiInCall = $settings.showEmojiInCall ?? false; + voiceInterruption = $settings.voiceInterruption ?? false; chatBubble = $settings.chatBubble ?? true; widescreenMode = $settings.widescreenMode ?? false; @@ -399,6 +406,26 @@
{$i18n.t('Voice')}
+
+
+
{$i18n.t('Voice Interruption in Call')}
+ + +
+
+
{$i18n.t('Display Emoji in Call')}
From 3af8c5b03d7bfa04a16079fe9a65e7f046e2dafb Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sat, 22 Jun 2024 13:22:26 -0700 Subject: [PATCH 23/71] refac: wording --- src/lib/components/chat/Settings/Interface.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Settings/Interface.svelte b/src/lib/components/chat/Settings/Interface.svelte index f8a7019fbe..49632f00ec 100644 --- a/src/lib/components/chat/Settings/Interface.svelte +++ b/src/lib/components/chat/Settings/Interface.svelte @@ -408,7 +408,7 @@
-
{$i18n.t('Voice Interruption in Call')}
+
{$i18n.t('Allow Voice Interruption in Call')}
- - - - - - - - - +
- +
{/each}
diff --git a/src/lib/components/workspace/Tools/ToolMenu.svelte b/src/lib/components/workspace/Tools/ToolMenu.svelte new file mode 100644 index 0000000000..9a4177b1ed --- /dev/null +++ b/src/lib/components/workspace/Tools/ToolMenu.svelte @@ -0,0 +1,92 @@ + + + { + if (e.detail === false) { + onClose(); + } + }} +> + + + + +
+ + { + shareHandler(); + }} + > + +
{$i18n.t('Share')}
+
+ + { + cloneHandler(); + }} + > + + +
{$i18n.t('Clone')}
+
+ + { + exportHandler(); + }} + > + + +
{$i18n.t('Export')}
+
+ +
+ + { + deleteHandler(); + }} + > + +
{$i18n.t('Delete')}
+
+
+
+
From 57455f084b761d5766ccd7e2e87197cec1754ae4 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 15:51:19 -0700 Subject: [PATCH 36/71] refac: functions ui --- src/lib/components/workspace/Functions.svelte | 189 +++++++----------- .../workspace/Functions/FunctionMenu.svelte | 92 +++++++++ 2 files changed, 169 insertions(+), 112 deletions(-) create mode 100644 src/lib/components/workspace/Functions/FunctionMenu.svelte diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index 5ecfd19f98..25d16ea167 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -20,6 +20,8 @@ import Tooltip from '../common/Tooltip.svelte'; import ConfirmDialog from '../common/ConfirmDialog.svelte'; import { getModels } from '$lib/apis'; + import FunctionMenu from './Functions/FunctionMenu.svelte'; + import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; const i18n = getContext('i18n'); @@ -28,6 +30,54 @@ let showConfirm = false; let query = ''; + + const shareHandler = async (tool) => { + console.log(tool); + }; + + const cloneHandler = async (func) => { + const _function = await getFunctionById(localStorage.token, func.id).catch((error) => { + toast.error(error); + return null; + }); + + if (_function) { + sessionStorage.function = JSON.stringify({ + ..._function, + id: `${_function.id}_clone`, + name: `${_function.name} (Clone)` + }); + goto('/workspace/functions/create'); + } + }; + + const exportHandler = async (func) => { + const _function = await getFunctionById(localStorage.token, func.id).catch((error) => { + toast.error(error); + return null; + }); + + if (_function) { + let blob = new Blob([JSON.stringify([_function])], { + type: 'application/json' + }); + saveAs(blob, `function-${_function.id}-export-${Date.now()}.json`); + } + }; + + const deleteHandler = async (func) => { + const res = await deleteFunctionById(localStorage.token, func.id).catch((error) => { + toast.error(error); + return null; + }); + + if (res) { + toast.success('Function deleted successfully'); + + functions.set(await getFunctions(localStorage.token)); + models.set(await getModels(localStorage.token)); + } + }; @@ -87,18 +137,14 @@ {#each $functions.filter((f) => query === '' || f.name .toLowerCase() .includes(query.toLowerCase()) || f.id.toLowerCase().includes(query.toLowerCase())) as func} -
- - - - - - - - - +
- +
{/each}
diff --git a/src/lib/components/workspace/Functions/FunctionMenu.svelte b/src/lib/components/workspace/Functions/FunctionMenu.svelte new file mode 100644 index 0000000000..9a4177b1ed --- /dev/null +++ b/src/lib/components/workspace/Functions/FunctionMenu.svelte @@ -0,0 +1,92 @@ + + + { + if (e.detail === false) { + onClose(); + } + }} +> + + + + +
+ + { + shareHandler(); + }} + > + +
{$i18n.t('Share')}
+
+ + { + cloneHandler(); + }} + > + + +
{$i18n.t('Clone')}
+
+ + { + exportHandler(); + }} + > + + +
{$i18n.t('Export')}
+
+ +
+ + { + deleteHandler(); + }} + > + +
{$i18n.t('Delete')}
+
+
+
+
From ecf1d89a8b03d99882b1a652cdb15ce8017b5649 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 15:57:16 -0700 Subject: [PATCH 37/71] refac: prompts ui --- src/lib/components/workspace/Prompts.svelte | 102 ++++++------------ .../workspace/Prompts/PromptMenu.svelte | 92 ++++++++++++++++ 2 files changed, 127 insertions(+), 67 deletions(-) create mode 100644 src/lib/components/workspace/Prompts/PromptMenu.svelte diff --git a/src/lib/components/workspace/Prompts.svelte b/src/lib/components/workspace/Prompts.svelte index 65c8442e86..05884208b4 100644 --- a/src/lib/components/workspace/Prompts.svelte +++ b/src/lib/components/workspace/Prompts.svelte @@ -8,13 +8,16 @@ import { createNewPrompt, deletePromptByCommand, getPrompts } from '$lib/apis/prompts'; import { error } from '@sveltejs/kit'; import { goto } from '$app/navigation'; + import PromptMenu from './Prompts/PromptMenu.svelte'; + import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; const i18n = getContext('i18n'); let importFiles = ''; let query = ''; let promptsImportInputElement: HTMLInputElement; - const sharePrompt = async (prompt) => { + + const shareHandler = async (prompt) => { toast.success($i18n.t('Redirecting you to OpenWebUI Community')); const url = 'https://openwebui.com'; @@ -32,7 +35,20 @@ ); }; - const deletePrompt = async (command) => { + const cloneHandler = async (prompt) => { + sessionStorage.prompt = JSON.stringify(prompt); + goto('/workspace/prompts/create'); + }; + + const exportHandler = async (prompt) => { + let blob = new Blob([JSON.stringify([prompt])], { + type: 'application/json' + }); + saveAs(blob, `prompt-export-${Date.now()}.json`); + }; + + const deleteHandler = async (prompt) => { + const command = prompt.command; await deletePromptByCommand(localStorage.token, command); await prompts.set(await getPrompts(localStorage.token)); }; @@ -128,76 +144,28 @@
- - - - - + + +
{/each} diff --git a/src/lib/components/workspace/Prompts/PromptMenu.svelte b/src/lib/components/workspace/Prompts/PromptMenu.svelte new file mode 100644 index 0000000000..9a4177b1ed --- /dev/null +++ b/src/lib/components/workspace/Prompts/PromptMenu.svelte @@ -0,0 +1,92 @@ + + + { + if (e.detail === false) { + onClose(); + } + }} +> + + + + +
+ + { + shareHandler(); + }} + > + +
{$i18n.t('Share')}
+
+ + { + cloneHandler(); + }} + > + + +
{$i18n.t('Clone')}
+
+ + { + exportHandler(); + }} + > + + +
{$i18n.t('Export')}
+
+ +
+ + { + deleteHandler(); + }} + > + +
{$i18n.t('Delete')}
+
+
+
+
From 7a218d77b7cc2e4a1724775e4ffe91e39a613d69 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 16:03:21 -0700 Subject: [PATCH 38/71] refac: workspace --- src/lib/components/workspace/Documents.svelte | 8 +++- src/lib/components/workspace/Functions.svelte | 39 +++++++++++++++++-- src/lib/components/workspace/Models.svelte | 22 ++++++----- src/lib/components/workspace/Prompts.svelte | 22 ++++++----- src/lib/components/workspace/Tools.svelte | 39 +++++++++++++++++-- 5 files changed, 104 insertions(+), 26 deletions(-) diff --git a/src/lib/components/workspace/Documents.svelte b/src/lib/components/workspace/Documents.svelte index 5e918b6f09..9bb416468b 100644 --- a/src/lib/components/workspace/Documents.svelte +++ b/src/lib/components/workspace/Documents.svelte @@ -538,7 +538,9 @@ documentsImportInputElement.click(); }} > -
{$i18n.t('Import Documents Mapping')}
+
+ {$i18n.t('Import Documents Mapping')} +
-
{$i18n.t('Export Documents Mapping')}
+
+ {$i18n.t('Export Documents Mapping')} +
-
+
{func.name}
@@ -246,7 +246,7 @@ functionsImportInputElement.click(); }} > -
{$i18n.t('Import Functions')}
+
{$i18n.t('Import Functions')}
-
{$i18n.t('Export Functions')}
+
{$i18n.t('Export Functions')}
+ + { diff --git a/src/lib/components/workspace/Models.svelte b/src/lib/components/workspace/Models.svelte index e0a5c4fba2..ce2f6ba3a7 100644 --- a/src/lib/components/workspace/Models.svelte +++ b/src/lib/components/workspace/Models.svelte @@ -256,7 +256,7 @@
-
+
@@ -271,8 +271,8 @@
-
{$i18n.t('Create a model')}
-
{$i18n.t('Customize models for a specific purpose')}
+
{$i18n.t('Create a model')}
+
{$i18n.t('Customize models for a specific purpose')}
@@ -412,7 +412,7 @@ modelsImportInputElement.click(); }} > -
{$i18n.t('Import Models')}
+
{$i18n.t('Import Models')}
-
{$i18n.t('Export Models')}
+
{$i18n.t('Export Models')}
-
{$i18n.t('Made by OpenWebUI Community')}
+
+ {$i18n.t('Made by OpenWebUI Community')} +
-
+ diff --git a/src/lib/components/workspace/Prompts.svelte b/src/lib/components/workspace/Prompts.svelte index 05884208b4..b01d2935d9 100644 --- a/src/lib/components/workspace/Prompts.svelte +++ b/src/lib/components/workspace/Prompts.svelte @@ -115,7 +115,7 @@
-
{prompt.command}
+
{prompt.command}
{prompt.title}
@@ -213,7 +213,7 @@ promptsImportInputElement.click(); }} > -
{$i18n.t('Import Prompts')}
+
{$i18n.t('Import Prompts')}
-
{$i18n.t('Export Prompts')}
+
{$i18n.t('Export Prompts')}
-
{$i18n.t('Made by OpenWebUI Community')}
+
+ {$i18n.t('Made by OpenWebUI Community')} +
-
+ diff --git a/src/lib/components/workspace/Tools.svelte b/src/lib/components/workspace/Tools.svelte index a11c9f722b..9c70a4e52d 100644 --- a/src/lib/components/workspace/Tools.svelte +++ b/src/lib/components/workspace/Tools.svelte @@ -149,7 +149,7 @@ TOOL
-
+
{tool.name}
@@ -242,7 +242,7 @@ toolsImportInputElement.click(); }} > -
{$i18n.t('Import Tools')}
+
{$i18n.t('Import Tools')}
-
{$i18n.t('Export Tools')}
+
{$i18n.t('Export Tools')}
+ + { From 9c57402269b0ed7adf44fc02b332471e9da7822b Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 16:04:33 -0700 Subject: [PATCH 39/71] chore: format --- src/lib/i18n/locales/ar-BH/translation.json | 4 ++++ src/lib/i18n/locales/bg-BG/translation.json | 4 ++++ src/lib/i18n/locales/bn-BD/translation.json | 4 ++++ src/lib/i18n/locales/ca-ES/translation.json | 4 ++++ src/lib/i18n/locales/ceb-PH/translation.json | 4 ++++ src/lib/i18n/locales/de-DE/translation.json | 4 ++++ src/lib/i18n/locales/dg-DG/translation.json | 4 ++++ src/lib/i18n/locales/en-GB/translation.json | 4 ++++ src/lib/i18n/locales/en-US/translation.json | 4 ++++ src/lib/i18n/locales/es-ES/translation.json | 4 ++++ src/lib/i18n/locales/fa-IR/translation.json | 4 ++++ src/lib/i18n/locales/fi-FI/translation.json | 4 ++++ src/lib/i18n/locales/fr-CA/translation.json | 4 ++++ src/lib/i18n/locales/fr-FR/translation.json | 4 ++++ src/lib/i18n/locales/he-IL/translation.json | 4 ++++ src/lib/i18n/locales/hi-IN/translation.json | 4 ++++ src/lib/i18n/locales/hr-HR/translation.json | 4 ++++ src/lib/i18n/locales/it-IT/translation.json | 4 ++++ src/lib/i18n/locales/ja-JP/translation.json | 4 ++++ src/lib/i18n/locales/ka-GE/translation.json | 4 ++++ src/lib/i18n/locales/ko-KR/translation.json | 4 ++++ src/lib/i18n/locales/lt-LT/translation.json | 4 ++++ src/lib/i18n/locales/nb-NO/translation.json | 4 ++++ src/lib/i18n/locales/nl-NL/translation.json | 4 ++++ src/lib/i18n/locales/pa-IN/translation.json | 4 ++++ src/lib/i18n/locales/pl-PL/translation.json | 4 ++++ src/lib/i18n/locales/pt-BR/translation.json | 4 ++++ src/lib/i18n/locales/pt-PT/translation.json | 4 ++++ src/lib/i18n/locales/ru-RU/translation.json | 4 ++++ src/lib/i18n/locales/sr-RS/translation.json | 4 ++++ src/lib/i18n/locales/sv-SE/translation.json | 4 ++++ src/lib/i18n/locales/tk-TW/translation.json | 4 ++++ src/lib/i18n/locales/tr-TR/translation.json | 4 ++++ src/lib/i18n/locales/uk-UA/translation.json | 4 ++++ src/lib/i18n/locales/vi-VN/translation.json | 4 ++++ src/lib/i18n/locales/zh-CN/translation.json | 4 ++++ src/lib/i18n/locales/zh-TW/translation.json | 4 ++++ 37 files changed, 148 insertions(+) diff --git a/src/lib/i18n/locales/ar-BH/translation.json b/src/lib/i18n/locales/ar-BH/translation.json index a80bc6737e..165dc825bf 100644 --- a/src/lib/i18n/locales/ar-BH/translation.json +++ b/src/lib/i18n/locales/ar-BH/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "حذف {{name}}", "Description": "وصف", "Didn't fully follow instructions": "لم أتبع التعليمات بشكل كامل", + "Discover a function": "", "Discover a model": "اكتشف نموذجا", "Discover a prompt": "اكتشاف موجه", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "اكتشاف وتنزيل واستكشاف المطالبات المخصصة", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "اكتشاف وتنزيل واستكشاف الإعدادات المسبقة للنموذج", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/bg-BG/translation.json b/src/lib/i18n/locales/bg-BG/translation.json index 5de83dd7d5..ad6225eba1 100644 --- a/src/lib/i18n/locales/bg-BG/translation.json +++ b/src/lib/i18n/locales/bg-BG/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Изтрито {{име}}", "Description": "Описание", "Didn't fully follow instructions": "Не следва инструкциите", + "Discover a function": "", "Discover a model": "Открийте модел", "Discover a prompt": "Откриване на промпт", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Откриване, сваляне и преглед на персонализирани промптове", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Откриване, сваляне и преглед на пресетове на модели", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/bn-BD/translation.json b/src/lib/i18n/locales/bn-BD/translation.json index 32ee1889aa..49f0e06ef9 100644 --- a/src/lib/i18n/locales/bn-BD/translation.json +++ b/src/lib/i18n/locales/bn-BD/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}} মোছা হয়েছে", "Description": "বিবরণ", "Didn't fully follow instructions": "ইনস্ট্রাকশন সম্পূর্ণ অনুসরণ করা হয়নি", + "Discover a function": "", "Discover a model": "একটি মডেল আবিষ্কার করুন", "Discover a prompt": "একটি প্রম্পট খুঁজে বের করুন", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "কাস্টম প্রম্পটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "মডেল প্রিসেটগুলো আবিস্কার, ডাউনলোড এবং এক্সপ্লোর করুন", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index 4b90989063..98ae50aa56 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "S'ha eliminat {{name}}", "Description": "Descripció", "Didn't fully follow instructions": "No s'han seguit les instruccions completament", + "Discover a function": "", "Discover a model": "Descobrir un model", "Discover a prompt": "Descobrir una indicació", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Descobrir, descarregar i explorar indicacions personalitzades", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Descobrir, descarregar i explorar models preconfigurats", "Dismissible": "Descartable", "Display Emoji in Call": "Mostrar emojis a la trucada", diff --git a/src/lib/i18n/locales/ceb-PH/translation.json b/src/lib/i18n/locales/ceb-PH/translation.json index e59eb767a8..68e21d8bee 100644 --- a/src/lib/i18n/locales/ceb-PH/translation.json +++ b/src/lib/i18n/locales/ceb-PH/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "Deskripsyon", "Didn't fully follow instructions": "", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "Pagkaplag usa ka prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Pagdiskubre, pag-download ug pagsuhid sa mga naandan nga pag-aghat", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Pagdiskobre, pag-download, ug pagsuhid sa mga preset sa template", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index 1414c874ce..710aad09f5 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Gelöscht {{name}}", "Description": "Beschreibung", "Didn't fully follow instructions": "Nicht genau den Answeisungen gefolgt", + "Discover a function": "", "Discover a model": "Entdecken Sie ein Modell", "Discover a prompt": "Einen Prompt entdecken", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Benutzerdefinierte Prompts entdecken, herunterladen und erkunden", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Modellvorgaben entdecken, herunterladen und erkunden", "Dismissible": "ausblendbar", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/dg-DG/translation.json b/src/lib/i18n/locales/dg-DG/translation.json index b83200ad30..a26e8dda41 100644 --- a/src/lib/i18n/locales/dg-DG/translation.json +++ b/src/lib/i18n/locales/dg-DG/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "Description", "Didn't fully follow instructions": "", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "Discover a prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Discover, download, and explore custom prompts", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Discover, download, and explore model presets", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/en-GB/translation.json b/src/lib/i18n/locales/en-GB/translation.json index 707630dbcf..af9d122bb8 100644 --- a/src/lib/i18n/locales/en-GB/translation.json +++ b/src/lib/i18n/locales/en-GB/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "", "Didn't fully follow instructions": "", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index 707630dbcf..af9d122bb8 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "", "Didn't fully follow instructions": "", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/es-ES/translation.json b/src/lib/i18n/locales/es-ES/translation.json index 0acfe4d2fe..3394bd90ce 100644 --- a/src/lib/i18n/locales/es-ES/translation.json +++ b/src/lib/i18n/locales/es-ES/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Eliminado {{nombre}}", "Description": "Descripción", "Didn't fully follow instructions": "No siguió las instrucciones", + "Discover a function": "", "Discover a model": "Descubrir un modelo", "Discover a prompt": "Descubre un Prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Descubre, descarga, y explora Prompts personalizados", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Descubre, descarga y explora ajustes preestablecidos de modelos", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/fa-IR/translation.json b/src/lib/i18n/locales/fa-IR/translation.json index 8bf6744631..a8b59dca15 100644 --- a/src/lib/i18n/locales/fa-IR/translation.json +++ b/src/lib/i18n/locales/fa-IR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "حذف شده {{name}}", "Description": "توضیحات", "Didn't fully follow instructions": "نمی تواند دستورالعمل را کامل پیگیری کند", + "Discover a function": "", "Discover a model": "کشف یک مدل", "Discover a prompt": "یک اعلان را کشف کنید", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "پرامپت\u200cهای سفارشی را کشف، دانلود و کاوش کنید", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "پیش تنظیمات مدل را کشف، دانلود و کاوش کنید", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index 1cf07ac08c..00bbd8c007 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Poistettu {{nimi}}", "Description": "Kuvaus", "Didn't fully follow instructions": "Ei noudattanut ohjeita täysin", + "Discover a function": "", "Discover a model": "Tutustu malliin", "Discover a prompt": "Löydä kehote", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Löydä ja lataa mukautettuja kehotteita", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Löydä ja lataa mallien esiasetuksia", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/fr-CA/translation.json b/src/lib/i18n/locales/fr-CA/translation.json index 6949880dcb..0d0ba8d32e 100644 --- a/src/lib/i18n/locales/fr-CA/translation.json +++ b/src/lib/i18n/locales/fr-CA/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Supprimé {{nom}}", "Description": "Description", "Didn't fully follow instructions": "Ne suit pas les instructions", + "Discover a function": "", "Discover a model": "Découvrez un modèle", "Discover a prompt": "Découvrir un prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index ee402c2e00..103247e521 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}} supprimé", "Description": "Description", "Didn't fully follow instructions": "N'a pas suivi entièrement les instructions", + "Discover a function": "", "Discover a model": "Découvrir un modèle", "Discover a prompt": "Découvrir un prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Découvrir, télécharger et explorer des prompts personnalisés", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Découvrir, télécharger et explorer des préconfigurations de modèles", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/he-IL/translation.json b/src/lib/i18n/locales/he-IL/translation.json index eea250519a..9054fe03e8 100644 --- a/src/lib/i18n/locales/he-IL/translation.json +++ b/src/lib/i18n/locales/he-IL/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "נמחק {{name}}", "Description": "תיאור", "Didn't fully follow instructions": "לא עקב אחרי ההוראות באופן מלא", + "Discover a function": "", "Discover a model": "גלה מודל", "Discover a prompt": "גלה פקודה", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "גלה, הורד, וחקור פקודות מותאמות אישית", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "גלה, הורד, וחקור הגדרות מודל מוגדרות מראש", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/hi-IN/translation.json b/src/lib/i18n/locales/hi-IN/translation.json index 2e37b76408..3ee1cfe1ac 100644 --- a/src/lib/i18n/locales/hi-IN/translation.json +++ b/src/lib/i18n/locales/hi-IN/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}} हटा दिया गया", "Description": "विवरण", "Didn't fully follow instructions": "निर्देशों का पूरी तरह से पालन नहीं किया", + "Discover a function": "", "Discover a model": "एक मॉडल की खोज करें", "Discover a prompt": "प्रॉम्प्ट खोजें", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "कस्टम प्रॉम्प्ट को खोजें, डाउनलोड करें और एक्सप्लोर करें", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "मॉडल प्रीसेट खोजें, डाउनलोड करें और एक्सप्लोर करें", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/hr-HR/translation.json b/src/lib/i18n/locales/hr-HR/translation.json index 82733531aa..ecdc9057be 100644 --- a/src/lib/i18n/locales/hr-HR/translation.json +++ b/src/lib/i18n/locales/hr-HR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Izbrisano {{name}}", "Description": "Opis", "Didn't fully follow instructions": "Nije u potpunosti slijedio upute", + "Discover a function": "", "Discover a model": "Otkrijte model", "Discover a prompt": "Otkrijte prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Otkrijte, preuzmite i istražite prilagođene prompte", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Otkrijte, preuzmite i istražite unaprijed postavljene modele", "Dismissible": "Odbaciti", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/it-IT/translation.json b/src/lib/i18n/locales/it-IT/translation.json index 273689146e..0298134db6 100644 --- a/src/lib/i18n/locales/it-IT/translation.json +++ b/src/lib/i18n/locales/it-IT/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Eliminato {{name}}", "Description": "Descrizione", "Didn't fully follow instructions": "Non ha seguito completamente le istruzioni", + "Discover a function": "", "Discover a model": "Scopri un modello", "Discover a prompt": "Scopri un prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Scopri, scarica ed esplora prompt personalizzati", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Scopri, scarica ed esplora i preset del modello", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index 6c56e26eda..d91343dadd 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}}を削除しました", "Description": "説明", "Didn't fully follow instructions": "説明に沿って操作していませんでした", + "Discover a function": "", "Discover a model": "モデルを検出する", "Discover a prompt": "プロンプトを見つける", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "カスタムプロンプトを見つけて、ダウンロードして、探索", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "モデルプリセットを見つけて、ダウンロードして、探索", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/ka-GE/translation.json b/src/lib/i18n/locales/ka-GE/translation.json index 700a0151ad..78a3841aa4 100644 --- a/src/lib/i18n/locales/ka-GE/translation.json +++ b/src/lib/i18n/locales/ka-GE/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Deleted {{name}}", "Description": "აღწერა", "Didn't fully follow instructions": "ვერ ყველა ინფორმაციისთვის ვერ ხელახლა ჩაწერე", + "Discover a function": "", "Discover a model": "გაიგეთ მოდელი", "Discover a prompt": "აღმოაჩინეთ მოთხოვნა", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მორგებული მოთხოვნები", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "აღმოაჩინეთ, ჩამოტვირთეთ და შეისწავლეთ მოდელის წინასწარ პარამეტრები", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/ko-KR/translation.json b/src/lib/i18n/locales/ko-KR/translation.json index df8e57aa10..6c8498206e 100644 --- a/src/lib/i18n/locales/ko-KR/translation.json +++ b/src/lib/i18n/locales/ko-KR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}}을(를) 삭제했습니다.", "Description": "설명", "Didn't fully follow instructions": "완전히 지침을 따르지 않음", + "Discover a function": "", "Discover a model": "모델 검색", "Discover a prompt": "프롬프트 검색", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "사용자 정의 프롬프트 검색, 다운로드 및 탐색", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "모델 사전 설정 검색, 다운로드 및 탐색", "Dismissible": "제외가능", "Display Emoji in Call": "콜(call)에서 이모지 표시", diff --git a/src/lib/i18n/locales/lt-LT/translation.json b/src/lib/i18n/locales/lt-LT/translation.json index 7417a4f77d..c65693bfe8 100644 --- a/src/lib/i18n/locales/lt-LT/translation.json +++ b/src/lib/i18n/locales/lt-LT/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "Aprašymas", "Didn't fully follow instructions": "Pilnai nesekė instrukcijų", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "Atrasti užklausas", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Atrasti ir parsisiųsti užklausas", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Atrasti ir parsisiųsti modelių konfigūracija", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/nb-NO/translation.json b/src/lib/i18n/locales/nb-NO/translation.json index 6c03decf23..f3c91c88d3 100644 --- a/src/lib/i18n/locales/nb-NO/translation.json +++ b/src/lib/i18n/locales/nb-NO/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Slettet {{name}}", "Description": "Beskrivelse", "Didn't fully follow instructions": "Fulgte ikke instruksjonene fullt ut", + "Discover a function": "", "Discover a model": "Oppdag en modell", "Discover a prompt": "Oppdag en prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Oppdag, last ned og utforsk egendefinerte prompts", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Oppdag, last ned og utforsk modellforhåndsinnstillinger", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/nl-NL/translation.json b/src/lib/i18n/locales/nl-NL/translation.json index b8d16e428a..d51f7b590b 100644 --- a/src/lib/i18n/locales/nl-NL/translation.json +++ b/src/lib/i18n/locales/nl-NL/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}} verwijderd", "Description": "Beschrijving", "Didn't fully follow instructions": "Ik heb niet alle instructies volgt", + "Discover a function": "", "Discover a model": "Ontdek een model", "Discover a prompt": "Ontdek een prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Ontdek, download en verken aangepaste prompts", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Ontdek, download en verken model presets", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/pa-IN/translation.json b/src/lib/i18n/locales/pa-IN/translation.json index e20a615819..03c34cbb5b 100644 --- a/src/lib/i18n/locales/pa-IN/translation.json +++ b/src/lib/i18n/locales/pa-IN/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "ਮਿਟਾ ਦਿੱਤਾ ਗਿਆ {{name}}", "Description": "ਵਰਣਨਾ", "Didn't fully follow instructions": "ਹਦਾਇਤਾਂ ਨੂੰ ਪੂਰੀ ਤਰ੍ਹਾਂ ਫਾਲੋ ਨਹੀਂ ਕੀਤਾ", + "Discover a function": "", "Discover a model": "ਇੱਕ ਮਾਡਲ ਲੱਭੋ", "Discover a prompt": "ਇੱਕ ਪ੍ਰੰਪਟ ਖੋਜੋ", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "ਕਸਟਮ ਪ੍ਰੰਪਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "ਮਾਡਲ ਪ੍ਰੀਸੈਟਾਂ ਨੂੰ ਖੋਜੋ, ਡਾਊਨਲੋਡ ਕਰੋ ਅਤੇ ਪੜਚੋਲ ਕਰੋ", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/pl-PL/translation.json b/src/lib/i18n/locales/pl-PL/translation.json index efae236402..c57a1abe6d 100644 --- a/src/lib/i18n/locales/pl-PL/translation.json +++ b/src/lib/i18n/locales/pl-PL/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Usunięto {{name}}", "Description": "Opis", "Didn't fully follow instructions": "Nie postępował zgodnie z instrukcjami", + "Discover a function": "", "Discover a model": "Odkryj model", "Discover a prompt": "Odkryj prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Odkryj, pobierz i eksploruj niestandardowe prompty", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Odkryj, pobierz i eksploruj ustawienia modeli", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/pt-BR/translation.json b/src/lib/i18n/locales/pt-BR/translation.json index 13bc77bfa5..669209a5aa 100644 --- a/src/lib/i18n/locales/pt-BR/translation.json +++ b/src/lib/i18n/locales/pt-BR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Excluído {{nome}}", "Description": "Descrição", "Didn't fully follow instructions": "Não seguiu instruções com precisão", + "Discover a function": "", "Discover a model": "Descubra um modelo", "Discover a prompt": "Descobrir um prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Descubra, baixe e explore prompts personalizados", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Descubra, baixe e explore predefinições de modelo", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index 45ca4d9d6f..d98c002761 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Apagado {{name}}", "Description": "Descrição", "Didn't fully follow instructions": "Não seguiu instruções com precisão", + "Discover a function": "", "Discover a model": "Descubra um modelo", "Discover a prompt": "Descobrir um prompt", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Descubra, descarregue e explore prompts personalizados", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Descubra, descarregue e explore predefinições de modelo", "Dismissible": "Dispensável", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/ru-RU/translation.json b/src/lib/i18n/locales/ru-RU/translation.json index 9e8e3a44cb..e8e3431b8f 100644 --- a/src/lib/i18n/locales/ru-RU/translation.json +++ b/src/lib/i18n/locales/ru-RU/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Удалено {{name}}", "Description": "Описание", "Didn't fully follow instructions": "Не полностью следул инструкциям", + "Discover a function": "", "Discover a model": "Откройте для себя модель", "Discover a prompt": "Найти промт", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Находите, загружайте и исследуйте настраиваемые промты", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Находите, загружайте и исследуйте предустановки модели", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/sr-RS/translation.json b/src/lib/i18n/locales/sr-RS/translation.json index d0e395c232..f4483c7236 100644 --- a/src/lib/i18n/locales/sr-RS/translation.json +++ b/src/lib/i18n/locales/sr-RS/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Избрисано {{наме}}", "Description": "Опис", "Didn't fully follow instructions": "Упутства нису праћена у потпуности", + "Discover a function": "", "Discover a model": "Откријте модел", "Discover a prompt": "Откриј упит", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Откријте, преузмите и истражите прилагођене упите", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Откријте, преузмите и истражите образце модела", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/sv-SE/translation.json b/src/lib/i18n/locales/sv-SE/translation.json index e20551de50..d55eedaef9 100644 --- a/src/lib/i18n/locales/sv-SE/translation.json +++ b/src/lib/i18n/locales/sv-SE/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Borttagen {{name}}", "Description": "Beskrivning", "Didn't fully follow instructions": "Följde inte instruktionerna", + "Discover a function": "", "Discover a model": "Upptäck en modell", "Discover a prompt": "Upptäck en instruktion", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Upptäck, ladda ner och utforska anpassade instruktioner", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Upptäck, ladda ner och utforska modellförinställningar", "Dismissible": "Kan stängas", "Display Emoji in Call": "Visa Emoji under samtal", diff --git a/src/lib/i18n/locales/tk-TW/translation.json b/src/lib/i18n/locales/tk-TW/translation.json index 707630dbcf..af9d122bb8 100644 --- a/src/lib/i18n/locales/tk-TW/translation.json +++ b/src/lib/i18n/locales/tk-TW/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "", "Description": "", "Didn't fully follow instructions": "", + "Discover a function": "", "Discover a model": "", "Discover a prompt": "", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index 41f39592ee..de284a4c84 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "{{name}} silindi", "Description": "Açıklama", "Didn't fully follow instructions": "Talimatları tam olarak takip etmedi", + "Discover a function": "", "Discover a model": "Bir model keşfedin", "Discover a prompt": "Bir prompt keşfedin", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Özel promptları keşfedin, indirin ve inceleyin", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Model ön ayarlarını keşfedin, indirin ve inceleyin", "Dismissible": "", "Display Emoji in Call": "", diff --git a/src/lib/i18n/locales/uk-UA/translation.json b/src/lib/i18n/locales/uk-UA/translation.json index ba33b445eb..814f657b52 100644 --- a/src/lib/i18n/locales/uk-UA/translation.json +++ b/src/lib/i18n/locales/uk-UA/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Видалено {{name}}", "Description": "Опис", "Didn't fully follow instructions": "Не повністю дотримувалися інструкцій", + "Discover a function": "", "Discover a model": "Знайдіть модель", "Discover a prompt": "Знайти промт", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Знайдіть, завантажте та досліджуйте налаштовані промти", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Знайдіть, завантажте та досліджуйте налаштовані налаштування моделі", "Dismissible": "Неприйнятно", "Display Emoji in Call": "Відображати емодзі у викликах", diff --git a/src/lib/i18n/locales/vi-VN/translation.json b/src/lib/i18n/locales/vi-VN/translation.json index 18558a9df2..60db86300e 100644 --- a/src/lib/i18n/locales/vi-VN/translation.json +++ b/src/lib/i18n/locales/vi-VN/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "Đã xóa {{name}}", "Description": "Mô tả", "Didn't fully follow instructions": "Không tuân theo chỉ dẫn một cách đầy đủ", + "Discover a function": "", "Discover a model": "Khám phá model", "Discover a prompt": "Khám phá thêm prompt mới", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "Tìm kiếm, tải về và khám phá thêm các prompt tùy chỉnh", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "Tìm kiếm, tải về và khám phá thêm các thiết lập mô hình sẵn", "Dismissible": "Có thể loại bỏ", "Display Emoji in Call": "Hiển thị Emoji trong cuộc gọi", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 6f2b5ce78b..28e68e2e69 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "已删除 {{name}}", "Description": "描述", "Didn't fully follow instructions": "没有完全遵照指示", + "Discover a function": "", "Discover a model": "发现更多模型", "Discover a prompt": "发现更多提示词", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "发现、下载并探索更多自定义提示词", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "发现、下载并探索更多模型预设", "Dismissible": "是否可关闭", "Display Emoji in Call": "在通话中显示 Emoji 表情符号", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index 7cc074dba6..9c7d53458d 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -165,9 +165,13 @@ "Deleted {{name}}": "已刪除 {{name}}", "Description": "描述", "Didn't fully follow instructions": "未完全遵循指示", + "Discover a function": "", "Discover a model": "發現新模型", "Discover a prompt": "發現新提示詞", + "Discover a tool": "", + "Discover, download, and explore custom functions": "", "Discover, download, and explore custom prompts": "發現、下載並探索自訂提示詞", + "Discover, download, and explore custom tools": "", "Discover, download, and explore model presets": "發現、下載並探索模型預設值", "Dismissible": "可忽略", "Display Emoji in Call": "在呼叫中顯示表情符號", From e52ed258f08954bbfb826efc175f3855ef1c963e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 17:18:36 -0700 Subject: [PATCH 40/71] refac: styling --- src/lib/components/admin/SettingsModal.svelte | 43 --- .../Playground.svelte | 0 src/lib/components/workspace/Functions.svelte | 2 +- src/lib/components/workspace/Prompts.svelte | 2 +- src/lib/components/workspace/Tools.svelte | 2 +- .../components/workspace/ValvesModal.svelte | 337 ++++++++++++++++++ src/routes/(app)/playground/+page.svelte | 2 +- 7 files changed, 341 insertions(+), 47 deletions(-) delete mode 100644 src/lib/components/admin/SettingsModal.svelte rename src/lib/components/{workspace => playground}/Playground.svelte (100%) create mode 100644 src/lib/components/workspace/ValvesModal.svelte diff --git a/src/lib/components/admin/SettingsModal.svelte b/src/lib/components/admin/SettingsModal.svelte deleted file mode 100644 index 0ed32e5515..0000000000 --- a/src/lib/components/admin/SettingsModal.svelte +++ /dev/null @@ -1,43 +0,0 @@ - - - -
-
-
{$i18n.t('Admin Settings')}
- -
-
-
diff --git a/src/lib/components/workspace/Playground.svelte b/src/lib/components/playground/Playground.svelte similarity index 100% rename from src/lib/components/workspace/Playground.svelte rename to src/lib/components/playground/Playground.svelte diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index a7de54f911..ffa5c8b4bd 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -168,7 +168,7 @@
-
+ -
+ -
+
+ import { toast } from 'svelte-sonner'; + import { createEventDispatcher } from 'svelte'; + import { onMount, getContext } from 'svelte'; + import { addUser } from '$lib/apis/auths'; + + import Modal from '../common/Modal.svelte'; + import { WEBUI_BASE_URL } from '$lib/constants'; + + const i18n = getContext('i18n'); + const dispatch = createEventDispatcher(); + + export let show = false; + + let loading = false; + let tab = ''; + let inputFiles; + + let _user = { + name: '', + email: '', + password: '', + role: 'user' + }; + + $: if (show) { + _user = { + name: '', + email: '', + password: '', + role: 'user' + }; + } + + const submitHandler = async () => { + const stopLoading = () => { + dispatch('save'); + loading = false; + }; + + if (tab === '') { + loading = true; + + const res = await addUser( + localStorage.token, + _user.name, + _user.email, + _user.password, + _user.role + ).catch((error) => { + toast.error(error); + }); + + if (res) { + stopLoading(); + show = false; + } + } else { + if (inputFiles) { + loading = true; + + const file = inputFiles[0]; + const reader = new FileReader(); + + reader.onload = async (e) => { + const csv = e.target.result; + const rows = csv.split('\n'); + + let userCount = 0; + + for (const [idx, row] of rows.entries()) { + const columns = row.split(',').map((col) => col.trim()); + console.log(idx, columns); + + if (idx > 0) { + if ( + columns.length === 4 && + ['admin', 'user', 'pending'].includes(columns[3].toLowerCase()) + ) { + const res = await addUser( + localStorage.token, + columns[0], + columns[1], + columns[2], + columns[3].toLowerCase() + ).catch((error) => { + toast.error(`Row ${idx + 1}: ${error}`); + return null; + }); + + if (res) { + userCount = userCount + 1; + } + } else { + toast.error(`Row ${idx + 1}: invalid format.`); + } + } + } + + toast.success(`Successfully imported ${userCount} users.`); + inputFiles = null; + const uploadInputElement = document.getElementById('upload-user-csv-input'); + + if (uploadInputElement) { + uploadInputElement.value = null; + } + + stopLoading(); + }; + + reader.readAsText(file); + } else { + toast.error($i18n.t('File not found.')); + } + } + }; + + + +
+
+
{$i18n.t('Add User')}
+ +
+ +
+
+ + + diff --git a/src/routes/(app)/playground/+page.svelte b/src/routes/(app)/playground/+page.svelte index 40c1ce4d77..32e6e25bee 100644 --- a/src/routes/(app)/playground/+page.svelte +++ b/src/routes/(app)/playground/+page.svelte @@ -1,7 +1,7 @@
Date: Sun, 23 Jun 2024 17:22:11 -0700 Subject: [PATCH 41/71] chore: requirements --- backend/requirements.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/backend/requirements.txt b/backend/requirements.txt index be0e32c7d2..90f6548e77 100644 --- a/backend/requirements.txt +++ b/backend/requirements.txt @@ -17,7 +17,9 @@ peewee-migrate==1.12.2 psycopg2-binary==2.9.9 PyMySQL==1.1.1 bcrypt==4.1.3 - +SQLAlchemy +pymongo +redis boto3==1.34.110 argon2-cffi==23.1.0 From 5d7de927e52c26bd92bf946a6bdaf5d2caa012b8 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 17:34:25 -0700 Subject: [PATCH 42/71] enh: valve field desc support --- src/lib/components/chat/Settings/Valves.svelte | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/lib/components/chat/Settings/Valves.svelte b/src/lib/components/chat/Settings/Valves.svelte index 115dd3bd15..1001ddb28f 100644 --- a/src/lib/components/chat/Settings/Valves.svelte +++ b/src/lib/components/chat/Settings/Valves.svelte @@ -203,7 +203,7 @@
{#if (valves[property] ?? null) !== null} -
+
{/if} + + {#if (valvesSpec.properties[property]?.description ?? null) !== null} +
+ {valvesSpec.properties[property].description} +
+ {/if}
{/each} {:else} From fc2001da8302e49c2f3438ded6e8a5b548eeb471 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 17:41:59 -0700 Subject: [PATCH 43/71] refac: styling --- src/lib/components/workspace/Functions.svelte | 24 +++++++++++++----- .../workspace/Functions/FunctionMenu.svelte | 25 +++++++++++++++++++ src/lib/components/workspace/Tools.svelte | 19 +++++++++----- .../workspace/Tools/ToolMenu.svelte | 25 +++++++++++++++++++ .../components/workspace/ValvesModal.svelte | 2 +- 5 files changed, 82 insertions(+), 13 deletions(-) diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index ffa5c8b4bd..07c89eff83 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -22,6 +22,7 @@ import { getModels } from '$lib/apis'; import FunctionMenu from './Functions/FunctionMenu.svelte'; import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; + import Switch from '../common/Switch.svelte'; const i18n = getContext('i18n'); @@ -169,11 +170,10 @@
- - + { + goto(`/workspace/functions/edit?id=${encodeURIComponent(func.id)}`); + }} shareHandler={() => { shareHandler(func); }} @@ -214,6 +222,10 @@ + +
+ +
{/each} diff --git a/src/lib/components/workspace/Functions/FunctionMenu.svelte b/src/lib/components/workspace/Functions/FunctionMenu.svelte index 9a4177b1ed..93a26b118d 100644 --- a/src/lib/components/workspace/Functions/FunctionMenu.svelte +++ b/src/lib/components/workspace/Functions/FunctionMenu.svelte @@ -15,6 +15,7 @@ const i18n = getContext('i18n'); + export let editHandler: Function; export let shareHandler: Function; export let cloneHandler: Function; export let exportHandler: Function; @@ -44,6 +45,30 @@ align="start" transition={flyAndScale} > + { + editHandler(); + }} + > + + + + +
{$i18n.t('Edit')}
+
+ { diff --git a/src/lib/components/workspace/Tools.svelte b/src/lib/components/workspace/Tools.svelte index c0ac5b6057..184f5942a1 100644 --- a/src/lib/components/workspace/Tools.svelte +++ b/src/lib/components/workspace/Tools.svelte @@ -165,11 +165,10 @@
- - + { + goto(`/workspace/tools/edit?id=${encodeURIComponent(tool.id)}`); + }} shareHandler={() => { shareHandler(tool); }} diff --git a/src/lib/components/workspace/Tools/ToolMenu.svelte b/src/lib/components/workspace/Tools/ToolMenu.svelte index 9a4177b1ed..93a26b118d 100644 --- a/src/lib/components/workspace/Tools/ToolMenu.svelte +++ b/src/lib/components/workspace/Tools/ToolMenu.svelte @@ -15,6 +15,7 @@ const i18n = getContext('i18n'); + export let editHandler: Function; export let shareHandler: Function; export let cloneHandler: Function; export let exportHandler: Function; @@ -44,6 +45,30 @@ align="start" transition={flyAndScale} > + { + editHandler(); + }} + > + + + + +
{$i18n.t('Edit')}
+
+ { diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/ValvesModal.svelte index 8538ba04a8..58434a5597 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/ValvesModal.svelte @@ -119,7 +119,7 @@
-
{$i18n.t('Add User')}
+
{$i18n.t('Valves')}
-
+
From 120b1857b21ea25f7a2dddc5e6e288f3ce0a6ebe Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 18:05:33 -0700 Subject: [PATCH 45/71] enh: valves --- .../016_add_valves_and_is_active.py | 50 +++++++++++++++++++ backend/apps/webui/models/functions.py | 8 +++ backend/apps/webui/models/tools.py | 26 ++++++++++ src/routes/(app)/workspace/+layout.svelte | 2 +- 4 files changed, 85 insertions(+), 1 deletion(-) create mode 100644 backend/apps/webui/internal/migrations/016_add_valves_and_is_active.py diff --git a/backend/apps/webui/internal/migrations/016_add_valves_and_is_active.py b/backend/apps/webui/internal/migrations/016_add_valves_and_is_active.py new file mode 100644 index 0000000000..e3af521b7e --- /dev/null +++ b/backend/apps/webui/internal/migrations/016_add_valves_and_is_active.py @@ -0,0 +1,50 @@ +"""Peewee migrations -- 009_add_models.py. + +Some examples (model - class or model name):: + + > Model = migrator.orm['table_name'] # Return model in current state by name + > Model = migrator.ModelClass # Return model in current state by name + + > migrator.sql(sql) # Run custom SQL + > migrator.run(func, *args, **kwargs) # Run python function with the given args + > migrator.create_model(Model) # Create a model (could be used as decorator) + > migrator.remove_model(model, cascade=True) # Remove a model + > migrator.add_fields(model, **fields) # Add fields to a model + > migrator.change_fields(model, **fields) # Change fields + > migrator.remove_fields(model, *field_names, cascade=True) + > migrator.rename_field(model, old_field_name, new_field_name) + > migrator.rename_table(model, new_table_name) + > migrator.add_index(model, *col_names, unique=False) + > migrator.add_not_null(model, *field_names) + > migrator.add_default(model, field_name, default) + > migrator.add_constraint(model, name, sql) + > migrator.drop_index(model, *col_names) + > migrator.drop_not_null(model, *field_names) + > migrator.drop_constraints(model, *constraints) + +""" + +from contextlib import suppress + +import peewee as pw +from peewee_migrate import Migrator + + +with suppress(ImportError): + import playhouse.postgres_ext as pw_pext + + +def migrate(migrator: Migrator, database: pw.Database, *, fake=False): + """Write your migrations here.""" + + migrator.add_fields("tool", valves=pw.TextField(null=True)) + migrator.add_fields("function", valves=pw.TextField(null=True)) + migrator.add_fields("function", is_active=pw.BooleanField(default=False)) + + +def rollback(migrator: Migrator, database: pw.Database, *, fake=False): + """Write your rollback migrations here.""" + + migrator.remove_fields("tool", "valves") + migrator.remove_fields("function", "valves") + migrator.remove_fields("function", "is_active") diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index cd6320f953..779eef9efd 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -28,6 +28,8 @@ class Function(Model): type = TextField() content = TextField() meta = JSONField() + valves = JSONField() + is_active = BooleanField(default=False) updated_at = BigIntegerField() created_at = BigIntegerField() @@ -46,6 +48,7 @@ class FunctionModel(BaseModel): type: str content: str meta: FunctionMeta + is_active: bool updated_at: int # timestamp in epoch created_at: int # timestamp in epoch @@ -61,6 +64,7 @@ class FunctionResponse(BaseModel): type: str name: str meta: FunctionMeta + is_active: bool updated_at: int # timestamp in epoch created_at: int # timestamp in epoch @@ -72,6 +76,10 @@ class FunctionForm(BaseModel): meta: FunctionMeta +class FunctionValves(BaseModel): + valves: Optional[dict] = None + + class FunctionsTable: def __init__(self, db): self.db = db diff --git a/backend/apps/webui/models/tools.py b/backend/apps/webui/models/tools.py index ab322ac14a..0f5755e39f 100644 --- a/backend/apps/webui/models/tools.py +++ b/backend/apps/webui/models/tools.py @@ -28,6 +28,7 @@ class Tool(Model): content = TextField() specs = JSONField() meta = JSONField() + valves = JSONField() updated_at = BigIntegerField() created_at = BigIntegerField() @@ -71,6 +72,10 @@ class ToolForm(BaseModel): meta: ToolMeta +class ToolValves(BaseModel): + valves: Optional[dict] = None + + class ToolsTable: def __init__(self, db): self.db = db @@ -109,6 +114,27 @@ class ToolsTable: def get_tools(self) -> List[ToolModel]: return [ToolModel(**model_to_dict(tool)) for tool in Tool.select()] + def get_tool_valves_by_id(self, id: str) -> Optional[ToolValves]: + try: + tool = Tool.get(Tool.id == id) + return ToolValves(**model_to_dict(tool)) + except Exception as e: + print(f"An error occurred: {e}") + return None + + def update_tool_valves_by_id(self, id: str, valves: dict) -> Optional[ToolValves]: + try: + query = Tool.update( + **{"valves": valves}, + updated_at=int(time.time()), + ).where(Tool.id == id) + query.execute() + + tool = Tool.get(Tool.id == id) + return ToolValves(**model_to_dict(tool)) + except: + return None + def get_user_valves_by_id_and_user_id( self, id: str, user_id: str ) -> Optional[dict]: diff --git a/src/routes/(app)/workspace/+layout.svelte b/src/routes/(app)/workspace/+layout.svelte index 46e0f63c4d..794bd7ed53 100644 --- a/src/routes/(app)/workspace/+layout.svelte +++ b/src/routes/(app)/workspace/+layout.svelte @@ -9,7 +9,7 @@ const i18n = getContext('i18n'); onMount(async () => { - functions.set(await getFunctions(localStorage.token)); + // functions.set(await getFunctions(localStorage.token)); }); From 3034f3d310f22a992b26be2aed5ba199a61f24be Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 18:06:41 -0700 Subject: [PATCH 46/71] refac: styling --- src/lib/components/chat/Settings/Valves.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/Settings/Valves.svelte b/src/lib/components/chat/Settings/Valves.svelte index 1001ddb28f..d834bd014a 100644 --- a/src/lib/components/chat/Settings/Valves.svelte +++ b/src/lib/components/chat/Settings/Valves.svelte @@ -203,7 +203,7 @@
{#if (valves[property] ?? null) !== null} -
+
Date: Sun, 23 Jun 2024 18:34:42 -0700 Subject: [PATCH 47/71] feat: function toggle support --- backend/apps/webui/main.py | 2 +- backend/apps/webui/models/functions.py | 60 ++++- backend/apps/webui/routers/functions.py | 77 ++++++ backend/apps/webui/routers/tools.py | 50 ++++ backend/main.py | 1 - src/lib/apis/functions/index.ts | 99 +++++++ src/lib/components/workspace/Functions.svelte | 10 +- .../components/workspace/ValvesModal.svelte | 248 ++++-------------- 8 files changed, 338 insertions(+), 209 deletions(-) diff --git a/backend/apps/webui/main.py b/backend/apps/webui/main.py index a9f7fb2866..a8f45aff0b 100644 --- a/backend/apps/webui/main.py +++ b/backend/apps/webui/main.py @@ -103,7 +103,7 @@ async def get_status(): async def get_pipe_models(): - pipes = Functions.get_functions_by_type("pipe") + pipes = Functions.get_functions_by_type("pipe", active_only=True) pipe_models = [] for pipe in pipes: diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index 779eef9efd..6741f2d10e 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -48,7 +48,7 @@ class FunctionModel(BaseModel): type: str content: str meta: FunctionMeta - is_active: bool + is_active: bool = False updated_at: int # timestamp in epoch created_at: int # timestamp in epoch @@ -115,16 +115,56 @@ class FunctionsTable: except: return None - def get_functions(self) -> List[FunctionModel]: - return [ - FunctionModel(**model_to_dict(function)) for function in Function.select() - ] + def get_functions(self, active_only=False) -> List[FunctionModel]: + if active_only: + return [ + FunctionModel(**model_to_dict(function)) + for function in Function.select().where(Function.is_active == True) + ] + else: + return [ + FunctionModel(**model_to_dict(function)) + for function in Function.select() + ] - def get_functions_by_type(self, type: str) -> List[FunctionModel]: - return [ - FunctionModel(**model_to_dict(function)) - for function in Function.select().where(Function.type == type) - ] + def get_functions_by_type( + self, type: str, active_only=False + ) -> List[FunctionModel]: + if active_only: + return [ + FunctionModel(**model_to_dict(function)) + for function in Function.select().where( + Function.type == type, Function.is_active == True + ) + ] + else: + return [ + FunctionModel(**model_to_dict(function)) + for function in Function.select().where(Function.type == type) + ] + + def get_function_valves_by_id(self, id: str) -> Optional[FunctionValves]: + try: + function = Function.get(Function.id == id) + return FunctionValves(**model_to_dict(function)) + except Exception as e: + print(f"An error occurred: {e}") + return None + + def update_function_valves_by_id( + self, id: str, valves: dict + ) -> Optional[FunctionValves]: + try: + query = Function.update( + **{"valves": valves}, + updated_at=int(time.time()), + ).where(Function.id == id) + query.execute() + + function = Function.get(Function.id == id) + return FunctionValves(**model_to_dict(function)) + except: + return None def get_user_valves_by_id_and_user_id( self, id: str, user_id: str diff --git a/backend/apps/webui/routers/functions.py b/backend/apps/webui/routers/functions.py index acf1894fdb..8c6454eac0 100644 --- a/backend/apps/webui/routers/functions.py +++ b/backend/apps/webui/routers/functions.py @@ -117,6 +117,56 @@ async def get_function_by_id(id: str, user=Depends(get_admin_user)): ) +############################ +# GetFunctionValves +############################ + + +@router.get("/id/{id}/valves", response_model=Optional[dict]) +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 + except Exception as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + +############################ +# UpdateToolValves +############################ + + +@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) +): + 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: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + ############################ # FunctionUserValves ############################ @@ -204,6 +254,33 @@ async def update_function_user_valves_by_id( ) +############################ +# ToggleFunctionById +############################ + + +@router.post("/id/{id}/toggle", response_model=Optional[FunctionModel]) +async def toggle_function_by_id(id: str, user=Depends(get_admin_user)): + function = Functions.get_function_by_id(id) + if function: + function = Functions.update_function_by_id( + id, {"is_active": not function.is_active} + ) + + if function: + return function + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT("Error updating function"), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + ############################ # UpdateFunctionById ############################ diff --git a/backend/apps/webui/routers/tools.py b/backend/apps/webui/routers/tools.py index c71d2f01c7..7988acc868 100644 --- a/backend/apps/webui/routers/tools.py +++ b/backend/apps/webui/routers/tools.py @@ -123,6 +123,56 @@ async def get_toolkit_by_id(id: str, user=Depends(get_admin_user)): ) +############################ +# GetToolValves +############################ + + +@router.get("/id/{id}/valves", response_model=Optional[dict]) +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 + except Exception as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + +############################ +# UpdateToolValves +############################ + + +@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) +): + 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: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + ############################ # ToolUserValves ############################ diff --git a/backend/main.py b/backend/main.py index 7dda4e557b..02552f2097 100644 --- a/backend/main.py +++ b/backend/main.py @@ -863,7 +863,6 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u pipe = model.get("pipe") if pipe: - async def job(): pipe_id = form_data["model"] if "." in pipe_id: diff --git a/src/lib/apis/functions/index.ts b/src/lib/apis/functions/index.ts index 530702a3e1..c8607b091f 100644 --- a/src/lib/apis/functions/index.ts +++ b/src/lib/apis/functions/index.ts @@ -192,6 +192,105 @@ export const deleteFunctionById = async (token: string, id: string) => { return res; }; +export const toggleFunctionById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/id/${id}/toggle`, { + method: 'POST', + 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 getFunctionValvesById = async (token: string, id: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/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 updateFunctionValvesById = async (token: string, id: string, valves: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/functions/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 b389d6eab7..fc8e7a4515 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -13,7 +13,8 @@ deleteFunctionById, exportFunctions, getFunctionById, - getFunctions + getFunctions, + toggleFunctionById } from '$lib/apis/functions'; import ArrowDownTray from '../icons/ArrowDownTray.svelte'; @@ -224,7 +225,12 @@
- + { + toggleFunctionById(localStorage.token, func.id); + }} + />
diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/ValvesModal.svelte index 58434a5597..f67d948a90 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/ValvesModal.svelte @@ -5,16 +5,16 @@ import { addUser } from '$lib/apis/auths'; import Modal from '../common/Modal.svelte'; - import { WEBUI_BASE_URL } from '$lib/constants'; const i18n = getContext('i18n'); const dispatch = createEventDispatcher(); export let show = false; + export let type = 'tool'; + export let id = null; + let loading = false; - let tab = ''; - let inputFiles; let _user = { name: '', @@ -23,96 +23,11 @@ role: 'user' }; - $: if (show) { - _user = { - name: '', - email: '', - password: '', - role: 'user' - }; - } - const submitHandler = async () => { const stopLoading = () => { dispatch('save'); loading = false; }; - - if (tab === '') { - loading = true; - - const res = await addUser( - localStorage.token, - _user.name, - _user.email, - _user.password, - _user.role - ).catch((error) => { - toast.error(error); - }); - - if (res) { - stopLoading(); - show = false; - } - } else { - if (inputFiles) { - loading = true; - - const file = inputFiles[0]; - const reader = new FileReader(); - - reader.onload = async (e) => { - const csv = e.target.result; - const rows = csv.split('\n'); - - let userCount = 0; - - for (const [idx, row] of rows.entries()) { - const columns = row.split(',').map((col) => col.trim()); - console.log(idx, columns); - - if (idx > 0) { - if ( - columns.length === 4 && - ['admin', 'user', 'pending'].includes(columns[3].toLowerCase()) - ) { - const res = await addUser( - localStorage.token, - columns[0], - columns[1], - columns[2], - columns[3].toLowerCase() - ).catch((error) => { - toast.error(`Row ${idx + 1}: ${error}`); - return null; - }); - - if (res) { - userCount = userCount + 1; - } - } else { - toast.error(`Row ${idx + 1}: invalid format.`); - } - } - } - - toast.success(`Successfully imported ${userCount} users.`); - inputFiles = null; - const uploadInputElement = document.getElementById('upload-user-csv-input'); - - if (uploadInputElement) { - uploadInputElement.value = null; - } - - stopLoading(); - }; - - reader.readAsText(file); - } else { - toast.error($i18n.t('File not found.')); - } - } }; @@ -147,126 +62,69 @@ submitHandler(); }} > -
- - - -
- {#if tab === ''} -
-
{$i18n.t('Role')}
+
+
{$i18n.t('Role')}
-
- -
+
+
+
-
-
{$i18n.t('Name')}
+
+
{$i18n.t('Name')}
-
- -
+
+
+
-
+
-
-
{$i18n.t('Email')}
+
+
{$i18n.t('Email')}
-
- -
+
+
+
-
-
{$i18n.t('Password')}
+
+
{$i18n.t('Password')}
-
- -
+
+
- {:else if tab === 'import'} -
-
- - - -
- -
- ⓘ {$i18n.t( - 'Ensure your CSV file includes 4 columns in this order: Name, Email, Password, Role.' - )} - - {$i18n.t('Click here to download user import template file.')} - -
-
- {/if} +
From 3a629ffe0009cf3cbceccc6af53f0da03cbeb9c2 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 18:39:27 -0700 Subject: [PATCH 48/71] feat: global filter --- backend/main.py | 112 ++++++++++-------- src/lib/components/workspace/Functions.svelte | 3 +- 2 files changed, 62 insertions(+), 53 deletions(-) diff --git a/backend/main.py b/backend/main.py index 02552f2097..2a44d20293 100644 --- a/backend/main.py +++ b/backend/main.py @@ -376,70 +376,77 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): ) model = app.state.MODELS[model_id] + filter_ids = [ + function.id + for function in Functions.get_functions_by_type( + "filter", active_only=True + ) + ] # Check if the model has any filters if "info" in model and "meta" in model["info"]: - for filter_id in model["info"]["meta"].get("filterIds", []): - filter = Functions.get_function_by_id(filter_id) - if filter: - if filter_id in webui_app.state.FUNCTIONS: - function_module = webui_app.state.FUNCTIONS[filter_id] - else: - function_module, function_type = load_function_module_by_id( - filter_id - ) - webui_app.state.FUNCTIONS[filter_id] = function_module + filter_ids.extend(model["info"]["meta"].get("filterIds", [])) + filter_ids = list(set(filter_ids)) - # Check if the function has a file_handler variable - if hasattr(function_module, "file_handler"): - skip_files = function_module.file_handler + for filter_id in filter_ids: + filter = Functions.get_function_by_id(filter_id) + if filter: + if filter_id in webui_app.state.FUNCTIONS: + function_module = webui_app.state.FUNCTIONS[filter_id] + else: + function_module, function_type = load_function_module_by_id( + filter_id + ) + webui_app.state.FUNCTIONS[filter_id] = function_module - try: - if hasattr(function_module, "inlet"): - inlet = function_module.inlet + # Check if the function has a file_handler variable + if hasattr(function_module, "file_handler"): + skip_files = function_module.file_handler - # Get the signature of the function - sig = inspect.signature(inlet) - params = {"body": data} + try: + if hasattr(function_module, "inlet"): + inlet = function_module.inlet - if "__user__" in sig.parameters: - __user__ = { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - } + # Get the signature of the function + sig = inspect.signature(inlet) + params = {"body": data} - try: - if hasattr(function_module, "UserValves"): - __user__["valves"] = ( - function_module.UserValves( - **Functions.get_user_valves_by_id_and_user_id( - filter_id, user.id - ) - ) + if "__user__" in sig.parameters: + __user__ = { + "id": user.id, + "email": user.email, + "name": user.name, + "role": user.role, + } + + try: + if hasattr(function_module, "UserValves"): + __user__["valves"] = function_module.UserValves( + **Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id ) - except Exception as e: - print(e) + ) + except Exception as e: + print(e) - params = {**params, "__user__": __user__} + params = {**params, "__user__": __user__} - if "__id__" in sig.parameters: - params = { - **params, - "__id__": filter_id, - } + if "__id__" in sig.parameters: + params = { + **params, + "__id__": filter_id, + } - if inspect.iscoroutinefunction(inlet): - data = await inlet(**params) - else: - data = inlet(**params) + if inspect.iscoroutinefunction(inlet): + data = await inlet(**params) + else: + data = inlet(**params) - except Exception as e: - print(f"Error: {e}") - return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, - content={"detail": str(e)}, - ) + except Exception as e: + print(f"Error: {e}") + return JSONResponse( + status_code=status.HTTP_400_BAD_REQUEST, + content={"detail": str(e)}, + ) # Set the task model task_model_id = data["model"] @@ -863,6 +870,7 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u pipe = model.get("pipe") if pipe: + async def job(): pipe_id = form_data["model"] if "." in pipe_id: diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index fc8e7a4515..75e0ce4ffa 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -227,8 +227,9 @@
{ + on:change={async (e) => { toggleFunctionById(localStorage.token, func.id); + models.set(await getModels(localStorage.token)); }} />
From 627705a347bcddb6893b3a1b23cda6636d22d24e Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:02:27 -0700 Subject: [PATCH 49/71] 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 8c6454eac0..4da68a0527 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 7988acc868..7ddcf3ed9b 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 c8607b091f..2d5ad16b75 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 25d543febb..28e8dde86c 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 75e0ce4ffa..fb92cc32d9 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 @@
+ + { diff --git a/src/lib/components/workspace/Tools.svelte b/src/lib/components/workspace/Tools.svelte index 184f5942a1..687117f996 100644 --- a/src/lib/components/workspace/Tools.svelte +++ b/src/lib/components/workspace/Tools.svelte @@ -20,6 +20,7 @@ import ConfirmDialog from '../common/ConfirmDialog.svelte'; import ToolMenu from './Tools/ToolMenu.svelte'; import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; + import ValvesModal from './ValvesModal.svelte'; const i18n = getContext('i18n'); @@ -29,6 +30,9 @@ let showConfirm = false; let query = ''; + let showValvesModal = false; + let selectedTool = null; + const shareHandler = async (tool) => { console.log(tool); }; @@ -169,6 +173,10 @@
+ + { diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/ValvesModal.svelte index f67d948a90..8c15cdc646 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/ValvesModal.svelte @@ -5,6 +5,13 @@ import { addUser } from '$lib/apis/auths'; import Modal from '../common/Modal.svelte'; + import { + getFunctionValvesById, + getFunctionValvesSpecById, + updateFunctionValvesById + } from '$lib/apis/functions'; + import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools'; + import Spinner from '../common/Spinner.svelte'; const i18n = getContext('i18n'); const dispatch = createEventDispatcher(); @@ -14,21 +21,57 @@ export let type = 'tool'; export let id = null; + let saving = false; let loading = false; - let _user = { - name: '', - email: '', - password: '', - role: 'user' - }; + let valvesSpec = null; + let valves = {}; const submitHandler = async () => { - const stopLoading = () => { - dispatch('save'); - loading = false; - }; + saving = true; + + 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 (res) { + toast.success('Valves updated successfully'); + } + + saving = false; }; + + const initHandler = async () => { + loading = true; + 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); + } + + if (!valves) { + valves = {}; + } + + loading = false; + }; + + $: if (show) { + initHandler(); + } @@ -63,81 +106,81 @@ }} >
-
-
{$i18n.t('Role')}
+ {#if !loading} + {#if valvesSpec} + {#each Object.keys(valvesSpec.properties) as property, idx} +
+
+
+ {valvesSpec.properties[property].title} -
- -
-
+ {#if (valvesSpec?.required ?? []).includes(property)} + *required + {/if} +
-
-
{$i18n.t('Name')}
+ +
-
- -
-
+ {#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}
diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/ValvesModal.svelte index 9a3bc03a91..c6d1395070 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/ValvesModal.svelte @@ -149,7 +149,7 @@ placeholder={valvesSpec.properties[property].title} bind:value={valves[property]} autocomplete="off" - required={(valvesSpec?.required ?? []).includes(property)} + required />
From 2eb15ea1fc1b33477a4aad130ccd03e5d4c4f9b6 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:28:33 -0700 Subject: [PATCH 55/71] feat: SAFE_MODE --- backend/apps/webui/models/functions.py | 13 +++++++++++++ backend/config.py | 6 ++++++ backend/main.py | 7 ++++++- 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index 1a055f3271..966bd02311 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -221,6 +221,19 @@ class FunctionsTable: except: return None + def deactivate_all_functions(self) -> Optional[bool]: + try: + query = Function.update( + **{"is_active": False}, + updated_at=int(time.time()), + ) + + query.execute() + + return True + except: + return None + def delete_function_by_id(self, id: str) -> bool: try: query = Function.delete().where((Function.id == id)) diff --git a/backend/config.py b/backend/config.py index 842cea1ba0..2b78cc2526 100644 --- a/backend/config.py +++ b/backend/config.py @@ -167,6 +167,12 @@ for version in soup.find_all("h2"): CHANGELOG = changelog_json +#################################### +# SAFE_MODE +#################################### + +SAFE_MODE = os.environ.get("SAFE_MODE", "false").lower() == "true" + #################################### # WEBUI_BUILD_HASH #################################### diff --git a/backend/main.py b/backend/main.py index 991eb58394..4a889f1b34 100644 --- a/backend/main.py +++ b/backend/main.py @@ -55,7 +55,6 @@ from apps.webui.models.functions import Functions from apps.webui.utils import load_toolkit_module_by_id, load_function_module_by_id - from utils.utils import ( get_admin_user, get_verified_user, @@ -102,10 +101,16 @@ from config import ( SEARCH_QUERY_GENERATION_PROMPT_TEMPLATE, SEARCH_QUERY_PROMPT_LENGTH_THRESHOLD, TOOLS_FUNCTION_CALLING_PROMPT_TEMPLATE, + SAFE_MODE, AppConfig, ) from constants import ERROR_MESSAGES +if SAFE_MODE: + print("SAFE MODE ENABLED") + Functions.deactivate_all_functions() + + logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL) log = logging.getLogger(__name__) log.setLevel(SRC_LOG_LEVELS["MAIN"]) From 5f2d37dce5c657a05c5c1544657271e10afc1a33 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:37:35 -0700 Subject: [PATCH 56/71] fix: valves --- backend/main.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/backend/main.py b/backend/main.py index 4a889f1b34..2f2e549bda 100644 --- a/backend/main.py +++ b/backend/main.py @@ -270,8 +270,9 @@ async def get_function_call_response( if hasattr(toolkit_module, "valves") and hasattr( toolkit_module, "Valves" ): + valves = Tools.get_tool_valves_by_id(tool_id) toolkit_module.valves = toolkit_module.Valves( - **Tools.get_tool_valves_by_id(tool_id) + **(valves if valves else {}) ) function = getattr(toolkit_module, result["name"]) @@ -417,8 +418,9 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): if hasattr(function_module, "valves") and hasattr( function_module, "Valves" ): + valves = Functions.get_function_valves_by_id(filter_id) function_module.valves = function_module.Valves( - **Functions.get_function_valves_by_id(filter_id) + **(valves if valves else {}) ) try: @@ -906,8 +908,10 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u if hasattr(function_module, "valves") and hasattr( function_module, "Valves" ): + + valves = Functions.get_function_valves_by_id(pipe_id) function_module.valves = function_module.Valves( - **Functions.get_function_valves_by_id(pipe_id) + **(valves if valves else {}) ) pipe = function_module.pipe @@ -1134,8 +1138,9 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): if hasattr(function_module, "valves") and hasattr( function_module, "Valves" ): + valves = Functions.get_function_valves_by_id(filter_id) function_module.valves = function_module.Valves( - **Functions.get_function_valves_by_id(filter_id) + **(valves if valves else {}) ) try: From 0250f69da02d315d799a557714b3f6412089481a Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:48:16 -0700 Subject: [PATCH 57/71] fix: valves --- backend/apps/webui/models/functions.py | 2 +- backend/apps/webui/models/tools.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index 966bd02311..f4366a1a79 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -146,7 +146,7 @@ class FunctionsTable: def get_function_valves_by_id(self, id: str) -> Optional[dict]: try: function = Function.get(Function.id == id) - return function.valves if "valves" in function and function.valves else {} + return function.valves if function.valves else {} except Exception as e: print(f"An error occurred: {e}") return None diff --git a/backend/apps/webui/models/tools.py b/backend/apps/webui/models/tools.py index 41504bd4a4..bfa65742b7 100644 --- a/backend/apps/webui/models/tools.py +++ b/backend/apps/webui/models/tools.py @@ -117,7 +117,7 @@ class ToolsTable: def get_tool_valves_by_id(self, id: str) -> Optional[dict]: try: tool = Tool.get(Tool.id == id) - return tool.valves if "valves" in tool and tool.valves else {} + return tool.valves if tool.valves else {} except Exception as e: print(f"An error occurred: {e}") return None From f4a2ae5eacf5ccf585f7729815033345b77135f0 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 19:49:48 -0700 Subject: [PATCH 58/71] enh: list valve --- .../components/workspace/ValvesModal.svelte | 42 +++++++++++++------ 1 file changed, 30 insertions(+), 12 deletions(-) diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/ValvesModal.svelte index c6d1395070..124af83de7 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/ValvesModal.svelte @@ -30,20 +30,29 @@ const submitHandler = async () => { saving = true; - let res = null; + if (valvesSpec) { + // Convert string to array + for (const property in valvesSpec.properties) { + if (valvesSpec.properties[property]?.type === 'array') { + valves[property] = (valves[property] ?? '').split(',').map((v) => v.trim()); + } + } - 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); - }); - } + let res = null; - if (res) { - toast.success('Valves updated successfully'); + 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) { + toast.success('Valves updated successfully'); + } } saving = false; @@ -66,6 +75,15 @@ valves = {}; } + 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; }; From 8b998701896ef6e1b67ac76fb08392e019751b97 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 20:11:08 -0700 Subject: [PATCH 59/71] enh: filter function priority valve support --- backend/main.py | 131 ++++++++++++++++++++++++++++-------------------- 1 file changed, 77 insertions(+), 54 deletions(-) diff --git a/backend/main.py b/backend/main.py index 2f2e549bda..85fe16d3b6 100644 --- a/backend/main.py +++ b/backend/main.py @@ -389,6 +389,14 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): ) model = app.state.MODELS[model_id] + def get_priority(function_id): + function = Functions.get_function_by_id(function_id) + if function is not None and hasattr(function, "valves"): + return (function.valves if function.valves else {}).get( + "priority", 0 + ) + return 0 + filter_ids = [ function.id for function in Functions.get_functions_by_type( @@ -400,6 +408,7 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): filter_ids.extend(model["info"]["meta"].get("filterIds", [])) filter_ids = list(set(filter_ids)) + filter_ids.sort(key=get_priority) for filter_id in filter_ids: filter = Functions.get_function_by_id(filter_id) if filter: @@ -1122,72 +1131,86 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): else: pass + def get_priority(function_id): + function = Functions.get_function_by_id(function_id) + if function is not None and hasattr(function, "valves"): + return (function.valves if function.valves else {}).get("priority", 0) + return 0 + + filter_ids = [ + function.id + for function in Functions.get_functions_by_type("filter", active_only=True) + ] # Check if the model has any filters if "info" in model and "meta" in model["info"]: - for filter_id in model["info"]["meta"].get("filterIds", []): - filter = Functions.get_function_by_id(filter_id) - if filter: - if filter_id in webui_app.state.FUNCTIONS: - function_module = webui_app.state.FUNCTIONS[filter_id] - else: - function_module, function_type = load_function_module_by_id( - filter_id - ) - webui_app.state.FUNCTIONS[filter_id] = function_module + filter_ids.extend(model["info"]["meta"].get("filterIds", [])) + filter_ids = list(set(filter_ids)) - if hasattr(function_module, "valves") and hasattr( - function_module, "Valves" - ): - valves = Functions.get_function_valves_by_id(filter_id) - function_module.valves = function_module.Valves( - **(valves if valves else {}) - ) + # Sort filter_ids by priority, using the get_priority function + filter_ids.sort(key=get_priority) - try: - if hasattr(function_module, "outlet"): - outlet = function_module.outlet + for filter_id in filter_ids: + filter = Functions.get_function_by_id(filter_id) + if filter: + if filter_id in webui_app.state.FUNCTIONS: + function_module = webui_app.state.FUNCTIONS[filter_id] + else: + function_module, function_type = load_function_module_by_id(filter_id) + webui_app.state.FUNCTIONS[filter_id] = function_module - # Get the signature of the function - sig = inspect.signature(outlet) - params = {"body": data} + if hasattr(function_module, "valves") and hasattr( + function_module, "Valves" + ): + valves = Functions.get_function_valves_by_id(filter_id) + function_module.valves = function_module.Valves( + **(valves if valves else {}) + ) - if "__user__" in sig.parameters: - __user__ = { - "id": user.id, - "email": user.email, - "name": user.name, - "role": user.role, - } + try: + if hasattr(function_module, "outlet"): + outlet = function_module.outlet - try: - if hasattr(function_module, "UserValves"): - __user__["valves"] = function_module.UserValves( - **Functions.get_user_valves_by_id_and_user_id( - filter_id, user.id - ) + # Get the signature of the function + sig = inspect.signature(outlet) + params = {"body": data} + + if "__user__" in sig.parameters: + __user__ = { + "id": user.id, + "email": user.email, + "name": user.name, + "role": user.role, + } + + try: + if hasattr(function_module, "UserValves"): + __user__["valves"] = function_module.UserValves( + **Functions.get_user_valves_by_id_and_user_id( + filter_id, user.id ) - except Exception as e: - print(e) + ) + except Exception as e: + print(e) - params = {**params, "__user__": __user__} + params = {**params, "__user__": __user__} - if "__id__" in sig.parameters: - params = { - **params, - "__id__": filter_id, - } + if "__id__" in sig.parameters: + params = { + **params, + "__id__": filter_id, + } - if inspect.iscoroutinefunction(outlet): - data = await outlet(**params) - else: - data = outlet(**params) + if inspect.iscoroutinefunction(outlet): + data = await outlet(**params) + else: + data = outlet(**params) - except Exception as e: - print(f"Error: {e}") - return JSONResponse( - status_code=status.HTTP_400_BAD_REQUEST, - content={"detail": str(e)}, - ) + except Exception as e: + print(f"Error: {e}") + return JSONResponse( + status_code=status.HTTP_400_BAD_REQUEST, + content={"detail": str(e)}, + ) return data From abf212c28f1bd5a44403deb9339ecd43accf0495 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 20:31:40 -0700 Subject: [PATCH 60/71] enh: tools & functions frontmatter --- backend/apps/webui/main.py | 4 +- backend/apps/webui/models/functions.py | 1 + backend/apps/webui/models/tools.py | 1 + backend/apps/webui/routers/functions.py | 194 ++++++++++++------------ backend/apps/webui/routers/tools.py | 144 +++++++++--------- backend/apps/webui/utils.py | 29 +++- backend/main.py | 14 +- 7 files changed, 212 insertions(+), 175 deletions(-) diff --git a/backend/apps/webui/main.py b/backend/apps/webui/main.py index a8f45aff0b..f092da7adf 100644 --- a/backend/apps/webui/main.py +++ b/backend/apps/webui/main.py @@ -109,7 +109,9 @@ async def get_pipe_models(): for pipe in pipes: # Check if function is already loaded if pipe.id not in app.state.FUNCTIONS: - function_module, function_type = load_function_module_by_id(pipe.id) + function_module, function_type, frontmatter = load_function_module_by_id( + pipe.id + ) app.state.FUNCTIONS[pipe.id] = function_module else: function_module = app.state.FUNCTIONS[pipe.id] diff --git a/backend/apps/webui/models/functions.py b/backend/apps/webui/models/functions.py index f4366a1a79..2619879816 100644 --- a/backend/apps/webui/models/functions.py +++ b/backend/apps/webui/models/functions.py @@ -39,6 +39,7 @@ class Function(Model): class FunctionMeta(BaseModel): description: Optional[str] = None + manifest: Optional[dict] = {} class FunctionModel(BaseModel): diff --git a/backend/apps/webui/models/tools.py b/backend/apps/webui/models/tools.py index bfa65742b7..694081df9a 100644 --- a/backend/apps/webui/models/tools.py +++ b/backend/apps/webui/models/tools.py @@ -38,6 +38,7 @@ class Tool(Model): class ToolMeta(BaseModel): description: Optional[str] = None + manifest: Optional[dict] = {} class ToolModel(BaseModel): diff --git a/backend/apps/webui/routers/functions.py b/backend/apps/webui/routers/functions.py index fa3e3aeb96..4c89ca487c 100644 --- a/backend/apps/webui/routers/functions.py +++ b/backend/apps/webui/routers/functions.py @@ -69,7 +69,10 @@ async def create_new_function( with open(function_path, "w") as function_file: function_file.write(form_data.content) - function_module, function_type = load_function_module_by_id(form_data.id) + function_module, function_type, frontmatter = load_function_module_by_id( + form_data.id + ) + form_data.meta.manifest = frontmatter FUNCTIONS = request.app.state.FUNCTIONS FUNCTIONS[form_data.id] = function_module @@ -117,6 +120,97 @@ async def get_function_by_id(id: str, user=Depends(get_admin_user)): ) +############################ +# ToggleFunctionById +############################ + + +@router.post("/id/{id}/toggle", response_model=Optional[FunctionModel]) +async def toggle_function_by_id(id: str, user=Depends(get_admin_user)): + function = Functions.get_function_by_id(id) + if function: + function = Functions.update_function_by_id( + id, {"is_active": not function.is_active} + ) + + if function: + return function + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT("Error updating function"), + ) + else: + raise HTTPException( + status_code=status.HTTP_401_UNAUTHORIZED, + detail=ERROR_MESSAGES.NOT_FOUND, + ) + + +############################ +# UpdateFunctionById +############################ + + +@router.post("/id/{id}/update", response_model=Optional[FunctionModel]) +async def update_function_by_id( + request: Request, id: str, form_data: FunctionForm, user=Depends(get_admin_user) +): + function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py") + + try: + with open(function_path, "w") as function_file: + function_file.write(form_data.content) + + function_module, function_type, frontmatter = load_function_module_by_id(id) + form_data.meta.manifest = frontmatter + + FUNCTIONS = request.app.state.FUNCTIONS + FUNCTIONS[id] = function_module + + updated = {**form_data.model_dump(exclude={"id"}), "type": function_type} + print(updated) + + function = Functions.update_function_by_id(id, updated) + + if function: + return function + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT("Error updating function"), + ) + + except Exception as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + + +############################ +# DeleteFunctionById +############################ + + +@router.delete("/id/{id}/delete", response_model=bool) +async def delete_function_by_id( + request: Request, id: str, user=Depends(get_admin_user) +): + result = Functions.delete_function_by_id(id) + + if result: + FUNCTIONS = request.app.state.FUNCTIONS + if id in FUNCTIONS: + del FUNCTIONS[id] + + # delete the function file + function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py") + os.remove(function_path) + + return result + + ############################ # GetFunctionValves ############################ @@ -155,7 +249,7 @@ async def get_function_valves_spec_by_id( 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) + function_module, function_type, frontmatter = load_function_module_by_id(id) request.app.state.FUNCTIONS[id] = function_module if hasattr(function_module, "Valves"): @@ -184,7 +278,7 @@ async def update_function_valves_by_id( 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) + function_module, function_type, frontmatter = load_function_module_by_id(id) request.app.state.FUNCTIONS[id] = function_module if hasattr(function_module, "Valves"): @@ -247,7 +341,7 @@ async def get_function_user_valves_spec_by_id( 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) + function_module, function_type, frontmatter = load_function_module_by_id(id) request.app.state.FUNCTIONS[id] = function_module if hasattr(function_module, "UserValves"): @@ -271,7 +365,7 @@ async def update_function_user_valves_by_id( 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) + function_module, function_type, frontmatter = load_function_module_by_id(id) request.app.state.FUNCTIONS[id] = function_module if hasattr(function_module, "UserValves"): @@ -300,93 +394,3 @@ async def update_function_user_valves_by_id( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND, ) - - -############################ -# ToggleFunctionById -############################ - - -@router.post("/id/{id}/toggle", response_model=Optional[FunctionModel]) -async def toggle_function_by_id(id: str, user=Depends(get_admin_user)): - function = Functions.get_function_by_id(id) - if function: - function = Functions.update_function_by_id( - id, {"is_active": not function.is_active} - ) - - if function: - return function - else: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT("Error updating function"), - ) - else: - raise HTTPException( - status_code=status.HTTP_401_UNAUTHORIZED, - detail=ERROR_MESSAGES.NOT_FOUND, - ) - - -############################ -# UpdateFunctionById -############################ - - -@router.post("/id/{id}/update", response_model=Optional[FunctionModel]) -async def update_function_by_id( - request: Request, id: str, form_data: FunctionForm, user=Depends(get_admin_user) -): - function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py") - - try: - with open(function_path, "w") as function_file: - function_file.write(form_data.content) - - function_module, function_type = load_function_module_by_id(id) - - FUNCTIONS = request.app.state.FUNCTIONS - FUNCTIONS[id] = function_module - - updated = {**form_data.model_dump(exclude={"id"}), "type": function_type} - print(updated) - - function = Functions.update_function_by_id(id, updated) - - if function: - return function - else: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT("Error updating function"), - ) - - except Exception as e: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), - ) - - -############################ -# DeleteFunctionById -############################ - - -@router.delete("/id/{id}/delete", response_model=bool) -async def delete_function_by_id( - request: Request, id: str, user=Depends(get_admin_user) -): - result = Functions.delete_function_by_id(id) - - if result: - FUNCTIONS = request.app.state.FUNCTIONS - if id in FUNCTIONS: - del FUNCTIONS[id] - - # delete the function file - function_path = os.path.join(FUNCTIONS_DIR, f"{id}.py") - os.remove(function_path) - - return result diff --git a/backend/apps/webui/routers/tools.py b/backend/apps/webui/routers/tools.py index ab974391cb..d20584c228 100644 --- a/backend/apps/webui/routers/tools.py +++ b/backend/apps/webui/routers/tools.py @@ -74,7 +74,8 @@ async def create_new_toolkit( with open(toolkit_path, "w") as tool_file: tool_file.write(form_data.content) - toolkit_module = load_toolkit_module_by_id(form_data.id) + toolkit_module, frontmatter = load_toolkit_module_by_id(form_data.id) + form_data.meta.manifest = frontmatter TOOLS = request.app.state.TOOLS TOOLS[form_data.id] = toolkit_module @@ -123,6 +124,73 @@ async def get_toolkit_by_id(id: str, user=Depends(get_admin_user)): ) +############################ +# UpdateToolkitById +############################ + + +@router.post("/id/{id}/update", response_model=Optional[ToolModel]) +async def update_toolkit_by_id( + request: Request, id: str, form_data: ToolForm, user=Depends(get_admin_user) +): + toolkit_path = os.path.join(TOOLS_DIR, f"{id}.py") + + try: + with open(toolkit_path, "w") as tool_file: + tool_file.write(form_data.content) + + toolkit_module, frontmatter = load_toolkit_module_by_id(id) + form_data.meta.manifest = frontmatter + + TOOLS = request.app.state.TOOLS + TOOLS[id] = toolkit_module + + specs = get_tools_specs(TOOLS[id]) + + updated = { + **form_data.model_dump(exclude={"id"}), + "specs": specs, + } + + print(updated) + toolkit = Tools.update_tool_by_id(id, updated) + + if toolkit: + return toolkit + else: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT("Error updating toolkit"), + ) + + except Exception as e: + raise HTTPException( + status_code=status.HTTP_400_BAD_REQUEST, + detail=ERROR_MESSAGES.DEFAULT(e), + ) + + +############################ +# DeleteToolkitById +############################ + + +@router.delete("/id/{id}/delete", response_model=bool) +async def delete_toolkit_by_id(request: Request, id: str, user=Depends(get_admin_user)): + result = Tools.delete_tool_by_id(id) + + if result: + TOOLS = request.app.state.TOOLS + if id in TOOLS: + del TOOLS[id] + + # delete the toolkit file + toolkit_path = os.path.join(TOOLS_DIR, f"{id}.py") + os.remove(toolkit_path) + + return result + + ############################ # GetToolValves ############################ @@ -161,7 +229,7 @@ async def get_toolkit_valves_spec_by_id( if id in request.app.state.TOOLS: toolkit_module = request.app.state.TOOLS[id] else: - toolkit_module = load_toolkit_module_by_id(id) + toolkit_module, frontmatter = load_toolkit_module_by_id(id) request.app.state.TOOLS[id] = toolkit_module if hasattr(toolkit_module, "Valves"): @@ -189,7 +257,7 @@ async def update_toolkit_valves_by_id( if id in request.app.state.TOOLS: toolkit_module = request.app.state.TOOLS[id] else: - toolkit_module = load_toolkit_module_by_id(id) + toolkit_module, frontmatter = load_toolkit_module_by_id(id) request.app.state.TOOLS[id] = toolkit_module if hasattr(toolkit_module, "Valves"): @@ -252,7 +320,7 @@ async def get_toolkit_user_valves_spec_by_id( if id in request.app.state.TOOLS: toolkit_module = request.app.state.TOOLS[id] else: - toolkit_module = load_toolkit_module_by_id(id) + toolkit_module, frontmatter = load_toolkit_module_by_id(id) request.app.state.TOOLS[id] = toolkit_module if hasattr(toolkit_module, "UserValves"): @@ -276,7 +344,7 @@ async def update_toolkit_user_valves_by_id( if id in request.app.state.TOOLS: toolkit_module = request.app.state.TOOLS[id] else: - toolkit_module = load_toolkit_module_by_id(id) + toolkit_module, frontmatter = load_toolkit_module_by_id(id) request.app.state.TOOLS[id] = toolkit_module if hasattr(toolkit_module, "UserValves"): @@ -305,69 +373,3 @@ async def update_toolkit_user_valves_by_id( status_code=status.HTTP_401_UNAUTHORIZED, detail=ERROR_MESSAGES.NOT_FOUND, ) - - -############################ -# UpdateToolkitById -############################ - - -@router.post("/id/{id}/update", response_model=Optional[ToolModel]) -async def update_toolkit_by_id( - request: Request, id: str, form_data: ToolForm, user=Depends(get_admin_user) -): - toolkit_path = os.path.join(TOOLS_DIR, f"{id}.py") - - try: - with open(toolkit_path, "w") as tool_file: - tool_file.write(form_data.content) - - toolkit_module = load_toolkit_module_by_id(id) - - TOOLS = request.app.state.TOOLS - TOOLS[id] = toolkit_module - - specs = get_tools_specs(TOOLS[id]) - - updated = { - **form_data.model_dump(exclude={"id"}), - "specs": specs, - } - - print(updated) - toolkit = Tools.update_tool_by_id(id, updated) - - if toolkit: - return toolkit - else: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT("Error updating toolkit"), - ) - - except Exception as e: - raise HTTPException( - status_code=status.HTTP_400_BAD_REQUEST, - detail=ERROR_MESSAGES.DEFAULT(e), - ) - - -############################ -# DeleteToolkitById -############################ - - -@router.delete("/id/{id}/delete", response_model=bool) -async def delete_toolkit_by_id(request: Request, id: str, user=Depends(get_admin_user)): - result = Tools.delete_tool_by_id(id) - - if result: - TOOLS = request.app.state.TOOLS - if id in TOOLS: - del TOOLS[id] - - # delete the toolkit file - toolkit_path = os.path.join(TOOLS_DIR, f"{id}.py") - os.remove(toolkit_path) - - return result diff --git a/backend/apps/webui/utils.py b/backend/apps/webui/utils.py index 3e075a8a8f..f50b13f389 100644 --- a/backend/apps/webui/utils.py +++ b/backend/apps/webui/utils.py @@ -1,19 +1,41 @@ from importlib import util import os +import re from config import TOOLS_DIR, FUNCTIONS_DIR +def extract_frontmatter(file_path): + """ + Extract frontmatter as a dictionary from the specified file path. + """ + frontmatter = {} + frontmatter_pattern = re.compile(r"^([a-z_]+):\s*(.*)\s*$", re.IGNORECASE) + + with open(file_path, "r", encoding="utf-8") as file: + for line in file: + if line.strip() == '"""': + # End of frontmatter section + break + match = frontmatter_pattern.match(line) + if match: + key, value = match.groups() + frontmatter[key] = value + + return frontmatter + + def load_toolkit_module_by_id(toolkit_id): toolkit_path = os.path.join(TOOLS_DIR, f"{toolkit_id}.py") spec = util.spec_from_file_location(toolkit_id, toolkit_path) module = util.module_from_spec(spec) + frontmatter = extract_frontmatter(toolkit_path) try: spec.loader.exec_module(module) print(f"Loaded module: {module.__name__}") if hasattr(module, "Tools"): - return module.Tools() + return module.Tools(), frontmatter else: raise Exception("No Tools class found") except Exception as e: @@ -28,14 +50,15 @@ def load_function_module_by_id(function_id): spec = util.spec_from_file_location(function_id, function_path) module = util.module_from_spec(spec) + frontmatter = extract_frontmatter(function_path) try: spec.loader.exec_module(module) print(f"Loaded module: {module.__name__}") if hasattr(module, "Pipe"): - return module.Pipe(), "pipe" + return module.Pipe(), "pipe", frontmatter elif hasattr(module, "Filter"): - return module.Filter(), "filter" + return module.Filter(), "filter", frontmatter else: raise Exception("No Function class found") except Exception as e: diff --git a/backend/main.py b/backend/main.py index 85fe16d3b6..12e2d937e7 100644 --- a/backend/main.py +++ b/backend/main.py @@ -258,7 +258,7 @@ async def get_function_call_response( if tool_id in webui_app.state.TOOLS: toolkit_module = webui_app.state.TOOLS[tool_id] else: - toolkit_module = load_toolkit_module_by_id(tool_id) + toolkit_module, frontmatter = load_toolkit_module_by_id(tool_id) webui_app.state.TOOLS[tool_id] = toolkit_module file_handler = False @@ -415,8 +415,8 @@ class ChatCompletionMiddleware(BaseHTTPMiddleware): if filter_id in webui_app.state.FUNCTIONS: function_module = webui_app.state.FUNCTIONS[filter_id] else: - function_module, function_type = load_function_module_by_id( - filter_id + function_module, function_type, frontmatter = ( + load_function_module_by_id(filter_id) ) webui_app.state.FUNCTIONS[filter_id] = function_module @@ -909,7 +909,9 @@ async def generate_chat_completions(form_data: dict, user=Depends(get_verified_u # Check if function is already loaded if pipe_id not in webui_app.state.FUNCTIONS: - function_module, function_type = load_function_module_by_id(pipe_id) + function_module, function_type, frontmatter = ( + load_function_module_by_id(pipe_id) + ) webui_app.state.FUNCTIONS[pipe_id] = function_module else: function_module = webui_app.state.FUNCTIONS[pipe_id] @@ -1155,7 +1157,9 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)): if filter_id in webui_app.state.FUNCTIONS: function_module = webui_app.state.FUNCTIONS[filter_id] else: - function_module, function_type = load_function_module_by_id(filter_id) + function_module, function_type, frontmatter = ( + load_function_module_by_id(filter_id) + ) webui_app.state.FUNCTIONS[filter_id] = function_module if hasattr(function_module, "valves") and hasattr( From 5c0015cd66a3fd617e78cae3adbbfc2d4c6dd3fe Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 20:37:41 -0700 Subject: [PATCH 61/71] fix: frontmatter --- backend/apps/webui/utils.py | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/backend/apps/webui/utils.py b/backend/apps/webui/utils.py index f50b13f389..8bcda539ec 100644 --- a/backend/apps/webui/utils.py +++ b/backend/apps/webui/utils.py @@ -10,17 +10,32 @@ def extract_frontmatter(file_path): Extract frontmatter as a dictionary from the specified file path. """ frontmatter = {} - frontmatter_pattern = re.compile(r"^([a-z_]+):\s*(.*)\s*$", re.IGNORECASE) + frontmatter_started = False + frontmatter_ended = False + frontmatter_pattern = re.compile(r"^\s*([a-z_]+):\s*(.*)\s*$", re.IGNORECASE) - with open(file_path, "r", encoding="utf-8") as file: - for line in file: - if line.strip() == '"""': - # End of frontmatter section - break - match = frontmatter_pattern.match(line) - if match: - key, value = match.groups() - frontmatter[key] = value + try: + with open(file_path, "r", encoding="utf-8") as file: + for line in file: + if '"""' in line: + if not frontmatter_started: + frontmatter_started = True + continue # skip the line with the opening triple quotes + else: + frontmatter_ended = True + break + + if frontmatter_started and not frontmatter_ended: + match = frontmatter_pattern.match(line) + if match: + key, value = match.groups() + frontmatter[key.strip()] = value.strip() + except FileNotFoundError: + print(f"Error: The file {file_path} does not exist.") + return {} + except Exception as e: + print(f"An error occurred: {e}") + return {} return frontmatter From be2340d4ef907b2117ee8f7764cc928ec4b0ace9 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 20:40:12 -0700 Subject: [PATCH 62/71] refac: styling --- src/app.css | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/app.css b/src/app.css index baf620845b..2dacf5d726 100644 --- a/src/app.css +++ b/src/app.css @@ -32,6 +32,10 @@ math { @apply underline; } +iframe { + @apply rounded-lg; +} + ol > li { counter-increment: list-number; display: block; From 0b8f5c22326b8c4c4c82f7f126faec73ddf97ae4 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 21:00:34 -0700 Subject: [PATCH 63/71] enh: manifest modal --- src/lib/components/icons/Heart.svelte | 19 ++++ src/lib/components/workspace/Functions.svelte | 21 +++- src/lib/components/workspace/Tools.svelte | 21 +++- .../workspace/common/ManifestModal.svelte | 102 ++++++++++++++++++ .../workspace/{ => common}/ValvesModal.svelte | 4 +- 5 files changed, 163 insertions(+), 4 deletions(-) create mode 100644 src/lib/components/icons/Heart.svelte create mode 100644 src/lib/components/workspace/common/ManifestModal.svelte rename src/lib/components/workspace/{ => common}/ValvesModal.svelte (98%) diff --git a/src/lib/components/icons/Heart.svelte b/src/lib/components/icons/Heart.svelte new file mode 100644 index 0000000000..ba042ff655 --- /dev/null +++ b/src/lib/components/icons/Heart.svelte @@ -0,0 +1,19 @@ + + + + + diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index fb92cc32d9..39e77a4544 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -24,7 +24,9 @@ import FunctionMenu from './Functions/FunctionMenu.svelte'; import EllipsisHorizontal from '../icons/EllipsisHorizontal.svelte'; import Switch from '../common/Switch.svelte'; - import ValvesModal from './ValvesModal.svelte'; + import ValvesModal from './common/ValvesModal.svelte'; + import ManifestModal from './common/ManifestModal.svelte'; + import Heart from '../icons/Heart.svelte'; const i18n = getContext('i18n'); @@ -34,6 +36,7 @@ let showConfirm = false; let query = ''; + let showManifestModal = false; let showValvesModal = false; let selectedFunction = null; @@ -175,6 +178,21 @@
+ {#if func?.meta?.manifest?.funding_url ?? false} + + + + {/if} +
+
+ {#if tool?.meta?.manifest?.funding_url ?? false} + + + + {/if} + +
+ +
+
+
{ + show = false; + }} + > +
+
+ The developers behind this plugin are passionate volunteers from the community. If you + find this plugin helpful, please consider contributing to its development. +
+ +
+ Your entire contribution will go directly to the plugin developer; Open WebUI does not + take any percentage. However, the chosen funding platform might have its own fees. +
+ +
+ +
+ Support this plugin: {manifest.funding_url} +
+
+ +
+ +
+
+
+
+
+
+ + diff --git a/src/lib/components/workspace/ValvesModal.svelte b/src/lib/components/workspace/common/ValvesModal.svelte similarity index 98% rename from src/lib/components/workspace/ValvesModal.svelte rename to src/lib/components/workspace/common/ValvesModal.svelte index 124af83de7..0bf2b8f195 100644 --- a/src/lib/components/workspace/ValvesModal.svelte +++ b/src/lib/components/workspace/common/ValvesModal.svelte @@ -4,14 +4,14 @@ import { onMount, getContext } from 'svelte'; import { addUser } from '$lib/apis/auths'; - import Modal from '../common/Modal.svelte'; + import Modal from '../../common/Modal.svelte'; import { getFunctionValvesById, getFunctionValvesSpecById, updateFunctionValvesById } from '$lib/apis/functions'; import { getToolValvesById, getToolValvesSpecById, updateToolValvesById } from '$lib/apis/tools'; - import Spinner from '../common/Spinner.svelte'; + import Spinner from '../../common/Spinner.svelte'; const i18n = getContext('i18n'); const dispatch = createEventDispatcher(); From 9788633ce1fd7fcc22374f1406591ffad43ba049 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 21:01:07 -0700 Subject: [PATCH 64/71] refac: wording --- src/lib/components/workspace/Functions.svelte | 2 +- src/lib/components/workspace/Tools.svelte | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/workspace/Functions.svelte b/src/lib/components/workspace/Functions.svelte index 39e77a4544..bcfd570ead 100644 --- a/src/lib/components/workspace/Functions.svelte +++ b/src/lib/components/workspace/Functions.svelte @@ -179,7 +179,7 @@
{#if func?.meta?.manifest?.funding_url ?? false} - +
+ {#if func?.meta?.manifest?.version} +
+ v{func?.meta?.manifest?.version ?? ''} +
+ {/if} +
{func.name}
diff --git a/src/lib/components/workspace/Tools.svelte b/src/lib/components/workspace/Tools.svelte index 15008187f1..0b8f70e854 100644 --- a/src/lib/components/workspace/Tools.svelte +++ b/src/lib/components/workspace/Tools.svelte @@ -156,6 +156,14 @@ TOOL
+ {#if tool?.meta?.manifest?.version} +
+ v{tool?.meta?.manifest?.version ?? ''} +
+ {/if} +
{tool.name}
From 37a052327a2e421cf4733af476e253a2574c9f63 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 21:14:31 -0700 Subject: [PATCH 66/71] chore: format --- src/lib/i18n/locales/ar-BH/translation.json | 2 ++ src/lib/i18n/locales/bg-BG/translation.json | 2 ++ src/lib/i18n/locales/bn-BD/translation.json | 2 ++ src/lib/i18n/locales/ca-ES/translation.json | 2 ++ src/lib/i18n/locales/ceb-PH/translation.json | 2 ++ src/lib/i18n/locales/de-DE/translation.json | 2 ++ src/lib/i18n/locales/dg-DG/translation.json | 2 ++ src/lib/i18n/locales/en-GB/translation.json | 2 ++ src/lib/i18n/locales/en-US/translation.json | 2 ++ src/lib/i18n/locales/es-ES/translation.json | 2 ++ src/lib/i18n/locales/fa-IR/translation.json | 2 ++ src/lib/i18n/locales/fi-FI/translation.json | 2 ++ src/lib/i18n/locales/fr-CA/translation.json | 2 ++ src/lib/i18n/locales/fr-FR/translation.json | 2 ++ src/lib/i18n/locales/he-IL/translation.json | 2 ++ src/lib/i18n/locales/hi-IN/translation.json | 2 ++ src/lib/i18n/locales/hr-HR/translation.json | 2 ++ src/lib/i18n/locales/it-IT/translation.json | 2 ++ src/lib/i18n/locales/ja-JP/translation.json | 2 ++ src/lib/i18n/locales/ka-GE/translation.json | 2 ++ src/lib/i18n/locales/ko-KR/translation.json | 2 ++ src/lib/i18n/locales/lt-LT/translation.json | 2 ++ src/lib/i18n/locales/nb-NO/translation.json | 2 ++ src/lib/i18n/locales/nl-NL/translation.json | 2 ++ src/lib/i18n/locales/pa-IN/translation.json | 2 ++ src/lib/i18n/locales/pl-PL/translation.json | 2 ++ src/lib/i18n/locales/pt-BR/translation.json | 2 ++ src/lib/i18n/locales/pt-PT/translation.json | 2 ++ src/lib/i18n/locales/ru-RU/translation.json | 2 ++ src/lib/i18n/locales/sr-RS/translation.json | 2 ++ src/lib/i18n/locales/sv-SE/translation.json | 2 ++ src/lib/i18n/locales/tk-TW/translation.json | 2 ++ src/lib/i18n/locales/tr-TR/translation.json | 2 ++ src/lib/i18n/locales/uk-UA/translation.json | 2 ++ src/lib/i18n/locales/vi-VN/translation.json | 2 ++ src/lib/i18n/locales/zh-CN/translation.json | 2 ++ src/lib/i18n/locales/zh-TW/translation.json | 2 ++ 37 files changed, 74 insertions(+) diff --git a/src/lib/i18n/locales/ar-BH/translation.json b/src/lib/i18n/locales/ar-BH/translation.json index 165dc825bf..2847b854dd 100644 --- a/src/lib/i18n/locales/ar-BH/translation.json +++ b/src/lib/i18n/locales/ar-BH/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "لا تسمح بذلك", "Don't have an account?": "ليس لديك حساب؟", "Don't like the style": "لا أحب النمط", + "Done": "", "Download": "تحميل", "Download canceled": "تم اللغاء التحميل", "Download Database": "تحميل قاعدة البيانات", @@ -505,6 +506,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "إظهار الاختصارات", + "Show your support!": "", "Showcased creativity": "أظهر الإبداع", "sidebar": "الشريط الجانبي", "Sign in": "تسجيل الدخول", diff --git a/src/lib/i18n/locales/bg-BG/translation.json b/src/lib/i18n/locales/bg-BG/translation.json index ad6225eba1..fa534ef3ec 100644 --- a/src/lib/i18n/locales/bg-BG/translation.json +++ b/src/lib/i18n/locales/bg-BG/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Не Позволявай", "Don't have an account?": "Нямате акаунт?", "Don't like the style": "Не харесваш стила?", + "Done": "", "Download": "Изтегляне отменено", "Download canceled": "Изтегляне отменено", "Download Database": "Сваляне на база данни", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Покажи", + "Show your support!": "", "Showcased creativity": "Показана креативност", "sidebar": "sidebar", "Sign in": "Вписване", diff --git a/src/lib/i18n/locales/bn-BD/translation.json b/src/lib/i18n/locales/bn-BD/translation.json index 49f0e06ef9..27365e1fdc 100644 --- a/src/lib/i18n/locales/bn-BD/translation.json +++ b/src/lib/i18n/locales/bn-BD/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "অনুমোদন দেবেন না", "Don't have an account?": "একাউন্ট নেই?", "Don't like the style": "স্টাইল পছন্দ করেন না", + "Done": "", "Download": "ডাউনলোড", "Download canceled": "ডাউনলোড বাতিল করা হয়েছে", "Download Database": "ডেটাবেজ ডাউনলোড করুন", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "শর্টকাটগুলো দেখান", + "Show your support!": "", "Showcased creativity": "সৃজনশীলতা প্রদর্শন", "sidebar": "সাইডবার", "Sign in": "সাইন ইন", diff --git a/src/lib/i18n/locales/ca-ES/translation.json b/src/lib/i18n/locales/ca-ES/translation.json index 98ae50aa56..336f3eeb11 100644 --- a/src/lib/i18n/locales/ca-ES/translation.json +++ b/src/lib/i18n/locales/ca-ES/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "No permetre", "Don't have an account?": "No tens un compte?", "Don't like the style": "No t'agrada l'estil?", + "Done": "", "Download": "Descarregar", "Download canceled": "Descàrrega cancel·lada", "Download Database": "Descarregar la base de dades", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "Mostrar els detalls de l'administrador a la superposició del compte pendent", "Show Model": "Mostrar el model", "Show shortcuts": "Mostrar dreceres", + "Show your support!": "", "Showcased creativity": "Creativitat mostrada", "sidebar": "barra lateral", "Sign in": "Iniciar sessió", diff --git a/src/lib/i18n/locales/ceb-PH/translation.json b/src/lib/i18n/locales/ceb-PH/translation.json index 68e21d8bee..1923ef56fb 100644 --- a/src/lib/i18n/locales/ceb-PH/translation.json +++ b/src/lib/i18n/locales/ceb-PH/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Dili tugotan", "Don't have an account?": "Wala kay account ?", "Don't like the style": "", + "Done": "", "Download": "", "Download canceled": "", "Download Database": "I-download ang database", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Ipakita ang mga shortcut", + "Show your support!": "", "Showcased creativity": "", "sidebar": "lateral bar", "Sign in": "Para maka log in", diff --git a/src/lib/i18n/locales/de-DE/translation.json b/src/lib/i18n/locales/de-DE/translation.json index 710aad09f5..2d6c81831b 100644 --- a/src/lib/i18n/locales/de-DE/translation.json +++ b/src/lib/i18n/locales/de-DE/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Nicht erlauben", "Don't have an account?": "Hast du vielleicht noch kein Konto?", "Don't like the style": "Dir gefällt der Style nicht", + "Done": "", "Download": "Herunterladen", "Download canceled": "Download abgebrochen", "Download Database": "Datenbank herunterladen", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "Admin-Details im Account-Pending-Overlay anzeigen", "Show Model": "", "Show shortcuts": "Verknüpfungen anzeigen", + "Show your support!": "", "Showcased creativity": "Kreativität zur Schau gestellt", "sidebar": "Seitenleiste", "Sign in": "Anmelden", diff --git a/src/lib/i18n/locales/dg-DG/translation.json b/src/lib/i18n/locales/dg-DG/translation.json index a26e8dda41..15840440ec 100644 --- a/src/lib/i18n/locales/dg-DG/translation.json +++ b/src/lib/i18n/locales/dg-DG/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Don't Allow", "Don't have an account?": "No account? Much sad.", "Don't like the style": "", + "Done": "", "Download": "", "Download canceled": "", "Download Database": "Download Database", @@ -503,6 +504,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Show shortcuts much shortcut", + "Show your support!": "", "Showcased creativity": "", "sidebar": "sidebar much side", "Sign in": "Sign in very sign", diff --git a/src/lib/i18n/locales/en-GB/translation.json b/src/lib/i18n/locales/en-GB/translation.json index af9d122bb8..ad3109a952 100644 --- a/src/lib/i18n/locales/en-GB/translation.json +++ b/src/lib/i18n/locales/en-GB/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "", "Don't have an account?": "", "Don't like the style": "", + "Done": "", "Download": "", "Download canceled": "", "Download Database": "", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "", + "Show your support!": "", "Showcased creativity": "", "sidebar": "", "Sign in": "", diff --git a/src/lib/i18n/locales/en-US/translation.json b/src/lib/i18n/locales/en-US/translation.json index af9d122bb8..ad3109a952 100644 --- a/src/lib/i18n/locales/en-US/translation.json +++ b/src/lib/i18n/locales/en-US/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "", "Don't have an account?": "", "Don't like the style": "", + "Done": "", "Download": "", "Download canceled": "", "Download Database": "", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "", + "Show your support!": "", "Showcased creativity": "", "sidebar": "", "Sign in": "", diff --git a/src/lib/i18n/locales/es-ES/translation.json b/src/lib/i18n/locales/es-ES/translation.json index 3394bd90ce..a928ace1fc 100644 --- a/src/lib/i18n/locales/es-ES/translation.json +++ b/src/lib/i18n/locales/es-ES/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "No Permitir", "Don't have an account?": "¿No tienes una cuenta?", "Don't like the style": "No te gusta el estilo?", + "Done": "", "Download": "Descargar", "Download canceled": "Descarga cancelada", "Download Database": "Descarga la Base de Datos", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Mostrar atajos", + "Show your support!": "", "Showcased creativity": "Mostrar creatividad", "sidebar": "barra lateral", "Sign in": "Iniciar sesión", diff --git a/src/lib/i18n/locales/fa-IR/translation.json b/src/lib/i18n/locales/fa-IR/translation.json index a8b59dca15..1cc8dae6f6 100644 --- a/src/lib/i18n/locales/fa-IR/translation.json +++ b/src/lib/i18n/locales/fa-IR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "اجازه نده", "Don't have an account?": "حساب کاربری ندارید؟", "Don't like the style": "نظری ندارید؟", + "Done": "", "Download": "دانلود کن", "Download canceled": "دانلود لغو شد", "Download Database": "دانلود پایگاه داده", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "نمایش میانبرها", + "Show your support!": "", "Showcased creativity": "ایده\u200cآفرینی", "sidebar": "نوار کناری", "Sign in": "ورود", diff --git a/src/lib/i18n/locales/fi-FI/translation.json b/src/lib/i18n/locales/fi-FI/translation.json index 00bbd8c007..1cb1453a67 100644 --- a/src/lib/i18n/locales/fi-FI/translation.json +++ b/src/lib/i18n/locales/fi-FI/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Älä salli", "Don't have an account?": "Eikö sinulla ole tiliä?", "Don't like the style": "En pidä tyylistä", + "Done": "", "Download": "Lataa", "Download canceled": "Lataus peruutettu", "Download Database": "Lataa tietokanta", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Näytä pikanäppäimet", + "Show your support!": "", "Showcased creativity": "Näytti luovuutta", "sidebar": "sivupalkki", "Sign in": "Kirjaudu sisään", diff --git a/src/lib/i18n/locales/fr-CA/translation.json b/src/lib/i18n/locales/fr-CA/translation.json index 0d0ba8d32e..03b09764a2 100644 --- a/src/lib/i18n/locales/fr-CA/translation.json +++ b/src/lib/i18n/locales/fr-CA/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Ne pas autoriser", "Don't have an account?": "Vous n'avez pas de compte ?", "Don't like the style": "Vous n'aimez pas le style ?", + "Done": "", "Download": "Télécharger", "Download canceled": "Téléchargement annulé", "Download Database": "Télécharger la base de données", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Afficher les raccourcis", + "Show your support!": "", "Showcased creativity": "Créativité affichée", "sidebar": "barre latérale", "Sign in": "Se connecter", diff --git a/src/lib/i18n/locales/fr-FR/translation.json b/src/lib/i18n/locales/fr-FR/translation.json index 103247e521..021a20c468 100644 --- a/src/lib/i18n/locales/fr-FR/translation.json +++ b/src/lib/i18n/locales/fr-FR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Ne pas autoriser", "Don't have an account?": "Vous n'avez pas de compte ?", "Don't like the style": "N'aime pas le style", + "Done": "", "Download": "Télécharger", "Download canceled": "Téléchargement annulé", "Download Database": "Télécharger la base de données", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Afficher les raccourcis", + "Show your support!": "", "Showcased creativity": "Créativité affichée", "sidebar": "barre latérale", "Sign in": "Se connecter", diff --git a/src/lib/i18n/locales/he-IL/translation.json b/src/lib/i18n/locales/he-IL/translation.json index 9054fe03e8..7cad70c19c 100644 --- a/src/lib/i18n/locales/he-IL/translation.json +++ b/src/lib/i18n/locales/he-IL/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "אל תאפשר", "Don't have an account?": "אין לך חשבון?", "Don't like the style": "לא אוהב את הסגנון", + "Done": "", "Download": "הורד", "Download canceled": "ההורדה בוטלה", "Download Database": "הורד מסד נתונים", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "הצג קיצורי דרך", + "Show your support!": "", "Showcased creativity": "הצגת יצירתיות", "sidebar": "סרגל צד", "Sign in": "הירשם", diff --git a/src/lib/i18n/locales/hi-IN/translation.json b/src/lib/i18n/locales/hi-IN/translation.json index 3ee1cfe1ac..0cd959aa7c 100644 --- a/src/lib/i18n/locales/hi-IN/translation.json +++ b/src/lib/i18n/locales/hi-IN/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "अनुमति न दें", "Don't have an account?": "कोई खाता नहीं है?", "Don't like the style": "शैली पसंद नहीं है", + "Done": "", "Download": "डाउनलोड", "Download canceled": "डाउनलोड रद्द किया गया", "Download Database": "डेटाबेस डाउनलोड करें", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "शॉर्टकट दिखाएँ", + "Show your support!": "", "Showcased creativity": "रचनात्मकता का प्रदर्शन किया", "sidebar": "साइड बार", "Sign in": "साइन इन", diff --git a/src/lib/i18n/locales/hr-HR/translation.json b/src/lib/i18n/locales/hr-HR/translation.json index ecdc9057be..9f3412261c 100644 --- a/src/lib/i18n/locales/hr-HR/translation.json +++ b/src/lib/i18n/locales/hr-HR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Ne dopuštaj", "Don't have an account?": "Nemate račun?", "Don't like the style": "Ne sviđa mi se stil", + "Done": "", "Download": "Preuzimanje", "Download canceled": "Preuzimanje otkazano", "Download Database": "Preuzmi bazu podataka", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Pokaži prečace", + "Show your support!": "", "Showcased creativity": "Prikazana kreativnost", "sidebar": "bočna traka", "Sign in": "Prijava", diff --git a/src/lib/i18n/locales/it-IT/translation.json b/src/lib/i18n/locales/it-IT/translation.json index 0298134db6..d414a04a46 100644 --- a/src/lib/i18n/locales/it-IT/translation.json +++ b/src/lib/i18n/locales/it-IT/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Non consentire", "Don't have an account?": "Non hai un account?", "Don't like the style": "Non ti piace lo stile", + "Done": "", "Download": "Scarica", "Download canceled": "Scaricamento annullato", "Download Database": "Scarica database", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Mostra", + "Show your support!": "", "Showcased creativity": "Creatività messa in mostra", "sidebar": "barra laterale", "Sign in": "Accedi", diff --git a/src/lib/i18n/locales/ja-JP/translation.json b/src/lib/i18n/locales/ja-JP/translation.json index d91343dadd..765294c027 100644 --- a/src/lib/i18n/locales/ja-JP/translation.json +++ b/src/lib/i18n/locales/ja-JP/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "許可しない", "Don't have an account?": "アカウントをお持ちではありませんか?", "Don't like the style": "デザインが好きでない", + "Done": "", "Download": "ダウンロードをキャンセルしました", "Download canceled": "ダウンロードをキャンセルしました", "Download Database": "データベースをダウンロード", @@ -500,6 +501,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "表示", + "Show your support!": "", "Showcased creativity": "創造性を披露", "sidebar": "サイドバー", "Sign in": "サインイン", diff --git a/src/lib/i18n/locales/ka-GE/translation.json b/src/lib/i18n/locales/ka-GE/translation.json index 78a3841aa4..c814420c14 100644 --- a/src/lib/i18n/locales/ka-GE/translation.json +++ b/src/lib/i18n/locales/ka-GE/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "არ დაუშვა", "Don't have an account?": "არ გაქვს ანგარიში?", "Don't like the style": "არ ეთიკურია ფართოდ", + "Done": "", "Download": "ჩამოტვირთვა გაუქმებულია", "Download canceled": "ჩამოტვირთვა გაუქმებულია", "Download Database": "გადმოწერე მონაცემთა ბაზა", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "მალსახმობების ჩვენება", + "Show your support!": "", "Showcased creativity": "ჩვენებული ქონება", "sidebar": "საიდბარი", "Sign in": "ავტორიზაცია", diff --git a/src/lib/i18n/locales/ko-KR/translation.json b/src/lib/i18n/locales/ko-KR/translation.json index 6c8498206e..7abccd7fd5 100644 --- a/src/lib/i18n/locales/ko-KR/translation.json +++ b/src/lib/i18n/locales/ko-KR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "허용 안 함", "Don't have an account?": "계정이 없으신가요?", "Don't like the style": "스타일을 좋아하지 않으세요?", + "Done": "", "Download": "다운로드", "Download canceled": "다운로드 취소", "Download Database": "데이터베이스 다운로드", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "사용자용 계정 보류 설명창에, 관리자 상세 정보 노출", "Show Model": "", "Show shortcuts": "단축키 보기", + "Show your support!": "", "Showcased creativity": "창의성 발휘", "sidebar": "사이드바", "Sign in": "로그인", diff --git a/src/lib/i18n/locales/lt-LT/translation.json b/src/lib/i18n/locales/lt-LT/translation.json index c65693bfe8..7d2652513b 100644 --- a/src/lib/i18n/locales/lt-LT/translation.json +++ b/src/lib/i18n/locales/lt-LT/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Neleisti", "Don't have an account?": "Neturite paskyros?", "Don't like the style": "Nepatinka stilius", + "Done": "", "Download": "Parsisiųsti", "Download canceled": "Parsisiuntimas atšauktas", "Download Database": "Parsisiųsti duomenų bazę", @@ -503,6 +504,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Rodyti trumpinius", + "Show your support!": "", "Showcased creativity": "Kūrybingų užklausų paroda", "sidebar": "šoninis meniu", "Sign in": "Prisijungti", diff --git a/src/lib/i18n/locales/nb-NO/translation.json b/src/lib/i18n/locales/nb-NO/translation.json index f3c91c88d3..8de6b0861e 100644 --- a/src/lib/i18n/locales/nb-NO/translation.json +++ b/src/lib/i18n/locales/nb-NO/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Ikke tillat", "Don't have an account?": "Har du ikke en konto?", "Don't like the style": "Liker ikke stilen", + "Done": "", "Download": "Last ned", "Download canceled": "Nedlasting avbrutt", "Download Database": "Last ned database", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "Vis administratordetaljer i ventende kontooverlay", "Show Model": "", "Show shortcuts": "Vis snarveier", + "Show your support!": "", "Showcased creativity": "Vist frem kreativitet", "sidebar": "sidefelt", "Sign in": "Logg inn", diff --git a/src/lib/i18n/locales/nl-NL/translation.json b/src/lib/i18n/locales/nl-NL/translation.json index d51f7b590b..7476586987 100644 --- a/src/lib/i18n/locales/nl-NL/translation.json +++ b/src/lib/i18n/locales/nl-NL/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Niet Toestaan", "Don't have an account?": "Heb je geen account?", "Don't like the style": "Je vindt het stijl niet?", + "Done": "", "Download": "Download", "Download canceled": "Download geannuleerd", "Download Database": "Download Database", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Toon snelkoppelingen", + "Show your support!": "", "Showcased creativity": "Tooncase creativiteit", "sidebar": "sidebar", "Sign in": "Inloggen", diff --git a/src/lib/i18n/locales/pa-IN/translation.json b/src/lib/i18n/locales/pa-IN/translation.json index 03c34cbb5b..f742492d12 100644 --- a/src/lib/i18n/locales/pa-IN/translation.json +++ b/src/lib/i18n/locales/pa-IN/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "ਆਗਿਆ ਨਾ ਦਿਓ", "Don't have an account?": "ਖਾਤਾ ਨਹੀਂ ਹੈ?", "Don't like the style": "ਸਟਾਈਲ ਪਸੰਦ ਨਹੀਂ ਹੈ", + "Done": "", "Download": "ਡਾਊਨਲੋਡ", "Download canceled": "ਡਾਊਨਲੋਡ ਰੱਦ ਕੀਤਾ ਗਿਆ", "Download Database": "ਡਾਟਾਬੇਸ ਡਾਊਨਲੋਡ ਕਰੋ", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "ਸ਼ਾਰਟਕਟ ਦਿਖਾਓ", + "Show your support!": "", "Showcased creativity": "ਸਿਰਜਣਾਤਮਕਤਾ ਦਿਖਾਈ", "sidebar": "ਸਾਈਡਬਾਰ", "Sign in": "ਸਾਈਨ ਇਨ ਕਰੋ", diff --git a/src/lib/i18n/locales/pl-PL/translation.json b/src/lib/i18n/locales/pl-PL/translation.json index c57a1abe6d..3573d7c810 100644 --- a/src/lib/i18n/locales/pl-PL/translation.json +++ b/src/lib/i18n/locales/pl-PL/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Nie zezwalaj", "Don't have an account?": "Nie masz konta?", "Don't like the style": "Nie podobał mi się styl", + "Done": "", "Download": "Pobieranie", "Download canceled": "Pobieranie przerwane", "Download Database": "Pobierz bazę danych", @@ -503,6 +504,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Pokaż skróty", + "Show your support!": "", "Showcased creativity": "Pokaz kreatywności", "sidebar": "Panel boczny", "Sign in": "Zaloguj się", diff --git a/src/lib/i18n/locales/pt-BR/translation.json b/src/lib/i18n/locales/pt-BR/translation.json index 669209a5aa..ce40d80e43 100644 --- a/src/lib/i18n/locales/pt-BR/translation.json +++ b/src/lib/i18n/locales/pt-BR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Não Permitir", "Don't have an account?": "Não tem uma conta?", "Don't like the style": "Não gosta do estilo", + "Done": "", "Download": "Baixar", "Download canceled": "Download cancelado", "Download Database": "Baixar Banco de Dados", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Mostrar", + "Show your support!": "", "Showcased creativity": "Criatividade Exibida", "sidebar": "barra lateral", "Sign in": "Entrar", diff --git a/src/lib/i18n/locales/pt-PT/translation.json b/src/lib/i18n/locales/pt-PT/translation.json index d98c002761..bb48b4b901 100644 --- a/src/lib/i18n/locales/pt-PT/translation.json +++ b/src/lib/i18n/locales/pt-PT/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Não Permitir", "Don't have an account?": "Não tem uma conta?", "Don't like the style": "Não gosta do estilo", + "Done": "", "Download": "Descarregar", "Download canceled": "Download cancelado", "Download Database": "Descarregar Base de Dados", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "Mostrar Detalhes do Administrador na sobreposição de Conta Pendente", "Show Model": "", "Show shortcuts": "Mostrar atalhos", + "Show your support!": "", "Showcased creativity": "Criatividade Exibida", "sidebar": "barra lateral", "Sign in": "Entrar", diff --git a/src/lib/i18n/locales/ru-RU/translation.json b/src/lib/i18n/locales/ru-RU/translation.json index e8e3431b8f..7987953967 100644 --- a/src/lib/i18n/locales/ru-RU/translation.json +++ b/src/lib/i18n/locales/ru-RU/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Не разрешать", "Don't have an account?": "у вас не есть аккаунт?", "Don't like the style": "Не нравится стиль", + "Done": "", "Download": "Загрузить", "Download canceled": "Загрузка отменена", "Download Database": "Загрузить базу данных", @@ -503,6 +504,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Показать клавиатурные сокращения", + "Show your support!": "", "Showcased creativity": "Показать творчество", "sidebar": "боковая панель", "Sign in": "Войти", diff --git a/src/lib/i18n/locales/sr-RS/translation.json b/src/lib/i18n/locales/sr-RS/translation.json index f4483c7236..5abaa9984f 100644 --- a/src/lib/i18n/locales/sr-RS/translation.json +++ b/src/lib/i18n/locales/sr-RS/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Не дозволи", "Don't have an account?": "Немате налог?", "Don't like the style": "Не свиђа ми се стил", + "Done": "", "Download": "Преузми", "Download canceled": "Преузимање отказано", "Download Database": "Преузми базу података", @@ -502,6 +503,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Прикажи пречице", + "Show your support!": "", "Showcased creativity": "Приказана креативност", "sidebar": "бочна трака", "Sign in": "Пријави се", diff --git a/src/lib/i18n/locales/sv-SE/translation.json b/src/lib/i18n/locales/sv-SE/translation.json index d55eedaef9..618db37acd 100644 --- a/src/lib/i18n/locales/sv-SE/translation.json +++ b/src/lib/i18n/locales/sv-SE/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Tillåt inte", "Don't have an account?": "Har du inget konto?", "Don't like the style": "Tycker inte om utseendet", + "Done": "", "Download": "Ladda ner", "Download canceled": "Nedladdning avbruten", "Download Database": "Ladda ner databas", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "Visa administratörsinformation till väntande konton", "Show Model": "", "Show shortcuts": "Visa genvägar", + "Show your support!": "", "Showcased creativity": "Visade kreativitet", "sidebar": "sidofält", "Sign in": "Logga in", diff --git a/src/lib/i18n/locales/tk-TW/translation.json b/src/lib/i18n/locales/tk-TW/translation.json index af9d122bb8..ad3109a952 100644 --- a/src/lib/i18n/locales/tk-TW/translation.json +++ b/src/lib/i18n/locales/tk-TW/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "", "Don't have an account?": "", "Don't like the style": "", + "Done": "", "Download": "", "Download canceled": "", "Download Database": "", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "", + "Show your support!": "", "Showcased creativity": "", "sidebar": "", "Sign in": "", diff --git a/src/lib/i18n/locales/tr-TR/translation.json b/src/lib/i18n/locales/tr-TR/translation.json index de284a4c84..cb0ba78ae4 100644 --- a/src/lib/i18n/locales/tr-TR/translation.json +++ b/src/lib/i18n/locales/tr-TR/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "İzin Verme", "Don't have an account?": "Hesabınız yok mu?", "Don't like the style": "Tarzını beğenmedim", + "Done": "", "Download": "İndir", "Download canceled": "İndirme iptal edildi", "Download Database": "Veritabanını İndir", @@ -501,6 +502,7 @@ "Show Admin Details in Account Pending Overlay": "", "Show Model": "", "Show shortcuts": "Kısayolları göster", + "Show your support!": "", "Showcased creativity": "Sergilenen yaratıcılık", "sidebar": "kenar çubuğu", "Sign in": "Oturum aç", diff --git a/src/lib/i18n/locales/uk-UA/translation.json b/src/lib/i18n/locales/uk-UA/translation.json index 814f657b52..272f67cebf 100644 --- a/src/lib/i18n/locales/uk-UA/translation.json +++ b/src/lib/i18n/locales/uk-UA/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Не дозволяти", "Don't have an account?": "Немає облікового запису?", "Don't like the style": "Не подобається стиль", + "Done": "", "Download": "Завантажити", "Download canceled": "Завантаження скасовано", "Download Database": "Завантажити базу даних", @@ -503,6 +504,7 @@ "Show Admin Details in Account Pending Overlay": "Відобразити дані адміна у вікні очікування облікового запису", "Show Model": "Показати модель", "Show shortcuts": "Показати клавіатурні скорочення", + "Show your support!": "", "Showcased creativity": "Продемонстрований креатив", "sidebar": "бокова панель", "Sign in": "Увійти", diff --git a/src/lib/i18n/locales/vi-VN/translation.json b/src/lib/i18n/locales/vi-VN/translation.json index 60db86300e..94c7ea22d6 100644 --- a/src/lib/i18n/locales/vi-VN/translation.json +++ b/src/lib/i18n/locales/vi-VN/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "Không Cho phép", "Don't have an account?": "Không có tài khoản?", "Don't like the style": "Không thích phong cách trả lời", + "Done": "", "Download": "Tải về", "Download canceled": "Đã hủy download", "Download Database": "Tải xuống Cơ sở dữ liệu", @@ -500,6 +501,7 @@ "Show Admin Details in Account Pending Overlay": "Hiển thị thông tin của Quản trị viên trên màn hình hiển thị Tài khoản đang chờ xử lý", "Show Model": "Hiện mô hình", "Show shortcuts": "Hiển thị phím tắt", + "Show your support!": "", "Showcased creativity": "Thể hiện sự sáng tạo", "sidebar": "thanh bên", "Sign in": "Đăng nhập", diff --git a/src/lib/i18n/locales/zh-CN/translation.json b/src/lib/i18n/locales/zh-CN/translation.json index 28e68e2e69..3863f8f8d2 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "不允许", "Don't have an account?": "没有账号?", "Don't like the style": "不喜欢这个文风", + "Done": "", "Download": "下载", "Download canceled": "下载已取消", "Download Database": "下载数据库", @@ -500,6 +501,7 @@ "Show Admin Details in Account Pending Overlay": "在用户待激活界面中显示管理员邮箱等详细信息", "Show Model": "显示", "Show shortcuts": "显示快捷方式", + "Show your support!": "", "Showcased creativity": "很有创意", "sidebar": "侧边栏", "Sign in": "登录", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index 9c7d53458d..6ab58a4e07 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -184,6 +184,7 @@ "Don't Allow": "不允許", "Don't have an account?": "還沒有註冊帳號?", "Don't like the style": "不喜歡這個樣式?", + "Done": "", "Download": "下載", "Download canceled": "下載已取消", "Download Database": "下載資料庫", @@ -500,6 +501,7 @@ "Show Admin Details in Account Pending Overlay": "在帳號待審覆蓋層中顯示管理員詳細資訊", "Show Model": "顯示模型", "Show shortcuts": "顯示快速鍵", + "Show your support!": "", "Showcased creativity": "展示創造性", "sidebar": "側邊欄", "Sign in": "登入", From bc73cb139084db2e307ae7f05f314b23c51fd8e3 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 21:48:06 -0700 Subject: [PATCH 67/71] enh: iframe message event listener --- src/routes/+layout.svelte | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index c4cbc9cfde..675ecc5dc8 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -50,6 +50,33 @@ } }; + window.addEventListener('message', (event) => { + if (event.origin === window.origin) { + // Replace with your iframe's origin + console.log('Message received from iframe:', event.data); + if (event.data.type === 'input:prompt') { + console.log(event.data.text); + + const inputElement = document.getElementById('chat-textarea'); + + if (inputElement) { + inputElement.value = event.data.text; + inputElement.focus(); + } + } + + if (event.data.type === 'action:submit-prompt') { + console.log(event.data.text); + + const submitButtonElement = document.getElementById('send-message-button'); + + if (submitButtonElement) { + submitButtonElement.click(); + } + } + } + }); + window.addEventListener('resize', onResize); const setWakeLock = async () => { From f33ca4c9a5b7a618b54c25561ec98a358c2fa282 Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Sun, 23 Jun 2024 23:10:26 -0700 Subject: [PATCH 68/71] refac --- src/lib/components/chat/Chat.svelte | 35 +++++++++++++++++++++++++++++ src/routes/+layout.svelte | 27 ---------------------- 2 files changed, 35 insertions(+), 27 deletions(-) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 8f84488477..621dc827ed 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -127,6 +127,41 @@ } onMount(async () => { + window.addEventListener('message', async (event) => { + if (event.origin === window.origin) { + // Replace with your iframe's origin + console.log('Message received from iframe:', event.data); + if (event.data.type === 'input:prompt') { + console.log(event.data.text); + + const inputElement = document.getElementById('chat-textarea'); + + if (inputElement) { + prompt = event.data.text; + inputElement.focus(); + } + } + + if (event.data.type === 'action:submit') { + console.log(event.data.text); + + if (prompt !== '') { + await tick(); + submitPrompt(prompt); + } + } + + if (event.data.type === 'input:prompt:submit') { + console.log(event.data.text); + + if (prompt !== '') { + await tick(); + submitPrompt(event.data.text); + } + } + } + }); + if (!$chatId) { chatId.subscribe(async (value) => { if (!value) { diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index 675ecc5dc8..c4cbc9cfde 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -50,33 +50,6 @@ } }; - window.addEventListener('message', (event) => { - if (event.origin === window.origin) { - // Replace with your iframe's origin - console.log('Message received from iframe:', event.data); - if (event.data.type === 'input:prompt') { - console.log(event.data.text); - - const inputElement = document.getElementById('chat-textarea'); - - if (inputElement) { - inputElement.value = event.data.text; - inputElement.focus(); - } - } - - if (event.data.type === 'action:submit-prompt') { - console.log(event.data.text); - - const submitButtonElement = document.getElementById('send-message-button'); - - if (submitButtonElement) { - submitButtonElement.click(); - } - } - } - }); - window.addEventListener('resize', onResize); const setWakeLock = async () => { From 82b44740db8e84fd93f9791c6ce99722db747bbc Mon Sep 17 00:00:00 2001 From: josephrocca <1167575+josephrocca@users.noreply.github.com> Date: Mon, 24 Jun 2024 14:10:32 +0800 Subject: [PATCH 69/71] Fix scrollToBottom button container obstructing clicks on buttons beneath it --- src/lib/components/chat/MessageInput.svelte | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/MessageInput.svelte b/src/lib/components/chat/MessageInput.svelte index ba288829be..8814c6a7dd 100644 --- a/src/lib/components/chat/MessageInput.svelte +++ b/src/lib/components/chat/MessageInput.svelte @@ -291,9 +291,9 @@
{#if autoScroll === false && messages.length > 0} -
+