From bffbe5412096e8fb0d95c1655d52222e62ab6220 Mon Sep 17 00:00:00 2001
From: zyileven <40888939+zyileven@users.noreply.github.com>
Date: Wed, 3 Sep 2025 14:48:30 +0800
Subject: [PATCH 1/3] =?UTF-8?q?fix:=20=20Solve=20the=20problem=20of=20open?=
=?UTF-8?q?ing=20remarks=20appearing=20in=20the=20chat=20cont=E2=80=A6=20(?=
=?UTF-8?q?#25067)?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../chat/chat-with-history/chat-wrapper.tsx | 35 ++++++++++---------
1 file changed, 19 insertions(+), 16 deletions(-)
diff --git a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
index e856e6a88a..cc5e46deeb 100644
--- a/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
+++ b/web/app/components/base/chat/chat-with-history/chat-wrapper.tsx
@@ -52,6 +52,10 @@ const ChatWrapper = () => {
allInputsHidden,
initUserVariables,
} = useChatWithHistoryContext()
+
+ // Semantic variable for better code readability
+ const isHistoryConversation = !!currentConversationId
+
const appConfig = useMemo(() => {
const config = appParams || {}
@@ -62,9 +66,9 @@ const ChatWrapper = () => {
fileUploadConfig: (config as any).system_parameters,
},
supportFeedback: true,
- opening_statement: currentConversationId ? currentConversationItem?.introduction : (config as any).opening_statement,
+ opening_statement: isHistoryConversation ? currentConversationItem?.introduction : (config as any).opening_statement,
} as ChatConfig
- }, [appParams, currentConversationItem?.introduction, currentConversationId])
+ }, [appParams, currentConversationItem?.introduction, isHistoryConversation])
const {
chatList,
setTargetMessageId,
@@ -75,7 +79,7 @@ const ChatWrapper = () => {
} = useChat(
appConfig,
{
- inputs: (currentConversationId ? currentConversationInputs : newConversationInputs) as any,
+ inputs: (isHistoryConversation ? currentConversationInputs : newConversationInputs) as any,
inputsForm: inputsForms,
},
appPrevChatTree,
@@ -83,7 +87,7 @@ const ChatWrapper = () => {
clearChatList,
setClearChatList,
)
- const inputsFormValue = currentConversationId ? currentConversationInputs : newConversationInputsRef?.current
+ const inputsFormValue = isHistoryConversation ? currentConversationInputs : newConversationInputsRef?.current
const inputDisabled = useMemo(() => {
if (allInputsHidden)
return false
@@ -132,7 +136,7 @@ const ChatWrapper = () => {
const data: any = {
query: message,
files,
- inputs: formatBooleanInputs(inputsForms, currentConversationId ? currentConversationInputs : newConversationInputs),
+ inputs: formatBooleanInputs(inputsForms, isHistoryConversation ? currentConversationInputs : newConversationInputs),
conversation_id: currentConversationId,
parent_message_id: (isRegenerate ? parentAnswer?.id : getLastAnswer(chatList)?.id) || null,
}
@@ -142,11 +146,11 @@ const ChatWrapper = () => {
data,
{
onGetSuggestedQuestions: responseItemId => fetchSuggestedQuestions(responseItemId, isInstalledApp, appId),
- onConversationComplete: currentConversationId ? undefined : handleNewConversationCompleted,
+ onConversationComplete: isHistoryConversation ? undefined : handleNewConversationCompleted,
isPublicAPI: !isInstalledApp,
},
)
- }, [chatList, handleNewConversationCompleted, handleSend, currentConversationId, currentConversationInputs, newConversationInputs, isInstalledApp, appId])
+ }, [chatList, handleNewConversationCompleted, handleSend, isHistoryConversation, currentConversationInputs, newConversationInputs, isInstalledApp, appId])
const doRegenerate = useCallback((chatItem: ChatItemInTree, editedQuestion?: { message: string, files?: FileEntity[] }) => {
const question = editedQuestion ? chatItem : chatList.find(item => item.id === chatItem.parentMessageId)!
@@ -159,31 +163,30 @@ const ChatWrapper = () => {
}, [chatList, doSend])
const messageList = useMemo(() => {
- if (currentConversationId)
- return chatList
+ // Always filter out opening statement from message list as it's handled separately in welcome component
return chatList.filter(item => !item.isOpeningStatement)
- }, [chatList, currentConversationId])
+ }, [chatList])
- const [collapsed, setCollapsed] = useState(!!currentConversationId)
+ const [collapsed, setCollapsed] = useState(isHistoryConversation)
const chatNode = useMemo(() => {
if (allInputsHidden || !inputsForms.length)
return null
if (isMobile) {
- if (!currentConversationId)
+ if (!isHistoryConversation)
return
return null
}
else {
return
}
- }, [inputsForms.length, isMobile, currentConversationId, collapsed, allInputsHidden])
+ }, [inputsForms.length, isMobile, isHistoryConversation, collapsed, allInputsHidden])
const welcome = useMemo(() => {
const welcomeMessage = chatList.find(item => item.isOpeningStatement)
if (respondingState)
return null
- if (currentConversationId)
+ if (isHistoryConversation)
return null
if (!welcomeMessage)
return null
@@ -224,7 +227,7 @@ const ChatWrapper = () => {
)
- }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, currentConversationId, inputsForms.length, respondingState, allInputsHidden])
+ }, [appData?.site.icon, appData?.site.icon_background, appData?.site.icon_type, appData?.site.icon_url, chatList, collapsed, isHistoryConversation, inputsForms.length, respondingState, allInputsHidden])
const answerIcon = (appData?.site && appData.site.use_icon_as_answer_icon)
? {
chatFooterClassName='pb-4'
chatFooterInnerClassName={`mx-auto w-full max-w-[768px] ${isMobile ? 'px-2' : 'px-4'}`}
onSend={doSend}
- inputs={currentConversationId ? currentConversationInputs as any : newConversationInputs}
+ inputs={isHistoryConversation ? currentConversationInputs as any : newConversationInputs}
inputsForm={inputsForms}
onRegenerate={doRegenerate}
onStopResponding={handleStop}
From 0e8a37dca879d942324454e706ca92dc3c7c0499 Mon Sep 17 00:00:00 2001
From: "github-actions[bot]"
<41898282+github-actions[bot]@users.noreply.github.com>
Date: Wed, 3 Sep 2025 14:48:53 +0800
Subject: [PATCH 2/3] chore: translate i18n files (#25061)
Co-authored-by: zxhlyh <16177003+zxhlyh@users.noreply.github.com>
---
web/i18n/de-DE/common.ts | 1 +
web/i18n/fa-IR/common.ts | 1 +
web/i18n/hi-IN/common.ts | 1 +
web/i18n/ro-RO/common.ts | 1 +
web/i18n/th-TH/common.ts | 1 +
5 files changed, 5 insertions(+)
diff --git a/web/i18n/de-DE/common.ts b/web/i18n/de-DE/common.ts
index 70f3d97037..dec18fd4f2 100644
--- a/web/i18n/de-DE/common.ts
+++ b/web/i18n/de-DE/common.ts
@@ -490,6 +490,7 @@ const translation = {
providerManagedTip: 'Die aktuelle Konfiguration wird vom Anbieter gehostet.',
configLoadBalancing: 'Konfiguration Lastenverteilung',
specifyModelCredentialTip: 'Verwenden Sie ein konfiguriertes Modellzugang.',
+ manageCredentials: 'Anmeldeinformationen verwalten',
},
},
dataSource: {
diff --git a/web/i18n/fa-IR/common.ts b/web/i18n/fa-IR/common.ts
index 84bda8dfa5..d78dd45662 100644
--- a/web/i18n/fa-IR/common.ts
+++ b/web/i18n/fa-IR/common.ts
@@ -494,6 +494,7 @@ const translation = {
specifyModelCredentialTip: 'از اعتبارنامه مدل پیکربندی شده استفاده کنید.',
providerManagedTip: 'تنظیمات فعلی توسط ارائهدهنده میزبانی میشود.',
modelCredentials: 'مدل اعتبارنامه',
+ manageCredentials: 'مدیریت اعتبارنامه ها',
},
},
dataSource: {
diff --git a/web/i18n/hi-IN/common.ts b/web/i18n/hi-IN/common.ts
index a2de883cd9..ade633dec5 100644
--- a/web/i18n/hi-IN/common.ts
+++ b/web/i18n/hi-IN/common.ts
@@ -510,6 +510,7 @@ const translation = {
specifyModelCredential: 'मॉडल की क्रेडेंशियल निर्दिष्ट करें',
specifyModelCredentialTip: 'कॉन्फ़िगर की गई मॉडल क्रेडेंशियल का उपयोग करें।',
providerManagedTip: 'वर्तमान कॉन्फ़िगरेशन प्रदाता द्वारा होस्ट किया गया है।',
+ selectModelCredential: 'एक मॉडल क्रेडेंशियल चुनें',
},
},
dataSource: {
diff --git a/web/i18n/ro-RO/common.ts b/web/i18n/ro-RO/common.ts
index 5fa8a9e2b2..eea41d1c0e 100644
--- a/web/i18n/ro-RO/common.ts
+++ b/web/i18n/ro-RO/common.ts
@@ -490,6 +490,7 @@ const translation = {
providerManagedTip: 'Configurarea curentă este găzduită de furnizor.',
modelCredentials: 'Credențiale model',
specifyModelCredentialTip: 'Utilizați un acreditiv de model configurat.',
+ addNewModelCredential: 'Adăugați acreditive noi pentru model',
},
},
dataSource: {
diff --git a/web/i18n/th-TH/common.ts b/web/i18n/th-TH/common.ts
index db30f103b3..b78ad47f22 100644
--- a/web/i18n/th-TH/common.ts
+++ b/web/i18n/th-TH/common.ts
@@ -489,6 +489,7 @@ const translation = {
authorizationError: 'ข้อผิดพลาดในการอนุญาต',
specifyModelCredentialTip: 'ใช้ข้อมูลรับรองโมเดลที่กำหนดไว้',
providerManagedTip: 'การกำหนดค่าปัจจุบันถูกโฮสต์โดยผู้ให้บริการ.',
+ customModelCredentialsDeleteTip: 'ข้อมูลรับรองกำลังถูกใช้งานและไม่สามารถลบได้',
},
},
dataSource: {
From 462e764a3c0e3aedf1ad3d9f0f384eed1409786e Mon Sep 17 00:00:00 2001
From: Asuka Minato
Date: Wed, 3 Sep 2025 15:54:38 +0900
Subject: [PATCH 3/3] typevar example (#25064)
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
---
api/core/helper/position_helper.py | 23 +++++++++++++----------
1 file changed, 13 insertions(+), 10 deletions(-)
diff --git a/api/core/helper/position_helper.py b/api/core/helper/position_helper.py
index 8def6fe4ed..314f052832 100644
--- a/api/core/helper/position_helper.py
+++ b/api/core/helper/position_helper.py
@@ -1,7 +1,7 @@
import os
from collections import OrderedDict
from collections.abc import Callable
-from typing import Any
+from typing import TypeVar
from configs import dify_config
from core.tools.utils.yaml_utils import load_yaml_file
@@ -72,11 +72,14 @@ def pin_position_map(original_position_map: dict[str, int], pin_list: list[str])
return position_map
+T = TypeVar("T")
+
+
def is_filtered(
include_set: set[str],
exclude_set: set[str],
- data: Any,
- name_func: Callable[[Any], str],
+ data: T,
+ name_func: Callable[[T], str],
) -> bool:
"""
Check if the object should be filtered out.
@@ -103,9 +106,9 @@ def is_filtered(
def sort_by_position_map(
position_map: dict[str, int],
- data: list[Any],
- name_func: Callable[[Any], str],
-) -> list[Any]:
+ data: list[T],
+ name_func: Callable[[T], str],
+):
"""
Sort the objects by the position map.
If the name of the object is not in the position map, it will be put at the end.
@@ -122,9 +125,9 @@ def sort_by_position_map(
def sort_to_dict_by_position_map(
position_map: dict[str, int],
- data: list[Any],
- name_func: Callable[[Any], str],
-) -> OrderedDict[str, Any]:
+ data: list[T],
+ name_func: Callable[[T], str],
+):
"""
Sort the objects into a ordered dict by the position map.
If the name of the object is not in the position map, it will be put at the end.
@@ -134,4 +137,4 @@ def sort_to_dict_by_position_map(
:return: an OrderedDict with the sorted pairs of name and object
"""
sorted_items = sort_by_position_map(position_map, data, name_func)
- return OrderedDict([(name_func(item), item) for item in sorted_items])
+ return OrderedDict((name_func(item), item) for item in sorted_items)