From 62c413aca53e1899b7f76ead4f4bd009476ace0e Mon Sep 17 00:00:00 2001
From: Jyong <76649700+JohnJyong@users.noreply.github.com>
Date: Sun, 26 Jan 2025 10:58:47 +0800
Subject: [PATCH 01/17] add sign-content (#13050)
---
api/fields/hit_testing_fields.py | 1 +
api/fields/segment_fields.py | 1 +
api/models/dataset.py | 4 ++++
3 files changed, 6 insertions(+)
diff --git a/api/fields/hit_testing_fields.py b/api/fields/hit_testing_fields.py
index b9f7e78c17..d9758474f7 100644
--- a/api/fields/hit_testing_fields.py
+++ b/api/fields/hit_testing_fields.py
@@ -14,6 +14,7 @@ segment_fields = {
"position": fields.Integer,
"document_id": fields.String,
"content": fields.String,
+ "sign_content": fields.String,
"answer": fields.String,
"word_count": fields.Integer,
"tokens": fields.Integer,
diff --git a/api/fields/segment_fields.py b/api/fields/segment_fields.py
index 52f89859c9..aaac31cf40 100644
--- a/api/fields/segment_fields.py
+++ b/api/fields/segment_fields.py
@@ -18,6 +18,7 @@ segment_fields = {
"position": fields.Integer,
"document_id": fields.String,
"content": fields.String,
+ "sign_content": fields.String,
"answer": fields.String,
"word_count": fields.Integer,
"tokens": fields.Integer,
diff --git a/api/models/dataset.py b/api/models/dataset.py
index 1cf3dc42fe..e49a61a088 100644
--- a/api/models/dataset.py
+++ b/api/models/dataset.py
@@ -583,6 +583,10 @@ class DocumentSegment(db.Model): # type: ignore[name-defined]
return []
else:
return []
+
+ @property
+ def sign_content(self):
+ return self.get_sign_content()
def get_sign_content(self):
signed_urls = []
From 3befbc1d68ccd692f438a2d065665c76eb71949f Mon Sep 17 00:00:00 2001
From: Wu Tianwei <30284043+WTW0313@users.noreply.github.com>
Date: Sun, 26 Jan 2025 15:12:05 +0800
Subject: [PATCH 02/17] feat: docx image preview (#13057)
---
web/app/components/base/markdown.tsx | 4 +-
.../detail/completed/SegmentCard.tsx | 259 ------------------
.../detail/completed/common/chunk-content.tsx | 12 +-
.../completed/segment-card/chunk-content.tsx | 56 ++++
.../index.tsx} | 60 ++--
.../detail/completed/segment-detail.tsx | 4 +-
.../skeleton/general-list-skeleton.tsx | 2 +-
.../documents/detail/new-segment-modal.tsx | 156 -----------
.../components/chunk-detail-modal.tsx | 10 +-
.../hit-testing/components/result-item.tsx | 13 +-
.../components/datasets/hit-testing/index.tsx | 10 +-
web/models/datasets.ts | 8 +-
12 files changed, 115 insertions(+), 479 deletions(-)
delete mode 100644 web/app/components/datasets/documents/detail/completed/SegmentCard.tsx
create mode 100644 web/app/components/datasets/documents/detail/completed/segment-card/chunk-content.tsx
rename web/app/components/datasets/documents/detail/completed/{segment-card.tsx => segment-card/index.tsx} (85%)
delete mode 100644 web/app/components/datasets/documents/detail/new-segment-modal.tsx
diff --git a/web/app/components/base/markdown.tsx b/web/app/components/base/markdown.tsx
index abb9a546ca..978a34a60a 100644
--- a/web/app/components/base/markdown.tsx
+++ b/web/app/components/base/markdown.tsx
@@ -9,7 +9,7 @@ import RemarkGfm from 'remark-gfm'
import RehypeRaw from 'rehype-raw'
import SyntaxHighlighter from 'react-syntax-highlighter'
import { atelierHeathLight } from 'react-syntax-highlighter/dist/esm/styles/hljs'
-import { Component, createContext, memo, useContext, useEffect, useMemo, useRef, useState } from 'react'
+import { Component, createContext, memo, useContext, useMemo, useRef, useState } from 'react'
import cn from '@/utils/classnames'
import CopyBtn from '@/app/components/base/copy-btn'
import SVGBtn from '@/app/components/base/svg'
@@ -241,7 +241,7 @@ const Link: Components['a'] = ({ node, ...props }) => {
export function Markdown(props: { content: string; className?: string }) {
const latexContent = preprocessLaTeX(props.content)
return (
-
+
= ({ percent, loading }) => {
- return (
-
-
-
{loading ? null : percent.toFixed(2)}
-
- )
-}
-
-type DocumentTitleProps = {
- extension?: string
- name?: string
- iconCls?: string
- textCls?: string
- wrapperCls?: string
-}
-
-const DocumentTitle: FC = ({ extension, name, iconCls, textCls, wrapperCls }) => {
- const localExtension = extension?.toLowerCase() || name?.split('.')?.pop()?.toLowerCase()
- return
-}
-
-export type UsageScene = 'doc' | 'hitTesting'
-
-type ISegmentCardProps = {
- loading: boolean
- detail?: SegmentDetailModel & { document: { name: string } }
- contentExternal?: string
- refSource?: {
- title: string
- uri: string
- }
- isExternal?: boolean
- score?: number
- onClick?: () => void
- onChangeSwitch?: (segId: string, enabled: boolean) => Promise
- onDelete?: (segId: string) => Promise
- scene?: UsageScene
- className?: string
- archived?: boolean
- embeddingAvailable?: boolean
-}
-
-const SegmentCard: FC = ({
- detail = {},
- contentExternal,
- isExternal,
- refSource,
- score,
- onClick,
- onChangeSwitch,
- onDelete,
- loading = true,
- scene = 'doc',
- className = '',
- archived,
- embeddingAvailable,
-}) => {
- const { t } = useTranslation()
- const {
- id,
- position,
- enabled,
- content,
- word_count,
- hit_count,
- index_node_hash,
- answer,
- } = detail as Required['detail']
- const isDocScene = scene === 'doc'
- const [showModal, setShowModal] = useState(false)
-
- const renderContent = () => {
- if (answer) {
- return (
- <>
-
-
- >
- )
- }
-
- if (contentExternal)
- return contentExternal
-
- return content
- }
-
- return (
- onClick?.()}
- >
-
- {isDocScene
- ? <>
-
-
- {loading
- ? (
-
- )
- : (
- <>
-
- {embeddingAvailable && (
-
-
-
) =>
- e.stopPropagation()
- }
- className="inline-flex items-center"
- >
- {
- await onChangeSwitch?.(id, val)
- }}
- />
-
-
- )}
- >
- )}
-
- >
- : (
- score !== null
- ? (
-
- )
- : null
- )}
-
- {loading
- ? (
-
- )
- : (
- isDocScene
- ? <>
-
- {renderContent()}
-
-
-
-
-
{formatNumber(word_count)}
-
-
-
-
{formatNumber(hit_count)}
-
-
- {!archived && embeddingAvailable && (
-
{
- e.stopPropagation()
- setShowModal(true)
- }}>
-
-
- )}
-
- >
- : <>
-
- {renderContent()}
-
-
-
-
-
-
- {isExternal ? t('datasetHitTesting.viewDetail') : t('datasetHitTesting.viewChart')}
-
-
-
-
- >
- )}
- {showModal
- &&
{ await onDelete?.(id) }}
- onCancel={() => setShowModal(false)}
- />
- }
-
- )
-}
-
-export default SegmentCard
diff --git a/web/app/components/datasets/documents/detail/completed/common/chunk-content.tsx b/web/app/components/datasets/documents/detail/completed/common/chunk-content.tsx
index e6403fa12f..af2989b188 100644
--- a/web/app/components/datasets/documents/detail/completed/common/chunk-content.tsx
+++ b/web/app/components/datasets/documents/detail/completed/common/chunk-content.tsx
@@ -3,6 +3,7 @@ import type { ComponentProps, FC } from 'react'
import { useTranslation } from 'react-i18next'
import { ChunkingMode } from '@/models/datasets'
import classNames from '@/utils/classnames'
+import { Markdown } from '@/app/components/base/markdown'
type IContentProps = ComponentProps<'textarea'>
@@ -52,7 +53,7 @@ const AutoResizeTextArea: FC = React.memo(({
if (!textarea)
return
textarea.style.height = 'auto'
- const lineHeight = parseInt(getComputedStyle(textarea).lineHeight)
+ const lineHeight = Number.parseInt(getComputedStyle(textarea).lineHeight)
const textareaHeight = Math.max(textarea.scrollHeight, lineHeight)
textarea.style.height = `${textareaHeight}px`
}, [value])
@@ -175,6 +176,15 @@ const ChunkContent: FC = ({
/>
}
+ if (!isEditMode) {
+ return (
+
+ )
+ }
+
return (
-
- {renderContent()}
-
+
{isGeneralMode &&
{keywords?.map(keyword => )}
}
diff --git a/web/app/components/datasets/documents/detail/completed/segment-detail.tsx b/web/app/components/datasets/documents/detail/completed/segment-detail.tsx
index 307a5cfb80..8891ddee85 100644
--- a/web/app/components/datasets/documents/detail/completed/segment-detail.tsx
+++ b/web/app/components/datasets/documents/detail/completed/segment-detail.tsx
@@ -142,9 +142,9 @@ const SegmentDetail: FC
= ({
-
+
{
+export const CardSkelton = React.memo(() => {
return (
diff --git a/web/app/components/datasets/documents/detail/new-segment-modal.tsx b/web/app/components/datasets/documents/detail/new-segment-modal.tsx
deleted file mode 100644
index 4c51779f9c..0000000000
--- a/web/app/components/datasets/documents/detail/new-segment-modal.tsx
+++ /dev/null
@@ -1,156 +0,0 @@
-import { memo, useState } from 'react'
-import type { FC } from 'react'
-import { useTranslation } from 'react-i18next'
-import { useContext } from 'use-context-selector'
-import { useParams } from 'next/navigation'
-import { RiCloseLine } from '@remixicon/react'
-import Modal from '@/app/components/base/modal'
-import Button from '@/app/components/base/button'
-import AutoHeightTextarea from '@/app/components/base/auto-height-textarea/common'
-import { Hash02 } from '@/app/components/base/icons/src/vender/line/general'
-import { ToastContext } from '@/app/components/base/toast'
-import type { SegmentUpdater } from '@/models/datasets'
-import { addSegment } from '@/service/datasets'
-import TagInput from '@/app/components/base/tag-input'
-
-type NewSegmentModalProps = {
- isShow: boolean
- onCancel: () => void
- docForm: string
- onSave: () => void
-}
-
-const NewSegmentModal: FC = ({
- isShow,
- onCancel,
- docForm,
- onSave,
-}) => {
- const { t } = useTranslation()
- const { notify } = useContext(ToastContext)
- const [question, setQuestion] = useState('')
- const [answer, setAnswer] = useState('')
- const { datasetId, documentId } = useParams()
- const [keywords, setKeywords] = useState([])
- const [loading, setLoading] = useState(false)
-
- const handleCancel = () => {
- setQuestion('')
- setAnswer('')
- onCancel()
- setKeywords([])
- }
-
- const handleSave = async () => {
- const params: SegmentUpdater = { content: '' }
- if (docForm === 'qa_model') {
- if (!question.trim())
- return notify({ type: 'error', message: t('datasetDocuments.segment.questionEmpty') })
- if (!answer.trim())
- return notify({ type: 'error', message: t('datasetDocuments.segment.answerEmpty') })
-
- params.content = question
- params.answer = answer
- }
- else {
- if (!question.trim())
- return notify({ type: 'error', message: t('datasetDocuments.segment.contentEmpty') })
-
- params.content = question
- }
-
- if (keywords?.length)
- params.keywords = keywords
-
- setLoading(true)
- try {
- await addSegment({ datasetId, documentId, body: params })
- notify({ type: 'success', message: t('common.actionMsg.modifiedSuccessfully') })
- handleCancel()
- onSave()
- }
- finally {
- setLoading(false)
- }
- }
-
- const renderContent = () => {
- if (docForm === 'qa_model') {
- return (
- <>
- QUESTION
- setQuestion(e.target.value)}
- autoFocus
- />
- ANSWER
- setAnswer(e.target.value)}
- />
- >
- )
- }
-
- return (
- setQuestion(e.target.value)}
- autoFocus
- />
- )
- }
-
- return (
- { }} className='pt-8 px-8 pb-6 !max-w-[640px] !rounded-xl'>
-
-
-
-
-
-
- {
- docForm === 'qa_model'
- ? t('datasetDocuments.segment.newQaSegment')
- : t('datasetDocuments.segment.newTextSegment')
- }
-
-
-
-
{renderContent()}
-
{t('datasetDocuments.segment.keywords')}
-
- setKeywords(newKeywords)} />
-
-
-
-
-
-
-
- )
-}
-
-export default memo(NewSegmentModal)
diff --git a/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx b/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx
index fe2f2b8f36..463a32e4d0 100644
--- a/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx
+++ b/web/app/components/datasets/hit-testing/components/chunk-detail-modal.tsx
@@ -12,6 +12,7 @@ import FileIcon from '@/app/components/base/file-uploader/file-type-icon'
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
import cn from '@/utils/classnames'
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
+import { Markdown } from '@/app/components/base/markdown'
const i18nPrefix = 'datasetHitTesting'
@@ -26,7 +27,7 @@ const ChunkDetailModal: FC = ({
}) => {
const { t } = useTranslation()
const { segment, score, child_chunks } = payload
- const { position, content, keywords, document } = segment
+ const { position, content, sign_content, keywords, document } = segment
const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
const extension = document.name.split('.').slice(-1)[0] as FileAppearanceTypeEnum
const heighClassName = isParentChildRetrieval ? 'h-[min(627px,_80vh)] overflow-y-auto' : 'h-[min(539px,_80vh)] overflow-y-auto'
@@ -56,9 +57,10 @@ const ChunkDetailModal: FC = ({
-
- {content}
-
+
{!isParentChildRetrieval && keywords && keywords.length > 0 && (
{t(`${i18nPrefix}.keyword`)}
diff --git a/web/app/components/datasets/hit-testing/components/result-item.tsx b/web/app/components/datasets/hit-testing/components/result-item.tsx
index 16bc40f67c..12cbceff9c 100644
--- a/web/app/components/datasets/hit-testing/components/result-item.tsx
+++ b/web/app/components/datasets/hit-testing/components/result-item.tsx
@@ -13,6 +13,7 @@ import cn from '@/utils/classnames'
import type { FileAppearanceTypeEnum } from '@/app/components/base/file-uploader/types'
import Tag from '@/app/components/datasets/documents/detail/completed/common/tag'
import { extensionToFileType } from '@/app/components/datasets/hit-testing/utils/extension-to-file-type'
+import { Markdown } from '@/app/components/base/markdown'
const i18nPrefix = 'datasetHitTesting'
type Props = {
@@ -25,7 +26,7 @@ const ResultItem: FC
= ({
const { t } = useTranslation()
const { segment, score, child_chunks } = payload
const data = segment
- const { position, word_count, content, keywords, document } = data
+ const { position, word_count, content, sign_content, keywords, document } = data
const isParentChildRetrieval = !!(child_chunks && child_chunks.length > 0)
const extension = document.name.split('.').slice(-1)[0] as FileAppearanceTypeEnum
const fileType = extensionToFileType(extension)
@@ -46,10 +47,16 @@ const ResultItem: FC = ({
{/* Main */}
-
{content}
+
{isParentChildRetrieval && (
-
+
{
+ e.stopPropagation()
+ toggleFold()
+ }}
+ >
{t(`${i18nPrefix}.hitChunks`, { num: child_chunks.length })}
diff --git a/web/app/components/datasets/hit-testing/index.tsx b/web/app/components/datasets/hit-testing/index.tsx
index 33f2acc65b..983b700b5a 100644
--- a/web/app/components/datasets/hit-testing/index.tsx
+++ b/web/app/components/datasets/hit-testing/index.tsx
@@ -7,7 +7,6 @@ import { omit } from 'lodash-es'
import { useBoolean } from 'ahooks'
import { useContext } from 'use-context-selector'
import { RiApps2Line, RiFocus2Line } from '@remixicon/react'
-import SegmentCard from '../documents/detail/completed/SegmentCard'
import Textarea from './textarea'
import s from './style.module.css'
import ModifyRetrievalModal from './modify-retrieval-modal'
@@ -25,6 +24,7 @@ import type { RetrievalConfig } from '@/types/app'
import useBreakpoints, { MediaType } from '@/hooks/use-breakpoints'
import useTimestamp from '@/hooks/use-timestamp'
import docStyle from '@/app/components/datasets/documents/detail/completed/style.module.css'
+import { CardSkelton } from '../documents/detail/completed/skeleton/general-list-skeleton'
const limit = 10
@@ -180,11 +180,9 @@ const HitTestingPage: FC
= ({ datasetId }: Props) => {
{/* {renderHitResults(generalResultData)} */}
{submitLoading
- ?
+ ?
+
+
: (
(() => {
if (!hitResult?.records.length && !externalHitResult?.records.length)
diff --git a/web/models/datasets.ts b/web/models/datasets.ts
index 673fb5fb15..073312fae1 100644
--- a/web/models/datasets.ts
+++ b/web/models/datasets.ts
@@ -12,9 +12,9 @@ export enum DataSourceType {
export type DatasetPermission = 'only_me' | 'all_team_members' | 'partial_members'
export enum ChunkingMode {
- 'text' = 'text_model', // General text
- 'qa' = 'qa_model', // General QA
- 'parentChild' = 'hierarchical_model', // Parent-Child
+ text = 'text_model', // General text
+ qa = 'qa_model', // General QA
+ parentChild = 'hierarchical_model', // Parent-Child
}
export type DataSet = {
@@ -452,6 +452,7 @@ export type SegmentDetailModel = {
position: number
document_id: string
content: string
+ sign_content: string
word_count: number
tokens: number
keywords: string[]
@@ -520,6 +521,7 @@ export type Segment = {
id: string
document: Document
content: string
+ sign_content: string
position: number
word_count: number
tokens: number
From 1de84fdda0ccb3b7f2754626f0ac4a402059a8a9 Mon Sep 17 00:00:00 2001
From: kurokobo
Date: Mon, 27 Jan 2025 12:19:29 +0900
Subject: [PATCH 03/17] fix: correct env vars for docker deployment (#13055)
---
docker/.env.example | 2 +-
docker/docker-compose-template.yaml | 2 ++
docker/docker-compose.yaml | 4 +++-
3 files changed, 6 insertions(+), 2 deletions(-)
diff --git a/docker/.env.example b/docker/.env.example
index cf6a492b62..95548ee5d1 100644
--- a/docker/.env.example
+++ b/docker/.env.example
@@ -953,7 +953,7 @@ EXPOSE_PLUGIN_DEBUGGING_PORT=5003
PLUGIN_DIFY_INNER_API_KEY=QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1
PLUGIN_DIFY_INNER_API_URL=http://api:5001
-ENDPOINT_URL_TEMPLATE=http://localhost:5002/e/{hook_id}
+ENDPOINT_URL_TEMPLATE=http://localhost/e/{hook_id}
MARKETPLACE_ENABLED=true
MARKETPLACE_API_URL=https://marketplace.dify.ai
diff --git a/docker/docker-compose-template.yaml b/docker/docker-compose-template.yaml
index 6770f662af..90e600792d 100644
--- a/docker/docker-compose-template.yaml
+++ b/docker/docker-compose-template.yaml
@@ -12,6 +12,8 @@ services:
SENTRY_DSN: ${API_SENTRY_DSN:-}
SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
+ PLUGIN_API_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
+ PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002}
PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
depends_on:
diff --git a/docker/docker-compose.yaml b/docker/docker-compose.yaml
index 01eeeeaa65..cd1cea0dc6 100644
--- a/docker/docker-compose.yaml
+++ b/docker/docker-compose.yaml
@@ -402,7 +402,7 @@ x-shared-env: &shared-api-worker-env
EXPOSE_PLUGIN_DEBUGGING_PORT: ${EXPOSE_PLUGIN_DEBUGGING_PORT:-5003}
PLUGIN_DIFY_INNER_API_KEY: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
PLUGIN_DIFY_INNER_API_URL: ${PLUGIN_DIFY_INNER_API_URL:-http://api:5001}
- ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost:5002/e/{hook_id}}
+ ENDPOINT_URL_TEMPLATE: ${ENDPOINT_URL_TEMPLATE:-http://localhost/e/{hook_id}}
MARKETPLACE_ENABLED: ${MARKETPLACE_ENABLED:-true}
MARKETPLACE_API_URL: ${MARKETPLACE_API_URL:-https://marketplace.dify.ai}
FORCE_VERIFYING_SIGNATURE: ${FORCE_VERIFYING_SIGNATURE:-true}
@@ -420,6 +420,8 @@ services:
SENTRY_DSN: ${API_SENTRY_DSN:-}
SENTRY_TRACES_SAMPLE_RATE: ${API_SENTRY_TRACES_SAMPLE_RATE:-1.0}
SENTRY_PROFILES_SAMPLE_RATE: ${API_SENTRY_PROFILES_SAMPLE_RATE:-1.0}
+ PLUGIN_API_KEY: ${PLUGIN_DAEMON_KEY:-lYkiYYT6owG+71oLerGzA7GXCgOT++6ovaezWAjpCjf+Sjc3ZtU+qUEi}
+ PLUGIN_API_URL: ${PLUGIN_DAEMON_URL:-http://plugin_daemon:5002}
PLUGIN_MAX_PACKAGE_SIZE: ${PLUGIN_MAX_PACKAGE_SIZE:-52428800}
INNER_API_KEY_FOR_PLUGIN: ${PLUGIN_DIFY_INNER_API_KEY:-QaHbTe77CtuXmsfyhR7+vRjI/+XbV1AaFy691iy+kGDv2Jvy0/eAh8Y1}
depends_on:
From 2710242982273c3190e33eac1747a6abeccc0489 Mon Sep 17 00:00:00 2001
From: KVOJJJin
Date: Wed, 5 Feb 2025 13:58:19 +0800
Subject: [PATCH 04/17] Feat: feature and log dark mode (#13208)
---
.../agent-tools/setting-built-in-tool.tsx | 3 +-
.../app/configuration/debug/index.tsx | 2 +-
.../base/agent-log-modal/detail.tsx | 14 +++---
.../components/base/agent-log-modal/index.tsx | 6 +--
.../base/agent-log-modal/iteration.tsx | 9 ++--
.../base/agent-log-modal/result.tsx | 38 ++++++++--------
.../base/agent-log-modal/tool-call.tsx | 14 +++---
.../base/agent-log-modal/tracing.tsx | 2 +-
.../components/base/copy-feedback/index.tsx | 2 +-
.../conversation-opener/modal.tsx | 32 ++++++++++----
.../moderation/form-generation.tsx | 4 +-
.../moderation/moderation-content.tsx | 20 ++++-----
.../moderation/moderation-setting-modal.tsx | 44 ++++++++++---------
.../text-to-speech/param-config-content.tsx | 28 ++++++------
.../components/base/prompt-log-modal/card.tsx | 6 +--
.../base/prompt-log-modal/index.tsx | 10 ++---
.../api-based-extension-page/modal.tsx | 18 ++++----
.../api-based-extension-page/selector.tsx | 28 ++++++------
.../multiple-tool-selector/index.tsx | 9 +++-
.../tool-selector/index.tsx | 12 +++--
.../workflow/block-selector/tool-picker.tsx | 5 ++-
.../workflow/run/assets/highlight-dark.svg | 9 ++++
.../workflow/run/status-container.tsx | 33 +++++++++++---
web/app/components/workflow/run/status.tsx | 2 +-
web/context/app-context.tsx | 1 +
25 files changed, 208 insertions(+), 143 deletions(-)
create mode 100644 web/app/components/workflow/run/assets/highlight-dark.svg
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 e4fae3fbc1..da6063045a 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
@@ -151,7 +151,6 @@ const SettingBuiltInTool: FC = ({
isEditMode={false}
showOnVariableMap={{}}
validating={false}
- inputClassName='!bg-gray-50'
readonly={readonly}
/>
)
@@ -224,7 +223,7 @@ const SettingBuiltInTool: FC = ({
{!readonly && !isInfoActive && (
-
+
)}
diff --git a/web/app/components/app/configuration/debug/index.tsx b/web/app/components/app/configuration/debug/index.tsx
index 99632eb0d3..480bd782ae 100644
--- a/web/app/components/app/configuration/debug/index.tsx
+++ b/web/app/components/app/configuration/debug/index.tsx
@@ -48,7 +48,7 @@ import PromptLogModal from '@/app/components/base/prompt-log-modal'
import { useStore as useAppStore } from '@/app/components/app/store'
import { useFeatures, useFeaturesStore } from '@/app/components/base/features/hooks'
-interface IDebug {
+type IDebug = {
isAPIKeySet: boolean
onSetting: () => void
inputs: Inputs
diff --git a/web/app/components/base/agent-log-modal/detail.tsx b/web/app/components/base/agent-log-modal/detail.tsx
index e90f593ad0..62bdb4b172 100644
--- a/web/app/components/base/agent-log-modal/detail.tsx
+++ b/web/app/components/base/agent-log-modal/detail.tsx
@@ -81,26 +81,26 @@ const AgentLogDetail: FC = ({
return (
{/* tab */}
-
+
switchTab('DETAIL')}
>{t('runLog.detail')}
switchTab('TRACING')}
>{t('runLog.tracing')}
{/* panel detail */}
-
+
{loading && (
-
+
)}
diff --git a/web/app/components/base/agent-log-modal/index.tsx b/web/app/components/base/agent-log-modal/index.tsx
index bbe1167f57..3e62a7f121 100644
--- a/web/app/components/base/agent-log-modal/index.tsx
+++ b/web/app/components/base/agent-log-modal/index.tsx
@@ -35,7 +35,7 @@ const AgentLogModal: FC
= ({
return (
= ({
}}
ref={ref}
>
-
{t('appLog.runDetail.workflowTitle')}
+
{t('appLog.runDetail.workflowTitle')}
-
+
= ({ iterationInfo, isFinal, index }) => {
{isFinal && (
-
{t('appLog.agentLogDetail.finalProcessing')}
+
{t('appLog.agentLogDetail.finalProcessing')}
)}
{!isFinal && (
-
{`${t('appLog.agentLogDetail.iteration').toUpperCase()} ${index}`}
+
{`${t('appLog.agentLogDetail.iteration').toUpperCase()} ${index}`}
)}
-
+
= ({
const { formatTime } = useTimestamp()
return (
-
+
= ({
/>
-
{t('runLog.meta.title')}
+
{t('runLog.meta.title')}
-
{t('runLog.meta.status')}
-
+
{t('runLog.meta.status')}
+
SUCCESS
-
{t('runLog.meta.executor')}
-
+
{t('runLog.meta.executor')}
+
{created_by || 'N/A'}
-
{t('runLog.meta.startTime')}
-
+
{t('runLog.meta.startTime')}
+
{formatTime(Date.parse(created_at) / 1000, t('appLog.dateTimeFormat') as string)}
-
{t('runLog.meta.time')}
-
+
{t('runLog.meta.time')}
+
{`${elapsed_time?.toFixed(3)}s`}
-
{t('runLog.meta.tokens')}
-
+
{t('runLog.meta.tokens')}
+
{`${total_tokens || 0} Tokens`}
-
{t('appLog.agentLogDetail.agentMode')}
-
+
{t('appLog.agentLogDetail.agentMode')}
+
{agentMode === 'function_call' ? t('appDebug.agent.agentModeType.functionCall') : t('appDebug.agent.agentModeType.ReACT')}
-
{t('appLog.agentLogDetail.toolUsed')}
-
+
{t('appLog.agentLogDetail.toolUsed')}
+
{tools?.length ? tools?.join(', ') : 'Null'}
-
{t('appLog.agentLogDetail.iterations')}
-
+
{t('appLog.agentLogDetail.iterations')}
+
{iterations}
diff --git a/web/app/components/base/agent-log-modal/tool-call.tsx b/web/app/components/base/agent-log-modal/tool-call.tsx
index 8d8e583126..d77a3f60b9 100644
--- a/web/app/components/base/agent-log-modal/tool-call.tsx
+++ b/web/app/components/base/agent-log-modal/tool-call.tsx
@@ -33,7 +33,7 @@ const ToolCallItem: FC
= ({ toolCall, isLLM = false, isFinal, tokens, obs
if (time < 1)
return `${(time * 1000).toFixed(3)} ms`
if (time > 60)
- return `${parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s`
+ return `${Number.parseInt(Math.round(time / 60).toString())} m ${(time % 60).toFixed(3)} s`
return `${time.toFixed(3)} s`
}
@@ -41,14 +41,14 @@ const ToolCallItem: FC = ({ toolCall, isLLM = false, isFinal, tokens, obs
if (tokens < 1000)
return tokens
if (tokens >= 1000 && tokens < 1000000)
- return `${parseFloat((tokens / 1000).toFixed(3))}K`
+ return `${Number.parseFloat((tokens / 1000).toFixed(3))}K`
if (tokens >= 1000000)
- return `${parseFloat((tokens / 1000000).toFixed(3))}M`
+ return `${Number.parseFloat((tokens / 1000000).toFixed(3))}M`
}
return (
-
+
= ({ toolCall, isLLM = false, isFinal, tokens, obs
>
{toolName}
-
+
{toolCall.time_cost && (
{getTime(toolCall.time_cost || 0)}
)}
diff --git a/web/app/components/base/agent-log-modal/tracing.tsx b/web/app/components/base/agent-log-modal/tracing.tsx
index 59cffa0055..c390d256e1 100644
--- a/web/app/components/base/agent-log-modal/tracing.tsx
+++ b/web/app/components/base/agent-log-modal/tracing.tsx
@@ -9,7 +9,7 @@ type TracingPanelProps = {
const TracingPanel: FC
= ({ list }) => {
return (
-
+
{list.map((iteration, index) => (
diff --git a/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx b/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
index 41ed043e93..a03886923e 100644
--- a/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
+++ b/web/app/components/base/features/new-feature-panel/conversation-opener/modal.tsx
@@ -6,12 +6,14 @@ import { ReactSortable } from 'react-sortablejs'
import { RiAddLine, RiAsterisk, RiCloseLine, RiDeleteBinLine, RiDraggable } from '@remixicon/react'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
+import Divider from '@/app/components/base/divider'
import ConfirmAddVar from '@/app/components/app/configuration/config-prompt/confirm-add-var'
import type { OpeningStatement } from '@/app/components/base/features/types'
import { getInputKeys } from '@/app/components/base/block-input'
import type { PromptVariable } from '@/models/debug'
import type { InputVar } from '@/app/components/workflow/types'
import { getNewVar } from '@/utils/var'
+import cn from '@/utils/classnames'
type OpeningSettingModalProps = {
data: OpeningStatement
@@ -86,16 +88,19 @@ const OpeningSettingModal = ({
handleSave(true)
}, [handleSave, hideConfirmAddVar, notIncludeKeys, onAutoAddPromptVariable])
+ const [focusID, setFocusID] = useState
(null)
+ const [deletingID, setDeletingID] = useState(null)
+
const renderQuestions = () => {
return (
-
+
{t('appDebug.openingStatement.openingQuestion')}
·
{tempSuggestedQuestions.length}/{MAX_QUESTION_NUM}
-
+
{tempSuggestedQuestions.map((question, index) => {
return (
-
-
+
+
setFocusID(index)}
+ onBlur={() => setFocusID(null)}
/>
{
setTempSuggestedQuestions(tempSuggestedQuestions.filter((_, i) => index !== i))
}}
+ onMouseEnter={() => setDeletingID(index)}
+ onMouseLeave={() => setDeletingID(null)}
>
@@ -143,9 +159,9 @@ const OpeningSettingModal = ({
{tempSuggestedQuestions.length < MAX_QUESTION_NUM && (
{ setTempSuggestedQuestions([...tempSuggestedQuestions, '']) }}
- className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-gray-400 bg-gray-100 hover:bg-gray-200'>
+ className='mt-1 flex items-center h-9 px-3 gap-2 rounded-lg cursor-pointer text-components-button-tertiary-text bg-components-button-tertiary-bg hover:bg-components-button-tertiary-bg-hover'>
-
{t('appDebug.variableConfig.addOption')}
+
{t('appDebug.variableConfig.addOption')}
)}
diff --git a/web/app/components/base/features/new-feature-panel/moderation/form-generation.tsx b/web/app/components/base/features/new-feature-panel/moderation/form-generation.tsx
index 067d00923a..f5cddcc9a0 100644
--- a/web/app/components/base/features/new-feature-panel/moderation/form-generation.tsx
+++ b/web/app/components/base/features/new-feature-panel/moderation/form-generation.tsx
@@ -30,14 +30,14 @@ const FormGeneration: FC
= ({
key={index}
className='py-2'
>
-
+
{locale === 'zh-Hans' ? form.label['zh-Hans'] : form.label['en-US']}
{
form.type === 'text-input' && (
handleFormChange(form.variable, e.target.value)}
/>
diff --git a/web/app/components/base/features/new-feature-panel/moderation/moderation-content.tsx b/web/app/components/base/features/new-feature-panel/moderation/moderation-content.tsx
index 7cb8114959..a6e122fb2b 100644
--- a/web/app/components/base/features/new-feature-panel/moderation/moderation-content.tsx
+++ b/web/app/components/base/features/new-feature-panel/moderation/moderation-content.tsx
@@ -27,13 +27,13 @@ const ModerationContent: FC
= ({
return (
-
+
-
{title}
+
{title}
{
info && (
-
{info}
+
{info}
)
}
= ({
{
config.enabled && showPreset && (
-
-
+
+
{t('appDebug.feature.moderation.modal.content.preset')}
- {t('appDebug.feature.moderation.modal.content.supportMarkdown')}
+ {t('appDebug.feature.moderation.modal.content.supportMarkdown')}
-
+
diff --git a/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx b/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx
index c77d22dc01..24501c32c1 100644
--- a/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx
+++ b/web/app/components/base/features/new-feature-panel/moderation/moderation-setting-modal.tsx
@@ -9,6 +9,7 @@ import FormGeneration from './form-generation'
import ApiBasedExtensionSelector from '@/app/components/header/account-setting/api-based-extension-page/selector'
import Modal from '@/app/components/base/modal'
import Button from '@/app/components/base/button'
+import Divider from '@/app/components/base/divider'
import { BookOpen01 } from '@/app/components/base/icons/src/vender/line/education'
import type { ModerationConfig, ModerationContentConfig } from '@/models/debug'
import { useToastContext } from '@/app/components/base/toast'
@@ -22,6 +23,7 @@ import { LanguagesSupported } from '@/i18n/language'
import { InfoCircle } from '@/app/components/base/icons/src/vender/line/general'
import { useModalContext } from '@/context/modal-context'
import { CustomConfigurationStatusEnum } from '@/app/components/header/account-setting/model-provider-page/declarations'
+import cn from '@/utils/classnames'
const systemTypes = ['openai_moderation', 'keywords', 'api']
@@ -245,7 +247,7 @@ const ModerationSettingModal: FC
= ({
-
+
{t('appDebug.feature.moderation.modal.provider.title')}
@@ -253,16 +255,18 @@ const ModerationSettingModal: FC
= ({
providers.map(provider => (
handleDataTypeChange(provider.key)}
>
-
+
{provider.name}
))
@@ -289,17 +293,17 @@ const ModerationSettingModal: FC = ({
{
localeData.type === 'keywords' && (
-
{t('appDebug.feature.moderation.modal.provider.keywords')}
-
{t('appDebug.feature.moderation.modal.keywords.tip')}
-
+
{t('appDebug.feature.moderation.modal.provider.keywords')}
+
{t('appDebug.feature.moderation.modal.keywords.tip')}
+
-
-
{(localeData.config?.keywords || '').split('\n').filter(Boolean).length}/
100 {t('appDebug.feature.moderation.modal.keywords.line')}
+
+ {(localeData.config?.keywords || '').split('\n').filter(Boolean).length}/100 {t('appDebug.feature.moderation.modal.keywords.line')}
@@ -309,13 +313,13 @@ const ModerationSettingModal: FC
= ({
localeData.type === 'api' && (
@@ -337,7 +341,7 @@ const ModerationSettingModal: FC
= ({
/>
)
}
-
+
= ({
info={(localeData.type === 'api' && t('appDebug.feature.moderation.modal.content.fromApi')) || ''}
showPreset={!(localeData.type === 'api')}
/>
- {t('appDebug.feature.moderation.modal.content.condition')}
+ {t('appDebug.feature.moderation.modal.content.condition')}