mirror of
https://github.com/langgenius/dify.git
synced 2026-05-06 02:18:08 +08:00
Merge branch 'main' into feat/attachments
This commit is contained in:
@ -922,6 +922,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
<Property name='dataset_id' type='string' key='dataset_id'>
|
||||
Knowledge ID
|
||||
</Property>
|
||||
<Property name='document_id' type='string' key='document_id'>
|
||||
Document ID
|
||||
</Property>
|
||||
<Property name='segment_id' type='string' key='segment_id'>
|
||||
Document Segment ID
|
||||
</Property>
|
||||
@ -965,6 +968,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
<Property name='dataset_id' type='string' key='dataset_id'>
|
||||
Knowledge ID
|
||||
</Property>
|
||||
<Property name='document_id' type='string' key='document_id'>
|
||||
Document ID
|
||||
</Property>
|
||||
<Property name='segment_id' type='string' key='segment_id'>
|
||||
Document Segment ID
|
||||
</Property>
|
||||
|
||||
@ -922,6 +922,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
<Property name='dataset_id' type='string' key='dataset_id'>
|
||||
知识库 ID
|
||||
</Property>
|
||||
<Property name='document_id' type='string' key='document_id'>
|
||||
文档 ID
|
||||
</Property>
|
||||
<Property name='segment_id' type='string' key='segment_id'>
|
||||
文档分段ID
|
||||
</Property>
|
||||
@ -965,6 +968,9 @@ import { Row, Col, Properties, Property, Heading, SubProperty, Paragraph } from
|
||||
<Property name='dataset_id' type='string' key='dataset_id'>
|
||||
知识库 ID
|
||||
</Property>
|
||||
<Property name='document_id' type='string' key='document_id'>
|
||||
文档 ID
|
||||
</Property>
|
||||
<Property name='segment_id' type='string' key='segment_id'>
|
||||
文档分段ID
|
||||
</Property>
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
import ReactMarkdown from 'react-markdown'
|
||||
import ReactEcharts from 'echarts-for-react'
|
||||
import 'katex/dist/katex.min.css'
|
||||
import RemarkMath from 'remark-math'
|
||||
import RemarkBreaks from 'remark-breaks'
|
||||
@ -30,6 +31,7 @@ const capitalizationLanguageNameMap: Record<string, string> = {
|
||||
mermaid: 'Mermaid',
|
||||
markdown: 'MarkDown',
|
||||
makefile: 'MakeFile',
|
||||
echarts: 'ECharts',
|
||||
}
|
||||
const getCorrectCapitalizationLanguageName = (language: string) => {
|
||||
if (!language)
|
||||
@ -107,6 +109,14 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props }
|
||||
const match = /language-(\w+)/.exec(className || '')
|
||||
const language = match?.[1]
|
||||
const languageShowName = getCorrectCapitalizationLanguageName(language || '')
|
||||
let chartData = JSON.parse(String('{"title":{"text":"Something went wrong."}}').replace(/\n$/, ''))
|
||||
if (language === 'echarts') {
|
||||
try {
|
||||
chartData = JSON.parse(String(children).replace(/\n$/, ''))
|
||||
}
|
||||
catch (error) {
|
||||
}
|
||||
}
|
||||
|
||||
// Use `useMemo` to ensure that `SyntaxHighlighter` only re-renders when necessary
|
||||
return useMemo(() => {
|
||||
@ -136,19 +146,25 @@ const CodeBlock: CodeComponent = memo(({ inline, className, children, ...props }
|
||||
</div>
|
||||
{(language === 'mermaid' && isSVG)
|
||||
? (<Flowchart PrimitiveCode={String(children).replace(/\n$/, '')} />)
|
||||
: (<SyntaxHighlighter
|
||||
{...props}
|
||||
style={atelierHeathLight}
|
||||
customStyle={{
|
||||
paddingLeft: 12,
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
language={match[1]}
|
||||
showLineNumbers
|
||||
PreTag="div"
|
||||
>
|
||||
{String(children).replace(/\n$/, '')}
|
||||
</SyntaxHighlighter>)}
|
||||
: (
|
||||
(language === 'echarts')
|
||||
? (<div style={{ minHeight: '250px', minWidth: '250px' }}><ReactEcharts
|
||||
option={chartData}
|
||||
>
|
||||
</ReactEcharts></div>)
|
||||
: (<SyntaxHighlighter
|
||||
{...props}
|
||||
style={atelierHeathLight}
|
||||
customStyle={{
|
||||
paddingLeft: 12,
|
||||
backgroundColor: '#fff',
|
||||
}}
|
||||
language={match[1]}
|
||||
showLineNumbers
|
||||
PreTag="div"
|
||||
>
|
||||
{String(children).replace(/\n$/, '')}
|
||||
</SyntaxHighlighter>))}
|
||||
</div>
|
||||
)
|
||||
: (
|
||||
|
||||
@ -329,36 +329,36 @@ const EditCustomCollectionModal: FC<Props> = ({
|
||||
<Button variant='primary' onClick={handleSave}>{t('common.operation.save')}</Button>
|
||||
</div>
|
||||
</div>
|
||||
{showEmojiPicker && <EmojiPicker
|
||||
onSelect={(icon, icon_background) => {
|
||||
setEmoji({ content: icon, background: icon_background })
|
||||
setShowEmojiPicker(false)
|
||||
}}
|
||||
onClose={() => {
|
||||
setShowEmojiPicker(false)
|
||||
}}
|
||||
/>}
|
||||
{credentialsModalShow && (
|
||||
<ConfigCredentials
|
||||
positionCenter={isAdd}
|
||||
credential={credential}
|
||||
onChange={setCredential}
|
||||
onHide={() => setCredentialsModalShow(false)}
|
||||
/>)
|
||||
}
|
||||
{isShowTestApi && (
|
||||
<TestApi
|
||||
positionCenter={isAdd}
|
||||
tool={currTool as CustomParamSchema}
|
||||
customCollection={customCollection}
|
||||
onHide={() => setIsShowTestApi(false)}
|
||||
/>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
isShowMask={true}
|
||||
clickOutsideNotOpen={true}
|
||||
/>
|
||||
{showEmojiPicker && <EmojiPicker
|
||||
onSelect={(icon, icon_background) => {
|
||||
setEmoji({ content: icon, background: icon_background })
|
||||
setShowEmojiPicker(false)
|
||||
}}
|
||||
onClose={() => {
|
||||
setShowEmojiPicker(false)
|
||||
}}
|
||||
/>}
|
||||
{credentialsModalShow && (
|
||||
<ConfigCredentials
|
||||
positionCenter={isAdd}
|
||||
credential={credential}
|
||||
onChange={setCredential}
|
||||
onHide={() => setCredentialsModalShow(false)}
|
||||
/>)
|
||||
}
|
||||
{isShowTestApi && (
|
||||
<TestApi
|
||||
positionCenter={isAdd}
|
||||
tool={currTool as CustomParamSchema}
|
||||
customCollection={customCollection}
|
||||
onHide={() => setIsShowTestApi(false)}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
|
||||
)
|
||||
|
||||
@ -7,12 +7,16 @@ import {
|
||||
import type { ValueSelector, Var } from '@/app/components/workflow/types'
|
||||
type Params = {
|
||||
onlyLeafNodeVar?: boolean
|
||||
hideEnv?: boolean
|
||||
hideChatVar?: boolean
|
||||
filterVar: (payload: Var, selector: ValueSelector) => boolean
|
||||
}
|
||||
|
||||
const useAvailableVarList = (nodeId: string, {
|
||||
onlyLeafNodeVar,
|
||||
filterVar,
|
||||
hideEnv,
|
||||
hideChatVar,
|
||||
}: Params = {
|
||||
onlyLeafNodeVar: false,
|
||||
filterVar: () => true,
|
||||
@ -32,6 +36,8 @@ const useAvailableVarList = (nodeId: string, {
|
||||
beforeNodes: availableNodes,
|
||||
isChatMode,
|
||||
filterVar,
|
||||
hideEnv,
|
||||
hideChatVar,
|
||||
})
|
||||
|
||||
return {
|
||||
|
||||
@ -23,6 +23,8 @@ const Panel: FC<NodePanelProps<AnswerNodeType>> = ({
|
||||
|
||||
const { availableVars, availableNodesWithParent } = useAvailableVarList(id, {
|
||||
onlyLeafNodeVar: false,
|
||||
hideChatVar: true,
|
||||
hideEnv: true,
|
||||
filterVar,
|
||||
})
|
||||
|
||||
|
||||
@ -62,30 +62,25 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
||||
const formatNodeList = useCallback((list: NodeTracing[]) => {
|
||||
const allItems = list.reverse()
|
||||
const result: NodeTracing[] = []
|
||||
let iterationIndexInfos: {
|
||||
start: number
|
||||
end: number
|
||||
}[] = []
|
||||
let iterationIndex = 0
|
||||
allItems.forEach((item) => {
|
||||
const { node_type, index, execution_metadata } = item
|
||||
const { node_type, execution_metadata } = item
|
||||
if (node_type !== BlockEnum.Iteration) {
|
||||
let isInIteration = false
|
||||
let isIterationFirstNode = false
|
||||
iterationIndexInfos.forEach(({ start, end }) => {
|
||||
if (index >= start && index < end) {
|
||||
if (index === start)
|
||||
isIterationFirstNode = true
|
||||
const isInIteration = !!execution_metadata?.iteration_id
|
||||
|
||||
isInIteration = true
|
||||
}
|
||||
})
|
||||
if (isInIteration) {
|
||||
const iterationDetails = result[result.length - 1].details!
|
||||
if (isIterationFirstNode)
|
||||
iterationDetails!.push([item])
|
||||
const currentIterationIndex = execution_metadata?.iteration_index
|
||||
const isIterationFirstNode = iterationIndex !== currentIterationIndex || iterationDetails.length === 0
|
||||
|
||||
else
|
||||
if (isIterationFirstNode) {
|
||||
iterationDetails!.push([item])
|
||||
iterationIndex = currentIterationIndex!
|
||||
}
|
||||
|
||||
else {
|
||||
iterationDetails[iterationDetails.length - 1].push(item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
@ -95,26 +90,6 @@ const RunPanel: FC<RunProps> = ({ hideResult, activeTab = 'RESULT', runID, getRe
|
||||
return
|
||||
}
|
||||
|
||||
const { steps_boundary } = execution_metadata
|
||||
iterationIndexInfos = []
|
||||
steps_boundary.forEach((boundary, index) => {
|
||||
if (index === 0) {
|
||||
iterationIndexInfos.push({
|
||||
start: boundary,
|
||||
end: 0,
|
||||
})
|
||||
}
|
||||
else if (index === steps_boundary.length - 1) {
|
||||
iterationIndexInfos[iterationIndexInfos.length - 1].end = boundary
|
||||
}
|
||||
else {
|
||||
iterationIndexInfos[iterationIndexInfos.length - 1].end = boundary
|
||||
iterationIndexInfos.push({
|
||||
start: boundary,
|
||||
end: 0,
|
||||
})
|
||||
}
|
||||
})
|
||||
result.push({
|
||||
...item,
|
||||
details: [],
|
||||
|
||||
@ -123,7 +123,7 @@ const NodePanel: FC<Props> = ({
|
||||
<div
|
||||
className='flex items-center h-[34px] justify-between px-3 bg-gray-100 border-[0.5px] border-gray-200 rounded-lg cursor-pointer'
|
||||
onClick={handleOnShowIterationDetail}>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-gray-700'>{t('workflow.nodes.iteration.iteration', { count: nodeInfo.metadata?.iterator_length || (nodeInfo.execution_metadata?.steps_boundary?.length - 1) })}</div>
|
||||
<div className='leading-[18px] text-[13px] font-medium text-gray-700'>{t('workflow.nodes.iteration.iteration', { count: nodeInfo.metadata?.iterator_length })}</div>
|
||||
{justShowIterationNavArrow
|
||||
? (
|
||||
<RiArrowRightSLine className='w-3.5 h-3.5 text-gray-500' />
|
||||
|
||||
@ -94,11 +94,38 @@ const translation = {
|
||||
},
|
||||
export: {
|
||||
title: 'シークレット環境変数をエクスポートしますか?',
|
||||
checkbox: 'シクレート値をエクスポート',
|
||||
checkbox: 'シークレット値をエクスポート',
|
||||
ignore: 'DSLをエクスポート',
|
||||
export: 'シクレート値を含むDSLをエクスポート',
|
||||
export: 'シークレット値を含むDSLをエクスポート',
|
||||
},
|
||||
},
|
||||
chatVariable: {
|
||||
panelTitle: '会話変数',
|
||||
panelDescription: '会話変数は、LLMが記憶すべき対話情報を保存するために使用されます。この情報には、対話の履歴、アップロードされたファイル、ユーザーの好みなどが含まれます。読み書きが可能です。',
|
||||
docLink: '詳しくはドキュメントをご覧ください。',
|
||||
button: '変数を追加',
|
||||
modal: {
|
||||
title: '会話変数を追加',
|
||||
editTitle: '会話変数を編集',
|
||||
name: '名前',
|
||||
namePlaceholder: '変数名前',
|
||||
type: 'タイプ',
|
||||
value: 'デフォルト値',
|
||||
valuePlaceholder: 'デフォルト値、設定しない場合は空白にしでください',
|
||||
description: '説明',
|
||||
descriptionPlaceholder: '変数の説明',
|
||||
editInJSON: 'JSONで編集する',
|
||||
oneByOne: '次々に追加する',
|
||||
editInForm: 'フォームで編集',
|
||||
arrayValue: '値',
|
||||
addArrayValue: '値を追加',
|
||||
objectKey: 'キー',
|
||||
objectType: 'タイプ',
|
||||
objectValue: 'デフォルト値',
|
||||
},
|
||||
storedContent: '保存されたコンテンツ',
|
||||
updatedAt: '更新日は',
|
||||
},
|
||||
changeHistory: {
|
||||
title: '変更履歴',
|
||||
placeholder: 'まだ何も変更していません',
|
||||
@ -149,6 +176,7 @@ const translation = {
|
||||
tabs: {
|
||||
'searchBlock': 'ブロックを検索',
|
||||
'blocks': 'ブロック',
|
||||
'searchTool': '検索ツール',
|
||||
'tools': 'ツール',
|
||||
'allTool': 'すべて',
|
||||
'workflowTool': 'ワークフロー',
|
||||
@ -171,8 +199,9 @@ const translation = {
|
||||
'code': 'コード',
|
||||
'template-transform': 'テンプレート',
|
||||
'http-request': 'HTTPリクエスト',
|
||||
'variable-assigner': '変数代入',
|
||||
'variable-assigner': '変数代入器',
|
||||
'variable-aggregator': '変数集約器',
|
||||
'assigner': '変数代入',
|
||||
'iteration-start': 'イテレーション開始',
|
||||
'iteration': 'イテレーション',
|
||||
'parameter-extractor': 'パラメーター抽出',
|
||||
@ -189,6 +218,7 @@ const translation = {
|
||||
'template-transform': 'Jinjaテンプレート構文を使用してデータを文字列に変換します',
|
||||
'http-request': 'HTTPプロトコル経由でサーバーリクエストを送信できます',
|
||||
'variable-assigner': '複数のブランチの変数を1つの変数に集約し、下流のノードに対して統一された設定を行います。',
|
||||
'assigner': '変数代入ノードは、書き込み可能な変数(例えば、会話変数)に値を割り当てるために使用されます。',
|
||||
'variable-aggregator': '複数のブランチの変数を1つの変数に集約し、下流のノードに対して統一された設定を行います。',
|
||||
'iteration': 'リストオブジェクトに対して複数のステップを実行し、すべての結果が出力されるまで繰り返します。',
|
||||
'parameter-extractor': '自然言語からツールの呼び出しやHTTPリクエストのための構造化されたパラメーターを抽出するためにLLMを使用します。',
|
||||
@ -215,6 +245,7 @@ const translation = {
|
||||
checklistResolved: 'すべての問題が解決されました',
|
||||
organizeBlocks: 'ブロックを整理',
|
||||
change: '変更',
|
||||
optional: '(オプション)',
|
||||
},
|
||||
nodes: {
|
||||
common: {
|
||||
@ -406,6 +437,17 @@ const translation = {
|
||||
},
|
||||
setAssignVariable: '代入された変数を設定',
|
||||
},
|
||||
assigner: {
|
||||
'assignedVariable': '代入された変数',
|
||||
'writeMode': '書き込みモード',
|
||||
'writeModeTip': '代入された変数が配列の場合, 末尾に追記モードを追加する。',
|
||||
'over-write': '上書き',
|
||||
'append': '追記',
|
||||
'plus': 'プラス',
|
||||
'clear': 'クリア',
|
||||
'setVariable': '変数を設定する',
|
||||
'variable': '変数',
|
||||
},
|
||||
tool: {
|
||||
toAuthorize: '承認するには',
|
||||
inputVars: '入力変数',
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dify-web",
|
||||
"version": "0.6.16",
|
||||
"version": "0.7.0",
|
||||
"private": true,
|
||||
"engines": {
|
||||
"node": ">=18.17.0"
|
||||
|
||||
@ -24,7 +24,8 @@ export type NodeTracing = {
|
||||
total_tokens: number
|
||||
total_price: number
|
||||
currency: string
|
||||
steps_boundary: number[]
|
||||
iteration_id?: string
|
||||
iteration_index?: number
|
||||
}
|
||||
metadata: {
|
||||
iterator_length: number
|
||||
|
||||
Reference in New Issue
Block a user