feat(api): Human Input Node (backend part) (#31646)

The backend part of the human in the loop (HITL) feature and relevant architecture / workflow engine changes.

Signed-off-by: yihong0618 <zouzou0208@gmail.com>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: -LAN- <laipz8200@outlook.com>
Co-authored-by: 盐粒 Yanli <yanli@dify.ai>
Co-authored-by: CrabSAMA <40541269+CrabSAMA@users.noreply.github.com>
Co-authored-by: Stephen Zhou <38493346+hyoban@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: yihong <zouzou0208@gmail.com>
Co-authored-by: Joel <iamjoel007@gmail.com>
This commit is contained in:
QuantumGhost
2026-01-30 10:18:49 +08:00
committed by GitHub
parent fedd097f63
commit 03e3acfc71
207 changed files with 19006 additions and 373 deletions

View File

@ -1,6 +1,9 @@
import json
from collections.abc import Sequence
from typing import Union
from sqlalchemy.orm import sessionmaker
from core.app.apps.advanced_chat.app_config_manager import AdvancedChatAppConfigManager
from core.app.entities.app_invoke_entities import InvokeFrom
from core.llm_generator.llm_generator import LLMGenerator
@ -14,6 +17,10 @@ from extensions.ext_database import db
from libs.infinite_scroll_pagination import InfiniteScrollPagination
from models import Account
from models.model import App, AppMode, AppModelConfig, EndUser, Message, MessageFeedback
from repositories.execution_extra_content_repository import ExecutionExtraContentRepository
from repositories.sqlalchemy_execution_extra_content_repository import (
SQLAlchemyExecutionExtraContentRepository,
)
from services.conversation_service import ConversationService
from services.errors.message import (
FirstMessageNotExistsError,
@ -24,6 +31,23 @@ from services.errors.message import (
from services.workflow_service import WorkflowService
def _create_execution_extra_content_repository() -> ExecutionExtraContentRepository:
session_maker = sessionmaker(bind=db.engine, expire_on_commit=False)
return SQLAlchemyExecutionExtraContentRepository(session_maker=session_maker)
def attach_message_extra_contents(messages: Sequence[Message]) -> None:
if not messages:
return
repository = _create_execution_extra_content_repository()
extra_contents_lists = repository.get_by_message_ids([message.id for message in messages])
for index, message in enumerate(messages):
contents = extra_contents_lists[index] if index < len(extra_contents_lists) else []
message.set_extra_contents([content.model_dump(mode="json", exclude_none=True) for content in contents])
class MessageService:
@classmethod
def pagination_by_first_id(
@ -85,6 +109,8 @@ class MessageService:
if order == "asc":
history_messages = list(reversed(history_messages))
attach_message_extra_contents(history_messages)
return InfiniteScrollPagination(data=history_messages, limit=limit, has_more=has_more)
@classmethod