Skip to content

feat: surface separated-mode LLM reasoning in CLI and workflow run preview#37828

Merged
lin-snow merged 13 commits into
mainfrom
feat/followup-separated-reasoning
Jun 24, 2026
Merged

feat: surface separated-mode LLM reasoning in CLI and workflow run preview#37828
lin-snow merged 13 commits into
mainfrom
feat/followup-separated-reasoning

Conversation

@lin-snow

@lin-snow lin-snow commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Summary

Follow-up to #37460 (chatflow live reasoning). Extends separated-mode (reasoning_format=separated) LLM reasoning — where <think> is streamed out of band instead of inline — to the difyctl CLI and the workflow run preview, and fixes the reasoning display in the workflow preview along the way.

The CLI surfaces reasoning across a combinatorial space: Flow (Chatflow / Workflow) × mode (tagged / separated) × --think, over two channels (stdout / stderr), in both streaming and structured (-o json) output. Two rules collapse it:

  1. tagged and separated must be indistinguishable to the user.
  2. stdout is for machines, stderr is for humans — clean answer/outputs on stdout, human-readable <think> on stderr (only under --think), structured reasoning always in the JSON envelope.

Behavior matrix

A — Text / streaming (--stream)

Flow --think stdout stderr
Chatflow off clean answer (streamed) session hint only
Chatflow on clean answer (streamed) <think>…</think> reasoning + hint
Workflow off clean outputs (JSON line) node progress only (→ <NodeTitle>)
Workflow on clean outputs → <NodeTitle> + per-node <think>…</think>

B — Structured (-o json)

Flow stdout (envelope) stderr (only with --think)
Chatflow { answer: clean, metadata: { reasoning: { <nodeId>: "…" } } } <think>…</think>
Workflow { data: { outputs: clean }, metadata: { reasoning: { <nodeId>: "…" } } } per-node <think>…</think>

metadata.reasoning is always preserved per node — regardless of tagged/separated and regardless of --think.

Changes

  • CLI (run / resume) — surfaces streamed reasoning out of band via the SSE collector + stream handlers; rendered to stderr under --think identically to inline <think>, and kept under metadata.reasoning in structured output. Adds an opt-in e2e suite.
  • Workflow pipeline — now emits reasoning_chunk events. The shared runner already published them; only the chatflow pipeline consumed them — the workflow pipeline silently dropped them.
  • Workflow run preview — accumulates separated-mode deltas per LLM node and live-renders a single "thinking" panel above the result, reusing the chatflow ReasoningPanel.

Workflow preview fixes

  • Reasoning timer was wrong under both tagged and separated — now ticks while running and freezes once the answer starts streaming.
  • Tagged <think> froze at 0s because the result panel renders Markdown outside ChatContext, so ThinkBlock never saw isResponding — now provided via ChatContextProvider (from isRunning).
  • Separated mode wasn't stream-rendering reasoning in the preview — now live in the RESULT panel.
  • With multiple LLM nodes the RESULT page concatenates each node's answer; separated mode preserves that concatenation.

Out of band is preserved end to end: message / text_chunk output never contains <think>. Tagged mode (the default) is unchanged. Terminal reasoning_content remains a normal node output variable.

Note: the new reasoning_chunk SSE event is additive on /v1/workflows/run (old clients ignore unknown events); a Service API docs note is a follow-up.

Screenshots

Before After
Separated mode: no reasoning shown in the workflow run preview RESULT tab shows a live "深度思考中 → 已深度思考" panel above the answer
Tagged mode: result-panel thinking timer stuck at 0.0s Timer ticks while running, freezes when the answer starts

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • I've updated the documentation accordingly.
  • I ran make lint && make type-check (backend) and cd web && pnpm exec vp staged (frontend) to appease the lint gods

@dosubot dosubot Bot added the size:L This PR changes 100-499 lines, ignoring generated files. label Jun 23, 2026
@github-actions github-actions Bot added the web This relates to changes on the web. label Jun 23, 2026
@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Pyrefly Type Coverage

Metric Base PR Delta
Type coverage 51.10% 51.09% -0.01%
Strict coverage 50.61% 50.61% -0.01%
Typed symbols 30,346 30,346 0
Untyped symbols 29,319 29,327 +8
Modules 2928 2928 0

@github-actions

github-actions Bot commented Jun 23, 2026

Copy link
Copy Markdown
Contributor

Pyrefly Diff

base → PR
--- /tmp/pyrefly_base.txt	2026-06-24 07:48:32.499773425 +0000
+++ /tmp/pyrefly_pr.txt	2026-06-24 07:48:17.263684770 +0000
@@ -3052,81 +3052,95 @@
 ERROR `SimpleNamespace` is not assignable to attribute `_application_generate_entity` with type `AdvancedChatAppGenerateEntity` [bad-assignment]
    --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline.py:240:45
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:99:23
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:101:23
 ERROR Argument `(**kwargs: Unknown) -> None` is not assignable to parameter `draft_var_saver_factory` with type `DraftVariableSaverFactory` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:105:33
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:107:33
 ERROR `SimpleNamespace` is not assignable to attribute `_message_cycle_manager` with type `MessageCycleManager` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:186:43
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:188:43
 ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueTextChunkEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:194:60
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:196:60
 ERROR Argument `SimpleNamespace` is not assignable to parameter `publisher` with type `AppGeneratorTTSPublisher | None` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._listen_audio_msg` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:203:57
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:241:57
 ERROR `(err: Unknown) -> Unknown` is not assignable to attribute `error_to_stream_response` with type `(self: BasedGenerateTaskPipeline[Unknown], e: Exception) -> ErrorStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:218:65
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:256:65
 ERROR `() -> _GeneratorContextManager[SimpleNamespace]` is not assignable to attribute `_database_session` with type `(self: AdvancedChatAppGenerateTaskPipeline) -> _GeneratorContextManager[Session]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:224:38
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:262:38
 ERROR `(**kwargs: Unknown) -> Literal['started']` is not assignable to attribute `workflow_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_run_id: str, workflow_id: str, reason: WorkflowStartReason) -> WorkflowStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:236:83
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:274:83
 ERROR `TestAdvancedChatGenerateTaskPipeline.test_handle_output_moderation_chunk_publishes_stop._Moderation` is not assignable to attribute `output_moderation_handler` with type `OutputModeration | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:290:66
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:328:66
 ERROR `SimpleNamespace` is not assignable to attribute `queue_manager` with type `AppQueueManager` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:291:54
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:329:54
 ERROR `(outputs: Unknown) -> list[dict[str, str]]` is not assignable to attribute `fetch_files_from_node_outputs` with type `(cls: type[WorkflowResponseConverter], outputs_dict: Mapping[str, Any] | None) -> Sequence[Mapping[str, Any]]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:304:79
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:342:79
 ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:307:89
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:345:89
 ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueNodeSucceededEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_node_succeeded_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:317:64
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:355:64
+ERROR `(outputs: Unknown) -> list[@_]` is not assignable to attribute `fetch_files_from_node_outputs` with type `(cls: type[WorkflowResponseConverter], outputs_dict: Mapping[str, Any] | None) -> Sequence[Mapping[str, Any]]` [bad-assignment]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:362:79
+ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:363:89
+ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueNodeSucceededEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_node_succeeded_event` [bad-argument-type]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:373:52
+ERROR `(outputs: Unknown) -> list[@_]` is not assignable to attribute `fetch_files_from_node_outputs` with type `(cls: type[WorkflowResponseConverter], outputs_dict: Mapping[str, Any] | None) -> Sequence[Mapping[str, Any]]` [bad-assignment]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:379:79
+ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:380:89
+ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueNodeSucceededEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_node_succeeded_event` [bad-argument-type]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:392:52
+ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueNodeSucceededEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_node_succeeded_event` [bad-argument-type]
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:393:52
 ERROR `(**kwargs: Unknown) -> Literal['iter_start']` is not assignable to attribute `workflow_iteration_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationStartEvent) -> IterationNodeStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:325:93
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:400:93
 ERROR `(**kwargs: Unknown) -> Literal['iter_next']` is not assignable to attribute `workflow_iteration_next_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationNextEvent) -> IterationNodeNextStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:328:92
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:403:92
 ERROR `(**kwargs: Unknown) -> Literal['iter_done']` is not assignable to attribute `workflow_iteration_completed_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationCompletedEvent) -> IterationNodeCompletedStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:329:97
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:404:97
 ERROR `(**kwargs: Unknown) -> Literal['loop_start']` is not assignable to attribute `workflow_loop_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopStartEvent) -> LoopNodeStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:332:88
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:407:88
 ERROR `(**kwargs: Unknown) -> Literal['loop_next']` is not assignable to attribute `workflow_loop_next_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopNextEvent) -> LoopNodeNextStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:333:87
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:408:87
 ERROR `(**kwargs: Unknown) -> Literal['loop_done']` is not assignable to attribute `workflow_loop_completed_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopCompletedEvent) -> LoopNodeCompletedStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:334:92
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:409:92
 ERROR `(**kwargs: Unknown) -> Literal['finish']` is not assignable to attribute `workflow_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_id: str, status: WorkflowExecutionStatus, graph_runtime_state: GraphRuntimeState, error: str | None = None, exceptions_count: int = 0) -> WorkflowFinishStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:401:84
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:476:84
 ERROR `(**kwargs: Unknown) -> list[str]` is not assignable to attribute `workflow_pause_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueWorkflowPausedEvent, task_id: str, graph_runtime_state: GraphRuntimeState) -> list[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:402:83
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:477:83
 ERROR `(err: Unknown) -> Unknown` is not assignable to attribute `error_to_stream_response` with type `(self: BasedGenerateTaskPipeline[Unknown], e: Exception) -> ErrorStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:407:65
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:482:65
 ERROR `(**kwargs: Unknown) -> SimpleNamespace` is not assignable to attribute `_get_message` with type `(self: AdvancedChatAppGenerateTaskPipeline, *, session: Session) -> Message` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:408:33
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:483:33
 ERROR `(**kwargs: Unknown) -> Literal['node_finish']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:439:89
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:514:89
 ERROR `SimpleNamespace` is not assignable to attribute `_message_cycle_manager` with type `MessageCycleManager` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:474:43
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:549:43
 ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `QueueTextChunkEvent` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:480:47
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:555:47
 ERROR Argument `TestAdvancedChatGenerateTaskPipeline.test_handle_text_chunk_event_tracks_streaming_metrics._Publisher` is not assignable to parameter `tts_publisher` with type `AppGeneratorTTSPublisher | None` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:480:68
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:555:68
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_message` with type `MessageQueueMessage | WorkflowQueueMessage | None` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:480:96
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:555:96
 ERROR `TestAdvancedChatGenerateTaskPipeline.test_handle_output_moderation_chunk_appends_token._Moderation` is not assignable to attribute `output_moderation_handler` with type `OutputModeration | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:501:66
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:576:66
 ERROR `(**kwargs: Unknown) -> Literal['replace']` is not assignable to attribute `message_replace_to_stream_response` with type `(self: MessageCycleManager, answer: str, reason: str = '') -> MessageReplaceStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:530:78
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:605:78
 ERROR `(**kwargs: Unknown) -> Literal['filled']` is not assignable to attribute `human_input_form_filled_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueHumanInputFormFilledEvent, task_id: str) -> HumanInputFormFilledResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:543:92
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:618:92
 ERROR `(**kwargs: Unknown) -> Literal['timeout']` is not assignable to attribute `human_input_form_timeout_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueHumanInputFormTimeoutEvent, task_id: str) -> HumanInputFormTimeoutResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:544:93
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:619:93
 ERROR Argument `TestAdvancedChatGenerateTaskPipeline.test_save_message_preserves_full_answer_and_sets_usage._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.advanced_chat.generate_task_pipeline.AdvancedChatAppGenerateTaskPipeline._save_message` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:616:40
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:691:40
 ERROR `() -> Literal['end']` is not assignable to attribute `_message_end_to_stream_response` with type `(self: AdvancedChatAppGenerateTaskPipeline) -> MessageEndStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:624:52
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:699:52
 ERROR `(answer: Unknown) -> Literal['safe']` is not assignable to attribute `handle_output_moderation_when_task_finished` with type `(self: BasedGenerateTaskPipeline[Unknown], completion: str) -> str | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:651:84
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:726:84
 ERROR `(**kwargs: Unknown) -> Literal['replace']` is not assignable to attribute `message_replace_to_stream_response` with type `(self: MessageCycleManager, answer: str, reason: str = '') -> MessageReplaceStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:652:78
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:727:78
 ERROR `() -> Literal['end']` is not assignable to attribute `_message_end_to_stream_response` with type `(self: AdvancedChatAppGenerateTaskPipeline) -> MessageEndStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:653:52
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:728:52
 ERROR `(**kwargs: Unknown) -> Literal['failed']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:675:89
+   --> tests/unit_tests/core/app/apps/advanced_chat/test_generate_task_pipeline_core.py:750:89
 ERROR Argument `DummyAccount` is not assignable to parameter `user` with type `Account | EndUser` in function `core.app.apps.agent_app.app_generator.AgentAppGenerator.generate` [bad-argument-type]
   --> tests/unit_tests/core/app/apps/agent_app/test_app_generator.py:43:22
 ERROR Argument `DummyAccount` is not assignable to parameter `user` with type `Account | EndUser` in function `core.app.apps.agent_app.app_generator.AgentAppGenerator.generate` [bad-argument-type]
@@ -3566,65 +3580,67 @@
 ERROR Argument `SimpleNamespace` is not assignable to parameter `pause_state_config` with type `PauseStateLayerConfig | None` in function `core.app.apps.workflow.app_generator.WorkflowAppGenerator.resume` [bad-argument-type]
    --> tests/unit_tests/core/app/apps/test_workflow_app_generator.py:321:28
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:50:55
+  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:52:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:57:55
+  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:59:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:89:55
+  --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:91:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:118:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:120:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._prepare_single_node_execution` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:123:51
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:125:51
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:126:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:128:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._get_graph_and_variable_pool_for_single_node_run` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:165:22
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:167:22
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:180:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:182:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._get_graph_and_variable_pool_for_single_node_run` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:216:22
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:218:22
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:245:27
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:247:27
 ERROR Argument `SimpleNamespace` is not assignable to parameter `variable_loader` with type `VariableLoader` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:246:29
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:248:29
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._get_graph_and_variable_pool_for_single_node_run` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:309:22
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:311:22
 ERROR Object of class `NoneType` has no attribute `value` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:318:16
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:320:16
 ERROR Argument `TestWorkflowBasedAppRunner.test_handle_graph_run_events_and_pause_notifications._QueueManager` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:327:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:329:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:353:30
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:355:30
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:354:30
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:356:30
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:355:30
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:357:30
 ERROR Type `object` is not iterable [not-iterable]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:357:69
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:359:69
 ERROR Type `object` is not iterable [not-iterable]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:358:71
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:360:71
 ERROR Type `object` is not iterable [not-iterable]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:359:39
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:361:39
 ERROR Argument `TestWorkflowBasedAppRunner.test_handle_node_events_publishes_queue_events._QueueManager` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:370:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:372:55
+ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:380:13
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:378:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:390:13
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:388:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:401:13
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:399:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:412:13
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:415:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:428:13
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:429:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:442:13
 ERROR Argument `TestWorkflowBasedAppRunner.test_handle_human_input_form_filled_event_preserves_submitted_data._QueueManager` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:456:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:470:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:468:13
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:482:13
 ERROR Argument `TestWorkflowBasedAppRunner.test_handle_start_node_result_events_project_outputs._QueueManager` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:545:55
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:559:55
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:563:30
+   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_core.py:577:30
 ERROR Argument `_DummyQueueManager` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner.__init__` [bad-argument-type]
   --> tests/unit_tests/core/app/apps/test_workflow_app_runner_notifications.py:36:51
 ERROR Argument `_DummyWorkflowEntry` is not assignable to parameter `workflow_entry` with type `WorkflowEntry` in function `core.app.apps.workflow_app_runner.WorkflowBasedAppRunner._handle_event` [bad-argument-type]
@@ -3773,129 +3789,129 @@
 ERROR Cannot index into `str` [bad-index]
    --> tests/unit_tests/core/app/apps/workflow/test_generate_response_converter.py:133:16
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:84:18
+  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:86:18
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:85:23
+  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:87:23
 ERROR Argument `SimpleNamespace` is not assignable to parameter `user` with type `Account | EndUser` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:86:14
+  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:88:14
 ERROR Argument `(**kwargs: Unknown) -> None` is not assignable to parameter `draft_var_saver_factory` with type `DraftVariableSaverFactory` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:88:33
+  --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:90:33
 ERROR Argument `SimpleNamespace` is not assignable to parameter `publisher` with type `AppGeneratorTTSPublisher | None` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._listen_audio_msg` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:172:57
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:174:57
 ERROR `(err: Unknown) -> Unknown` is not assignable to attribute `error_to_stream_response` with type `(self: BasedGenerateTaskPipeline[Unknown], e: Exception) -> ErrorStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:187:65
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:189:65
 ERROR `(**kwargs: Unknown) -> Literal['started']` is not assignable to attribute `workflow_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_run_id: str, workflow_id: str, reason: WorkflowStartReason) -> WorkflowStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:199:83
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:201:83
 ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:215:89
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:217:89
 ERROR `(**kwargs: Unknown) -> Literal['finish']` is not assignable to attribute `workflow_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_id: str, status: WorkflowExecutionStatus, graph_runtime_state: GraphRuntimeState, error: str | None = None, exceptions_count: int = 0) -> WorkflowFinishStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:240:84
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:242:84
 ERROR `(err: Unknown) -> Unknown` is not assignable to attribute `error_to_stream_response` with type `(self: BasedGenerateTaskPipeline[Unknown], e: Exception) -> ErrorStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:242:65
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:244:65
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_handle_text_chunk_event_publishes_tts._Publisher` is not assignable to parameter `tts_publisher` with type `AppGeneratorTTSPublisher | None` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:262:68
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:264:68
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_message` with type `MessageQueueMessage | WorkflowQueueMessage | None` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._handle_text_chunk_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:262:96
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:264:96
 ERROR Object of class `StreamResponse` has no attribute `data` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:265:16
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:267:16
 ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:270:89
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:307:89
 ERROR `(**kwargs: Unknown) -> Literal['finish']` is not assignable to attribute `workflow_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_id: str, status: WorkflowExecutionStatus, graph_runtime_state: GraphRuntimeState, error: str | None = None, exceptions_count: int = 0) -> WorkflowFinishStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:294:84
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:331:84
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_save_workflow_app_log_created_from._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._save_workflow_app_log` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:314:49
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:351:49
 ERROR `(**kwargs: Unknown) -> Literal['iter']` is not assignable to attribute `workflow_iteration_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationStartEvent) -> IterationNodeStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:321:93
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:358:93
 ERROR `(**kwargs: Unknown) -> Literal['next']` is not assignable to attribute `workflow_iteration_next_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationNextEvent) -> IterationNodeNextStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:322:92
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:359:92
 ERROR `(**kwargs: Unknown) -> Literal['done']` is not assignable to attribute `workflow_iteration_completed_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueIterationCompletedEvent) -> IterationNodeCompletedStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:323:97
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:360:97
 ERROR `(**kwargs: Unknown) -> Literal['loop']` is not assignable to attribute `workflow_loop_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopStartEvent) -> LoopNodeStartStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:324:88
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:361:88
 ERROR `(**kwargs: Unknown) -> Literal['loop_next']` is not assignable to attribute `workflow_loop_next_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopNextEvent) -> LoopNodeNextStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:325:87
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:362:87
 ERROR `(**kwargs: Unknown) -> Literal['loop_done']` is not assignable to attribute `workflow_loop_completed_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_execution_id: str, event: QueueLoopCompletedEvent) -> LoopNodeCompletedStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:326:92
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:363:92
 ERROR `(**kwargs: Unknown) -> Literal['filled']` is not assignable to attribute `human_input_form_filled_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueHumanInputFormFilledEvent, task_id: str) -> HumanInputFormFilledResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:327:92
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:364:92
 ERROR `(**kwargs: Unknown) -> Literal['timeout']` is not assignable to attribute `human_input_form_timeout_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueHumanInputFormTimeoutEvent, task_id: str) -> HumanInputFormTimeoutResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:328:93
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:365:93
 ERROR `(**kwargs: Unknown) -> Literal['log']` is not assignable to attribute `handle_agent_log` with type `(self: WorkflowResponseConverter, task_id: str, event: QueueAgentLogEvent) -> AgentLogStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:329:66
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:366:66
 ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:421:45
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:458:45
 ERROR Argument `SimpleNamespace` is not assignable to parameter `workflow` with type `Workflow` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:477:22
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:514:22
 ERROR Argument `SimpleNamespace` is not assignable to parameter `queue_manager` with type `AppQueueManager` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:478:27
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:515:27
 ERROR Argument `(**kwargs: Unknown) -> None` is not assignable to parameter `draft_var_saver_factory` with type `DraftVariableSaverFactory` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline.__init__` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:481:37
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:518:37
 ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_wrapper_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:490:53
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:527:53
 ERROR Object of class `tuple` has no attribute `workflow_run_id` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:494:16
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:531:16
 ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_wrapper_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:497:53
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:534:53
 ERROR Object of class `Generator` has no attribute `workflow_run_id` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:519:16
-ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:563:45
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:556:16
 ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:573:45
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:600:45
 ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
    --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:610:45
+ERROR `(**kwargs: Unknown) -> Iterator[Any]` is not assignable to attribute `_process_stream_response` with type `(self: WorkflowAppGenerateTaskPipeline, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None) -> Generator[StreamResponse]` [bad-assignment]
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:647:45
 ERROR `(**kwargs: Unknown) -> Literal['retry']` is not assignable to attribute `workflow_node_retry_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeRetryEvent, task_id: str) -> NodeRetryStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:700:88
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:737:88
 ERROR `(**kwargs: Unknown) -> Literal['started']` is not assignable to attribute `workflow_node_start_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeStartedEvent, task_id: str) -> NodeStartStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:705:88
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:742:88
 ERROR `(**kwargs: Unknown) -> Literal['failed']` is not assignable to attribute `workflow_node_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueNodeExceptionEvent | QueueNodeFailedEvent | QueueNodeSucceededEvent, task_id: str) -> NodeFinishStreamResponse | None` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:711:89
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:748:89
 ERROR `(**kwargs: Unknown) -> Literal['finish']` is not assignable to attribute `workflow_finish_to_stream_response` with type `(self: WorkflowResponseConverter, *, task_id: str, workflow_id: str, status: WorkflowExecutionStatus, graph_runtime_state: GraphRuntimeState, error: str | None = None, exceptions_count: int = 0) -> WorkflowFinishStreamResponse` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:739:84
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:776:84
 ERROR `(**kwargs: Unknown) -> list[str]` is not assignable to attribute `workflow_pause_to_stream_response` with type `(self: WorkflowResponseConverter, *, event: QueueWorkflowPausedEvent, task_id: str, graph_runtime_state: GraphRuntimeState) -> list[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:747:83
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:784:83
 ERROR `(event: QueuePingEvent, **kwargs: Unknown) -> Iterator[PingStreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_ping_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueuePingEvent, **kwargs: Unknown) -> Generator[PingStreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:768:39
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:805:39
 ERROR `(event: QueueStopEvent | QueueWorkflowFailedEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_workflow_failed_and_stop_events` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueStopEvent | QueueWorkflowFailedEvent, *, trace_manager: TraceQueueManager | None = None, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:771:60
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:808:60
 ERROR Argument `SimpleNamespace` is not assignable to parameter `event` with type `AppQueueEvent` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._dispatch_event` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:776:46
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:813:46
 ERROR `() -> Iterator[MessageQueueMessage | WorkflowQueueMessage] | Iterator[Any]` is not assignable to attribute `listen` with type `(self: AppQueueManager) -> Generator[MessageQueueMessage | WorkflowQueueMessage, Unknown]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:786:61
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:823:61
 ERROR `(event: QueueWorkflowStartedEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_workflow_started_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueWorkflowStartedEvent, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:794:51
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:831:51
 ERROR `(event: QueueTextChunkEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_text_chunk_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueTextChunkEvent, *, tts_publisher: AppGeneratorTTSPublisher | None = None, queue_message: MessageQueueMessage | WorkflowQueueMessage | None = None, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:795:45
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:832:45
 ERROR `(event: AppQueueEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_dispatch_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: AppQueueEvent, *, tts_publisher: AppGeneratorTTSPublisher | None = None, trace_manager: TraceQueueManager | None = None, queue_message: MessageQueueMessage | WorkflowQueueMessage | None = None) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:796:36
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:833:36
 ERROR `(event: QueueErrorEvent, **kwargs: Unknown) -> Iterator[ErrorStreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_error_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueErrorEvent, **kwargs: Unknown) -> Generator[ErrorStreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:797:40
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:834:40
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_process_stream_response_main_match_paths_and_cleanup._Publisher` is not assignable to parameter `tts_publisher` with type `AppGeneratorTTSPublisher | None` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._process_stream_response` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:804:74
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:841:74
 ERROR `() -> Iterator[MessageQueueMessage | WorkflowQueueMessage] | Iterator[Any]` is not assignable to attribute `listen` with type `(self: AppQueueManager) -> Generator[MessageQueueMessage | WorkflowQueueMessage, Unknown]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:811:61
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:848:61
 ERROR `(event: QueueStopEvent | QueueWorkflowFailedEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_workflow_failed_and_stop_events` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueStopEvent | QueueWorkflowFailedEvent, *, trace_manager: TraceQueueManager | None = None, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:814:60
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:851:60
 ERROR `() -> Iterator[MessageQueueMessage | WorkflowQueueMessage] | Iterator[Any]` is not assignable to attribute `listen` with type `(self: AppQueueManager) -> Generator[MessageQueueMessage | WorkflowQueueMessage, Unknown]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:817:61
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:854:61
 ERROR `(event: QueueWorkflowPausedEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_workflow_paused_event` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueWorkflowPausedEvent, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:820:50
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:857:50
 ERROR `() -> Iterator[MessageQueueMessage | WorkflowQueueMessage] | Iterator[Any]` is not assignable to attribute `listen` with type `(self: AppQueueManager) -> Generator[MessageQueueMessage | WorkflowQueueMessage, Unknown]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:823:61
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:860:61
 ERROR `(event: QueueStopEvent | QueueWorkflowFailedEvent, **kwargs: Unknown) -> Iterator[StreamResponse] | Iterator[Any]` is not assignable to attribute `_handle_workflow_failed_and_stop_events` with type `(self: WorkflowAppGenerateTaskPipeline, event: QueueStopEvent | QueueWorkflowFailedEvent, *, trace_manager: TraceQueueManager | None = None, **kwargs: Unknown) -> Generator[StreamResponse]` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:826:60
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:863:60
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_save_workflow_app_log_covers_invoke_from_variants._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._save_workflow_app_log` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:839:49
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:876:49
 ERROR Object of class `object` has no attribute `created_from` [missing-attribute]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:840:16
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:877:16
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_save_workflow_app_log_covers_invoke_from_variants._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._save_workflow_app_log` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:843:49
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:880:49
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_save_workflow_app_log_covers_invoke_from_variants._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._save_workflow_app_log` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:848:49
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:885:49
 ERROR Argument `TestWorkflowGenerateTaskPipeline.test_save_workflow_app_log_covers_invoke_from_variants._Session` is not assignable to parameter `session` with type `Session` in function `core.app.apps.workflow.generate_task_pipeline.WorkflowAppGenerateTaskPipeline._save_workflow_app_log` [bad-argument-type]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:852:49
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:889:49
 ERROR `(**kwargs: Unknown) -> TestWorkflowGenerateTaskPipeline.test_save_output_for_event_writes_draft_variables._Saver` is not assignable to attribute `_draft_var_saver_factory` with type `DraftVariableSaverFactory` [bad-assignment]
-   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:868:45
+   --> tests/unit_tests/core/app/apps/workflow/test_generate_task_pipeline_core.py:905:45
 ERROR `Literal['unknown']` is not assignable to attribute `stopped_by` with type `QueueStopEvent.StopBy` [bad-assignment]
   --> tests/unit_tests/core/app/entities/test_queue_entities.py:11:28
 ERROR Cannot index into `bool` [bad-index]

@codecov

codecov Bot commented Jun 23, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 85.38%. Comparing base (32dc9ff) to head (0225355).

Additional details and impacted files
@@            Coverage Diff             @@
##             main   #37828      +/-   ##
==========================================
+ Coverage   85.37%   85.38%   +0.01%     
==========================================
  Files        5091     5093       +2     
  Lines      259616   259961     +345     
  Branches    49375    49433      +58     
==========================================
+ Hits       221637   221978     +341     
- Misses      33748    33750       +2     
- Partials     4231     4233       +2     
Flag Coverage Δ
api 85.55% <100.00%> (+0.01%) ⬆️
cli 88.45% <100.00%> (+0.41%) ⬆️
dify-ui 94.94% <ø> (ø)
web 84.93% <100.00%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@lin-snow lin-snow marked this pull request as draft June 23, 2026 15:16
@lin-snow lin-snow force-pushed the feat/followup-separated-reasoning branch from c367f77 to 19b7359 Compare June 24, 2026 02:53
@lin-snow lin-snow marked this pull request as ready for review June 24, 2026 03:37
@dosubot dosubot Bot added the feat:webapp Ready-to-use AI web app. Also the "Preview" / "Debug & Preview" inside the orchestrate page. label Jun 24, 2026
@lin-snow lin-snow self-assigned this Jun 24, 2026
Comment thread cli/src/sys/io/reasoning.ts
Comment thread cli/src/commands/run/app/sse-collector.ts Outdated
@lin-snow lin-snow force-pushed the feat/followup-separated-reasoning branch from be88410 to 5956801 Compare June 24, 2026 07:10
@lin-snow lin-snow requested a review from GareArc June 24, 2026 07:26
@lin-snow lin-snow enabled auto-merge June 24, 2026 07:33
lin-snow added 8 commits June 24, 2026 15:33
PR #37460 added an out-of-band `reasoning_chunk` SSE channel for chatflow
apps whose LLM node uses reasoning_format=separated: the answer stream stays
free of <think> and the chain-of-thought streams on its own channel. difyctl
dropped these events, so `--think` showed nothing for such apps.

- new sys/io/reasoning module: parse reasoning_chunk payloads (nested under
  `data`), frame them to stderr identically to inline <think> blocks
- ChatStreamPrinter renders reasoning_chunk deltas to stderr under --think
- ChatCollector accumulates reasoning as a fallback; the server's persisted
  message_end metadata.reasoning stays the JSON source of truth
- streaming-structured echoes separated reasoning to stderr under --think
- update --think help to mention separated reasoning streams
Backfill the test gap left by #37460's reasoning streaming:

- _handle_reasoning_chunk_event guard: non-empty emit, empty+non-final
  dropped, empty+final terminal marker emitted
- _handle_node_succeeded_event: LLM reasoning_content persisted into
  metadata.reasoning, accumulating across passes (not overwriting)
- workflow_app_runner: NodeRunReasoningChunkEvent translates to a
  published QueueReasoningChunkEvent
Live coverage for the reasoning_chunk adaptation, gated to skip by default:

- reasoning-chat.yml fixture: chatflow with an LLM node (reasoning_format:
  separated) whose system prompt forces a <think> block, so any chat model
  triggers the separated path — no dedicated reasoning model needed
- run-app-reasoning.e2e.ts: --think surfaces reasoning to stderr as <think>,
  answer stays clean, -o json persists metadata.reasoning, no --think hides it
- thread DIFY_E2E_REASONING_APP_ID through env.ts / global-setup capabilities;
  optionalIt skips the suite unless it resolves
- DIFY_E2E_REASONING_PROVISION=1 opts into auto-provisioning the fixture, so
  the shared bootstrap stays free of any model dependency by default
- document both vars in README + .env.e2e.example
Workflow apps now stream LLM reasoning_content out of band like chatflow: the
workflow task pipeline emits reasoning_chunk events, and the run preview
accumulates them per LLM node and renders a thinking panel above the result.
The run result panel renders tagged <think> blocks via Markdown but sits
outside ChatContext, so ThinkBlock read no isResponding and froze the timer at
0s. Provide isResponding (from isRunning) via ChatContextProvider.
The server now emits reasoning_chunk for Workflow apps too (same event as
chatflow, but with no message_id). difyctl received them but WorkflowStreamPrinter
and WorkflowCollector dropped them, so --think showed nothing and -o json omitted
reasoning for workflow runs.

Mirror the chat-mode handling into the workflow path, reusing the existing
sys/io/reasoning primitives:
- WorkflowStreamPrinter renders reasoning_chunk to stderr under --think (the
  preceding node_started "→ <title>" line attributes each per-node block);
  flush on stream end
- WorkflowCollector accumulates reasoning per node into metadata.reasoning
  (workflow has no persisted metadata, so the live deltas are the only source)
- streaming-structured needs no change: its reasoningBlocksFromMetadata echo
  already reads metadata.reasoning, so workflow --think echo works for free
- tests + a workflow-reasoning mock scenario

Verified live against a 2-LLM-node separated workflow: two <think> blocks on
stderr, clean outputs on stdout, metadata.reasoning keyed by both node ids.
…omposition

useWorkflowRunEvent now composes handleWorkflowReasoning from the
separate use-workflow-reasoning module. Mock that module and add the
handler to the expected set so the composed-handlers assertion matches.
The result panel only latched the reasoning timer on reasoningFinished
(a node-terminal marker that trails the whole answer) or a non-Running
status (set only when the run ends), so the thinking timer kept ticking
through the entire answer stream for both single- and multi-LLM-node
runs. Mirror Chatflow by also latching on the answer-started signal
(resultText non-empty).
lin-snow added 4 commits June 24, 2026 15:33
Trim verbose multi-line comment blocks across the CLI/API/web separated-reasoning code down to terse single-line notes, matching the sparse comment style used elsewhere (e.g. think-filter.ts, sibling _handle_*_event docstrings). Comment text only; no logic changes.
…r merge

Close the two patch-coverage gaps from the reasoning work:
- exercise the onReasoning wrappers in both base and final workflow run
  callbacks (web), which the routing tests never invoked
- cover WorkflowCollector merging live reasoning deltas into metadata
  already carried by workflow_finished (cli)
ReasoningChunkRenderer tracked a single open flag, so reasoning deltas
from LLM nodes on parallel branches (which interleave on one SSE stream)
got merged into one <think> block and a node's is_final prematurely
closed another's block. Key the renderer by node id and switch blocks on
node change, keeping at most one block open; single-node output is
unchanged.

Also extract accumulateReasoning/reasoningKey into sys/io/reasoning.ts to
de-dupe the per-node accumulation shared by the chat and workflow
collectors.
Under parallel branches, reasoning deltas from different LLM nodes
interleave on one stream, producing back-to-back <think> blocks. Tag each
block with its node id (<think> [<node_id>]) so the interleaved fragments
stay distinguishable; chunks without a node id keep the bare <think>.
@lin-snow lin-snow force-pushed the feat/followup-separated-reasoning branch from 5956801 to 1ca3029 Compare June 24, 2026 07:33

@GareArc GareArc left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dosubot dosubot Bot added the lgtm This PR has been approved by a maintainer label Jun 24, 2026
@lin-snow lin-snow added this pull request to the merge queue Jun 24, 2026
Merged via the queue into main with commit 94d365e Jun 24, 2026
46 checks passed
@lin-snow lin-snow deleted the feat/followup-separated-reasoning branch June 24, 2026 08:18
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feat:webapp Ready-to-use AI web app. Also the "Preview" / "Debug & Preview" inside the orchestrate page. lgtm This PR has been approved by a maintainer size:L This PR changes 100-499 lines, ignoring generated files. web This relates to changes on the web.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants