Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
D
dify
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
ai-tech
dify
Commits
049e858e
Commit
049e858e
authored
Mar 11, 2024
by
StyleZhang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
run
parent
405e99d2
Changes
11
Show whitespace changes
Inline
Side-by-side
Showing
11 changed files
with
360 additions
and
17 deletions
+360
-17
run-and-history.tsx
web/app/components/workflow/header/run-and-history.tsx
+6
-2
hooks.ts
web/app/components/workflow/hooks.ts
+53
-0
form-item.tsx
...flow/nodes/_base/components/before-run-form/form-item.tsx
+4
-2
node.tsx
web/app/components/workflow/nodes/_base/node.tsx
+29
-3
index.tsx
web/app/components/workflow/operator/index.tsx
+18
-8
index.tsx
web/app/components/workflow/panel/index.tsx
+7
-0
inputs-panel.tsx
web/app/components/workflow/panel/inputs-panel.tsx
+79
-0
store.ts
web/app/components/workflow/store.ts
+9
-0
types.ts
web/app/components/workflow/types.ts
+15
-1
base.ts
web/service/base.ts
+55
-1
workflow.ts
web/types/workflow.ts
+85
-0
No files found.
web/app/components/workflow/header/run-and-history.tsx
View file @
049e858e
...
...
@@ -7,7 +7,6 @@ import { Play } from '@/app/components/base/icons/src/vender/line/mediaAndDevice
import
{
ClockPlay
}
from
'@/app/components/base/icons/src/vender/line/time'
import
TooltipPlus
from
'@/app/components/base/tooltip-plus'
import
{
Loading02
}
from
'@/app/components/base/icons/src/vender/line/general'
import
{
Mode
}
from
'@/app/components/workflow/types'
const
RunAndHistory
:
FC
=
()
=>
{
const
{
t
}
=
useTranslation
()
...
...
@@ -15,6 +14,11 @@ const RunAndHistory: FC = () => {
const
mode
=
useStore
(
state
=>
state
.
mode
)
const
showRunHistory
=
useStore
(
state
=>
state
.
showRunHistory
)
const
handleClick
=
()
=>
{
if
(
!
isChatMode
)
useStore
.
setState
({
showInputsPanel
:
true
})
}
return
(
<
div
className=
'flex items-center px-0.5 h-8 rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xs'
>
<
div
...
...
@@ -24,7 +28,7 @@ const RunAndHistory: FC = () => {
${mode === 'running' && 'bg-primary-50 !cursor-not-allowed'}
${mode === 'running' && isChatMode && 'opacity-50'}
`
}
onClick=
{
()
=>
mode
!==
'running'
&&
useStore
.
setState
({
mode
:
Mode
.
Running
}
)
}
onClick=
{
()
=>
mode
!==
'running'
&&
handleClick
(
)
}
>
{
mode
===
'running'
...
...
web/app/components/workflow/hooks.ts
View file @
049e858e
...
...
@@ -21,6 +21,10 @@ import type {
BlockEnum
,
Node
,
}
from
'./types'
import
{
NodeRunningStatus
,
WorkflowRunningStatus
,
}
from
'./types'
import
{
NODES_EXTRA_DATA
,
NODES_INITIAL_DATA
,
...
...
@@ -31,6 +35,7 @@ import type { ToolDefaultValue } from './block-selector/types'
import
{
syncWorkflowDraft
}
from
'@/service/workflow'
import
{
useFeaturesStore
}
from
'@/app/components/base/features/hooks'
import
{
useStore
as
useAppStore
}
from
'@/app/components/app/store'
import
{
ssePost
}
from
'@/service/base'
export
const
useIsChatMode
=
()
=>
{
const
appDetail
=
useAppStore
(
s
=>
s
.
appDetail
)
...
...
@@ -560,3 +565,51 @@ export const useWorkflow = () => {
handleEdgesChange
,
}
}
export
const
useWorkflowRun
=
()
=>
{
const
store
=
useStoreApi
()
return
(
params
:
any
)
=>
{
const
{
getNodes
,
setNodes
,
}
=
store
.
getState
()
const
appDetail
=
useAppStore
.
getState
().
appDetail
let
url
=
''
if
(
appDetail
?.
mode
===
'advanced-chat'
)
url
=
`/apps/
${
appDetail
.
id
}
/advanced-chat/workflows/draft/run`
if
(
appDetail
?.
mode
===
'workflow'
)
url
=
`/apps/
${
appDetail
.
id
}
/workflows/draft/run`
ssePost
(
url
,
params
,
{
onWorkflowStarted
:
()
=>
{
useStore
.
setState
({
runningStatus
:
WorkflowRunningStatus
.
Running
})
},
onWorkflowFinished
:
({
data
})
=>
{
useStore
.
setState
({
runningStatus
:
data
.
status
as
WorkflowRunningStatus
})
},
onNodeStarted
:
({
data
})
=>
{
const
newNodes
=
produce
(
getNodes
(),
(
draft
)
=>
{
const
currentNode
=
draft
.
find
(
node
=>
node
.
id
===
data
.
node_id
)
!
currentNode
.
data
.
_running
=
NodeRunningStatus
.
Running
})
setNodes
(
newNodes
)
},
onNodeFinished
:
({
data
})
=>
{
const
newNodes
=
produce
(
getNodes
(),
(
draft
)
=>
{
const
currentNode
=
draft
.
find
(
node
=>
node
.
id
===
data
.
node_id
)
!
currentNode
.
data
.
_running
=
data
.
status
})
setNodes
(
newNodes
)
},
},
)
}
}
web/app/components/workflow/nodes/_base/components/before-run-form/form-item.tsx
View file @
049e858e
...
...
@@ -15,12 +15,14 @@ type Props = {
payload
:
InputVar
value
:
any
onChange
:
(
value
:
any
)
=>
void
className
?:
string
}
const
FormItem
:
FC
<
Props
>
=
({
payload
,
value
,
onChange
,
className
,
})
=>
{
const
{
type
}
=
payload
const
handleContextItemChange
=
useCallback
((
index
:
number
)
=>
{
...
...
@@ -41,9 +43,9 @@ const FormItem: FC<Props> = ({
}
},
[
value
,
onChange
])
return
(
<
div
className=
'flex justify-between items-start'
>
<
div
className=
{
`flex justify-between items-start ${className}`
}
>
{
type
!==
InputVarType
.
contexts
&&
<
div
className=
'shrink-0 w-[96px] pr-1 h-8 leading-8 text-[13px] font-medium text-gray-700 truncate'
>
{
payload
.
label
}
</
div
>
}
<
div
className=
'
w-0
grow'
>
<
div
className=
'grow'
>
{
type
===
InputVarType
.
textInput
&&
(
<
input
...
...
web/app/components/workflow/nodes/_base/node.tsx
View file @
049e858e
...
...
@@ -7,13 +7,21 @@ import {
memo
,
}
from
'react'
import
type
{
NodeProps
}
from
'../../types'
import
{
BlockEnum
}
from
'../../types'
import
{
BlockEnum
,
NodeRunningStatus
,
}
from
'../../types'
import
{
NodeSourceHandle
,
NodeTargetHandle
,
}
from
'./components/node-handle'
import
NodeControl
from
'./components/node-control'
import
BlockIcon
from
'@/app/components/workflow/block-icon'
import
{
CheckCircle
,
Loading02
,
}
from
'@/app/components/base/icons/src/vender/line/general'
import
{
AlertCircle
}
from
'@/app/components/base/icons/src/vender/line/alertsAndFeedback'
type
BaseNodeProps
=
{
children
:
ReactElement
...
...
@@ -28,7 +36,7 @@ const BaseNode: FC<BaseNodeProps> = ({
<
div
className=
{
`
flex border-[2px] rounded-2xl
${
data.selected
? 'border-primary-600' : 'border-transparent'}
${
(data.selected && !data._runningStatus)
? 'border-primary-600' : 'border-transparent'}
`
}
>
<
div
...
...
@@ -36,6 +44,9 @@ const BaseNode: FC<BaseNodeProps> = ({
group relative w-[240px] bg-[#fcfdff] shadow-xs
border border-transparent rounded-[15px]
hover:shadow-lg
${data._runningStatus === NodeRunningStatus.Running && 'border-primary-500'}
${data._runningStatus === NodeRunningStatus.Succeeded && 'border-[#12B76A]'}
${data._runningStatus === NodeRunningStatus.Failed && 'border-[#F04438]'}
`
}
>
{
...
...
@@ -71,10 +82,25 @@ const BaseNode: FC<BaseNodeProps> = ({
/>
<
div
title=
{
data
.
title
}
className=
'grow text-[13px] font-semibold text-gray-700 truncate'
className=
'grow
mr-1
text-[13px] font-semibold text-gray-700 truncate'
>
{
data
.
title
}
</
div
>
{
data
.
_runningStatus
===
NodeRunningStatus
.
Running
&&
(
<
Loading02
className=
'w-3.5 h-3.5 text-primary-600 animate-spin'
/>
)
}
{
data
.
_runningStatus
===
NodeRunningStatus
.
Succeeded
&&
(
<
CheckCircle
className=
'w-3.5 h-3.5 text-[#12B76A]'
/>
)
}
{
data
.
_runningStatus
===
NodeRunningStatus
.
Failed
&&
(
<
AlertCircle
className=
'w-3.5 h-3.5 text-[#F04438]'
/>
)
}
</
div
>
<
div
className=
'mb-1'
>
{
cloneElement
(
children
,
{
id
,
data
})
}
...
...
web/app/components/workflow/operator/index.tsx
View file @
049e858e
import
{
memo
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
MiniMap
}
from
'reactflow'
import
ZoomInOut
from
'./zoom-in-out'
import
{
OrganizeGrid
}
from
'@/app/components/base/icons/src/vender/line/layout'
import
TooltipPlus
from
'@/app/components/base/tooltip-plus'
...
...
@@ -9,9 +10,17 @@ const Operator = () => {
return
(
<
div
className=
{
`
absolute left-6 bottom-6 flex items-center p-0.5
rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500 z-10
absolute left-6 bottom-6 z-10
`
}
>
<
MiniMap
style=
{
{
width
:
128
,
height
:
80
,
}
}
className=
'!static !m-0 !w-[128px] !h-[80px] border-[0.5px] border-black/[0.08]'
pannable
/>
<
div
className=
'flex items-center mt-1 p-0.5 rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500'
>
<
ZoomInOut
/>
<
TooltipPlus
popupContent=
{
t
(
'workflow.panel.organizeBlocks'
)
}
>
<
div
className=
'ml-[1px] flex items-center justify-center w-8 h-8 cursor-pointer hover:bg-black/5 rounded-lg'
>
...
...
@@ -19,6 +28,7 @@ const Operator = () => {
</
div
>
</
TooltipPlus
>
</
div
>
</
div
>
)
}
...
...
web/app/components/workflow/panel/index.tsx
View file @
049e858e
...
...
@@ -12,6 +12,7 @@ import WorkflowInfo from './workflow-info'
import
DebugAndPreview
from
'./debug-and-preview'
import
RunHistory
from
'./run-history'
import
Record
from
'./record'
import
InputsPanel
from
'./inputs-panel'
const
Panel
:
FC
=
()
=>
{
const
isChatMode
=
useIsChatMode
()
...
...
@@ -19,6 +20,7 @@ const Panel: FC = () => {
const
nodes
=
useNodes
<
CommonNodeType
>
()
const
selectedNode
=
nodes
.
find
(
node
=>
node
.
data
.
selected
)
const
showRunHistory
=
useStore
(
state
=>
state
.
showRunHistory
)
const
showInputsPanel
=
useStore
(
s
=>
s
.
showInputsPanel
)
const
{
showWorkflowInfoPanel
,
showNodePanel
,
...
...
@@ -33,6 +35,11 @@ const Panel: FC = () => {
return
(
<
div
className=
'absolute top-14 right-0 bottom-2 flex z-10'
>
{
showInputsPanel
&&
(
<
InputsPanel
/>
)
}
{
runTaskId
&&
(
<
Record
/>
...
...
web/app/components/workflow/panel/inputs-panel.tsx
0 → 100644
View file @
049e858e
import
{
memo
,
useCallback
,
useState
,
}
from
'react'
import
{
useTranslation
}
from
'react-i18next'
import
{
useNodes
}
from
'reactflow'
import
FormItem
from
'../nodes/_base/components/before-run-form/form-item'
import
{
BlockEnum
}
from
'../types'
import
{
useStore
}
from
'../store'
import
{
useWorkflowRun
}
from
'../hooks'
import
type
{
StartNodeType
}
from
'../nodes/start/types'
import
Button
from
'@/app/components/base/button'
const
InputsPanel
=
()
=>
{
const
{
t
}
=
useTranslation
()
const
nodes
=
useNodes
<
StartNodeType
>
()
const
run
=
useWorkflowRun
()
const
[
inputs
,
setInputs
]
=
useState
<
Record
<
string
,
string
>>
({})
const
startNode
=
nodes
.
find
(
node
=>
node
.
data
.
type
===
BlockEnum
.
Start
)
const
variables
=
startNode
?.
data
.
variables
||
[]
const
handleValueChange
=
(
variable
:
string
,
v
:
string
)
=>
{
setInputs
({
...
inputs
,
[
variable
]:
v
,
})
}
const
handleCancel
=
useCallback
(()
=>
{
useStore
.
setState
({
showInputsPanel
:
false
})
},
[])
const
handleRun
=
()
=>
{
run
(
inputs
)
}
return
(
<
div
className=
'absolute top-0 right-2 w-[420px] pb-2 rounded-2xl border-[0.5px] border-gray-200 bg-white shadow-xl z-[11]'
>
<
div
className=
'flex items-center pt-3 px-4 h-[44px] text-base font-semibold text-gray-900'
>
{
t
(
'workflow.singleRun.testRun'
)
}
</
div
>
<
div
className=
'px-4 pb-2'
>
{
variables
.
map
(
variable
=>
(
<
div
key=
{
variable
.
variable
}
className=
'mb-2 last-of-type:mb-0'
>
<
FormItem
className=
'!block'
payload=
{
variable
}
value=
{
inputs
[
variable
.
variable
]
}
onChange=
{
v
=>
handleValueChange
(
variable
.
variable
,
v
)
}
/>
</
div
>
))
}
</
div
>
<
div
className=
'flex items-center justify-between px-4 py-2'
>
<
Button
className=
'py-0 w-[190px] h-8 rounded-lg border-[0.5px] border-gray-200 shadow-xs text-[13px] font-medium text-gray-700'
onClick=
{
handleCancel
}
>
{
t
(
'common.operation.cancel'
)
}
</
Button
>
<
Button
type=
'primary'
className=
'py-0 w-[190px] h-8 rounded-lg text-[13px] font-medium'
onClick=
{
handleRun
}
>
{
t
(
'workflow.singleRun.startRun'
)
}
</
Button
>
</
div
>
</
div
>
)
}
export
default
memo
(
InputsPanel
)
web/app/components/workflow/store.ts
View file @
049e858e
...
...
@@ -9,6 +9,7 @@ import type {
ToolsMap
,
}
from
'./block-selector/types'
import
{
Mode
}
from
'./types'
import
type
{
WorkflowRunningStatus
}
from
'./types'
type
State
=
{
mode
:
Mode
...
...
@@ -22,6 +23,8 @@ type State = {
toolsMap
:
ToolsMap
draftUpdatedAt
:
number
publishedAt
:
number
runningStatus
?:
WorkflowRunningStatus
showInputsPanel
:
boolean
}
type
Action
=
{
...
...
@@ -36,6 +39,8 @@ type Action = {
setToolsMap
:
(
toolsMap
:
Record
<
string
,
ToolInWorkflow
[]
>
)
=>
void
setDraftUpdatedAt
:
(
draftUpdatedAt
:
number
)
=>
void
setPublishedAt
:
(
publishedAt
:
number
)
=>
void
setRunningStatus
:
(
runningStatus
?:
WorkflowRunningStatus
)
=>
void
setShowInputsPanel
:
(
showInputsPanel
:
boolean
)
=>
void
}
export
const
useStore
=
create
<
State
&
Action
>
(
set
=>
({
...
...
@@ -61,4 +66,8 @@ export const useStore = create<State & Action>(set => ({
setDraftUpdatedAt
:
draftUpdatedAt
=>
set
(()
=>
({
draftUpdatedAt
})),
publishedAt
:
0
,
setPublishedAt
:
publishedAt
=>
set
(()
=>
({
publishedAt
})),
runningStatus
:
undefined
,
setRunningStatus
:
runningStatus
=>
set
(()
=>
({
runningStatus
})),
showInputsPanel
:
false
,
setShowInputsPanel
:
showInputsPanel
=>
set
(()
=>
({
showInputsPanel
})),
}))
web/app/components/workflow/types.ts
View file @
049e858e
...
...
@@ -27,6 +27,7 @@ export type Branch = {
export
type
CommonNodeType
<
T
=
{}
>
=
{
_targetBranches
?:
Branch
[]
_isSingleRun
?:
boolean
_runningStatus
?:
NodeRunningStatus
selected
?:
boolean
title
:
string
desc
:
string
...
...
@@ -38,7 +39,7 @@ export type CommonEdgeType = {
_connectedNodeIsHovering
:
boolean
}
export
type
Node
=
ReactFlowNode
<
CommonNodeType
>
export
type
Node
<
T
=
{}
>
=
ReactFlowNode
<
CommonNodeType
<
T
>
>
export
type
SelectedNode
=
Pick
<
Node
,
'id'
|
'data'
>
export
type
NodeProps
<
T
=
unknown
>
=
{
id
:
string
;
data
:
CommonNodeType
<
T
>
}
export
type
NodePanelProps
<
T
>
=
{
...
...
@@ -147,3 +148,16 @@ export enum Mode {
Editing
=
'editing'
,
Running
=
'running'
,
}
export
enum
WorkflowRunningStatus
{
Running
=
'running'
,
Succeeded
=
'succeeded'
,
Failed
=
'failed'
,
Stopped
=
'stopped'
,
}
export
enum
NodeRunningStatus
{
Running
=
'running'
,
Succeeded
=
'succeeded'
,
Failed
=
'failed'
,
}
web/service/base.ts
View file @
049e858e
...
...
@@ -2,6 +2,14 @@ import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
import
Toast
from
'@/app/components/base/toast'
import
type
{
AnnotationReply
,
MessageEnd
,
MessageReplace
,
ThoughtItem
}
from
'@/app/components/app/chat/type'
import
type
{
VisionFile
}
from
'@/types/app'
import
type
{
NodeFinishedResponse
,
NodeStartedResponse
,
TextChunkResponse
,
TextReplaceResponse
,
WorkflowFinishedResponse
,
WorkflowStartedResponse
,
}
from
'@/types/workflow'
const
TIME_OUT
=
100000
const
ContentType
=
{
...
...
@@ -39,6 +47,13 @@ export type IOnAnnotationReply = (messageReplace: AnnotationReply) => void
export
type
IOnCompleted
=
(
hasError
?:
boolean
)
=>
void
export
type
IOnError
=
(
msg
:
string
,
code
?:
string
)
=>
void
export
type
IOnWorkflowStarted
=
(
workflowStarted
:
WorkflowStartedResponse
)
=>
void
export
type
IOnWorkflowFinished
=
(
workflowFinished
:
WorkflowFinishedResponse
)
=>
void
export
type
IOnNodeStarted
=
(
nodeStarted
:
NodeStartedResponse
)
=>
void
export
type
IOnNodeFinished
=
(
nodeFinished
:
NodeFinishedResponse
)
=>
void
export
type
IOnTextChunk
=
(
textChunk
:
TextChunkResponse
)
=>
void
export
type
IOnTextReplace
=
(
textReplace
:
TextReplaceResponse
)
=>
void
type
IOtherOptions
=
{
isPublicAPI
?:
boolean
bodyStringify
?:
boolean
...
...
@@ -53,6 +68,13 @@ type IOtherOptions = {
onError
?:
IOnError
onCompleted
?:
IOnCompleted
// for stream
getAbortController
?:
(
abortController
:
AbortController
)
=>
void
onWorkflowStarted
?:
IOnWorkflowStarted
onWorkflowFinished
?:
IOnWorkflowFinished
onNodeStarted
?:
IOnNodeStarted
onNodeFinished
?:
IOnNodeFinished
onTextChunk
?:
IOnTextChunk
onTextReplace
?:
IOnTextReplace
}
type
ResponseError
=
{
...
...
@@ -83,7 +105,21 @@ export function format(text: string) {
return
res
.
replaceAll
(
'
\
n'
,
'<br/>'
).
replaceAll
(
'```'
,
''
)
}
const
handleStream
=
(
response
:
Response
,
onData
:
IOnData
,
onCompleted
?:
IOnCompleted
,
onThought
?:
IOnThought
,
onMessageEnd
?:
IOnMessageEnd
,
onMessageReplace
?:
IOnMessageReplace
,
onFile
?:
IOnFile
)
=>
{
const
handleStream
=
(
response
:
Response
,
onData
:
IOnData
,
onCompleted
?:
IOnCompleted
,
onThought
?:
IOnThought
,
onMessageEnd
?:
IOnMessageEnd
,
onMessageReplace
?:
IOnMessageReplace
,
onFile
?:
IOnFile
,
onWorkflowStarted
?:
IOnWorkflowStarted
,
onWorkflowFinished
?:
IOnWorkflowFinished
,
onNodeStarted
?:
IOnNodeStarted
,
onNodeFinished
?:
IOnNodeFinished
,
onTextChunk
?:
IOnTextChunk
,
onTextReplace
?:
IOnTextReplace
,
)
=>
{
if
(
!
response
.
ok
)
throw
new
Error
(
'Network response was not ok'
)
...
...
@@ -147,6 +183,24 @@ const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnComp
else
if
(
bufferObj
.
event
===
'message_replace'
)
{
onMessageReplace
?.(
bufferObj
as
MessageReplace
)
}
else
if
(
bufferObj
.
event
===
'workflow_started'
)
{
onWorkflowStarted
?.(
bufferObj
as
WorkflowStartedResponse
)
}
else
if
(
bufferObj
.
event
===
'workflow_finished'
)
{
onWorkflowFinished
?.(
bufferObj
as
WorkflowFinishedResponse
)
}
else
if
(
bufferObj
.
event
===
'node_started'
)
{
onNodeStarted
?.(
bufferObj
as
NodeStartedResponse
)
}
else
if
(
bufferObj
.
event
===
'node_finished'
)
{
onNodeFinished
?.(
bufferObj
as
NodeFinishedResponse
)
}
else
if
(
bufferObj
.
event
===
'text_chunk'
)
{
onTextChunk
?.(
bufferObj
as
TextChunkResponse
)
}
else
if
(
bufferObj
.
event
===
'text_replace'
)
{
onTextReplace
?.(
bufferObj
as
TextReplaceResponse
)
}
}
})
buffer
=
lines
[
lines
.
length
-
1
]
...
...
web/types/workflow.ts
View file @
049e858e
...
...
@@ -46,3 +46,88 @@ export type FetchWorkflowDraftResponse = {
export
type
NodeTracingListResponse
=
{
data
:
NodeTracing
[]
}
export
type
WorkflowStartedResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
id
:
string
workflow_id
:
string
created_at
:
number
}
}
export
type
WorkflowFinishedResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
id
:
string
workflow_id
:
string
status
:
string
outputs
:
any
error
:
string
elapsed_time
:
number
total_tokens
:
number
total_steps
:
number
created_at
:
number
finished_at
:
number
}
}
export
type
NodeStartedResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
id
:
string
node_id
:
string
index
:
number
predecessor_node_id
?:
string
inputs
:
any
created_at
:
number
}
}
export
type
NodeFinishedResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
id
:
string
node_id
:
string
index
:
number
predecessor_node_id
?:
string
inputs
:
any
process_data
:
any
outputs
:
any
status
:
string
error
:
string
elapsed_time
:
number
execution_metadata
:
{
total_tokens
:
number
total_price
:
number
currency
:
string
}
created_at
:
number
}
}
export
type
TextChunkResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
text
:
string
}
}
export
type
TextReplaceResponse
=
{
task_id
:
string
workflow_run_id
:
string
event
:
string
data
:
{
text
:
string
}
}
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