feat(workflow): support human input in loop and iteration (#39243)

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
This commit is contained in:
-LAN-andautofix-ci[bot] authored and GitHub committed 2026-08-03 02:24:18 +00:00
1 parent 8dbac96621
commit 351577bdb0
86 files changed
+1454 -762

No files matched your search

@@ -4,7 +4,7 @@ import json
from datetime import UTC, datetime
from inspect import unwrap
from types import SimpleNamespace
from unittest.mock import Mock
from unittest.mock import ANY, Mock
import pytest
from flask import Flask, Response
@@ -18,6 +18,7 @@ from controllers.console.human_input_form import (
WorkflowResponseConverter,
_jsonify_form_definition,
)
from core.workflow.human_input_policy import HumanInputSurface
from models.account import AccountStatus
from models.enums import CreatorUserRole
from models.human_input import RecipientType
@@ -344,3 +345,62 @@ def test_workflow_events_finished(app: Flask, monkeypatch: pytest.MonkeyPatch) -
assert response.mimetype == "text/event-stream"
assert "data" in response.get_data(as_text=True)
def test_workflow_events_snapshot_can_continue_across_pauses(app: Flask, monkeypatch: pytest.MonkeyPatch) -> None:
workflow_run = SimpleNamespace(
id="run-1",
created_by_role=CreatorUserRole.ACCOUNT,
created_by="user-1",
tenant_id="t1",
app_id="app-1",
finished_at=None,
)
app_model = SimpleNamespace(mode=AppMode.WORKFLOW)
class _RepoStub:
def get_workflow_run_by_id_and_tenant_id(self, **_kwargs):
return workflow_run
workflow_generator = Mock()
workflow_generator.convert_to_event_stream.return_value = iter(["data: snapshot\n\n"])
snapshot_builder = Mock(return_value=["snapshot-events"])
monkeypatch.setattr(
DifyAPIRepositoryFactory,
"create_api_workflow_run_repository",
lambda *_args, **_kwargs: _RepoStub(),
)
monkeypatch.setattr(
"controllers.console.human_input_form._retrieve_app_for_workflow_run",
lambda *_args, **_kwargs: app_model,
)
monkeypatch.setattr(
"controllers.console.human_input_form.WorkflowAppGenerator",
lambda: workflow_generator,
)
monkeypatch.setattr(
"controllers.console.human_input_form.build_workflow_event_stream",
snapshot_builder,
)
monkeypatch.setattr("controllers.console.human_input_form.db", SimpleNamespace(engine=object()))
api = ConsoleWorkflowEventsApi()
handler = unwrap(api.get)
with app.test_request_context(
"/console/api/workflow/run-1/events?include_state_snapshot=true&continue_on_pause=true",
method="GET",
):
response = handler(api, "t1", SimpleNamespace(id="user-1"), workflow_run_id="run-1")
assert response.get_data(as_text=True) == "data: snapshot\n\n"
snapshot_builder.assert_called_once_with(
app_mode=AppMode.WORKFLOW,
workflow_run=workflow_run,
tenant_id="t1",
app_id="app-1",
session_maker=ANY,
human_input_surface=HumanInputSurface.CONSOLE,
close_on_pause=False,
)