mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
A build for a workflow app whose goal reads like a chatbot produced an empty canvas while the assistant reported "Workflow built on the canvas.": the plan was chatbot-shaped, build_nodes fed it to the generator (mode="workflow"), the LLM emitted a chatflow graph (answer node / no end node), the generator rejected it as MISSING_TERMINAL -- a class it does NOT retry -- and build_nodes swallowed the error into []. handle_plan_approval then treated [] as a successful build: it deleted the placeholder start and advanced to build.execution, leaving nothing on the canvas. Two parts: 1. build_nodes now prepends an explicit workflow-topology directive (one start + >=1 end node, no answer nodes) to the generator instruction, and retries ONCE on an error/empty result with the specific error fed back as a corrective nudge -- covering the terminal-node failure the shared generator skips. 2. handle_plan_approval refuses to fake success: when build_nodes yields zero create_node intents it surfaces an honest error and stays in build.plan_approval (retryable) without deleting the placeholder, instead of emptying the canvas and claiming a build. A loop-back re-approve still returns the fixed create intents (only filtered as already-present), so zero create intents unambiguously means a genuine generation failure. Adds regression tests for both. Note: part 1 improves LLM reliability (verifiable live); part 2 is the deterministic guarantee against the false-success empty canvas. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>