mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
When a session crashes mid working-step (e.g. build.publish; the async advance raised and released the lock), it was a locked dead-end: working states surface no UI actions and the composer locked with no way forward. - Surface a RecoveryRef offer (can_continue=Retry, can_restart=Start over, recovery_class="") on an interrupted working-state view -- built directly so a real drift class still wins. - Allow recovery_continue / recovery_restart at an interrupted working state in _internal_action_allowed. recovery_continue returns the working state (non-settled) so the runner re-runs the stalled handler; recovery_restart resets working fields and re-enters the entry state -- both reuse existing recovery machinery, no new action kinds / no runner change. Adds unit tests (offer surfaced, allowance) + regression tests (recovery_continue re-runs handle_publish and advances; recovery_restart resets to entry state; repeat-failure re-surfaces the offer with no wedge). This reconciler was reviewed as a standalone plan on the pre-merge base; here it is re-applied onto feat/dify-builder after PR #41677 merged in the reworked service.py + _internal_action_allowed gate (which makes the allowance necessary). The apply_repair idempotency + delete-guard commits (safe fix.apply Retry) land alongside it. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>