Skip to content
Toggle navigation
P
Projects
G
Groups
S
Snippets
Help
赵月辉
/
fastgpt-migrated
This project
Loading...
Sign in
Toggle navigation
Go to a project
Project
Repository
Issues
0
Merge Requests
0
Pipelines
Wiki
Snippets
Members
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Unverified
Commit
d52700c6
authored
Mar 19, 2025
by
heheer
Committed by
archer
Mar 27, 2025
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
add external variable debug (#4204)
* add external variable debug * fix ui * plugin variables
parent
ec30d792
Hide whitespace changes
Inline
Side-by-side
Showing
15 changed files
with
471 additions
and
95 deletions
+471
-95
packages/web/i18n/en/common.json
+2
-0
packages/web/i18n/zh-CN/common.json
+2
-0
packages/web/i18n/zh-Hant/common.json
+2
-0
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/VariableInput.tsx
+182
-35
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/VariablePopover.tsx
+98
-0
projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx
+51
-4
projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderInput.tsx
+37
-29
projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx
+15
-3
projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx
+9
-3
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx
+5
-1
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useDebug.tsx
+27
-10
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx
+16
-5
projects/app/src/pageComponents/app/detail/useChatTest.tsx
+1
-1
projects/app/src/pageComponents/chat/ChatHeader.tsx
+10
-2
projects/app/src/web/core/chat/context/chatItemContext.tsx
+14
-2
No files found.
packages/web/i18n/en/common.json
View file @
d52700c6
...
...
@@ -430,6 +430,8 @@
"core.chat.Start Chat"
:
"Start Chat"
,
"core.chat.Type a message"
:
"Enter a Question, Press [Enter] to Send / Press [Ctrl(Alt/Shift) + Enter] for New Line"
,
"core.chat.Unpin"
:
"Unpin"
,
"core.chat.Variable_Visiable_in_test"
:
"This variable is not visible in the login-free link"
,
"core.chat.Visiable_in_test"
:
"Custom variables are not visible in login-free links"
,
"core.chat.You need to a chat app"
:
"You Do Not Have an Available App"
,
"core.chat.error.Chat error"
:
"Chat Error"
,
"core.chat.error.Messages empty"
:
"API Content is Empty, Possibly Due to Text Being Too Long"
,
...
...
packages/web/i18n/zh-CN/common.json
View file @
d52700c6
...
...
@@ -433,6 +433,8 @@
"core.chat.Start Chat"
:
"开始对话"
,
"core.chat.Type a message"
:
"输入问题,发送 [Enter]/换行 [Ctrl(Alt/Shift) + Enter]"
,
"core.chat.Unpin"
:
"取消置顶"
,
"core.chat.Variable_Visiable_in_test"
:
"该变量在免登录链接中不可见"
,
"core.chat.Visiable_in_test"
:
"自定义变量在免登录链接中不可见"
,
"core.chat.You need to a chat app"
:
"你没有可用的应用"
,
"core.chat.error.Chat error"
:
"对话出现异常"
,
"core.chat.error.Messages empty"
:
"接口内容为空,可能文本超长了~"
,
...
...
packages/web/i18n/zh-Hant/common.json
View file @
d52700c6
...
...
@@ -429,6 +429,8 @@
"core.chat.Start Chat"
:
"開始對話"
,
"core.chat.Type a message"
:
"輸入問題,按 [Enter] 傳送 / 按 [Ctrl(Alt/Shift) + Enter] 換行"
,
"core.chat.Unpin"
:
"取消釘選"
,
"core.chat.Variable_Visiable_in_test"
:
"該變量在免登錄鏈接中不可見"
,
"core.chat.Visiable_in_test"
:
"自定義變量在免登錄鏈接中不可見"
,
"core.chat.You need to a chat app"
:
"您沒有可用的應用程式"
,
"core.chat.error.Chat error"
:
"對話發生錯誤"
,
"core.chat.error.Messages empty"
:
"API 內容為空,可能是文字過長"
,
...
...
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/VariableInput.tsx
View file @
d52700c6
import
React
,
{
useEffect
}
from
'react'
;
import
React
,
{
useEffect
,
useMemo
}
from
'react'
;
import
{
Controller
,
UseFormReturn
}
from
'react-hook-form'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
{
Box
,
Button
,
Card
,
Textarea
}
from
'@chakra-ui/react'
;
import
{
Box
,
Button
,
Card
,
Flex
,
Switch
,
Textarea
}
from
'@chakra-ui/react'
;
import
ChatAvatar
from
'./ChatAvatar'
;
import
{
MessageCardStyle
}
from
'../constants'
;
import
{
VariableInputEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
VariableInputEnum
,
WorkflowIOValueTypeEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
MySelect
from
'@fastgpt/web/components/common/MySelect'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
ChatBoxInputFormType
}
from
'../type.d'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
ChatBoxContext
}
from
'../Provider'
;
import
QuestionTip
from
'@fastgpt/web/components/common/MyTooltip/QuestionTip'
;
import
{
VariableItemType
}
from
'@fastgpt/global/core/app/type'
;
import
MyTextarea
from
'@/components/common/Textarea/MyTextarea'
;
import
MyNumberInput
from
'@fastgpt/web/components/common/Input/NumberInput'
;
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
{
ChatBoxContext
}
from
'../Provider'
;
import
dynamic
from
'next/dynamic'
;
const
JsonEditor
=
dynamic
(()
=>
import
(
'@fastgpt/web/components/common/Textarea/JsonEditor'
));
export
const
VariableInputItem
=
({
item
,
...
...
@@ -108,23 +114,118 @@ export const VariableInputItem = ({
);
};
export
const
ExternalVariableInputItem
=
({
item
,
variablesForm
,
showTag
=
false
}:
{
item
:
VariableItemType
;
variablesForm
:
UseFormReturn
<
any
>
;
showTag
?:
boolean
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
{
register
,
control
}
=
variablesForm
;
return
(
<
Box
key=
{
item
.
id
}
mb=
{
4
}
pl=
{
1
}
>
<
Box
as=
{
'label'
}
display=
{
'flex'
}
position=
{
'relative'
}
mb=
{
1
}
alignItems=
{
'center'
}
w=
{
'full'
}
>
{
item
.
label
}
{
item
.
required
&&
(
<
Box
position=
{
'absolute'
}
top=
{
'-2px'
}
left=
{
'-8px'
}
color=
{
'red.500'
}
>
*
</
Box
>
)
}
{
item
.
description
&&
<
QuestionTip
ml=
{
1
}
label=
{
item
.
description
}
/>
}
{
showTag
&&
(
<
Flex
color=
{
'primary.600'
}
bg=
{
'primary.100'
}
px=
{
2
}
py=
{
1
}
gap=
{
1
}
ml=
{
2
}
fontSize=
{
'mini'
}
rounded=
{
'sm'
}
>
<
MyIcon
name=
{
'common/info'
}
color=
{
'primary.600'
}
w=
{
4
}
/>
{
t
(
'common:core.chat.Variable_Visiable_in_test'
)
}
</
Flex
>
)
}
</
Box
>
<
Controller
control=
{
control
}
name=
{
`variables.${item.key}`
}
rules=
{
{
required
:
item
.
required
,
validate
:
(
value
)
=>
{
if
(
item
.
valueType
===
WorkflowIOValueTypeEnum
.
boolean
)
{
return
value
!==
undefined
;
}
return
!!
value
;
}
}
}
render=
{
({
field
:
{
onChange
,
value
}
})
=>
{
if
(
item
.
valueType
===
WorkflowIOValueTypeEnum
.
string
)
{
return
(
<
MyTextarea
autoHeight
minH=
{
40
}
maxH=
{
160
}
bg=
{
'myGray.50'
}
{
...
register
(`
variables
.
$
{
item
.
key
}`,
{
required
:
item
.
required
})}
/>
);
}
if
(
item
.
valueType
===
WorkflowIOValueTypeEnum
.
number
)
{
return
<
MyNumberInput
step=
{
1
}
bg=
{
'myGray.50'
}
value=
{
value
}
onChange=
{
onChange
}
/>;
}
if
(
item
.
valueType
===
WorkflowIOValueTypeEnum
.
boolean
)
{
return
<
Switch
isChecked=
{
value
}
onChange=
{
onChange
}
/>;
}
return
<
JsonEditor
bg=
{
'myGray.50'
}
resize
value=
{
value
}
onChange=
{
onChange
}
/>;
}
}
/>
</
Box
>
);
};
const
VariableInput
=
({
chatForm
,
chatStarted
chatStarted
,
showExternalVariables
=
false
}:
{
chatStarted
:
boolean
;
chatForm
:
UseFormReturn
<
ChatBoxInputFormType
>
;
chatStarted
:
boolean
;
showExternalVariables
?:
boolean
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
appAvatar
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
chatBoxData
?.
app
?.
avatar
);
const
variablesForm
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
variablesForm
);
const
variableList
=
useContextSelector
(
ChatBoxContext
,
(
v
)
=>
v
.
variableList
);
const
allVariableList
=
useContextSelector
(
ChatBoxContext
,
(
v
)
=>
v
.
allVariableList
);
const
externalVariableList
=
useMemo
(
()
=>
allVariableList
.
filter
((
item
)
=>
showExternalVariables
?
item
.
type
===
VariableInputEnum
.
custom
:
false
),
[
allVariableList
,
showExternalVariables
]
);
const
{
getValues
,
setValue
,
handleSubmit
:
handleSubmitChat
}
=
variablesForm
;
useEffect
(()
=>
{
v
ariableList
.
forEach
((
item
)
=>
{
allV
ariableList
.
forEach
((
item
)
=>
{
const
val
=
getValues
(
`variables.
${
item
.
key
}
`
);
if
(
item
.
defaultValue
!==
undefined
&&
(
val
===
undefined
||
val
===
null
||
val
===
''
))
{
setValue
(
`variables.
${
item
.
key
}
`
,
item
.
defaultValue
);
...
...
@@ -135,34 +236,80 @@ const VariableInput = ({
return
(
<
Box
py=
{
3
}
>
<
ChatAvatar
src=
{
appAvatar
}
type=
{
'AI'
}
/>
<
Box
textAlign=
{
'left'
}
>
<
Card
order=
{
2
}
mt=
{
2
}
w=
{
'400px'
}
{
...
MessageCardStyle
}
bg=
{
'white'
}
boxShadow=
{
'0 0 8px rgba(0,0,0,0.15)'
}
>
{
variableList
.
map
((
item
)
=>
(
<
VariableInputItem
key=
{
item
.
id
}
item=
{
item
}
variablesForm=
{
variablesForm
}
/>
))
}
{
!
chatStarted
&&
(
<
Box
>
<
Button
leftIcon=
{
<
MyIcon
name=
{
'core/chat/chatFill'
}
w=
{
'16px'
}
/>
}
size=
{
'sm'
}
maxW=
{
'100px'
}
onClick=
{
handleSubmitChat
(()
=>
{
chatForm
.
setValue
(
'chatStarted'
,
true
);
})
}
>
{
t
(
'common:core.chat.Start Chat'
)
}
</
Button
>
</
Box
>
)
}
</
Card
>
</
Box
>
{
externalVariableList
.
length
>
0
&&
(
<
Box
textAlign=
{
'left'
}
>
<
Card
order=
{
2
}
mt=
{
2
}
w=
{
'400px'
}
{
...
MessageCardStyle
}
bg=
{
'white'
}
boxShadow=
{
'0 0 8px rgba(0,0,0,0.15)'
}
>
<
Flex
color=
{
'primary.600'
}
bg=
{
'primary.100'
}
mb=
{
3
}
px=
{
3
}
py=
{
1.5
}
gap=
{
1
}
fontSize=
{
'mini'
}
rounded=
{
'sm'
}
>
<
MyIcon
name=
{
'common/info'
}
color=
{
'primary.600'
}
w=
{
4
}
/>
{
t
(
'common:core.chat.Visiable_in_test'
)
}
</
Flex
>
{
externalVariableList
.
map
((
item
)
=>
(
<
ExternalVariableInputItem
key=
{
item
.
id
}
item=
{
item
}
variablesForm=
{
variablesForm
}
/>
))
}
{
variableList
.
length
===
0
&&
!
chatStarted
&&
(
<
Box
>
<
Button
leftIcon=
{
<
MyIcon
name=
{
'core/chat/chatFill'
}
w=
{
'16px'
}
/>
}
size=
{
'sm'
}
maxW=
{
'100px'
}
onClick=
{
handleSubmitChat
(()
=>
{
chatForm
.
setValue
(
'chatStarted'
,
true
);
})
}
>
{
t
(
'common:core.chat.Start Chat'
)
}
</
Button
>
</
Box
>
)
}
</
Card
>
</
Box
>
)
}
{
variableList
.
length
>
0
&&
(
<
Box
textAlign=
{
'left'
}
>
<
Card
order=
{
2
}
mt=
{
2
}
w=
{
'400px'
}
{
...
MessageCardStyle
}
bg=
{
'white'
}
boxShadow=
{
'0 0 8px rgba(0,0,0,0.15)'
}
>
{
variableList
.
map
((
item
)
=>
(
<
VariableInputItem
key=
{
item
.
id
}
item=
{
item
}
variablesForm=
{
variablesForm
}
/>
))
}
{
!
chatStarted
&&
(
<
Box
>
<
Button
leftIcon=
{
<
MyIcon
name=
{
'core/chat/chatFill'
}
w=
{
'16px'
}
/>
}
size=
{
'sm'
}
maxW=
{
'100px'
}
onClick=
{
handleSubmitChat
(()
=>
{
chatForm
.
setValue
(
'chatStarted'
,
true
);
})
}
>
{
t
(
'common:core.chat.Start Chat'
)
}
</
Button
>
</
Box
>
)
}
</
Card
>
</
Box
>
)
}
</
Box
>
);
};
...
...
projects/app/src/components/core/chat/ChatContainer/ChatBox/components/VariablePopover.tsx
0 → 100644
View file @
d52700c6
import
{
Box
,
Button
,
Flex
}
from
'@chakra-ui/react'
;
import
MyPopover
from
'@fastgpt/web/components/common/MyPopover'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
MyIcon
from
'@fastgpt/web/components/common/Icon'
;
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
{
VariableInputEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
import
{
useEffect
}
from
'react'
;
import
{
ExternalVariableInputItem
,
VariableInputItem
}
from
'./VariableInput'
;
import
MyDivider
from
'@fastgpt/web/components/common/MyDivider'
;
const
VariablePopover
=
({
showExternalVariables
=
false
}:
{
showExternalVariables
?:
boolean
;
})
=>
{
const
{
t
}
=
useTranslation
();
const
variablesForm
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
variablesForm
);
const
variables
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
chatBoxData
?.
app
?.
chatConfig
?.
variables
??
[]
);
const
variableList
=
variables
.
filter
((
item
)
=>
item
.
type
!==
VariableInputEnum
.
custom
);
const
externalVariableList
=
variables
.
filter
((
item
)
=>
showExternalVariables
?
item
.
type
===
VariableInputEnum
.
custom
:
false
);
const
hasExternalVariable
=
externalVariableList
.
length
>
0
;
const
hasVariable
=
variableList
.
length
>
0
;
const
{
getValues
,
setValue
}
=
variablesForm
;
useEffect
(()
=>
{
variables
.
forEach
((
item
)
=>
{
const
val
=
getValues
(
`variables.
${
item
.
key
}
`
);
if
(
item
.
defaultValue
!==
undefined
&&
(
val
===
undefined
||
val
===
null
||
val
===
''
))
{
setValue
(
`variables.
${
item
.
key
}
`
,
item
.
defaultValue
);
}
});
},
[
variables
]);
return
(
<
MyPopover
placement=
"bottom"
trigger=
{
'click'
}
closeOnBlur=
{
true
}
Trigger=
{
<
Button
variant=
{
'whiteBase'
}
leftIcon=
{
<
MyIcon
name=
{
'edit'
}
w=
{
4
}
/>
}
>
{
t
(
'common:core.module.Variable'
)
}
</
Button
>
}
>
{
({
onClose
})
=>
(
<
Box
p=
{
4
}
>
{
hasExternalVariable
&&
(
<
Box
textAlign=
{
'left'
}
>
<
Flex
color=
{
'primary.600'
}
bg=
{
'primary.100'
}
mb=
{
3
}
px=
{
3
}
py=
{
1.5
}
gap=
{
1
}
fontSize=
{
'mini'
}
rounded=
{
'sm'
}
>
<
MyIcon
name=
{
'common/info'
}
color=
{
'primary.600'
}
w=
{
4
}
/>
{
t
(
'common:core.chat.Visiable_in_test'
)
}
</
Flex
>
{
externalVariableList
.
map
((
item
)
=>
(
<
ExternalVariableInputItem
key=
{
item
.
id
}
item=
{
item
}
variablesForm=
{
variablesForm
}
/>
))
}
</
Box
>
)
}
{
hasExternalVariable
&&
hasVariable
&&
<
MyDivider
h=
{
'1px'
}
/>
}
{
hasVariable
&&
(
<
Box
textAlign=
{
'left'
}
>
{
variableList
.
map
((
item
)
=>
(
<
VariableInputItem
key=
{
item
.
id
}
item=
{
item
}
variablesForm=
{
variablesForm
}
/>
))
}
</
Box
>
)
}
<
Flex
w=
{
'full'
}
justifyContent=
{
'flex-end'
}
>
<
Button
size=
{
'sm'
}
onClick=
{
onClose
}
>
{
t
(
'common:common.Confirm'
)
}
</
Button
>
</
Flex
>
</
Box
>
)
}
</
MyPopover
>
);
};
export
default
VariablePopover
;
projects/app/src/components/core/chat/ChatContainer/ChatBox/index.tsx
View file @
d52700c6
...
...
@@ -65,6 +65,7 @@ import { ChatRecordContext } from '@/web/core/chat/context/chatRecordContext';
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
TimeBox
from
'./components/TimeBox'
;
import
MyBox
from
'@fastgpt/web/components/common/MyBox'
;
import
{
VariableInputEnum
}
from
'@fastgpt/global/core/workflow/constants'
;
const
ResponseTags
=
dynamic
(()
=>
import
(
'./components/ResponseTags'
));
const
FeedbackModal
=
dynamic
(()
=>
import
(
'./components/FeedbackModal'
));
...
...
@@ -103,7 +104,8 @@ const ChatBox = ({
showVoiceIcon
=
true
,
showEmptyIntro
=
false
,
active
=
true
,
onStartChat
onStartChat
,
chatType
}:
Props
)
=>
{
const
ScrollContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
{
t
}
=
useTranslation
();
...
...
@@ -129,6 +131,8 @@ const ChatBox = ({
const
chatBoxData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
chatBoxData
);
const
ChatBoxRef
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
ChatBoxRef
);
const
variablesForm
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
variablesForm
);
const
setIsVariableVisible
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
setIsVariableVisible
);
const
chatRecords
=
useContextSelector
(
ChatRecordContext
,
(
v
)
=>
v
.
chatRecords
);
const
setChatRecords
=
useContextSelector
(
ChatRecordContext
,
(
v
)
=>
v
.
setChatRecords
);
const
isChatRecordsLoaded
=
useContextSelector
(
ChatRecordContext
,
(
v
)
=>
v
.
isChatRecordsLoaded
);
...
...
@@ -150,6 +154,12 @@ const ChatBox = ({
// Workflow running, there are user input or selection
const
isInteractive
=
useMemo
(()
=>
checkIsInteractiveByHistories
(
chatRecords
),
[
chatRecords
]);
const
externalVariableList
=
useMemo
(()
=>
{
if
(
chatType
===
'chat'
)
{
return
allVariableList
.
filter
((
item
)
=>
item
.
type
===
VariableInputEnum
.
custom
);
}
return
[];
},
[
allVariableList
,
chatType
]);
// compute variable input is finish.
const
chatForm
=
useForm
<
ChatBoxInputFormType
>
({
defaultValues
:
{
...
...
@@ -162,7 +172,9 @@ const ChatBox = ({
const
chatStartedWatch
=
watch
(
'chatStarted'
);
const
chatStarted
=
chatBoxData
?.
appId
===
appId
&&
(
chatStartedWatch
||
chatRecords
.
length
>
0
||
variableList
.
length
===
0
);
(
chatStartedWatch
||
chatRecords
.
length
>
0
||
[...
variableList
,
...
externalVariableList
].
length
===
0
);
// 滚动到底部
const
scrollToBottom
=
useMemoizedFn
((
behavior
:
'smooth'
|
'auto'
=
'smooth'
,
delay
=
0
)
=>
{
...
...
@@ -891,6 +903,33 @@ const ChatBox = ({
}
}));
// Visibility check
useEffect
(()
=>
{
const
checkVariableVisibility
=
()
=>
{
if
(
!
ScrollContainerRef
.
current
)
return
;
const
container
=
ScrollContainerRef
.
current
;
const
variableInput
=
container
.
querySelector
(
'#variable-input'
);
if
(
!
variableInput
)
return
;
const
containerRect
=
container
.
getBoundingClientRect
();
const
elementRect
=
variableInput
.
getBoundingClientRect
();
setIsVariableVisible
(
elementRect
.
bottom
>
containerRect
.
top
&&
elementRect
.
top
<
containerRect
.
bottom
);
};
const
container
=
ScrollContainerRef
.
current
;
if
(
container
)
{
container
.
addEventListener
(
'scroll'
,
checkVariableVisibility
);
checkVariableVisibility
();
return
()
=>
{
container
.
removeEventListener
(
'scroll'
,
checkVariableVisibility
);
};
}
},
[
setIsVariableVisible
]);
const
RenderRecords
=
useMemo
(()
=>
{
return
(
<
ScrollData
...
...
@@ -906,8 +945,14 @@ const ChatBox = ({
{
showEmpty
&&
<
Empty
/>
}
{
!!
welcomeText
&&
<
WelcomeBox
welcomeText=
{
welcomeText
}
/>
}
{
/* variable input */
}
{
!!
variableList
?.
length
&&
(
<
VariableInput
chatStarted=
{
chatStarted
}
chatForm=
{
chatForm
}
/>
{
(
!!
variableList
?.
length
||
!!
externalVariableList
?.
length
)
&&
(
<
Box
id=
"variable-input"
>
<
VariableInput
chatStarted=
{
chatStarted
}
chatForm=
{
chatForm
}
showExternalVariables=
{
chatType
===
'chat'
}
/>
</
Box
>
)
}
{
/* chat history */
}
<
Box
id=
{
'history'
}
>
...
...
@@ -1006,7 +1051,9 @@ const ChatBox = ({
chatForm
,
chatRecords
,
chatStarted
,
chatType
,
delOneMessage
,
externalVariableList
?.
length
,
isChatting
,
onAddUserDislike
,
onAddUserLike
,
...
...
projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/RenderInput.tsx
View file @
d52700c6
...
...
@@ -18,6 +18,7 @@ import { ChatBoxInputFormType } from '../../ChatBox/type';
import
{
FlowNodeInputItemType
}
from
'@fastgpt/global/core/workflow/type/io'
;
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
{
ChatRecordContext
}
from
'@/web/core/chat/context/chatRecordContext'
;
import
{
FlowNodeInputTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
const
RenderInput
=
()
=>
{
const
{
t
}
=
useTranslation
();
...
...
@@ -213,36 +214,43 @@ const RenderInput = () => {
</
Box
>
)
}
{
/* Filed */
}
{
formatPluginInputs
.
map
((
input
)
=>
{
return
(
<
Controller
key=
{
`variables.${input.key}`
}
control=
{
control
}
name=
{
`variables.${input.key}`
}
rules=
{
{
validate
:
(
value
)
=>
{
if
(
!
input
.
required
)
return
true
;
if
(
input
.
valueType
===
WorkflowIOValueTypeEnum
.
boolean
)
{
return
value
!==
undefined
;
{
formatPluginInputs
.
filter
((
input
)
=>
{
if
(
outLinkAuthData
&&
Object
.
keys
(
outLinkAuthData
).
length
>
0
)
{
return
input
.
renderTypeList
[
0
]
!==
FlowNodeInputTypeEnum
.
customVariable
;
}
return
true
;
})
.
map
((
input
)
=>
{
return
(
<
Controller
key=
{
`variables.${input.key}`
}
control=
{
control
}
name=
{
`variables.${input.key}`
}
rules=
{
{
validate
:
(
value
)
=>
{
if
(
!
input
.
required
)
return
true
;
if
(
input
.
valueType
===
WorkflowIOValueTypeEnum
.
boolean
)
{
return
value
!==
undefined
;
}
return
!!
value
;
}
return
!!
value
;
}
}
}
render=
{
({
field
:
{
onChange
,
value
}
})
=>
{
return
(
<
RenderPluginInput
value=
{
value
}
onChange=
{
onChange
}
isDisabled=
{
isDisabledInput
}
isInvalid=
{
errors
&&
Object
.
keys
(
errors
).
includes
(
input
.
key
)
}
input=
{
input
}
setUploading=
{
setUploading
}
/>
);
}
}
/>
);
})
}
}
}
render=
{
({
field
:
{
onChange
,
value
}
})
=>
{
return
(
<
RenderPluginInput
value=
{
value
}
onChange=
{
onChange
}
isDisabled=
{
isDisabledInput
}
isInvalid=
{
errors
&&
Object
.
keys
(
errors
).
includes
(
input
.
key
)
}
input=
{
input
}
setUploading=
{
setUploading
}
/>
);
}
}
/>
);
})
}
{
/* Run Button */
}
{
onStartChat
&&
onNewChat
&&
(
<
Flex
justifyContent=
{
'end'
}
mt=
{
8
}
>
...
...
projects/app/src/components/core/chat/ChatContainer/PluginRunBox/components/renderPluginInput.tsx
View file @
d52700c6
...
...
@@ -157,9 +157,6 @@ const RenderPluginInput = ({
const
{
llmModelList
}
=
useSystemStore
();
const
render
=
(()
=>
{
if
(
inputType
===
FlowNodeInputTypeEnum
.
customVariable
)
{
return
null
;
}
if
(
inputType
===
FlowNodeInputTypeEnum
.
select
&&
input
.
list
)
{
return
(
<
MySelect
list=
{
input
.
list
}
value=
{
value
}
onChange=
{
onChange
}
isDisabled=
{
isDisabled
}
/>
...
...
@@ -246,6 +243,21 @@ const RenderPluginInput = ({
<
FormLabel
fontWeight=
{
'500'
}
>
{
t
(
input
.
label
as
any
)
}
</
FormLabel
>
</
Box
>
{
input
.
description
&&
<
QuestionTip
ml=
{
2
}
label=
{
t
(
input
.
description
as
any
)
}
/>
}
{
inputType
===
FlowNodeInputTypeEnum
.
customVariable
&&
(
<
Flex
color=
{
'primary.600'
}
bg=
{
'primary.100'
}
px=
{
2
}
py=
{
1
}
gap=
{
1
}
ml=
{
2
}
fontSize=
{
'mini'
}
rounded=
{
'sm'
}
>
<
MyIcon
name=
{
'common/info'
}
color=
{
'primary.600'
}
w=
{
4
}
/>
{
t
(
'common:core.chat.Variable_Visiable_in_test'
)
}
</
Flex
>
)
}
</
Flex
>
)
}
...
...
projects/app/src/pageComponents/app/detail/SimpleApp/ChatTest.tsx
View file @
d52700c6
import
{
Box
,
Flex
,
IconButton
}
from
'@chakra-ui/react'
;
import
{
Box
,
Button
,
Flex
,
IconButton
}
from
'@chakra-ui/react'
;
import
{
useTranslation
}
from
'next-i18next'
;
import
React
,
{
useEffect
,
useMemo
}
from
'react'
;
import
MyTooltip
from
'@fastgpt/web/components/common/MyTooltip'
;
...
...
@@ -10,12 +10,14 @@ import { form2AppWorkflow } from '@/web/core/app/utils';
import
{
useContextSelector
}
from
'use-context-selector'
;
import
{
AppContext
}
from
'../context'
;
import
{
useChatTest
}
from
'../useChatTest'
;
import
{
useDatasetStore
}
from
'@/web/core/dataset/store/dataset'
;
import
ChatItemContextProvider
,
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
ChatRecordContextProvider
from
'@/web/core/chat/context/chatRecordContext'
;
import
{
useChatStore
}
from
'@/web/core/chat/context/useChatStore'
;
import
MyBox
from
'@fastgpt/web/components/common/MyBox'
;
import
{
cardStyles
}
from
'../constants'
;
import
ChatQuoteList
from
'@/pageComponents/chat/ChatQuoteList'
;
import
VariablePopover
from
'@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'
;
type
Props
=
{
appForm
:
AppSimpleEditFormType
;
...
...
@@ -27,6 +29,8 @@ const ChatTest = ({ appForm, setRenderEdit }: Props) => {
const
{
appDetail
}
=
useContextSelector
(
AppContext
,
(
v
)
=>
v
);
const
quoteData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
quoteData
);
const
setQuoteData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
setQuoteData
);
// form2AppWorkflow dependent allDatasets
const
isVariableVisible
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
isVariableVisible
);
const
[
workflowData
,
setWorkflowData
]
=
useSafeState
({
nodes
:
appDetail
.
modules
||
[],
...
...
@@ -62,10 +66,12 @@ const ChatTest = ({ appForm, setRenderEdit }: Props) => {
{
...
cardStyles
}
boxShadow=
{
'3'
}
>
<
Flex
px=
{
[
2
,
5
]
}
>
<
Box
fontSize=
{
[
'md'
,
'lg'
]
}
fontWeight=
{
'bold'
}
flex=
{
1
}
color=
{
'myGray.900'
}
>
<
Flex
px=
{
[
2
,
5
]
}
pb=
{
2
}
>
<
Box
fontSize=
{
[
'md'
,
'lg'
]
}
fontWeight=
{
'bold'
}
color=
{
'myGray.900'
}
mr=
{
3
}
>
{
t
(
'app:chat_debug'
)
}
</
Box
>
{
!
isVariableVisible
&&
<
VariablePopover
showExternalVariables=
{
true
}
/>
}
<
Box
flex=
{
1
}
/>
<
MyTooltip
label=
{
t
(
'common:core.chat.Restart'
)
}
>
<
IconButton
className=
"chat"
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/ChatTest.tsx
View file @
d52700c6
...
...
@@ -21,6 +21,7 @@ import ChatRecordContextProvider, {
import
{
useChatStore
}
from
'@/web/core/chat/context/useChatStore'
;
import
MyBox
from
'@fastgpt/web/components/common/MyBox'
;
import
ChatQuoteList
from
'@/pageComponents/chat/ChatQuoteList'
;
import
VariablePopover
from
'@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'
;
type
Props
=
{
isOpen
:
boolean
;
...
...
@@ -45,6 +46,7 @@ const ChatTest = ({ isOpen, nodes = [], edges = [], onClose }: Props) => {
const
quoteData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
quoteData
);
const
setQuoteData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
setQuoteData
);
const
isVariableVisible
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
isVariableVisible
);
const
chatRecords
=
useContextSelector
(
ChatRecordContext
,
(
v
)
=>
v
.
chatRecords
);
return
(
...
...
@@ -115,10 +117,12 @@ const ChatTest = ({ isOpen, nodes = [], edges = [], onClose }: Props) => {
bg=
{
'myGray.25'
}
borderBottom=
{
'1px solid #F4F4F7'
}
>
<
Flex
fontSize=
{
'16px'
}
fontWeight=
{
'bold'
}
flex=
{
1
}
alignItems=
{
'center'
}
>
<
Flex
fontSize=
{
'16px'
}
fontWeight=
{
'bold'
}
alignItems=
{
'center'
}
mr=
{
3
}
>
<
MyIcon
name=
{
'common/paused'
}
w=
{
'14px'
}
mr=
{
2.5
}
/>
{
t
(
'common:core.chat.Run test'
)
}
</
Flex
>
{
!
isVariableVisible
&&
<
VariablePopover
showExternalVariables=
{
true
}
/>
}
<
Box
flex=
{
1
}
/>
<
MyTooltip
label=
{
t
(
'common:core.chat.Restart'
)
}
>
<
IconButton
className=
"chat"
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/hooks/useDebug.tsx
View file @
d52700c6
...
...
@@ -31,7 +31,10 @@ import { WorkflowContext } from '../../context';
import
QuestionTip
from
'@fastgpt/web/components/common/MyTooltip/QuestionTip'
;
import
{
FlowNodeTypeEnum
}
from
'@fastgpt/global/core/workflow/node/constant'
;
import
{
AppContext
}
from
'../../../context'
;
import
{
VariableInputItem
}
from
'@/components/core/chat/ChatContainer/ChatBox/components/VariableInput'
;
import
{
ExternalVariableInputItem
,
VariableInputItem
}
from
'@/components/core/chat/ChatContainer/ChatBox/components/VariableInput'
;
import
LightRowTabs
from
'@fastgpt/web/components/common/Tabs/LightRowTabs'
;
import
MyTextarea
from
'@/components/common/Textarea/MyTextarea'
;
import
{
WorkflowNodeEdgeContext
}
from
'../../context/workflowInitContext'
;
...
...
@@ -58,13 +61,17 @@ export const useDebug = () => {
const
appDetail
=
useContextSelector
(
AppContext
,
(
v
)
=>
v
.
appDetail
);
const
filteredVar
=
useMemo
(()
=>
{
const
variables
=
appDetail
.
chatConfig
?.
variables
;
return
variables
?.
filter
((
item
)
=>
item
.
type
!==
VariableInputEnum
.
custom
)
||
[];
const
{
filteredVar
,
customVar
,
variables
}
=
useMemo
(()
=>
{
const
variables
=
appDetail
.
chatConfig
?.
variables
||
[];
return
{
filteredVar
:
variables
.
filter
((
item
)
=>
item
.
type
!==
VariableInputEnum
.
custom
)
||
[],
customVar
:
variables
.
filter
((
item
)
=>
item
.
type
===
VariableInputEnum
.
custom
)
||
[],
variables
};
},
[
appDetail
.
chatConfig
?.
variables
]);
const
[
defaultGlobalVariables
,
setDefaultGlobalVariables
]
=
useState
<
Record
<
string
,
any
>>
(
filteredVar
.
reduce
(
variables
.
reduce
(
(
acc
,
item
)
=>
{
acc
[
item
.
key
]
=
item
.
defaultValue
;
return
acc
;
...
...
@@ -241,7 +248,7 @@ export const useDebug = () => {
px=
{
0
}
>
<
Box
flex=
{
'1 0 0'
}
overflow=
{
'auto'
}
px=
{
6
}
>
{
filteredVar
.
length
>
0
&&
(
{
variables
.
length
>
0
&&
(
<
LightRowTabs
<
TabEnum
>
gap=
{
3
}
ml=
{
-
2
}
...
...
@@ -256,6 +263,14 @@ export const useDebug = () => {
/
>
)
}
<
Box
display=
{
currentTab
===
TabEnum
.
global
?
'block'
:
'none'
}
>
{
customVar
.
map
((
item
)
=>
(
<
ExternalVariableInputItem
key=
{
item
.
id
}
item=
{
{
...
item
,
key
:
item
.
key
}
}
variablesForm=
{
variablesForm
}
showTag=
{
true
}
/>
))
}
{
filteredVar
.
map
((
item
)
=>
(
<
VariableInputItem
key=
{
item
.
id
}
...
...
@@ -354,13 +369,15 @@ export const useDebug = () => {
</
MyRightDrawer
>
);
},
[
runtimeNodes
,
runtimeEdges
,
defaultGlobalVariables
,
t
,
variables
.
length
,
customVar
,
filteredVar
,
onStartNodeDebug
,
runtimeEdges
,
runtimeNodeId
,
runtimeNodes
,
t
onStartNodeDebug
]);
return
{
...
...
projects/app/src/pageComponents/app/detail/WorkflowComponents/Flow/nodes/NodePluginIO/InputTypeConfig.tsx
View file @
d52700c6
...
...
@@ -297,8 +297,10 @@ const InputTypeConfig = ({
<
FormLabel
flex=
{
'0 0 132px'
}
fontWeight=
{
'medium'
}
>
{
t
(
'common:core.module.Default Value'
)
}
</
FormLabel
>
<
Flex
alignItems=
{
'start'
}
flex=
{
1
}
h=
{
10
}
>
{
inputType
===
FlowNodeInputTypeEnum
.
numberInput
&&
(
<
Flex
alignItems=
{
'center'
}
flex=
{
1
}
h=
{
10
}
>
{
(
inputType
===
FlowNodeInputTypeEnum
.
numberInput
||
(
inputType
===
VariableInputEnum
.
custom
&&
valueType
===
WorkflowIOValueTypeEnum
.
number
))
&&
(
<
MyNumberInput
value=
{
defaultValue
}
min=
{
min
}
...
...
@@ -310,7 +312,8 @@ const InputTypeConfig = ({
/>
)
}
{
(
inputType
===
FlowNodeInputTypeEnum
.
input
||
inputType
===
VariableInputEnum
.
custom
)
&&
(
(
inputType
===
VariableInputEnum
.
custom
&&
valueType
===
WorkflowIOValueTypeEnum
.
string
))
&&
(
<
MyTextarea
{
...
register
('
defaultValue
')}
bg=
{
'myGray.50'
}
...
...
@@ -319,7 +322,13 @@ const InputTypeConfig = ({
maxH=
{
100
}
/>
)
}
{
inputType
===
FlowNodeInputTypeEnum
.
JSONEditor
&&
(
{
(
inputType
===
FlowNodeInputTypeEnum
.
JSONEditor
||
(
inputType
===
VariableInputEnum
.
custom
&&
!
[
WorkflowIOValueTypeEnum
.
number
,
WorkflowIOValueTypeEnum
.
string
,
WorkflowIOValueTypeEnum
.
boolean
].
includes
(
valueType
)))
&&
(
<
JsonEditor
bg=
{
'myGray.50'
}
resize
...
...
@@ -330,7 +339,9 @@ const InputTypeConfig = ({
defaultValue=
{
defaultValue
}
/>
)
}
{
inputType
===
FlowNodeInputTypeEnum
.
switch
&&
(
{
(
inputType
===
FlowNodeInputTypeEnum
.
switch
||
(
inputType
===
VariableInputEnum
.
custom
&&
valueType
===
WorkflowIOValueTypeEnum
.
boolean
))
&&
(
<
Switch
{
...
register
('
defaultValue
')}
/>
)
}
{
inputType
===
FlowNodeInputTypeEnum
.
select
&&
(
...
...
projects/app/src/pageComponents/app/detail/useChatTest.tsx
View file @
d52700c6
...
...
@@ -140,7 +140,7 @@ export const useChatTest = ({
appId=
{
appId
}
chatId=
{
chatId
}
showMarkIcon
chatType=
"chat"
chatType=
{
'chat'
}
onStartChat=
{
startChat
}
/>
)
...
...
projects/app/src/pageComponents/chat/ChatHeader.tsx
View file @
d52700c6
...
...
@@ -22,6 +22,7 @@ import {
import
{
getMyApps
}
from
'@/web/core/app/api'
;
import
SelectOneResource
from
'@/components/common/folder/SelectOneResource'
;
import
{
ChatItemContext
}
from
'@/web/core/chat/context/chatItemContext'
;
import
VariablePopover
from
'@/components/core/chat/ChatContainer/ChatBox/components/VariablePopover'
;
const
ChatHeader
=
({
history
,
...
...
@@ -38,7 +39,10 @@ const ChatHeader = ({
const
{
isPc
}
=
useSystem
();
const
chatData
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
chatBoxData
);
const
isVariableVisible
=
useContextSelector
(
ChatItemContext
,
(
v
)
=>
v
.
isVariableVisible
);
const
isPlugin
=
chatData
.
app
.
type
===
AppTypeEnum
.
plugin
;
const
router
=
useRouter
();
const
isChat
=
router
.
pathname
===
'/chat'
;
return
isPc
&&
isPlugin
?
null
:
(
<
Flex
...
...
@@ -68,8 +72,12 @@ const ChatHeader = ({
/>
)
}
{
/* control */
}
{
!
isPlugin
&&
<
ToolMenu
history=
{
history
}
/>
}
<
Flex
gap=
{
2
}
alignItems=
{
'center'
}
>
{
!
isVariableVisible
&&
<
VariablePopover
showExternalVariables=
{
isChat
}
/>
}
{
/* control */
}
{
!
isPlugin
&&
<
ToolMenu
history=
{
history
}
/>
}
</
Flex
>
</
Flex
>
);
};
...
...
projects/app/src/web/core/chat/context/chatItemContext.tsx
View file @
d52700c6
...
...
@@ -74,6 +74,8 @@ type ChatItemContextType = {
quoteData
?:
QuoteDataType
;
setQuoteData
:
React
.
Dispatch
<
React
.
SetStateAction
<
QuoteDataType
|
undefined
>>
;
isVariableVisible
:
boolean
;
setIsVariableVisible
:
React
.
Dispatch
<
React
.
SetStateAction
<
boolean
>>
;
}
&
ContextProps
;
export
const
ChatItemContext
=
createContext
<
ChatItemContextType
>
({
...
...
@@ -97,6 +99,10 @@ export const ChatItemContext = createContext<ChatItemContextType>({
quoteData
:
undefined
,
setQuoteData
:
function
(
value
:
React
.
SetStateAction
<
QuoteDataType
|
undefined
>
):
void
{
throw
new
Error
(
'Function not implemented.'
);
},
isVariableVisible
:
true
,
setIsVariableVisible
:
function
(
value
:
React
.
SetStateAction
<
boolean
>
):
void
{
throw
new
Error
(
'Function not implemented.'
);
}
});
...
...
@@ -116,6 +122,8 @@ const ChatItemContextProvider = ({
const
ChatBoxRef
=
useRef
<
ChatComponentRef
>
(
null
);
const
variablesForm
=
useForm
<
ChatBoxInputFormType
>
();
const
[
quoteData
,
setQuoteData
]
=
useState
<
QuoteDataType
>
();
const
[
isVariableVisible
,
setIsVariableVisible
]
=
useState
(
true
);
const
[
chatBoxData
,
setChatBoxData
]
=
useState
<
ChatBoxDataType
>
({
...
defaultChatData
});
...
...
@@ -172,7 +180,9 @@ const ChatItemContextProvider = ({
showNodeStatus
,
quoteData
,
setQuoteData
setQuoteData
,
isVariableVisible
,
setIsVariableVisible
};
},
[
chatBoxData
,
...
...
@@ -187,7 +197,9 @@ const ChatItemContextProvider = ({
// isShowFullText,
showNodeStatus
,
quoteData
,
setQuoteData
setQuoteData
,
isVariableVisible
,
setIsVariableVisible
]);
return
<
ChatItemContext
.
Provider
value=
{
contextValue
}
>
{
children
}
</
ChatItemContext
.
Provider
>;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment