From fe837d80e78ef2efa84d87b8e3852179335bca5f Mon Sep 17 00:00:00 2001 From: Algorithm5838 <108630393+Algorithm5838@users.noreply.github.com> Date: Mon, 2 Mar 2026 01:34:50 +0300 Subject: [PATCH 001/176] fix: pass params when saving a temporary chat The system prompt and other chat controls overrides were lost after saving because `params` wasn't included in the `createNewChat` call. --- src/lib/components/chat/Chat.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte index 14a7de457f..4d8d06f54c 100644 --- a/src/lib/components/chat/Chat.svelte +++ b/src/lib/components/chat/Chat.svelte @@ -2724,6 +2724,7 @@ id: uuidv4(), title: title.length > 50 ? `${title.slice(0, 50)}...` : title, models: selectedModels, + params: params, history: history, messages: messages, timestamp: Date.now() From a9e9fe7899d9db3061032b060ffe9b9349259468 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Mon, 2 Mar 2026 09:06:20 +0800 Subject: [PATCH 002/176] fix: fix memory leaking of ChatControls (#22112) --- src/lib/components/chat/ChatControls.svelte | 88 ++++++++++++--------- 1 file changed, 49 insertions(+), 39 deletions(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index e5398f7f91..e091c48db3 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -50,9 +50,8 @@ export let files; export let modelId; - export let pane; + export let pane: Pane | null = null; - let mediaQuery; let largeScreen = false; let dragged = false; let minSize = 0; @@ -172,58 +171,69 @@ dragged = false; }; - onMount(async () => { - mediaQuery = window.matchMedia('(min-width: 1024px)'); + onMount(() => { + const mediaQuery = window.matchMedia('(min-width: 1024px)'); mediaQuery.addEventListener('change', handleMediaQuery); handleMediaQuery(mediaQuery); + let resizeObserver: ResizeObserver | null = null; + let isDestroyed = false; + // Wait for Svelte to render the Pane after largeScreen changed - await tick(); + const init = async () => { + await tick(); - const container = document.getElementById('chat-container'); - minSize = Math.floor((350 / container.clientWidth) * 100); + if (isDestroyed) return; - const resizeObserver = new ResizeObserver((entries) => { - for (let entry of entries) { - const width = entry.contentRect.width; - minSize = Math.floor((350 / width) * 100); - if ($showControls) { - if (pane && pane.isExpanded() && pane.getSize() < minSize) { - pane.resize(minSize); - } else { - let size = Math.floor( - (parseInt(localStorage?.chatControlsSize) / container.clientWidth) * 100 - ); - if (size < minSize) pane.resize(minSize); + // If controls were persisted as open, set the pane to the saved size + if ($showControls && pane) { + openPane(); + } + + setTimeout(() => { + paneReady = true; + }, 0); + + const container = document.getElementById('chat-container') as HTMLElement; + if (!container) return; + + minSize = Math.floor((350 / container.clientWidth) * 100); + resizeObserver = new ResizeObserver((entries) => { + for (let entry of entries) { + const width = entry.contentRect.width; + minSize = Math.floor((350 / width) * 100); + if ($showControls) { + if (pane && pane.isExpanded() && pane.getSize() < minSize) { + pane.resize(minSize); + } else { + let size = Math.floor( + (parseInt(localStorage?.chatControlsSize) / container.clientWidth) * 100 + ); + if (size < minSize && pane) pane.resize(minSize); + } } } - } - }); - resizeObserver.observe(container); + }); + resizeObserver.observe(container); + }; + init(); document.addEventListener('mousedown', onMouseDown); document.addEventListener('mouseup', onMouseUp); - setTimeout(() => { - paneReady = true; - }, 0); - - // If controls were persisted as open, set the pane to the saved size - if ($showControls && pane) { - openPane(); + return () => { + isDestroyed = true; + paneReady = false; + resizeObserver?.disconnect(); + if (!largeScreen) { + showControls.set(false); + } + mediaQuery.removeEventListener('change', handleMediaQuery); + document.removeEventListener('mousedown', onMouseDown); + document.removeEventListener('mouseup', onMouseUp); } }); - onDestroy(() => { - paneReady = false; - if (!largeScreen) { - showControls.set(false); - } - mediaQuery.removeEventListener('change', handleMediaQuery); - document.removeEventListener('mousedown', onMouseDown); - document.removeEventListener('mouseup', onMouseUp); - }); - const closeHandler = () => { if (!largeScreen) { showControls.set(false); From 2751a0f0b64b8a58b89b9fc275e81fa5424d5b01 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sun, 1 Mar 2026 19:09:10 -0600 Subject: [PATCH 003/176] refac --- backend/open_webui/utils/access_control/__init__.py | 7 ++----- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 5 insertions(+), 8 deletions(-) diff --git a/backend/open_webui/utils/access_control/__init__.py b/backend/open_webui/utils/access_control/__init__.py index 232bd20d60..a228bbd6a8 100644 --- a/backend/open_webui/utils/access_control/__init__.py +++ b/backend/open_webui/utils/access_control/__init__.py @@ -163,8 +163,8 @@ def has_connection_access( based on ``config.access_grants`` within the connection dict. - Admin with BYPASS_ADMIN_ACCESS_CONTROL → always allowed - - Empty / missing access_grants → allowed for all users - - Otherwise → delegates to ``has_access`` + - Missing, None, or empty access_grants → private, admin-only + - access_grants has entries → delegates to ``has_access`` """ from open_webui.config import BYPASS_ADMIN_ACCESS_CONTROL @@ -175,9 +175,6 @@ def has_connection_access( user_group_ids = {group.id for group in Groups.get_groups_by_member_id(user.id)} access_grants = (connection.get("config") or {}).get("access_grants", []) - if not access_grants: - return True - return has_access(user.id, "read", access_grants, user_group_ids) diff --git a/package-lock.json b/package-lock.json index 7681c6b6f9..14ce3d6500 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "open-webui", - "version": "0.8.6", + "version": "0.8.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "open-webui", - "version": "0.8.6", + "version": "0.8.7", "dependencies": { "@azure/msal-browser": "^4.5.0", "@codemirror/lang-javascript": "^6.2.2", diff --git a/package.json b/package.json index 8477f654b4..c0fef7e548 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "open-webui", - "version": "0.8.6", + "version": "0.8.7", "private": true, "scripts": { "dev": "npm run pyodide:fetch && vite dev --host", From d1dd449f63a1c95965a183ba00939a0c6436f577 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sun, 1 Mar 2026 19:12:06 -0600 Subject: [PATCH 004/176] doc: changelog --- CHANGELOG.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index e5579c2832..d38676eef3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,15 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.8.7] - 2026-03-01 + +### Fixed + +- 🔒 **Connection access control privacy.** Tool server and terminal connections without explicit access grants are now private (admin-only) by default, fixing a bug where connections configured with no access grants were visible to all users instead of being restricted. [Commit](https://github.com/open-webui/open-webui/commit/2751a0f0b) +- 🧠 **ChatControls memory leak.** The ChatControls panel no longer leaks event listeners, ResizeObserver instances, and media query handlers when navigating between chats, fixing memory accumulation that could degrade performance during extended use. [#22112](https://github.com/open-webui/open-webui/pull/22112) +- 💾 **Temporary chat params preservation.** Model parameters are now correctly saved when creating a temporary chat, ensuring custom settings like temperature and top_p persist across the session. [Commit](https://github.com/open-webui/open-webui/commit/fe837d80e) +- ⚡ **Faster artifact content updates.** Artifact content extraction during streaming is now debounced via requestAnimationFrame, reducing redundant DOM reads and improving CPU efficiency when tokens arrive faster than the browser can paint. [Commit](https://github.com/open-webui/open-webui/commit/6863ca482) + ## [0.8.6] - 2026-03-01 ### Added From 832d0181b6e90ac94d82d6f9849f86b6dcac5a4f Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Sun, 1 Mar 2026 19:13:14 -0600 Subject: [PATCH 005/176] chore: format --- src/lib/components/chat/ChatControls.svelte | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index e091c48db3..d7f546c228 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -231,7 +231,7 @@ mediaQuery.removeEventListener('change', handleMediaQuery); document.removeEventListener('mousedown', onMouseDown); document.removeEventListener('mouseup', onMouseUp); - } + }; }); const closeHandler = () => { From d7147d6cddfd314f0f1be77b15cec406a609ef36 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 11:24:15 -0600 Subject: [PATCH 006/176] refac --- src/lib/components/chat/Messages.svelte | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 36c0a2788e..9328f43961 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -67,6 +67,7 @@ messagesLoading = true; messagesCount += 20; + buildMessages(); await tick(); From 64957db7b3474574f7e083f4f306dc5a060faadf Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 11:26:33 -0600 Subject: [PATCH 007/176] refac --- backend/open_webui/utils/middleware.py | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/backend/open_webui/utils/middleware.py b/backend/open_webui/utils/middleware.py index 55f55ab033..1950148568 100644 --- a/backend/open_webui/utils/middleware.py +++ b/backend/open_webui/utils/middleware.py @@ -375,9 +375,9 @@ def serialize_output(output: list) -> str: result_item = tool_outputs.get(call_id) if result_item: result_text = "" - for output in result_item.get("output", []): - if "text" in output: - output_text = output.get("text", "") + for result_output in result_item.get("output", []): + if "text" in result_output: + output_text = result_output.get("text", "") result_text += ( str(output_text) if not isinstance(output_text, str) @@ -4424,7 +4424,8 @@ async def streaming_chat_response_handler(response, ctx): code = sanitize_code(code) if CODE_INTERPRETER_BLOCKED_MODULES: - blocking_code = textwrap.dedent(f""" + blocking_code = textwrap.dedent( + f""" import builtins BLOCKED_MODULES = {CODE_INTERPRETER_BLOCKED_MODULES} @@ -4440,7 +4441,8 @@ async def streaming_chat_response_handler(response, ctx): return _real_import(name, globals, locals, fromlist, level) builtins.__import__ = restricted_import - """) + """ + ) code = blocking_code + "\n" + code if ( From b338850cc1f7da884f395193bdf9c0c880d70de3 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Tue, 3 Mar 2026 01:26:58 +0800 Subject: [PATCH 008/176] Merge pull request #22127 from ShirasawaSama/patch-49 fix: Fix TypeScript syntax compilation errors --- src/lib/components/chat/ChatControls.svelte | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lib/components/chat/ChatControls.svelte b/src/lib/components/chat/ChatControls.svelte index d7f546c228..f9c68c2350 100644 --- a/src/lib/components/chat/ChatControls.svelte +++ b/src/lib/components/chat/ChatControls.svelte @@ -1,4 +1,4 @@ - @@ -58,8 +58,10 @@ let paneReady = false; // Tab state for Controls+Files panel - let activeTab: 'controls' | 'files' | 'overview' = savedTab; - $: savedTab = activeTab; + let activeTab = savedTab; + // svelte-ignore reactive_declaration_module_script_dependency + $: { savedTab = activeTab }; + $: hasMessages = history?.messages && Object.keys(history.messages).length > 0; $: showControlsTab = $user?.role === 'admin' || ($user?.permissions?.chat?.controls ?? true); From c701ebe07bd152eecb42b0bf6de26071358a5c76 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 11:29:29 -0600 Subject: [PATCH 009/176] refac --- src/lib/components/chat/Messages.svelte | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/lib/components/chat/Messages.svelte b/src/lib/components/chat/Messages.svelte index 9328f43961..dbd8daa16e 100644 --- a/src/lib/components/chat/Messages.svelte +++ b/src/lib/components/chat/Messages.svelte @@ -99,16 +99,21 @@ // Throttle message list rebuilds to once per animation frame during streaming. // Structural changes (currentId change) always rebuild immediately. - $: if (history.currentId) { - const currentIdChanged = history.currentId !== lastCurrentId; - lastCurrentId = history.currentId; + const handleHistoryChange = (currentId, _messages) => { + if (!currentId) { + messages = []; + return; + } + + const currentIdChanged = currentId !== lastCurrentId; + lastCurrentId = currentId; if (currentIdChanged) { // Structural change: new chat, navigation, new message — rebuild immediately cancelAnimationFrame(pendingRebuild); pendingRebuild = null; buildMessages(); - } else if (history.messages) { + } else if (_messages) { // Content update (streaming) — throttle to once per frame if (!pendingRebuild) { pendingRebuild = requestAnimationFrame(() => { @@ -117,9 +122,9 @@ }); } } - } else { - messages = []; - } + }; + + $: handleHistoryChange(history.currentId, history.messages); $: if (autoScroll && bottomPadding) { (async () => { From 0c42cd2c012f9f49816adac897e2b46573b3cb6c Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 12:03:23 -0600 Subject: [PATCH 010/176] enh: ot move --- src/lib/apis/terminal/index.ts | 26 ++++++++ src/lib/components/chat/FileNav.svelte | 19 ++++++ .../chat/FileNav/FileEntryRow.svelte | 62 ++++++++++++++++--- 3 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/lib/apis/terminal/index.ts b/src/lib/apis/terminal/index.ts index 5815bcd3c8..74c936af7e 100644 --- a/src/lib/apis/terminal/index.ts +++ b/src/lib/apis/terminal/index.ts @@ -193,3 +193,29 @@ export const setCwd = async ( }); return res; }; + +export const moveEntry = async ( + baseUrl: string, + apiKey: string, + source: string, + destination: string +): Promise<{ source: string; destination: string } | null> => { + const url = `${baseUrl.replace(/\/$/, '')}/files/move`; + const res = await fetch(url, { + method: 'POST', + headers: { + Authorization: `Bearer ${apiKey}`, + 'Content-Type': 'application/json' + }, + body: JSON.stringify({ source, destination }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.error('open-terminal moveEntry error:', err); + return null; + }); + return res; +}; diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 84ad18a71a..2f70afc179 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -21,6 +21,7 @@ uploadToTerminal, createDirectory, deleteEntry, + moveEntry, setCwd, type FileEntry } from '$lib/apis/terminal'; @@ -323,6 +324,23 @@ showDeleteConfirm = true; }; + // ── Move (drag-and-drop) ──────────────────────────────────────────── + const handleMove = async (source: string, destFolder: string) => { + const terminal = selectedTerminal; + if (!terminal) return; + + const fileName = source.split('/').pop() ?? ''; + const destination = `${destFolder}${fileName}`; + + if (source === destination) return; + + const result = await moveEntry(terminal.url, terminal.key, source, destination); + toast[result ? 'success' : 'error']( + $i18n.t(result ? 'Moved {{name}}' : 'Failed to move {{name}}', { name: fileName }) + ); + await loadDir(currentPath); + }; + // ── Lifecycle ──────────────────────────────────────────────────────── onMount(async () => { const terminal = getTerminal(); @@ -717,6 +735,7 @@ onOpen={openEntry} onDownload={downloadFile} onDelete={requestDelete} + onMove={handleMove} /> {/each} diff --git a/src/lib/components/chat/FileNav/FileEntryRow.svelte b/src/lib/components/chat/FileNav/FileEntryRow.svelte index c5d778555e..f97aa7270e 100644 --- a/src/lib/components/chat/FileNav/FileEntryRow.svelte +++ b/src/lib/components/chat/FileNav/FileEntryRow.svelte @@ -18,24 +18,66 @@ export let onOpen: (entry: FileEntry) => void = () => {}; export let onDownload: (path: string) => void = () => {}; export let onDelete: (path: string, name: string) => void = () => {}; + export let onMove: (source: string, destFolder: string) => void = () => {}; + + let dragOverFolder = false;
  • -
    +
    { + if (entry.type !== 'directory') return; + if (!e.dataTransfer?.types.includes('application/x-terminal-file-move')) return; + e.preventDefault(); + e.stopPropagation(); + dragOverFolder = true; + }} + on:dragleave={(e) => { + if (entry.type !== 'directory') return; + e.stopPropagation(); + dragOverFolder = false; + }} + on:drop={(e) => { + if (entry.type !== 'directory') return; + const raw = e.dataTransfer?.getData('application/x-terminal-file-move'); + if (!raw) return; + e.preventDefault(); + e.stopPropagation(); + dragOverFolder = false; + try { + const data = JSON.parse(raw); + if (data.path) { + const destFolder = `${currentPath}${entry.name}/`; + onMove(data.path, destFolder); + } + } catch {} + }} + > From 395098c6f1b7499d37ad55145a5931431d3e72e9 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 12:07:55 -0600 Subject: [PATCH 012/176] refac --- src/lib/components/chat/FileNav.svelte | 4 ++++ src/lib/components/chat/FileNav/FileEntryRow.svelte | 2 ++ 2 files changed, 6 insertions(+) diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index d081b98bd3..4fc148bb71 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -334,6 +334,10 @@ if (source === destination) return; + // Prevent moving a folder into itself or its own subtree + const sourceDir = source.endsWith('/') ? source : source + '/'; + if (destFolder.startsWith(sourceDir)) return; + const result = await moveEntry(terminal.url, terminal.key, source, destination); toast[result ? 'success' : 'error']( $i18n.t(result ? 'Moved {{name}}' : 'Failed to move {{name}}', { name: fileName }) diff --git a/src/lib/components/chat/FileNav/FileEntryRow.svelte b/src/lib/components/chat/FileNav/FileEntryRow.svelte index f97aa7270e..6f531b0f01 100644 --- a/src/lib/components/chat/FileNav/FileEntryRow.svelte +++ b/src/lib/components/chat/FileNav/FileEntryRow.svelte @@ -51,6 +51,8 @@ const data = JSON.parse(raw); if (data.path) { const destFolder = `${currentPath}${entry.name}/`; + // Don't allow dropping a folder onto itself + if (data.path + '/' === destFolder || data.path === destFolder) return; onMove(data.path, destFolder); } } catch {} From 11487d66fc1a2dfafbdaa2b7ef939a86caaf3872 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 12:09:49 -0600 Subject: [PATCH 013/176] refac --- src/lib/apis/terminal/index.ts | 4 ++-- src/lib/components/chat/FileNav.svelte | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/lib/apis/terminal/index.ts b/src/lib/apis/terminal/index.ts index 74c936af7e..5ab2039833 100644 --- a/src/lib/apis/terminal/index.ts +++ b/src/lib/apis/terminal/index.ts @@ -199,7 +199,7 @@ export const moveEntry = async ( apiKey: string, source: string, destination: string -): Promise<{ source: string; destination: string } | null> => { +): Promise<{ source: string; destination: string } | { error: string }> => { const url = `${baseUrl.replace(/\/$/, '')}/files/move`; const res = await fetch(url, { method: 'POST', @@ -215,7 +215,7 @@ export const moveEntry = async ( }) .catch((err) => { console.error('open-terminal moveEntry error:', err); - return null; + return { error: err?.detail ?? 'Move failed' }; }); return res; }; diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 4fc148bb71..8f85f1e504 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -339,9 +339,11 @@ if (destFolder.startsWith(sourceDir)) return; const result = await moveEntry(terminal.url, terminal.key, source, destination); - toast[result ? 'success' : 'error']( - $i18n.t(result ? 'Moved {{name}}' : 'Failed to move {{name}}', { name: fileName }) - ); + if ('error' in result) { + toast.error(result.error); + } else { + toast.success($i18n.t('Moved {{name}}', { name: fileName })); + } await loadDir(currentPath); }; From bec227da302dca93b2525baa71dec3ebb5205fe0 Mon Sep 17 00:00:00 2001 From: Shirasawa <764798966@qq.com> Date: Tue, 3 Mar 2026 02:23:00 +0800 Subject: [PATCH 014/176] i18n: improve Chinese translations (#22148) --- src/lib/i18n/locales/zh-CN/translation.json | 4 ++-- src/lib/i18n/locales/zh-TW/translation.json | 4 ++-- 2 files 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 04f6678546..776dfd7a63 100644 --- a/src/lib/i18n/locales/zh-CN/translation.json +++ b/src/lib/i18n/locales/zh-CN/translation.json @@ -872,7 +872,7 @@ "File Context": "文件上下文", "File deleted successfully.": "文件已成功删除。", "File Mode": "文件模式", - "File name": "", + "File name": "文件名", "File not found.": "文件未找到。", "File removed successfully.": "文件成功删除", "File size should not exceed {{maxSize}} MB.": "文件大小不应超过 {{maxSize}} MB", @@ -1265,7 +1265,7 @@ "New": "最新", "New Button": "新按钮", "New Chat": "新对话", - "New File": "", + "New File": "新建文件", "New Folder": "创建分组", "New Function": "新函数", "New Group": "新建权限组", diff --git a/src/lib/i18n/locales/zh-TW/translation.json b/src/lib/i18n/locales/zh-TW/translation.json index d4618f1630..4850a4477a 100644 --- a/src/lib/i18n/locales/zh-TW/translation.json +++ b/src/lib/i18n/locales/zh-TW/translation.json @@ -872,7 +872,7 @@ "File Context": "檔案上下文", "File deleted successfully.": "檔案已成功刪除。", "File Mode": "檔案模式", - "File name": "", + "File name": "檔案名稱", "File not found.": "未找到檔案。", "File removed successfully.": "成功移除檔案。", "File size should not exceed {{maxSize}} MB.": "檔案大小不應超過 {{maxSize}} MB。", @@ -1265,7 +1265,7 @@ "New": "最新", "New Button": "新按鈕", "New Chat": "新增對話", - "New File": "", + "New File": "新增檔案", "New Folder": "新增資料夾", "New Function": "新增函式", "New Group": "新增權限群組", From 3909b62ffcf49839fa57346ed8487ae759811503 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Mon, 2 Mar 2026 12:45:50 -0600 Subject: [PATCH 015/176] enh: file nav html rendering --- src/lib/components/chat/FileNav.svelte | 4 +++- src/lib/components/chat/FileNav/FilePreview.svelte | 14 +++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/src/lib/components/chat/FileNav.svelte b/src/lib/components/chat/FileNav.svelte index 8f85f1e504..07728d1499 100644 --- a/src/lib/components/chat/FileNav.svelte +++ b/src/lib/components/chat/FileNav.svelte @@ -62,10 +62,12 @@ const MD_EXTS = new Set(['md', 'markdown', 'mdx']); const CSV_EXTS = new Set(['csv', 'tsv']); + const HTML_EXTS = new Set(['html', 'htm']); const getFileExt = (path: string | null) => path?.split('.').pop()?.toLowerCase() ?? ''; $: isMarkdown = MD_EXTS.has(getFileExt(selectedFile)); $: isCsv = CSV_EXTS.has(getFileExt(selectedFile)); + $: isHtml = HTML_EXTS.has(getFileExt(selectedFile)); $: isTextFile = fileContent !== null && fileImageUrl === null && filePdfData === null; // ── Upload / folder creation ───────────────────────────────────────── @@ -513,7 +515,7 @@ {/if} - {#if (isMarkdown || isCsv) && fileContent !== null && !editing} + {#if (isMarkdown || isCsv || isHtml) && fileContent !== null && !editing}