mirror of
https://github.com/langgenius/dify.git
synced 2026-07-21 18:58:35 +08:00
feat(agent-v2): resolve Dify core tools in agent runtime runner (#38316)
This commit is contained in:
parent
88864ae086
commit
92618f5e20
@ -38,6 +38,7 @@ from pydantic_ai.tools import DeferredToolRequests, DeferredToolResults
|
||||
from agenton.compositor import CompositorSessionSnapshot, LayerProviderInput
|
||||
from agenton.layers.types import PydanticAITool
|
||||
from dify_agent.layers.ask_human.layer import get_ask_human_layer, validate_ask_human_layer_composition
|
||||
from dify_agent.layers.dify_core_tools.layer import DifyCoreToolsLayer
|
||||
from dify_agent.layers.dify_plugin.llm_layer import DifyPluginLLMLayer
|
||||
from dify_agent.layers.dify_plugin.tools_layer import DifyPluginToolsLayer
|
||||
from dify_agent.layers.knowledge.layer import DifyKnowledgeBaseLayer
|
||||
@ -285,6 +286,8 @@ async def _resolve_run_tools(
|
||||
layer = slot.layer
|
||||
if isinstance(layer, DifyPluginToolsLayer):
|
||||
resolved_tools.extend(await layer.get_tools(http_client=plugin_daemon_http_client))
|
||||
if isinstance(layer, DifyCoreToolsLayer):
|
||||
resolved_tools.extend(await layer.get_tools(http_client=dify_api_http_client))
|
||||
if isinstance(layer, DifyKnowledgeBaseLayer):
|
||||
resolved_tools.extend(await layer.get_tools(http_client=dify_api_http_client))
|
||||
_validate_unique_tool_names(resolved_tools)
|
||||
|
||||
@ -42,6 +42,12 @@ from dify_agent.layers.dify_plugin.configs import (
|
||||
)
|
||||
from dify_agent.layers.dify_plugin.llm_layer import DifyPluginLLMLayer
|
||||
from dify_agent.layers.dify_plugin.tools_layer import DifyPluginToolsLayer
|
||||
from dify_agent.layers.dify_core_tools.configs import (
|
||||
DIFY_CORE_TOOLS_LAYER_TYPE_ID,
|
||||
DifyCoreToolConfig,
|
||||
DifyCoreToolsLayerConfig,
|
||||
)
|
||||
from dify_agent.layers.dify_core_tools.layer import DifyCoreToolsLayer
|
||||
from dify_agent.layers.knowledge.configs import DIFY_KNOWLEDGE_BASE_LAYER_TYPE_ID, DifyKnowledgeBaseLayerConfig
|
||||
from dify_agent.layers.knowledge.layer import DifyKnowledgeBaseLayer
|
||||
from dify_agent.layers.output import DIFY_OUTPUT_LAYER_TYPE_ID, DifyOutputLayerConfig
|
||||
@ -1093,6 +1099,111 @@ def test_runner_passes_dynamic_dify_knowledge_tools_to_agent(monkeypatch: pytest
|
||||
assert [tool.name for tool in seen_tools] == ["knowledge_base_search"]
|
||||
|
||||
|
||||
def test_runner_passes_dynamic_dify_core_tools_to_agent(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
seen_tools: list[Tool[object]] = []
|
||||
|
||||
async def core_tool() -> str:
|
||||
return "core"
|
||||
|
||||
def fake_get_model(_self: DifyPluginLLMLayer, *, http_client: httpx.AsyncClient):
|
||||
assert http_client.is_closed is False
|
||||
return TestModel(custom_output_text="done") # pyright: ignore[reportReturnType]
|
||||
|
||||
async def fake_get_tools(self: DifyCoreToolsLayer, *, http_client: httpx.AsyncClient) -> list[Tool[object]]:
|
||||
assert self.config.tools[0].provider_type == "builtin"
|
||||
assert self.config.tools[0].tool_name == "draft_message"
|
||||
assert http_client.headers.get("X-Test-Client") == "dify-api"
|
||||
return [Tool(core_tool, name="draft_message")]
|
||||
|
||||
class FakeResult:
|
||||
output: str = "done"
|
||||
|
||||
def new_messages(self) -> list[ModelMessage]:
|
||||
return []
|
||||
|
||||
class FakeAgent:
|
||||
async def run(self, *_args: object, **_kwargs: object) -> FakeResult:
|
||||
return FakeResult()
|
||||
|
||||
def fake_create_agent(model: object, *, tools: list[Tool[object]], output_type: object) -> FakeAgent:
|
||||
del model, output_type
|
||||
seen_tools.extend(tools)
|
||||
return FakeAgent()
|
||||
|
||||
monkeypatch.setattr(DifyPluginLLMLayer, "get_model", fake_get_model)
|
||||
monkeypatch.setattr(DifyCoreToolsLayer, "get_tools", fake_get_tools)
|
||||
monkeypatch.setattr("dify_agent.runtime.runner.create_agent", fake_create_agent)
|
||||
|
||||
request = CreateRunRequest(
|
||||
composition=RunComposition(
|
||||
layers=[
|
||||
RunLayerSpec(
|
||||
name="prompt",
|
||||
type="plain.prompt",
|
||||
config=PromptLayerConfig(prefix="system", user="hello"),
|
||||
),
|
||||
RunLayerSpec(
|
||||
name="execution_context",
|
||||
type=DIFY_EXECUTION_CONTEXT_LAYER_TYPE_ID,
|
||||
config=DifyExecutionContextLayerConfig(
|
||||
tenant_id="tenant-1",
|
||||
user_id="user-1",
|
||||
user_from="account",
|
||||
app_id="app-1",
|
||||
agent_mode="workflow_run",
|
||||
invoke_from="service-api",
|
||||
),
|
||||
),
|
||||
RunLayerSpec(
|
||||
name=DIFY_AGENT_MODEL_LAYER_ID,
|
||||
type="dify.plugin.llm",
|
||||
deps={"execution_context": "execution_context"},
|
||||
config=DifyPluginLLMLayerConfig(
|
||||
plugin_id="langgenius/openai",
|
||||
model_provider="openai",
|
||||
model="demo-model",
|
||||
credentials={"api_key": "secret"},
|
||||
),
|
||||
),
|
||||
RunLayerSpec(
|
||||
name="core-tools",
|
||||
type=DIFY_CORE_TOOLS_LAYER_TYPE_ID,
|
||||
deps={"execution_context": "execution_context"},
|
||||
config=DifyCoreToolsLayerConfig(
|
||||
tools=[
|
||||
DifyCoreToolConfig(
|
||||
provider_type="builtin",
|
||||
provider_id="langgenius/dify-gmail/dify-gmail",
|
||||
tool_name="draft_message",
|
||||
credential_id="credential-1",
|
||||
parameters_json_schema={"type": "object", "properties": {}, "required": []},
|
||||
)
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
)
|
||||
)
|
||||
sink = InMemoryRunEventSink()
|
||||
|
||||
async def scenario() -> None:
|
||||
async with (
|
||||
httpx.AsyncClient() as plugin_client,
|
||||
httpx.AsyncClient(headers={"X-Test-Client": "dify-api"}) as dify_api_client,
|
||||
):
|
||||
await AgentRunRunner(
|
||||
sink=sink,
|
||||
request=request,
|
||||
run_id="run-core-tools",
|
||||
plugin_daemon_http_client=plugin_client,
|
||||
dify_api_http_client=dify_api_client,
|
||||
).run()
|
||||
|
||||
asyncio.run(scenario())
|
||||
|
||||
assert [tool.name for tool in seen_tools] == ["draft_message"]
|
||||
|
||||
|
||||
def test_runner_rejects_duplicate_tool_names_across_dynamic_tool_layers(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user