mirror of
https://github.com/langgenius/dify.git
synced 2026-04-29 04:26:30 +08:00
add debug run schedule node
This commit is contained in:
parent
6795015d00
commit
2ff4af8ce3
@ -1151,3 +1151,66 @@ class DraftWorkflowTriggerRunApi(Resource):
|
|||||||
}
|
}
|
||||||
), 500
|
), 500
|
||||||
|
|
||||||
|
|
||||||
|
@console_ns.route("/apps/<uuid:app_id>/workflows/draft/trigger/schedule/run")
|
||||||
|
class DraftWorkflowTriggerScheduleRunApi(Resource):
|
||||||
|
"""
|
||||||
|
Full workflow debug when the start node is a schedule trigger
|
||||||
|
Path: /apps/<uuid:app_id>/workflows/draft/trigger/schedule/run
|
||||||
|
"""
|
||||||
|
|
||||||
|
@api.doc("draft_workflow_trigger_schedule_run")
|
||||||
|
@api.doc(description="Full workflow debug when the start node is a schedule trigger")
|
||||||
|
@api.doc(params={"app_id": "Application ID"})
|
||||||
|
@api.expect(
|
||||||
|
api.model(
|
||||||
|
"DraftWorkflowTriggerScheduleRunRequest",
|
||||||
|
{
|
||||||
|
"node_id": fields.String(required=True, description="Node ID"),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@api.response(200, "Workflow executed successfully")
|
||||||
|
@api.response(403, "Permission denied")
|
||||||
|
@api.response(500, "Internal server error")
|
||||||
|
@setup_required
|
||||||
|
@login_required
|
||||||
|
@account_initialization_required
|
||||||
|
@get_app_model(mode=[AppMode.WORKFLOW])
|
||||||
|
def post(self, app_model: App):
|
||||||
|
"""
|
||||||
|
Full workflow debug when the start node is a schedule trigger
|
||||||
|
"""
|
||||||
|
if not isinstance(current_user, Account) or not current_user.has_edit_permission:
|
||||||
|
raise Forbidden()
|
||||||
|
|
||||||
|
parser = reqparse.RequestParser()
|
||||||
|
parser.add_argument("node_id", type=str, required=True, location="json", nullable=False)
|
||||||
|
args = parser.parse_args()
|
||||||
|
node_id = args["node_id"]
|
||||||
|
|
||||||
|
workflow_args = {
|
||||||
|
"inputs": {},
|
||||||
|
"query": "",
|
||||||
|
"files": [],
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
response = AppGenerateService.generate(
|
||||||
|
app_model=app_model,
|
||||||
|
user=current_user,
|
||||||
|
args=workflow_args,
|
||||||
|
invoke_from=InvokeFrom.DEBUGGER,
|
||||||
|
streaming=True,
|
||||||
|
root_node_id=node_id
|
||||||
|
)
|
||||||
|
return helper.compact_generate_response(response)
|
||||||
|
except InvokeRateLimitError as ex:
|
||||||
|
raise InvokeRateLimitHttpError(ex.description)
|
||||||
|
except Exception:
|
||||||
|
logger.exception("Error running draft workflow trigger schedule run")
|
||||||
|
return jsonable_encoder(
|
||||||
|
{
|
||||||
|
"status": "error",
|
||||||
|
}
|
||||||
|
), 500
|
||||||
|
|||||||
@ -1,6 +1,6 @@
|
|||||||
import uuid
|
import uuid
|
||||||
from collections.abc import Generator, Mapping
|
from collections.abc import Generator, Mapping
|
||||||
from typing import Any, Union
|
from typing import Any, Optional, Union
|
||||||
|
|
||||||
from openai._exceptions import RateLimitError
|
from openai._exceptions import RateLimitError
|
||||||
|
|
||||||
@ -32,6 +32,7 @@ class AppGenerateService:
|
|||||||
args: Mapping[str, Any],
|
args: Mapping[str, Any],
|
||||||
invoke_from: InvokeFrom,
|
invoke_from: InvokeFrom,
|
||||||
streaming: bool = True,
|
streaming: bool = True,
|
||||||
|
root_node_id: Optional[str] = None,
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
App Content Generate
|
App Content Generate
|
||||||
@ -115,6 +116,7 @@ class AppGenerateService:
|
|||||||
args=args,
|
args=args,
|
||||||
invoke_from=invoke_from,
|
invoke_from=invoke_from,
|
||||||
streaming=streaming,
|
streaming=streaming,
|
||||||
|
root_node_id=root_node_id,
|
||||||
call_depth=0,
|
call_depth=0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@ -66,6 +66,7 @@ const WorkflowMain = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
} = useWorkflowStartRun()
|
} = useWorkflowStartRun()
|
||||||
const availableNodesMetaData = useAvailableNodesMetaData()
|
const availableNodesMetaData = useAvailableNodesMetaData()
|
||||||
const { getWorkflowRunAndTraceUrl } = useGetRunAndTraceUrl()
|
const { getWorkflowRunAndTraceUrl } = useGetRunAndTraceUrl()
|
||||||
@ -108,6 +109,7 @@ const WorkflowMain = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
availableNodesMetaData,
|
availableNodesMetaData,
|
||||||
getWorkflowRunAndTraceUrl,
|
getWorkflowRunAndTraceUrl,
|
||||||
exportCheck,
|
exportCheck,
|
||||||
@ -141,6 +143,7 @@ const WorkflowMain = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
availableNodesMetaData,
|
availableNodesMetaData,
|
||||||
getWorkflowRunAndTraceUrl,
|
getWorkflowRunAndTraceUrl,
|
||||||
exportCheck,
|
exportCheck,
|
||||||
|
|||||||
@ -23,6 +23,13 @@ import { useInvalidAllLastRun } from '@/service/use-workflow'
|
|||||||
import { useSetWorkflowVarsWithValue } from '../../workflow/hooks/use-fetch-workflow-inspect-vars'
|
import { useSetWorkflowVarsWithValue } from '../../workflow/hooks/use-fetch-workflow-inspect-vars'
|
||||||
import { useConfigsMap } from './use-configs-map'
|
import { useConfigsMap } from './use-configs-map'
|
||||||
|
|
||||||
|
type HandleRunMode = 'default' | 'schedule'
|
||||||
|
|
||||||
|
type HandleRunOptions = {
|
||||||
|
mode?: HandleRunMode
|
||||||
|
scheduleNodeId?: string
|
||||||
|
}
|
||||||
|
|
||||||
export const useWorkflowRun = () => {
|
export const useWorkflowRun = () => {
|
||||||
const store = useStoreApi()
|
const store = useStoreApi()
|
||||||
const workflowStore = useWorkflowStore()
|
const workflowStore = useWorkflowStore()
|
||||||
@ -111,7 +118,10 @@ export const useWorkflowRun = () => {
|
|||||||
const handleRun = useCallback(async (
|
const handleRun = useCallback(async (
|
||||||
params: any,
|
params: any,
|
||||||
callback?: IOtherOptions,
|
callback?: IOtherOptions,
|
||||||
|
options?: HandleRunOptions,
|
||||||
) => {
|
) => {
|
||||||
|
const runMode: HandleRunMode = options?.mode ?? 'default'
|
||||||
|
const resolvedParams = params ?? {}
|
||||||
const {
|
const {
|
||||||
getNodes,
|
getNodes,
|
||||||
setNodes,
|
setNodes,
|
||||||
@ -153,11 +163,31 @@ export const useWorkflowRun = () => {
|
|||||||
const isInWorkflowDebug = appDetail?.mode === 'workflow'
|
const isInWorkflowDebug = appDetail?.mode === 'workflow'
|
||||||
|
|
||||||
let url = ''
|
let url = ''
|
||||||
if (appDetail?.mode === 'advanced-chat')
|
if (runMode === 'schedule') {
|
||||||
|
if (!appDetail?.id) {
|
||||||
|
console.error('handleRun: missing app id for schedule trigger run')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
url = `/apps/${appDetail.id}/workflows/draft/trigger/schedule/run`
|
||||||
|
}
|
||||||
|
else if (appDetail?.mode === 'advanced-chat') {
|
||||||
url = `/apps/${appDetail.id}/advanced-chat/workflows/draft/run`
|
url = `/apps/${appDetail.id}/advanced-chat/workflows/draft/run`
|
||||||
|
}
|
||||||
if (isInWorkflowDebug)
|
else if (isInWorkflowDebug && appDetail?.id) {
|
||||||
url = `/apps/${appDetail.id}/workflows/draft/run`
|
url = `/apps/${appDetail.id}/workflows/draft/run`
|
||||||
|
}
|
||||||
|
|
||||||
|
const requestBody = runMode === 'schedule'
|
||||||
|
? { node_id: options?.scheduleNodeId }
|
||||||
|
: resolvedParams
|
||||||
|
|
||||||
|
if (!url)
|
||||||
|
return
|
||||||
|
|
||||||
|
if (runMode === 'schedule' && !options?.scheduleNodeId) {
|
||||||
|
console.error('handleRun: schedule trigger run requires node id')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const {
|
const {
|
||||||
setWorkflowRunningData,
|
setWorkflowRunningData,
|
||||||
@ -172,22 +202,22 @@ export const useWorkflowRun = () => {
|
|||||||
|
|
||||||
let ttsUrl = ''
|
let ttsUrl = ''
|
||||||
let ttsIsPublic = false
|
let ttsIsPublic = false
|
||||||
if (params.token) {
|
if (resolvedParams.token) {
|
||||||
ttsUrl = '/text-to-audio'
|
ttsUrl = '/text-to-audio'
|
||||||
ttsIsPublic = true
|
ttsIsPublic = true
|
||||||
}
|
}
|
||||||
else if (params.appId) {
|
else if (resolvedParams.appId) {
|
||||||
if (pathname.search('explore/installed') > -1)
|
if (pathname.search('explore/installed') > -1)
|
||||||
ttsUrl = `/installed-apps/${params.appId}/text-to-audio`
|
ttsUrl = `/installed-apps/${resolvedParams.appId}/text-to-audio`
|
||||||
else
|
else
|
||||||
ttsUrl = `/apps/${params.appId}/text-to-audio`
|
ttsUrl = `/apps/${resolvedParams.appId}/text-to-audio`
|
||||||
}
|
}
|
||||||
const player = AudioPlayerManager.getInstance().getAudioPlayer(ttsUrl, ttsIsPublic, uuidV4(), 'none', 'none', noop)
|
const player = AudioPlayerManager.getInstance().getAudioPlayer(ttsUrl, ttsIsPublic, uuidV4(), 'none', 'none', noop)
|
||||||
|
|
||||||
ssePost(
|
ssePost(
|
||||||
url,
|
url,
|
||||||
{
|
{
|
||||||
body: params,
|
body: requestBody,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
onWorkflowStarted: (params) => {
|
onWorkflowStarted: (params) => {
|
||||||
|
|||||||
@ -61,6 +61,50 @@ export const useWorkflowStartRun = () => {
|
|||||||
}
|
}
|
||||||
}, [store, workflowStore, featuresStore, handleCancelDebugAndPreviewPanel, handleRun, doSyncWorkflowDraft])
|
}, [store, workflowStore, featuresStore, handleCancelDebugAndPreviewPanel, handleRun, doSyncWorkflowDraft])
|
||||||
|
|
||||||
|
const handleWorkflowTriggerScheduleRunInWorkflow = useCallback(async (nodeId?: string) => {
|
||||||
|
if (!nodeId)
|
||||||
|
return
|
||||||
|
|
||||||
|
const {
|
||||||
|
workflowRunningData,
|
||||||
|
showDebugAndPreviewPanel,
|
||||||
|
setShowDebugAndPreviewPanel,
|
||||||
|
setShowInputsPanel,
|
||||||
|
setShowEnvPanel,
|
||||||
|
} = workflowStore.getState()
|
||||||
|
|
||||||
|
if (workflowRunningData?.result.status === WorkflowRunningStatus.Running)
|
||||||
|
return
|
||||||
|
|
||||||
|
const { getNodes } = store.getState()
|
||||||
|
const nodes = getNodes()
|
||||||
|
const scheduleNode = nodes.find(node => node.id === nodeId && node.data.type === BlockEnum.TriggerSchedule)
|
||||||
|
|
||||||
|
if (!scheduleNode) {
|
||||||
|
console.warn('handleWorkflowTriggerScheduleRunInWorkflow: schedule node not found', nodeId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
setShowEnvPanel(false)
|
||||||
|
|
||||||
|
if (showDebugAndPreviewPanel) {
|
||||||
|
handleCancelDebugAndPreviewPanel()
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
await doSyncWorkflowDraft()
|
||||||
|
handleRun(
|
||||||
|
{},
|
||||||
|
undefined,
|
||||||
|
{
|
||||||
|
mode: 'schedule',
|
||||||
|
scheduleNodeId: nodeId,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
setShowDebugAndPreviewPanel(true)
|
||||||
|
setShowInputsPanel(false)
|
||||||
|
}, [store, workflowStore, handleCancelDebugAndPreviewPanel, handleRun, doSyncWorkflowDraft])
|
||||||
|
|
||||||
const handleWorkflowStartRunInChatflow = useCallback(async () => {
|
const handleWorkflowStartRunInChatflow = useCallback(async () => {
|
||||||
const {
|
const {
|
||||||
showDebugAndPreviewPanel,
|
showDebugAndPreviewPanel,
|
||||||
@ -92,5 +136,6 @@ export const useWorkflowStartRun = () => {
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -20,7 +20,10 @@ const RunMode = ({
|
|||||||
text,
|
text,
|
||||||
}: RunModeProps) => {
|
}: RunModeProps) => {
|
||||||
const { t } = useTranslation()
|
const { t } = useTranslation()
|
||||||
const { handleWorkflowStartRunInWorkflow } = useWorkflowStartRun()
|
const {
|
||||||
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
|
} = useWorkflowStartRun()
|
||||||
const { handleStopRun } = useWorkflowRun()
|
const { handleStopRun } = useWorkflowRun()
|
||||||
const { validateBeforeRun } = useWorkflowRunValidation()
|
const { validateBeforeRun } = useWorkflowRunValidation()
|
||||||
const workflowRunningData = useStore(s => s.workflowRunningData)
|
const workflowRunningData = useStore(s => s.workflowRunningData)
|
||||||
@ -53,11 +56,18 @@ const RunMode = ({
|
|||||||
if (option.type === 'user_input') {
|
if (option.type === 'user_input') {
|
||||||
handleWorkflowStartRunInWorkflow()
|
handleWorkflowStartRunInWorkflow()
|
||||||
}
|
}
|
||||||
|
else if (option.type === 'schedule') {
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow(option.nodeId)
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
// Placeholder for trigger-specific execution logic for schedule, webhook, plugin types
|
// Placeholder for trigger-specific execution logic for schedule, webhook, plugin types
|
||||||
console.log('TODO: Handle trigger execution for type:', option.type, 'nodeId:', option.nodeId)
|
console.log('TODO: Handle trigger execution for type:', option.type, 'nodeId:', option.nodeId)
|
||||||
}
|
}
|
||||||
}, [validateBeforeRun, handleWorkflowStartRunInWorkflow])
|
}, [
|
||||||
|
validateBeforeRun,
|
||||||
|
handleWorkflowStartRunInWorkflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
|
])
|
||||||
|
|
||||||
const { eventEmitter } = useEventEmitterContextContext()
|
const { eventEmitter } = useEventEmitterContextContext()
|
||||||
eventEmitter?.useSubscription((v: any) => {
|
eventEmitter?.useSubscription((v: any) => {
|
||||||
|
|||||||
@ -40,11 +40,12 @@ export type CommonHooksFnMap = {
|
|||||||
handleBackupDraft: () => void
|
handleBackupDraft: () => void
|
||||||
handleLoadBackupDraft: () => void
|
handleLoadBackupDraft: () => void
|
||||||
handleRestoreFromPublishedWorkflow: (...args: any[]) => void
|
handleRestoreFromPublishedWorkflow: (...args: any[]) => void
|
||||||
handleRun: (params: any, callback?: IOtherOptions,) => void
|
handleRun: (params: any, callback?: IOtherOptions, options?: any) => void
|
||||||
handleStopRun: (...args: any[]) => void
|
handleStopRun: (...args: any[]) => void
|
||||||
handleStartWorkflowRun: () => void
|
handleStartWorkflowRun: () => void
|
||||||
handleWorkflowStartRunInWorkflow: () => void
|
handleWorkflowStartRunInWorkflow: () => void
|
||||||
handleWorkflowStartRunInChatflow: () => void
|
handleWorkflowStartRunInChatflow: () => void
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow: (nodeId?: string) => void
|
||||||
availableNodesMetaData?: AvailableNodesMetaData
|
availableNodesMetaData?: AvailableNodesMetaData
|
||||||
getWorkflowRunAndTraceUrl: (runId?: string) => { runUrl: string; traceUrl: string }
|
getWorkflowRunAndTraceUrl: (runId?: string) => { runUrl: string; traceUrl: string }
|
||||||
exportCheck?: () => Promise<void>
|
exportCheck?: () => Promise<void>
|
||||||
@ -87,6 +88,7 @@ export const createHooksStore = ({
|
|||||||
handleStartWorkflowRun = noop,
|
handleStartWorkflowRun = noop,
|
||||||
handleWorkflowStartRunInWorkflow = noop,
|
handleWorkflowStartRunInWorkflow = noop,
|
||||||
handleWorkflowStartRunInChatflow = noop,
|
handleWorkflowStartRunInChatflow = noop,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow = noop,
|
||||||
availableNodesMetaData = {
|
availableNodesMetaData = {
|
||||||
nodes: [],
|
nodes: [],
|
||||||
},
|
},
|
||||||
@ -125,6 +127,7 @@ export const createHooksStore = ({
|
|||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
availableNodesMetaData,
|
availableNodesMetaData,
|
||||||
getWorkflowRunAndTraceUrl,
|
getWorkflowRunAndTraceUrl,
|
||||||
exportCheck,
|
exportCheck,
|
||||||
|
|||||||
@ -4,10 +4,12 @@ export const useWorkflowStartRun = () => {
|
|||||||
const handleStartWorkflowRun = useHooksStore(s => s.handleStartWorkflowRun)
|
const handleStartWorkflowRun = useHooksStore(s => s.handleStartWorkflowRun)
|
||||||
const handleWorkflowStartRunInWorkflow = useHooksStore(s => s.handleWorkflowStartRunInWorkflow)
|
const handleWorkflowStartRunInWorkflow = useHooksStore(s => s.handleWorkflowStartRunInWorkflow)
|
||||||
const handleWorkflowStartRunInChatflow = useHooksStore(s => s.handleWorkflowStartRunInChatflow)
|
const handleWorkflowStartRunInChatflow = useHooksStore(s => s.handleWorkflowStartRunInChatflow)
|
||||||
|
const handleWorkflowTriggerScheduleRunInWorkflow = useHooksStore(s => s.handleWorkflowTriggerScheduleRunInWorkflow)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
handleStartWorkflowRun,
|
handleStartWorkflowRun,
|
||||||
handleWorkflowStartRunInWorkflow,
|
handleWorkflowStartRunInWorkflow,
|
||||||
handleWorkflowStartRunInChatflow,
|
handleWorkflowStartRunInChatflow,
|
||||||
|
handleWorkflowTriggerScheduleRunInWorkflow,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user