From d22c351221522ed095d02636ac0f7f5aa1286524 Mon Sep 17 00:00:00 2001 From: Joel Date: Wed, 4 Jun 2025 15:56:29 +0800 Subject: [PATCH 01/14] chore: fix some security issues in markdown (#20639) --- .../components/base/markdown-blocks/button.tsx | 16 ++++------------ web/app/components/base/markdown-blocks/link.tsx | 7 ++++++- web/app/components/base/markdown-blocks/utils.ts | 3 +++ 3 files changed, 13 insertions(+), 13 deletions(-) create mode 100644 web/app/components/base/markdown-blocks/utils.ts diff --git a/web/app/components/base/markdown-blocks/button.tsx b/web/app/components/base/markdown-blocks/button.tsx index 81a3f30660..4646b12921 100644 --- a/web/app/components/base/markdown-blocks/button.tsx +++ b/web/app/components/base/markdown-blocks/button.tsx @@ -1,7 +1,7 @@ import { useChatContext } from '@/app/components/base/chat/chat/context' import Button from '@/app/components/base/button' import cn from '@/utils/classnames' - +import { isValidUrl } from './utils' const MarkdownButton = ({ node }: any) => { const { onSend } = useChatContext() const variant = node.properties.dataVariant @@ -9,25 +9,17 @@ const MarkdownButton = ({ node }: any) => { const link = node.properties.dataLink const size = node.properties.dataSize - function is_valid_url(url: string): boolean { - try { - const parsed_url = new URL(url) - return ['http:', 'https:'].includes(parsed_url.protocol) - } - catch { - return false - } - } - return + {/* Data source form Preview */}
+ {/* Process documents form Preview */} ) diff --git a/web/app/components/rag-pipeline/components/panel/test-run/data-source-options/index.tsx b/web/app/components/rag-pipeline/components/panel/test-run/data-source-options/index.tsx index 9c00aa1d7d..afbba09594 100644 --- a/web/app/components/rag-pipeline/components/panel/test-run/data-source-options/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/test-run/data-source-options/index.tsx @@ -4,12 +4,12 @@ import OptionCard from './option-card' import type { Datasource } from '../types' type DataSourceOptionsProps = { - datasourceNodeId: string + dataSourceNodeId: string onSelect: (option: Datasource) => void } const DataSourceOptions = ({ - datasourceNodeId, + dataSourceNodeId, onSelect, }: DataSourceOptionsProps) => { const { datasources, options } = useDatasourceOptions() @@ -34,7 +34,7 @@ const DataSourceOptions = ({ key={option.value} label={option.label} nodeData={option.data} - selected={datasourceNodeId === option.value} + selected={dataSourceNodeId === option.value} onClick={handelSelect.bind(null, option.value)} /> ))} diff --git a/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/base/crawler.tsx b/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/base/crawler.tsx index e3f3edac0a..4c598bfc10 100644 --- a/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/base/crawler.tsx +++ b/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/base/crawler.tsx @@ -1,5 +1,5 @@ 'use client' -import React, { useCallback, useEffect, useState } from 'react' +import React, { useCallback, useEffect, useRef, useState } from 'react' import { useTranslation } from 'react-i18next' import type { CrawlResultItem } from '@/models/datasets' import Header from '@/app/components/datasets/create/website/base/header' @@ -7,15 +7,17 @@ import Options from './options' import Crawling from './crawling' import ErrorMessage from './error-message' import CrawledResult from './crawled-result' -import type { RAGPipelineVariables } from '@/models/pipeline' -import { useDatasourceNodeRun } from '@/service/use-pipeline' -import { useDatasetDetailContextWithSelector } from '@/context/dataset-detail' +import { + useDatasourceNodeRun, + useDraftPipelinePreProcessingParams, + usePublishedPipelineProcessingParams, +} from '@/service/use-pipeline' +import { useStore } from '@/app/components/workflow/store' const I18N_PREFIX = 'datasetCreation.stepOne.website' type CrawlerProps = { nodeId: string - variables: RAGPipelineVariables checkedCrawlResult: CrawlResultItem[] onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void onJobIdChange: (jobId: string) => void @@ -25,6 +27,7 @@ type CrawlerProps = { docLink: string } onPreview?: (payload: CrawlResultItem) => void + usingPublished?: boolean } enum Step { @@ -35,17 +38,23 @@ enum Step { const Crawler = ({ nodeId, - variables, checkedCrawlResult, headerInfo, onCheckedCrawlResultChange, onJobIdChange, onPreview, + usingPublished = false, }: CrawlerProps) => { const { t } = useTranslation() const [step, setStep] = useState(Step.init) const [controlFoldOptions, setControlFoldOptions] = useState(0) - const pipelineId = useDatasetDetailContextWithSelector(s => s.dataset?.pipeline_id) + const pipelineId = useStore(s => s.pipelineId) + + const usePreProcessingParams = useRef(usingPublished ? usePublishedPipelineProcessingParams : useDraftPipelinePreProcessingParams) + const { data: paramsConfig } = usePreProcessingParams.current({ + pipeline_id: pipelineId!, + node_id: nodeId, + }, !!pipelineId && !!nodeId) useEffect(() => { if (step !== Step.init) @@ -95,7 +104,7 @@ const Crawler = ({ />
{ diff --git a/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/index.tsx b/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/index.tsx index 181322256f..50be76e524 100644 --- a/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/test-run/data-source/website-crawl/index.tsx @@ -1,12 +1,10 @@ 'use client' import React from 'react' import type { CrawlResultItem } from '@/models/datasets' -import type { RAGPipelineVariables } from '@/models/pipeline' import Crawler from './base/crawler' type WebsiteCrawlProps = { nodeId: string - variables: RAGPipelineVariables checkedCrawlResult: CrawlResultItem[] onCheckedCrawlResultChange: (payload: CrawlResultItem[]) => void onJobIdChange: (jobId: string) => void @@ -16,26 +14,27 @@ type WebsiteCrawlProps = { docLink: string } onPreview?: (payload: CrawlResultItem) => void + usingPublished?: boolean } const WebsiteCrawl = ({ nodeId, - variables, checkedCrawlResult, headerInfo, onCheckedCrawlResultChange, onJobIdChange, onPreview, + usingPublished, }: WebsiteCrawlProps) => { return ( ) } diff --git a/web/app/components/rag-pipeline/components/panel/test-run/index.tsx b/web/app/components/rag-pipeline/components/panel/test-run/index.tsx index 84b48c3653..97c0a4002f 100644 --- a/web/app/components/rag-pipeline/components/panel/test-run/index.tsx +++ b/web/app/components/rag-pipeline/components/panel/test-run/index.tsx @@ -117,7 +117,7 @@ const TestRunPanel = () => { <>
{datasource?.type === DatasourceType.localFile && ( @@ -139,7 +139,6 @@ const TestRunPanel = () => { {datasource?.type === DatasourceType.websiteCrawl && ( { const { pipeline_id, node_id } = params return useQuery({ - queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id], + queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id, node_id], queryFn: () => { return get(`/rag/pipelines/${pipeline_id}/workflows/draft/processing/parameters`, { params: { @@ -157,7 +157,7 @@ export const useDraftPipelineProcessingParams = (params: PipelineProcessingParam export const usePublishedPipelineProcessingParams = (params: PipelineProcessingParamsRequest) => { const { pipeline_id, node_id } = params return useQuery({ - queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id], + queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id, node_id], queryFn: () => { return get(`/rag/pipelines/${pipeline_id}/workflows/published/processing/parameters`, { params: { @@ -165,6 +165,7 @@ export const usePublishedPipelineProcessingParams = (params: PipelineProcessingP }, }) }, + staleTime: 0, }) } @@ -254,7 +255,7 @@ export const useUpdateDataSourceCredentials = ( export const useDraftPipelinePreProcessingParams = (params: PipelinePreProcessingParamsRequest, enabled = true) => { const { pipeline_id, node_id } = params return useQuery({ - queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id], + queryKey: [NAME_SPACE, 'pipeline-pre-processing-params', pipeline_id, node_id], queryFn: () => { return get(`/rag/pipelines/${pipeline_id}/workflows/draft/pre-processing/parameters`, { params: { @@ -270,7 +271,7 @@ export const useDraftPipelinePreProcessingParams = (params: PipelinePreProcessin export const usePublishedPipelinePreProcessingParams = (params: PipelinePreProcessingParamsRequest, enabled = true) => { const { pipeline_id, node_id } = params return useQuery({ - queryKey: [NAME_SPACE, 'pipeline-processing-params', pipeline_id], + queryKey: [NAME_SPACE, 'pipeline-pre-processing-params', pipeline_id, node_id], queryFn: () => { return get(`/rag/pipelines/${pipeline_id}/workflows/published/processing/parameters`, { params: { @@ -278,6 +279,7 @@ export const usePublishedPipelinePreProcessingParams = (params: PipelinePreProce }, }) }, + staleTime: 0, enabled, }) } From c83370f701c5d8b25b3adcb429184935a0c7c3da Mon Sep 17 00:00:00 2001 From: twwu Date: Thu, 5 Jun 2025 11:07:28 +0800 Subject: [PATCH 13/14] refactor: simplify workflow draft synchronization in InputFieldDialog --- .../components/input-field/index.tsx | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/web/app/components/rag-pipeline/components/input-field/index.tsx b/web/app/components/rag-pipeline/components/input-field/index.tsx index c4947a68a7..81eb4c7809 100644 --- a/web/app/components/rag-pipeline/components/input-field/index.tsx +++ b/web/app/components/rag-pipeline/components/input-field/index.tsx @@ -24,7 +24,6 @@ import Divider from '@/app/components/base/divider' import Tooltip from '@/app/components/base/tooltip' import cn from '@/utils/classnames' import PreviewPanel from './preview' -import { useDebounceFn, useUnmount } from 'ahooks' type InputFieldDialogProps = { readonly?: boolean @@ -54,18 +53,7 @@ const InputFieldDialog = ({ } const inputFieldsMap = useRef(getInputFieldsMap()) - const { doSyncWorkflowDraft } = useNodesSyncDraft() - - const { run: syncWorkflowDraft, cancel: cancelSyncWorkflowDraft } = useDebounceFn(async () => { - await doSyncWorkflowDraft() - }, { - wait: 500, - }) - - useUnmount(() => { - cancelSyncWorkflowDraft() - doSyncWorkflowDraft() - }) + const { handleSyncWorkflowDraft } = useNodesSyncDraft() const datasourceNodeDataMap = useMemo(() => { const datasourceNodeDataMap: Record = {} @@ -90,8 +78,8 @@ const InputFieldDialog = ({ }) }) setRagPipelineVariables?.(newRagPipelineVariables) - await syncWorkflowDraft() - }, [setRagPipelineVariables, syncWorkflowDraft]) + handleSyncWorkflowDraft() + }, [setRagPipelineVariables, handleSyncWorkflowDraft]) const closePanel = useCallback(() => { setShowInputFieldDialog?.(false) From 6286f368f12796f90dc1637f6416c92491fdba43 Mon Sep 17 00:00:00 2001 From: twwu Date: Thu, 5 Jun 2025 11:21:17 +0800 Subject: [PATCH 14/14] refactor: replace ImagePlus icon with RiImageCircleAiLine and improve tab button styling --- web/app/components/base/app-icon-picker/index.tsx | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/web/app/components/base/app-icon-picker/index.tsx b/web/app/components/base/app-icon-picker/index.tsx index 975f8aeb6c..048ae2a576 100644 --- a/web/app/components/base/app-icon-picker/index.tsx +++ b/web/app/components/base/app-icon-picker/index.tsx @@ -5,7 +5,6 @@ import type { Area } from 'react-easy-crop' import Modal from '../modal' import Divider from '../divider' import Button from '../button' -import { ImagePlus } from '../icons/src/vender/line/images' import { useLocalFileUploader } from '../image-uploader/hooks' import EmojiPickerInner from '../emoji-picker/Inner' import type { OnImageInput } from './ImageInput' @@ -16,6 +15,7 @@ import type { AppIconType, ImageFile } from '@/types/app' import cn from '@/utils/classnames' import { DISABLE_UPLOAD_IMAGE_AS_ICON } from '@/config' import { noop } from 'lodash-es' +import { RiImageCircleAiLine } from '@remixicon/react' export type AppIconEmojiSelection = { type: 'emoji' @@ -46,7 +46,7 @@ const AppIconPicker: FC = ({ const tabs = [ { key: 'emoji', label: t('app.iconPicker.emoji'), icon: 🤖 }, - { key: 'image', label: t('app.iconPicker.image'), icon: }, + { key: 'image', label: t('app.iconPicker.image'), icon: }, ] const [activeTab, setActiveTab] = useState('emoji') @@ -119,10 +119,10 @@ const AppIconPicker: FC = ({ {tabs.map(tab => (