From 3136eb8e4b84d4a7614ce15db60f3627138a8cd0 Mon Sep 17 00:00:00 2001 From: KVOJJJin Date: Mon, 21 Apr 2025 17:58:01 +0800 Subject: [PATCH 1/6] Fix: json update in conversation variable (#18483) --- .../panel/chat-variable-panel/components/variable-modal.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx index 947007e93e..d8da0e69a3 100644 --- a/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx +++ b/web/app/components/workflow/panel/chat-variable-panel/components/variable-modal.tsx @@ -123,7 +123,7 @@ const ChatVariableModal = ({ case ChatVarType.Number: return value || 0 case ChatVarType.Object: - return formatValueFromObject(objectValue) + return editInJSON ? value : formatValueFromObject(objectValue) case ChatVarType.ArrayString: case ChatVarType.ArrayNumber: case ChatVarType.ArrayObject: From 2543162dec3768ae807ed6cf40b59d1bebfd2e95 Mon Sep 17 00:00:00 2001 From: -LAN- Date: Mon, 21 Apr 2025 18:58:22 +0900 Subject: [PATCH 2/6] fix: cannot delete workflow version if other version is published as a tool (#18486) Signed-off-by: -LAN- --- api/models/workflow.py | 7 +++++++ api/services/workflow_service.py | 16 ++++++++++++++-- .../services/workflow/test_workflow_deletion.py | 11 ++++++++++- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/api/models/workflow.py b/api/models/workflow.py index 51f2f4cc9f..5a67fa47a8 100644 --- a/api/models/workflow.py +++ b/api/models/workflow.py @@ -245,6 +245,13 @@ class Workflow(Base): @property def tool_published(self) -> bool: + """ + DEPRECATED: This property is not accurate for determining if a workflow is published as a tool. + It only checks if there's a WorkflowToolProvider for the app, not if this specific workflow version + is the one being used by the tool. + + For accurate checking, use a direct query with tenant_id, app_id, and version. + """ from models.tools import WorkflowToolProvider return ( diff --git a/api/services/workflow_service.py b/api/services/workflow_service.py index b88c7b296d..5cd5c55746 100644 --- a/api/services/workflow_service.py +++ b/api/services/workflow_service.py @@ -28,6 +28,7 @@ from extensions.ext_database import db from models.account import Account from models.enums import CreatedByRole from models.model import App, AppMode +from models.tools import WorkflowToolProvider from models.workflow import ( Workflow, WorkflowNodeExecution, @@ -523,8 +524,19 @@ class WorkflowService: # Cannot delete a workflow that's currently in use by an app raise WorkflowInUseError(f"Cannot delete workflow that is currently in use by app '{app.name}'") - # Check if this workflow is published as a tool - if workflow.tool_published: + # Don't use workflow.tool_published as it's not accurate for specific workflow versions + # Check if there's a tool provider using this specific workflow version + tool_provider = ( + session.query(WorkflowToolProvider) + .filter( + WorkflowToolProvider.tenant_id == workflow.tenant_id, + WorkflowToolProvider.app_id == workflow.app_id, + WorkflowToolProvider.version == workflow.version, + ) + .first() + ) + + if tool_provider: # Cannot delete a workflow that's published as a tool raise WorkflowInUseError("Cannot delete workflow that is published as a tool") diff --git a/api/tests/unit_tests/services/workflow/test_workflow_deletion.py b/api/tests/unit_tests/services/workflow/test_workflow_deletion.py index 56efcccc78..223020c2c5 100644 --- a/api/tests/unit_tests/services/workflow/test_workflow_deletion.py +++ b/api/tests/unit_tests/services/workflow/test_workflow_deletion.py @@ -40,6 +40,10 @@ def workflow_setup(): def test_delete_workflow_success(workflow_setup): # Setup mocks + + # Mock the tool provider query to return None (not published as a tool) + workflow_setup["session"].query.return_value.filter.return_value.first.return_value = None + workflow_setup["session"].scalar = MagicMock( side_effect=[workflow_setup["workflow"], None] ) # Return workflow first, then None for app @@ -97,7 +101,12 @@ def test_delete_workflow_in_use_by_app_error(workflow_setup): def test_delete_workflow_published_as_tool_error(workflow_setup): # Setup mocks - workflow_setup["workflow"].tool_published = True + from models.tools import WorkflowToolProvider + + # Mock the tool provider query + mock_tool_provider = MagicMock(spec=WorkflowToolProvider) + workflow_setup["session"].query.return_value.filter.return_value.first.return_value = mock_tool_provider + workflow_setup["session"].scalar = MagicMock( side_effect=[workflow_setup["workflow"], None] ) # Return workflow first, then None for app From be964c78ecf2d98cf8d484b31799eea5b751f7b4 Mon Sep 17 00:00:00 2001 From: GuanMu Date: Mon, 21 Apr 2025 21:00:04 +0800 Subject: [PATCH 3/6] fix: update document link based on client locale (#18493) --- web/app/components/datasets/documents/index.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/web/app/components/datasets/documents/index.tsx b/web/app/components/datasets/documents/index.tsx index 20e14a994b..854c984559 100644 --- a/web/app/components/datasets/documents/index.tsx +++ b/web/app/components/datasets/documents/index.tsx @@ -29,6 +29,8 @@ import { useChildSegmentListKey, useSegmentListKey } from '@/service/knowledge/u import useEditDocumentMetadata from '../metadata/hooks/use-edit-dataset-metadata' import DatasetMetadataDrawer from '../metadata/metadata-dataset/dataset-metadata-drawer' import StatusWithAction from '../common/document-status-with-action/status-with-action' +import { LanguagesSupported } from '@/i18n/language' +import { getLocaleOnClient } from '@/i18n' const FolderPlusIcon = ({ className }: React.SVGProps) => { return @@ -98,7 +100,7 @@ const Documents: FC = ({ datasetId }) => { const isDataSourceWeb = dataset?.data_source_type === DataSourceType.WEB const isDataSourceFile = dataset?.data_source_type === DataSourceType.FILE const embeddingAvailable = !!dataset?.embedding_available - + const locale = getLocaleOnClient() const debouncedSearchValue = useDebounce(searchValue, { wait: 500 }) const { data: documentsRes, isFetching: isListLoading } = useDocumentList({ @@ -260,7 +262,12 @@ const Documents: FC = ({ datasetId }) => { + href={ + locale === LanguagesSupported[1] + ? 'https://docs.dify.ai/v/zh-hans/guides/knowledge-base/integrate-knowledge-within-application' + : 'https://docs.dify.ai/guides/knowledge-base/integrate-knowledge-within-application' + } + > {t('datasetDocuments.list.learnMore')} From ee30497237d9963c2bf4f8b0d8f37b0192517231 Mon Sep 17 00:00:00 2001 From: Wunmi Sogunle Date: Tue, 22 Apr 2025 02:56:53 +0100 Subject: [PATCH 4/6] fix(markdown): correctly render links with inline code (#18500) --- web/app/components/base/markdown.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/web/app/components/base/markdown.tsx b/web/app/components/base/markdown.tsx index 52b880affa..6ea84a2842 100644 --- a/web/app/components/base/markdown.tsx +++ b/web/app/components/base/markdown.tsx @@ -252,7 +252,7 @@ const Img = ({ src }: any) => { return
} -const Link = ({ node, ...props }: any) => { +const Link = ({ node, children, ...props }: any) => { if (node.properties?.href && node.properties.href?.toString().startsWith('abbr')) { // eslint-disable-next-line react-hooks/rules-of-hooks const { onSend } = useChatContext() @@ -261,7 +261,7 @@ const Link = ({ node, ...props }: any) => { return onSend?.(hidden_text)} title={node.children[0]?.value}>{node.children[0]?.value} } else { - return {node.children[0] ? node.children[0]?.value : 'Download'} + return {children || 'Download'} } } From 80f5ee1eb2d12f2a0aba9a91025c1b965b41decb Mon Sep 17 00:00:00 2001 From: Wu Tianwei <30284043+WTW0313@users.noreply.github.com> Date: Tue, 22 Apr 2025 09:59:14 +0800 Subject: [PATCH 5/6] fix: fix workflow as a tool confirm dialog layout issue (#18494) --- .../agent/agent-tools/setting-built-in-tool.tsx | 2 +- .../dataset-config/card-item/item.tsx | 2 +- web/app/components/app/log/list.tsx | 2 +- web/app/components/app/workflow-log/list.tsx | 2 +- web/app/components/base/drawer-plus/index.tsx | 8 +++++++- web/app/components/base/drawer/index.tsx | 14 +++++++++----- .../detail/completed/common/full-screen-drawer.tsx | 2 +- .../components/datasets/documents/detail/index.tsx | 2 +- web/app/components/datasets/hit-testing/index.tsx | 4 ++-- .../metadata-dataset/dataset-metadata-drawer.tsx | 2 +- .../plugins/plugin-detail-panel/endpoint-modal.tsx | 2 +- .../plugins/plugin-detail-panel/index.tsx | 2 +- .../plugin-detail-panel/strategy-detail.tsx | 2 +- web/app/components/tools/add-tool-modal/index.tsx | 2 +- .../config-credentials.tsx | 4 +++- web/app/components/tools/provider/detail.tsx | 2 +- .../components/dataset-item.tsx | 2 +- 17 files changed, 34 insertions(+), 22 deletions(-) diff --git a/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx b/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx index 75183ab5a7..952ad66fc4 100644 --- a/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx +++ b/web/app/components/app/configuration/config/agent/agent-tools/setting-built-in-tool.tsx @@ -163,7 +163,7 @@ const SettingBuiltInTool: FC = ({ footer={null} mask={false} positionCenter={false} - panelClassname={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} + panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} > <> {isLoading && } diff --git a/web/app/components/app/configuration/dataset-config/card-item/item.tsx b/web/app/components/app/configuration/dataset-config/card-item/item.tsx index d44fb145bb..65ad2ca941 100644 --- a/web/app/components/app/configuration/dataset-config/card-item/item.tsx +++ b/web/app/components/app/configuration/dataset-config/card-item/item.tsx @@ -97,7 +97,7 @@ const Item: FC = ({ - setShowSettingsModal(false)} footer={null} mask={isMobile} panelClassname='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'> + setShowSettingsModal(false)} footer={null} mask={isMobile} panelClassName='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'> setShowSettingsModal(false)} diff --git a/web/app/components/app/log/list.tsx b/web/app/components/app/log/list.tsx index b78af5cdba..056ce84f1e 100644 --- a/web/app/components/app/log/list.tsx +++ b/web/app/components/app/log/list.tsx @@ -743,7 +743,7 @@ const ConversationList: FC = ({ logs, appDetail, onRefresh }) onClose={onCloseDrawer} mask={isMobile} footer={null} - panelClassname='mt-16 mx-2 sm:mr-2 mb-4 !p-0 !max-w-[640px] rounded-xl bg-components-panel-bg' + panelClassName='mt-16 mx-2 sm:mr-2 mb-4 !p-0 !max-w-[640px] rounded-xl bg-components-panel-bg' > = ({ logs, appDetail, onRefresh }) => { onClose={onCloseDrawer} mask={isMobile} footer={null} - panelClassname='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[600px] rounded-xl border border-components-panel-border' + panelClassName='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[600px] rounded-xl border border-components-panel-border' > diff --git a/web/app/components/base/drawer-plus/index.tsx b/web/app/components/base/drawer-plus/index.tsx index bb022acdcb..33a1948181 100644 --- a/web/app/components/base/drawer-plus/index.tsx +++ b/web/app/components/base/drawer-plus/index.tsx @@ -9,6 +9,8 @@ import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints' type Props = { isShow: boolean onHide: () => void + dialogClassName?: string + dialogBackdropClassName?: string panelClassName?: string maxWidthClassName?: string contentClassName?: string @@ -26,6 +28,8 @@ type Props = { const DrawerPlus: FC = ({ isShow, onHide, + dialogClassName = '', + dialogBackdropClassName = '', panelClassName = '', maxWidthClassName = '!max-w-[640px]', height = 'calc(100vh - 72px)', @@ -55,7 +59,9 @@ const DrawerPlus: FC = ({ footer={null} mask={isMobile || isShowMask} positionCenter={positionCenter} - panelClassname={cn('mx-2 mb-3 mt-16 rounded-xl !p-0 sm:mr-2', panelClassName, maxWidthClassName)} + dialogClassName={dialogClassName} + dialogBackdropClassName={dialogBackdropClassName} + panelClassName={cn('mx-2 mb-3 mt-16 rounded-xl !p-0 sm:mr-2', panelClassName, maxWidthClassName)} >
!clickOutsideNotOpen && onClose()} - className="fixed inset-0 z-[80] overflow-y-auto" + className={cn('fixed inset-0 z-[30] overflow-y-auto', dialogClassName)} >
{/* mask */} { !clickOutsideNotOpen && onClose() }} /> -
+
<>
{title && = ({ = ({ datasetId, documentId }) => { }
} - setShowMetadata(false)} isMobile={isMobile} panelClassname='!justify-start' footer={null}> + setShowMetadata(false)} isMobile={isMobile} panelClassName='!justify-start' footer={null}> = ({ datasetId }: Props) => { )}
- +
{/* {renderHitResults(generalResultData)} */} {submitLoading @@ -197,7 +197,7 @@ const HitTestingPage: FC = ({ datasetId }: Props) => { }
- setIsShowModifyRetrievalModal(false)} footer={null} mask={isMobile} panelClassname='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'> + setIsShowModifyRetrievalModal(false)} footer={null} mask={isMobile} panelClassName='mt-16 mx-2 sm:mr-2 mb-3 !p-0 !max-w-[640px] rounded-xl'> = ({ showClose title={t('dataset.metadata.metadata')} footer={null} - panelClassname='px-4 block !max-w-[420px] my-2 rounded-l-2xl' + panelClassName='px-4 block !max-w-[420px] my-2 rounded-l-2xl' >
{t(`${i18nPrefix}.description`)}
diff --git a/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx index 46aaf6a7d6..fd862720af 100644 --- a/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx +++ b/web/app/components/plugins/plugin-detail-panel/endpoint-modal.tsx @@ -46,7 +46,7 @@ const EndpointModal: FC = ({ footer={null} mask positionCenter={false} - panelClassname={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} + panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} > <>
diff --git a/web/app/components/plugins/plugin-detail-panel/index.tsx b/web/app/components/plugins/plugin-detail-panel/index.tsx index 70bd9edabc..3ec867faae 100644 --- a/web/app/components/plugins/plugin-detail-panel/index.tsx +++ b/web/app/components/plugins/plugin-detail-panel/index.tsx @@ -38,7 +38,7 @@ const PluginDetailPanel: FC = ({ footer={null} mask={false} positionCenter={false} - panelClassname={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} + panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} > {detail && ( <> diff --git a/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx b/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx index 89ee850e03..00794d83ed 100644 --- a/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx +++ b/web/app/components/plugins/plugin-detail-panel/strategy-detail.tsx @@ -78,7 +78,7 @@ const StrategyDetail: FC = ({ footer={null} mask={false} positionCenter={false} - panelClassname={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} + panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} > <> {/* header */} diff --git a/web/app/components/tools/add-tool-modal/index.tsx b/web/app/components/tools/add-tool-modal/index.tsx index 1129fe55ce..c45313fc09 100644 --- a/web/app/components/tools/add-tool-modal/index.tsx +++ b/web/app/components/tools/add-tool-modal/index.tsx @@ -178,7 +178,7 @@ const AddToolModal: FC = ({ clickOutsideNotOpen onClose={onHide} footer={null} - panelClassname={cn('mx-2 mb-3 mt-16 rounded-xl !p-0 sm:mr-2', 'mt-2 !w-[640px]', '!max-w-[640px]')} + panelClassName={cn('mx-2 mb-3 mt-16 rounded-xl !p-0 sm:mr-2', 'mt-2 !w-[640px]', '!max-w-[640px]')} >
= ({ positionCenter={positionCenter} onHide={onHide} title={t('tools.createTool.authMethod.title')!} - panelClassName='mt-2 !w-[520px] h-fit' + dialogClassName='z-[60]' + dialogBackdropClassName='z-[70]' + panelClassName='mt-2 !w-[520px] h-fit z-[80]' maxWidthClassName='!max-w-[520px]' height={'fit-content'} headerClassName='!border-b-divider-regular' diff --git a/web/app/components/tools/provider/detail.tsx b/web/app/components/tools/provider/detail.tsx index 5d3a1794d8..21ea8bc464 100644 --- a/web/app/components/tools/provider/detail.tsx +++ b/web/app/components/tools/provider/detail.tsx @@ -234,7 +234,7 @@ const ProviderDetail = ({ footer={null} mask={false} positionCenter={false} - panelClassname={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} + panelClassName={cn('mb-2 mr-2 mt-[64px] !w-[420px] !max-w-[420px] justify-start rounded-2xl border-[0.5px] border-components-panel-border !bg-components-panel-bg !p-0 shadow-xl')} >
diff --git a/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx b/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx index e424ea8e1f..f8d2dcfc75 100644 --- a/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx +++ b/web/app/components/workflow/nodes/knowledge-retrieval/components/dataset-item.tsx @@ -111,7 +111,7 @@ const DatasetItem: FC = ({ } {isShowSettingsModal && ( - + Date: Tue, 22 Apr 2025 10:13:22 +0800 Subject: [PATCH 6/6] fix: filter empty marketplace collection (#18511) --- .../plugins/marketplace/list/list-with-collection.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/web/app/components/plugins/marketplace/list/list-with-collection.tsx b/web/app/components/plugins/marketplace/list/list-with-collection.tsx index e18356cd85..4c396c565f 100644 --- a/web/app/components/plugins/marketplace/list/list-with-collection.tsx +++ b/web/app/components/plugins/marketplace/list/list-with-collection.tsx @@ -32,7 +32,9 @@ const ListWithCollection = ({ return ( <> { - marketplaceCollections.map(collection => ( + marketplaceCollections.filter((collection) => { + return marketplaceCollectionPluginsMap[collection.name]?.length + }).map(collection => (