mirror of
https://github.com/langgenius/dify.git
synced 2026-05-10 05:56:31 +08:00
feat(agent): add clarification extensibility hook
This commit is contained in:
parent
1b6e695520
commit
49da7fc7ca
@ -9,6 +9,7 @@ from dify_graph.node_events import NodeEventBase, NodeRunResult, StreamCompleted
|
||||
from dify_graph.nodes.base.node import Node
|
||||
from dify_graph.nodes.base.variable_template_parser import VariableTemplateParser
|
||||
|
||||
from .clarification_helper import should_enable_clarification
|
||||
from .entities import AgentNodeData
|
||||
from .exceptions import (
|
||||
AgentInvocationError,
|
||||
@ -150,6 +151,11 @@ class AgentNode(Node[AgentNodeData]):
|
||||
node_id=self._node_id,
|
||||
node_execution_id=self.id,
|
||||
)
|
||||
# Extensibility hook for human clarification (HITL support)
|
||||
# Currently a no-op, but allows future HITL implementation
|
||||
if should_enable_clarification(self.node_data):
|
||||
# Placeholder for future clarification logic
|
||||
pass
|
||||
except PluginDaemonClientSideError as e:
|
||||
transform_error = AgentMessageTransformError(
|
||||
f"Failed to transform agent message: {str(e)}", original_error=e
|
||||
|
||||
51
api/core/workflow/nodes/agent/clarification_helper.py
Normal file
51
api/core/workflow/nodes/agent/clarification_helper.py
Normal file
@ -0,0 +1,51 @@
|
||||
"""
|
||||
Clarification helper for agent node human-in-the-loop support.
|
||||
|
||||
This module provides extensibility hooks for future HITL (Human-In-The-Loop) features.
|
||||
Currently, it serves as a placeholder for clarification request extraction and handling.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from .entities import AgentNodeData
|
||||
|
||||
|
||||
def should_enable_clarification(node_data: AgentNodeData) -> bool:
|
||||
"""
|
||||
Check if human clarification is enabled for this agent node.
|
||||
|
||||
Args:
|
||||
node_data: The agent node data configuration.
|
||||
|
||||
Returns:
|
||||
True if human clarification is enabled, False otherwise.
|
||||
"""
|
||||
return node_data.enable_human_clarification
|
||||
|
||||
|
||||
def extract_clarification_request(
|
||||
agent_output: dict[str, Any],
|
||||
enable_clarification: bool,
|
||||
) -> dict[str, Any] | None:
|
||||
"""
|
||||
Extract clarification request from agent output if enabled.
|
||||
|
||||
This is a placeholder for future HITL implementation.
|
||||
Currently returns None as clarification is not yet implemented.
|
||||
|
||||
Args:
|
||||
agent_output: The output from agent execution.
|
||||
enable_clarification: Whether clarification is enabled.
|
||||
|
||||
Returns:
|
||||
Clarification request dict if found and enabled, None otherwise.
|
||||
"""
|
||||
if not enable_clarification:
|
||||
return None
|
||||
|
||||
# Placeholder for future clarification extraction logic
|
||||
# This will be extended when HITL feature is fully implemented
|
||||
return None
|
||||
@ -19,6 +19,8 @@ class AgentNodeData(BaseNodeData):
|
||||
# If this value is None, it indicates this is a previous version
|
||||
# and requires using the legacy parameter parsing rules.
|
||||
tool_node_version: str | None = None
|
||||
# Enable human clarification for agent reasoning
|
||||
enable_human_clarification: bool = False
|
||||
|
||||
class AgentInput(BaseModel):
|
||||
value: Union[list[str], list[ToolSelector], Any]
|
||||
|
||||
@ -0,0 +1,95 @@
|
||||
"""
|
||||
Tests for agent node clarification helper and configuration.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from core.workflow.nodes.agent.clarification_helper import (
|
||||
extract_clarification_request,
|
||||
should_enable_clarification,
|
||||
)
|
||||
from core.workflow.nodes.agent.entities import AgentNodeData
|
||||
from dify_graph.enums import NodeType
|
||||
|
||||
|
||||
class TestClarificationHelper:
|
||||
"""Test suite for clarification helper functions."""
|
||||
|
||||
def test_should_enable_clarification_when_enabled(self):
|
||||
"""Test that should_enable_clarification returns True when enabled."""
|
||||
node_data = AgentNodeData(
|
||||
id="test_node",
|
||||
type=NodeType.AGENT,
|
||||
agent_strategy_provider_name="test_provider",
|
||||
agent_strategy_name="test_strategy",
|
||||
agent_strategy_label="Test Strategy",
|
||||
agent_parameters={},
|
||||
enable_human_clarification=True,
|
||||
)
|
||||
assert should_enable_clarification(node_data) is True
|
||||
|
||||
def test_should_enable_clarification_when_disabled(self):
|
||||
"""Test that should_enable_clarification returns False when disabled."""
|
||||
node_data = AgentNodeData(
|
||||
id="test_node",
|
||||
type=NodeType.AGENT,
|
||||
agent_strategy_provider_name="test_provider",
|
||||
agent_strategy_name="test_strategy",
|
||||
agent_strategy_label="Test Strategy",
|
||||
agent_parameters={},
|
||||
enable_human_clarification=False,
|
||||
)
|
||||
assert should_enable_clarification(node_data) is False
|
||||
|
||||
def test_should_enable_clarification_default_false(self):
|
||||
"""Test that clarification is disabled by default."""
|
||||
node_data = AgentNodeData(
|
||||
id="test_node",
|
||||
type=NodeType.AGENT,
|
||||
agent_strategy_provider_name="test_provider",
|
||||
agent_strategy_name="test_strategy",
|
||||
agent_strategy_label="Test Strategy",
|
||||
agent_parameters={},
|
||||
)
|
||||
assert should_enable_clarification(node_data) is False
|
||||
|
||||
def test_extract_clarification_request_when_disabled(self):
|
||||
"""Test that extract_clarification_request returns None when disabled."""
|
||||
result = extract_clarification_request(
|
||||
agent_output={"text": "test output"},
|
||||
enable_clarification=False,
|
||||
)
|
||||
assert result is None
|
||||
|
||||
def test_extract_clarification_request_when_enabled(self):
|
||||
"""Test that extract_clarification_request returns None when enabled (placeholder)."""
|
||||
# Currently returns None as placeholder for future implementation
|
||||
result = extract_clarification_request(
|
||||
agent_output={"text": "test output"},
|
||||
enable_clarification=True,
|
||||
)
|
||||
assert result is None
|
||||
|
||||
def test_agent_node_data_with_clarification_field(self):
|
||||
"""Test that AgentNodeData properly stores enable_human_clarification."""
|
||||
node_data = AgentNodeData(
|
||||
id="test_node",
|
||||
type=NodeType.AGENT,
|
||||
agent_strategy_provider_name="test_provider",
|
||||
agent_strategy_name="test_strategy",
|
||||
agent_strategy_label="Test Strategy",
|
||||
agent_parameters={},
|
||||
enable_human_clarification=True,
|
||||
)
|
||||
assert node_data.enable_human_clarification is True
|
||||
|
||||
node_data_disabled = AgentNodeData(
|
||||
id="test_node",
|
||||
type=NodeType.AGENT,
|
||||
agent_strategy_provider_name="test_provider",
|
||||
agent_strategy_name="test_strategy",
|
||||
agent_strategy_label="Test Strategy",
|
||||
agent_parameters={},
|
||||
enable_human_clarification=False,
|
||||
)
|
||||
assert node_data_disabled.enable_human_clarification is False
|
||||
@ -10,6 +10,7 @@ import { isSupportMCP } from '@/utils/plugin-version-feature'
|
||||
import { useStore } from '../../store'
|
||||
import { AgentStrategy } from '../_base/components/agent-strategy'
|
||||
import Field from '../_base/components/field'
|
||||
import FormInputBoolean from '../_base/components/form-input-boolean'
|
||||
import { MCPToolAvailabilityProvider } from '../_base/components/mcp-tool-availability'
|
||||
import MemoryConfig from '../_base/components/memory-config'
|
||||
import OutputVars, { VarItem } from '../_base/components/output-vars'
|
||||
@ -101,6 +102,22 @@ const AgentPanel: FC<NodePanelProps<AgentNodeType>> = (props) => {
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
<Split />
|
||||
<Field
|
||||
title={t('nodes.agent.enableHumanClarification.label', { ns: 'workflow' })}
|
||||
tooltip={t('nodes.agent.enableHumanClarification.tooltip', { ns: 'workflow' })}
|
||||
className="px-0 py-2"
|
||||
>
|
||||
<FormInputBoolean
|
||||
value={inputs.enable_human_clarification ?? false}
|
||||
onChange={(value) => {
|
||||
setInputs({
|
||||
...inputs,
|
||||
enable_human_clarification: value,
|
||||
})
|
||||
}}
|
||||
/>
|
||||
</Field>
|
||||
</div>
|
||||
<div>
|
||||
<OutputVars>
|
||||
|
||||
@ -13,6 +13,7 @@ export type AgentNodeType = CommonNodeType & {
|
||||
memory?: Memory
|
||||
version?: string
|
||||
tool_node_version?: string
|
||||
enable_human_clarification?: boolean
|
||||
}
|
||||
|
||||
export enum AgentFeature {
|
||||
|
||||
@ -373,6 +373,8 @@
|
||||
"nodes.agent.toolbox": "toolbox",
|
||||
"nodes.agent.tools": "Tools",
|
||||
"nodes.agent.unsupportedStrategy": "Unsupported strategy",
|
||||
"nodes.agent.enableHumanClarification.label": "Enable Human Clarification",
|
||||
"nodes.agent.enableHumanClarification.tooltip": "Allow human intervention to clarify agent reasoning during execution",
|
||||
"nodes.answer.answer": "Answer",
|
||||
"nodes.answer.outputVars": "Output Variables",
|
||||
"nodes.assigner.append": "Append",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user