mirror of https://github.com/langgenius/dify.git
run
This commit is contained in:
parent
405e99d27f
commit
049e858ef7
|
|
@ -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'
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 })}
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
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,15 +10,24 @@ 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
|
||||
`}>
|
||||
<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>
|
||||
<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'>
|
||||
<OrganizeGrid className='w-4 h-4' />
|
||||
</div>
|
||||
</TooltipPlus>
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 />
|
||||
|
|
|
|||
|
|
@ -0,0 +1,79 @@
|
|||
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 {
|
|||
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 })),
|
||||
}))
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue