Commit 049e858e authored by StyleZhang's avatar StyleZhang

run

parent 405e99d2
...@@ -7,7 +7,6 @@ import { Play } from '@/app/components/base/icons/src/vender/line/mediaAndDevice ...@@ -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 { ClockPlay } from '@/app/components/base/icons/src/vender/line/time'
import TooltipPlus from '@/app/components/base/tooltip-plus' import TooltipPlus from '@/app/components/base/tooltip-plus'
import { Loading02 } from '@/app/components/base/icons/src/vender/line/general' import { Loading02 } from '@/app/components/base/icons/src/vender/line/general'
import { Mode } from '@/app/components/workflow/types'
const RunAndHistory: FC = () => { const RunAndHistory: FC = () => {
const { t } = useTranslation() const { t } = useTranslation()
...@@ -15,6 +14,11 @@ const RunAndHistory: FC = () => { ...@@ -15,6 +14,11 @@ const RunAndHistory: FC = () => {
const mode = useStore(state => state.mode) const mode = useStore(state => state.mode)
const showRunHistory = useStore(state => state.showRunHistory) const showRunHistory = useStore(state => state.showRunHistory)
const handleClick = () => {
if (!isChatMode)
useStore.setState({ showInputsPanel: true })
}
return ( return (
<div className='flex items-center px-0.5 h-8 rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xs'> <div className='flex items-center px-0.5 h-8 rounded-lg border-[0.5px] border-gray-200 bg-white shadow-xs'>
<div <div
...@@ -24,7 +28,7 @@ const RunAndHistory: FC = () => { ...@@ -24,7 +28,7 @@ const RunAndHistory: FC = () => {
${mode === 'running' && 'bg-primary-50 !cursor-not-allowed'} ${mode === 'running' && 'bg-primary-50 !cursor-not-allowed'}
${mode === 'running' && isChatMode && 'opacity-50'} ${mode === 'running' && isChatMode && 'opacity-50'}
`} `}
onClick={() => mode !== 'running' && useStore.setState({ mode: Mode.Running })} onClick={() => mode !== 'running' && handleClick()}
> >
{ {
mode === 'running' mode === 'running'
......
...@@ -21,6 +21,10 @@ import type { ...@@ -21,6 +21,10 @@ import type {
BlockEnum, BlockEnum,
Node, Node,
} from './types' } from './types'
import {
NodeRunningStatus,
WorkflowRunningStatus,
} from './types'
import { import {
NODES_EXTRA_DATA, NODES_EXTRA_DATA,
NODES_INITIAL_DATA, NODES_INITIAL_DATA,
...@@ -31,6 +35,7 @@ import type { ToolDefaultValue } from './block-selector/types' ...@@ -31,6 +35,7 @@ import type { ToolDefaultValue } from './block-selector/types'
import { syncWorkflowDraft } from '@/service/workflow' import { syncWorkflowDraft } from '@/service/workflow'
import { useFeaturesStore } from '@/app/components/base/features/hooks' import { useFeaturesStore } from '@/app/components/base/features/hooks'
import { useStore as useAppStore } from '@/app/components/app/store' import { useStore as useAppStore } from '@/app/components/app/store'
import { ssePost } from '@/service/base'
export const useIsChatMode = () => { export const useIsChatMode = () => {
const appDetail = useAppStore(s => s.appDetail) const appDetail = useAppStore(s => s.appDetail)
...@@ -560,3 +565,51 @@ export const useWorkflow = () => { ...@@ -560,3 +565,51 @@ export const useWorkflow = () => {
handleEdgesChange, 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)
},
},
)
}
}
...@@ -15,12 +15,14 @@ type Props = { ...@@ -15,12 +15,14 @@ type Props = {
payload: InputVar payload: InputVar
value: any value: any
onChange: (value: any) => void onChange: (value: any) => void
className?: string
} }
const FormItem: FC<Props> = ({ const FormItem: FC<Props> = ({
payload, payload,
value, value,
onChange, onChange,
className,
}) => { }) => {
const { type } = payload const { type } = payload
const handleContextItemChange = useCallback((index: number) => { const handleContextItemChange = useCallback((index: number) => {
...@@ -41,9 +43,9 @@ const FormItem: FC<Props> = ({ ...@@ -41,9 +43,9 @@ const FormItem: FC<Props> = ({
} }
}, [value, onChange]) }, [value, onChange])
return ( 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>} {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 && ( type === InputVarType.textInput && (
<input <input
......
...@@ -7,13 +7,21 @@ import { ...@@ -7,13 +7,21 @@ import {
memo, memo,
} from 'react' } from 'react'
import type { NodeProps } from '../../types' import type { NodeProps } from '../../types'
import { BlockEnum } from '../../types' import {
BlockEnum,
NodeRunningStatus,
} from '../../types'
import { import {
NodeSourceHandle, NodeSourceHandle,
NodeTargetHandle, NodeTargetHandle,
} from './components/node-handle' } from './components/node-handle'
import NodeControl from './components/node-control' import NodeControl from './components/node-control'
import BlockIcon from '@/app/components/workflow/block-icon' 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 = { type BaseNodeProps = {
children: ReactElement children: ReactElement
...@@ -28,7 +36,7 @@ const BaseNode: FC<BaseNodeProps> = ({ ...@@ -28,7 +36,7 @@ const BaseNode: FC<BaseNodeProps> = ({
<div <div
className={` className={`
flex border-[2px] rounded-2xl flex border-[2px] rounded-2xl
${data.selected ? 'border-primary-600' : 'border-transparent'} ${(data.selected && !data._runningStatus) ? 'border-primary-600' : 'border-transparent'}
`} `}
> >
<div <div
...@@ -36,6 +44,9 @@ const BaseNode: FC<BaseNodeProps> = ({ ...@@ -36,6 +44,9 @@ const BaseNode: FC<BaseNodeProps> = ({
group relative w-[240px] bg-[#fcfdff] shadow-xs group relative w-[240px] bg-[#fcfdff] shadow-xs
border border-transparent rounded-[15px] border border-transparent rounded-[15px]
hover:shadow-lg 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> = ({ ...@@ -71,10 +82,25 @@ const BaseNode: FC<BaseNodeProps> = ({
/> />
<div <div
title={data.title} 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} {data.title}
</div> </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>
<div className='mb-1'> <div className='mb-1'>
{cloneElement(children, { id, data })} {cloneElement(children, { id, data })}
......
import { memo } from 'react' import { memo } from 'react'
import { useTranslation } from 'react-i18next' import { useTranslation } from 'react-i18next'
import { MiniMap } from 'reactflow'
import ZoomInOut from './zoom-in-out' import ZoomInOut from './zoom-in-out'
import { OrganizeGrid } from '@/app/components/base/icons/src/vender/line/layout' import { OrganizeGrid } from '@/app/components/base/icons/src/vender/line/layout'
import TooltipPlus from '@/app/components/base/tooltip-plus' import TooltipPlus from '@/app/components/base/tooltip-plus'
...@@ -9,15 +10,24 @@ const Operator = () => { ...@@ -9,15 +10,24 @@ const Operator = () => {
return ( return (
<div className={` <div className={`
absolute left-6 bottom-6 flex items-center p-0.5 absolute left-6 bottom-6 z-10
rounded-lg border-[0.5px] border-gray-100 bg-white shadow-lg text-gray-500 z-10
`}> `}>
<ZoomInOut /> <MiniMap
<TooltipPlus popupContent={t('workflow.panel.organizeBlocks')}> style={{
<div className='ml-[1px] flex items-center justify-center w-8 h-8 cursor-pointer hover:bg-black/5 rounded-lg'> width: 128,
<OrganizeGrid className='w-4 h-4' /> height: 80,
</div> }}
</TooltipPlus> 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'>
<OrganizeGrid className='w-4 h-4' />
</div>
</TooltipPlus>
</div>
</div> </div>
) )
} }
......
...@@ -12,6 +12,7 @@ import WorkflowInfo from './workflow-info' ...@@ -12,6 +12,7 @@ import WorkflowInfo from './workflow-info'
import DebugAndPreview from './debug-and-preview' import DebugAndPreview from './debug-and-preview'
import RunHistory from './run-history' import RunHistory from './run-history'
import Record from './record' import Record from './record'
import InputsPanel from './inputs-panel'
const Panel: FC = () => { const Panel: FC = () => {
const isChatMode = useIsChatMode() const isChatMode = useIsChatMode()
...@@ -19,6 +20,7 @@ const Panel: FC = () => { ...@@ -19,6 +20,7 @@ const Panel: FC = () => {
const nodes = useNodes<CommonNodeType>() const nodes = useNodes<CommonNodeType>()
const selectedNode = nodes.find(node => node.data.selected) const selectedNode = nodes.find(node => node.data.selected)
const showRunHistory = useStore(state => state.showRunHistory) const showRunHistory = useStore(state => state.showRunHistory)
const showInputsPanel = useStore(s => s.showInputsPanel)
const { const {
showWorkflowInfoPanel, showWorkflowInfoPanel,
showNodePanel, showNodePanel,
...@@ -33,6 +35,11 @@ const Panel: FC = () => { ...@@ -33,6 +35,11 @@ const Panel: FC = () => {
return ( return (
<div className='absolute top-14 right-0 bottom-2 flex z-10'> <div className='absolute top-14 right-0 bottom-2 flex z-10'>
{
showInputsPanel && (
<InputsPanel />
)
}
{ {
runTaskId && ( runTaskId && (
<Record /> <Record />
......
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)
...@@ -9,6 +9,7 @@ import type { ...@@ -9,6 +9,7 @@ import type {
ToolsMap, ToolsMap,
} from './block-selector/types' } from './block-selector/types'
import { Mode } from './types' import { Mode } from './types'
import type { WorkflowRunningStatus } from './types'
type State = { type State = {
mode: Mode mode: Mode
...@@ -22,6 +23,8 @@ type State = { ...@@ -22,6 +23,8 @@ type State = {
toolsMap: ToolsMap toolsMap: ToolsMap
draftUpdatedAt: number draftUpdatedAt: number
publishedAt: number publishedAt: number
runningStatus?: WorkflowRunningStatus
showInputsPanel: boolean
} }
type Action = { type Action = {
...@@ -36,6 +39,8 @@ type Action = { ...@@ -36,6 +39,8 @@ type Action = {
setToolsMap: (toolsMap: Record<string, ToolInWorkflow[]>) => void setToolsMap: (toolsMap: Record<string, ToolInWorkflow[]>) => void
setDraftUpdatedAt: (draftUpdatedAt: number) => void setDraftUpdatedAt: (draftUpdatedAt: number) => void
setPublishedAt: (publishedAt: number) => void setPublishedAt: (publishedAt: number) => void
setRunningStatus: (runningStatus?: WorkflowRunningStatus) => void
setShowInputsPanel: (showInputsPanel: boolean) => void
} }
export const useStore = create<State & Action>(set => ({ export const useStore = create<State & Action>(set => ({
...@@ -61,4 +66,8 @@ export const useStore = create<State & Action>(set => ({ ...@@ -61,4 +66,8 @@ export const useStore = create<State & Action>(set => ({
setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt })), setDraftUpdatedAt: draftUpdatedAt => set(() => ({ draftUpdatedAt })),
publishedAt: 0, publishedAt: 0,
setPublishedAt: publishedAt => set(() => ({ publishedAt })), setPublishedAt: publishedAt => set(() => ({ publishedAt })),
runningStatus: undefined,
setRunningStatus: runningStatus => set(() => ({ runningStatus })),
showInputsPanel: false,
setShowInputsPanel: showInputsPanel => set(() => ({ showInputsPanel })),
})) }))
...@@ -27,6 +27,7 @@ export type Branch = { ...@@ -27,6 +27,7 @@ export type Branch = {
export type CommonNodeType<T = {}> = { export type CommonNodeType<T = {}> = {
_targetBranches?: Branch[] _targetBranches?: Branch[]
_isSingleRun?: boolean _isSingleRun?: boolean
_runningStatus?: NodeRunningStatus
selected?: boolean selected?: boolean
title: string title: string
desc: string desc: string
...@@ -38,7 +39,7 @@ export type CommonEdgeType = { ...@@ -38,7 +39,7 @@ export type CommonEdgeType = {
_connectedNodeIsHovering: boolean _connectedNodeIsHovering: boolean
} }
export type Node = ReactFlowNode<CommonNodeType> export type Node<T = {}> = ReactFlowNode<CommonNodeType<T>>
export type SelectedNode = Pick<Node, 'id' | 'data'> export type SelectedNode = Pick<Node, 'id' | 'data'>
export type NodeProps<T = unknown> = { id: string; data: CommonNodeType<T> } export type NodeProps<T = unknown> = { id: string; data: CommonNodeType<T> }
export type NodePanelProps<T> = { export type NodePanelProps<T> = {
...@@ -147,3 +148,16 @@ export enum Mode { ...@@ -147,3 +148,16 @@ export enum Mode {
Editing = 'editing', Editing = 'editing',
Running = 'running', Running = 'running',
} }
export enum WorkflowRunningStatus {
Running = 'running',
Succeeded = 'succeeded',
Failed = 'failed',
Stopped = 'stopped',
}
export enum NodeRunningStatus {
Running = 'running',
Succeeded = 'succeeded',
Failed = 'failed',
}
...@@ -2,6 +2,14 @@ import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config' ...@@ -2,6 +2,14 @@ import { API_PREFIX, IS_CE_EDITION, PUBLIC_API_PREFIX } from '@/config'
import Toast from '@/app/components/base/toast' import Toast from '@/app/components/base/toast'
import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/app/chat/type' import type { AnnotationReply, MessageEnd, MessageReplace, ThoughtItem } from '@/app/components/app/chat/type'
import type { VisionFile } from '@/types/app' import type { VisionFile } from '@/types/app'
import type {
NodeFinishedResponse,
NodeStartedResponse,
TextChunkResponse,
TextReplaceResponse,
WorkflowFinishedResponse,
WorkflowStartedResponse,
} from '@/types/workflow'
const TIME_OUT = 100000 const TIME_OUT = 100000
const ContentType = { const ContentType = {
...@@ -39,6 +47,13 @@ export type IOnAnnotationReply = (messageReplace: AnnotationReply) => void ...@@ -39,6 +47,13 @@ export type IOnAnnotationReply = (messageReplace: AnnotationReply) => void
export type IOnCompleted = (hasError?: boolean) => void export type IOnCompleted = (hasError?: boolean) => void
export type IOnError = (msg: string, code?: string) => 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 = { type IOtherOptions = {
isPublicAPI?: boolean isPublicAPI?: boolean
bodyStringify?: boolean bodyStringify?: boolean
...@@ -53,6 +68,13 @@ type IOtherOptions = { ...@@ -53,6 +68,13 @@ type IOtherOptions = {
onError?: IOnError onError?: IOnError
onCompleted?: IOnCompleted // for stream onCompleted?: IOnCompleted // for stream
getAbortController?: (abortController: AbortController) => void getAbortController?: (abortController: AbortController) => void
onWorkflowStarted?: IOnWorkflowStarted
onWorkflowFinished?: IOnWorkflowFinished
onNodeStarted?: IOnNodeStarted
onNodeFinished?: IOnNodeFinished
onTextChunk?: IOnTextChunk
onTextReplace?: IOnTextReplace
} }
type ResponseError = { type ResponseError = {
...@@ -83,7 +105,21 @@ export function format(text: string) { ...@@ -83,7 +105,21 @@ export function format(text: string) {
return res.replaceAll('\n', '<br/>').replaceAll('```', '') 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) if (!response.ok)
throw new Error('Network response was not ok') throw new Error('Network response was not ok')
...@@ -147,6 +183,24 @@ const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnComp ...@@ -147,6 +183,24 @@ const handleStream = (response: Response, onData: IOnData, onCompleted?: IOnComp
else if (bufferObj.event === 'message_replace') { else if (bufferObj.event === 'message_replace') {
onMessageReplace?.(bufferObj as MessageReplace) 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] buffer = lines[lines.length - 1]
......
...@@ -46,3 +46,88 @@ export type FetchWorkflowDraftResponse = { ...@@ -46,3 +46,88 @@ export type FetchWorkflowDraftResponse = {
export type NodeTracingListResponse = { export type NodeTracingListResponse = {
data: NodeTracing[] 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
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment