mirror of
https://github.com/langgenius/dify.git
synced 2026-09-08 02:43:49 +08:00
fix: fix test failed
This commit is contained in:
parent
58f17aa5a8
commit
f7dc60bf90
@ -48,9 +48,6 @@ from models.agent import (
|
||||
AgentConfigRevisionOperation,
|
||||
AgentConfigSnapshot,
|
||||
AgentKind,
|
||||
AgentRuntimeSession,
|
||||
AgentRuntimeSessionOwnerType,
|
||||
AgentRuntimeSessionStatus,
|
||||
AgentScope,
|
||||
AgentSource,
|
||||
AgentStatus,
|
||||
@ -1062,7 +1059,6 @@ class SkillManagementService:
|
||||
model_config: AgentSoulModelConfig,
|
||||
) -> None:
|
||||
model_changed = False
|
||||
cleaned_runtime_session_count = 0
|
||||
if assistant.active_config_snapshot_id:
|
||||
snapshot = session.get(AgentConfigSnapshot, assistant.active_config_snapshot_id)
|
||||
if snapshot is not None:
|
||||
@ -1094,24 +1090,11 @@ class SkillManagementService:
|
||||
draft_config.model = model_config
|
||||
draft.config_snapshot = draft_config
|
||||
if model_changed:
|
||||
for runtime_session in session.scalars(
|
||||
select(AgentRuntimeSession).where(
|
||||
AgentRuntimeSession.owner_type == AgentRuntimeSessionOwnerType.CONVERSATION,
|
||||
AgentRuntimeSession.tenant_id == assistant.tenant_id,
|
||||
AgentRuntimeSession.app_id == assistant.backing_app_id,
|
||||
AgentRuntimeSession.agent_id == assistant.id,
|
||||
AgentRuntimeSession.status == AgentRuntimeSessionStatus.ACTIVE,
|
||||
)
|
||||
):
|
||||
runtime_session.status = AgentRuntimeSessionStatus.CLEANED
|
||||
runtime_session.cleaned_at = naive_utc_now()
|
||||
cleaned_runtime_session_count += 1
|
||||
logger.info(
|
||||
"skill_assistant_model_synced assistant_id=%s provider=%s model=%s cleaned_runtime_sessions=%s",
|
||||
"skill_assistant_model_synced assistant_id=%s provider=%s model=%s",
|
||||
assistant.id,
|
||||
model_config.model_provider,
|
||||
model_config.model,
|
||||
cleaned_runtime_session_count,
|
||||
)
|
||||
|
||||
def update_metadata(
|
||||
|
||||
@ -33,7 +33,7 @@ def current_user() -> Account:
|
||||
return user
|
||||
|
||||
|
||||
def _skill_detail() -> dict:
|
||||
def _skill_detail() -> dict[str, object]:
|
||||
return {
|
||||
"id": "skill-1",
|
||||
"name": "finance-sop",
|
||||
@ -92,13 +92,14 @@ def test_list_skills_uses_default_pagination_when_query_omits_page_and_limit(app
|
||||
api = WorkspaceSkillsApi()
|
||||
method = unwrap(api.get)
|
||||
service = MagicMock()
|
||||
service.list_skills.return_value = {
|
||||
list_response: dict[str, object] = {
|
||||
"data": [],
|
||||
"has_more": False,
|
||||
"limit": 20,
|
||||
"page": 1,
|
||||
"total": 0,
|
||||
}
|
||||
service.list_skills.return_value = list_response
|
||||
|
||||
with (
|
||||
app.test_request_context("/?keyword=finance&tag=ops&tag=", method="GET"),
|
||||
@ -236,7 +237,7 @@ def test_get_skill_version_returns_version_detail(app: Flask) -> None:
|
||||
api = WorkspaceSkillVersionApi()
|
||||
method = unwrap(api.get)
|
||||
service = MagicMock()
|
||||
service.get_version.return_value = {
|
||||
version_response: dict[str, object] = {
|
||||
"id": "version-1",
|
||||
"skill_id": "skill-1",
|
||||
"version_number": 1,
|
||||
@ -262,6 +263,7 @@ def test_get_skill_version_returns_version_detail(app: Flask) -> None:
|
||||
}
|
||||
],
|
||||
}
|
||||
service.get_version.return_value = version_response
|
||||
|
||||
with (
|
||||
app.test_request_context("/", method="GET"),
|
||||
@ -341,11 +343,8 @@ def test_skill_assistant_runs_agent_app_stream(app: Flask, current_user: Account
|
||||
api = WorkspaceSkillAssistMessageApi()
|
||||
method = unwrap(api.post)
|
||||
service = MagicMock()
|
||||
assistant_app = MagicMock()
|
||||
assistant_app.id = "assistant-app-1"
|
||||
service.get_or_create_assistant_app.return_value = (assistant_app, "<skill_draft>draft</skill_draft>")
|
||||
app_model = MagicMock()
|
||||
app_response = MagicMock()
|
||||
action_stream = MagicMock()
|
||||
service.create_assistant_action_stream.return_value = action_stream
|
||||
compact_response = MagicMock()
|
||||
|
||||
with (
|
||||
@ -368,19 +367,18 @@ def test_skill_assistant_runs_agent_app_stream(app: Flask, current_user: Account
|
||||
),
|
||||
patch("controllers.console.workspace.skills.SkillManagementService", return_value=service),
|
||||
patch(
|
||||
"controllers.console.workspace.skills.db.session",
|
||||
return_value=MagicMock(get=MagicMock(return_value=app_model)),
|
||||
),
|
||||
patch("controllers.console.workspace.skills.AppGenerateService.generate", return_value=app_response),
|
||||
patch("controllers.console.workspace.skills.helper.compact_generate_response", return_value=compact_response),
|
||||
"controllers.console.workspace.skills.helper.compact_generate_response",
|
||||
return_value=compact_response,
|
||||
) as compact_generate_response,
|
||||
):
|
||||
response = method(api, "tenant-1", current_user, "skill-1")
|
||||
|
||||
assert response is compact_response
|
||||
service.get_or_create_assistant_app.assert_called_once_with(
|
||||
service.create_assistant_action_stream.assert_called_once_with(
|
||||
tenant_id="tenant-1",
|
||||
skill_id="skill-1",
|
||||
user_id="user-1",
|
||||
message="Create an approval checklist.",
|
||||
attachments=[
|
||||
SkillAssistAttachmentPayload(
|
||||
tool_file_id="tool-file-1",
|
||||
@ -389,6 +387,7 @@ def test_skill_assistant_runs_agent_app_stream(app: Flask, current_user: Account
|
||||
size=128,
|
||||
)
|
||||
],
|
||||
message="Create an approval checklist.",
|
||||
model_payload=None,
|
||||
target_path=None,
|
||||
)
|
||||
compact_generate_response.assert_called_once_with(action_stream)
|
||||
|
||||
@ -34,7 +34,7 @@ from models.agent_config_entities import AgentSoulConfig
|
||||
def _no_runtime_agent_skills(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(
|
||||
"core.app.apps.agent_app.runtime_request_builder.load_runtime_agent_skill_configs",
|
||||
lambda *, tenant_id, agent_id: [],
|
||||
lambda **_kwargs: [],
|
||||
)
|
||||
|
||||
|
||||
@ -523,7 +523,7 @@ class TestAgentAppConfigLayer:
|
||||
def test_config_layer_includes_bound_workspace_skills(self, monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(
|
||||
"core.app.apps.agent_app.runtime_request_builder.load_runtime_agent_skill_configs",
|
||||
lambda *, tenant_id, agent_id: [
|
||||
lambda **_kwargs: [
|
||||
DifyConfigSkillConfig(
|
||||
name="workspace-skill",
|
||||
description="Bound workspace skill.",
|
||||
|
||||
@ -45,7 +45,7 @@ from models.agent_config_entities import (
|
||||
def _no_runtime_agent_skills(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(
|
||||
"core.workflow.nodes.agent_v2.runtime_request_builder.load_runtime_agent_skill_configs",
|
||||
lambda *, tenant_id, agent_id: [],
|
||||
lambda **_kwargs: [],
|
||||
)
|
||||
|
||||
|
||||
@ -1541,7 +1541,7 @@ def test_workflow_run_request_contains_config_layer():
|
||||
def test_workflow_run_request_includes_bound_workspace_skills(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setattr(
|
||||
"core.workflow.nodes.agent_v2.runtime_request_builder.load_runtime_agent_skill_configs",
|
||||
lambda *, tenant_id, agent_id: [
|
||||
lambda **_kwargs: [
|
||||
DifyConfigSkillConfig(
|
||||
name="workspace-skill",
|
||||
description="Bound workspace skill.",
|
||||
|
||||
@ -7,13 +7,15 @@ import json
|
||||
import zipfile
|
||||
from collections.abc import Generator
|
||||
from types import SimpleNamespace
|
||||
from typing import cast, override
|
||||
from unittest.mock import patch
|
||||
from uuid import uuid4
|
||||
|
||||
import pytest
|
||||
from sqlalchemy import delete, func, select
|
||||
from sqlalchemy import Table, delete, func, select
|
||||
|
||||
from core.db.session_factory import session_factory
|
||||
from core.tools.tool_file_manager import ToolFileManager
|
||||
from models.account import Account
|
||||
from models.agent import (
|
||||
Agent,
|
||||
@ -22,9 +24,6 @@ from models.agent import (
|
||||
AgentConfigRevision,
|
||||
AgentConfigSnapshot,
|
||||
AgentKind,
|
||||
AgentRuntimeSession,
|
||||
AgentRuntimeSessionOwnerType,
|
||||
AgentRuntimeSessionStatus,
|
||||
AgentScope,
|
||||
AgentSource,
|
||||
AgentStatus,
|
||||
@ -62,27 +61,33 @@ AGENT = "22222222-2222-2222-2222-222222222222"
|
||||
USER = "33333333-3333-3333-3333-333333333333"
|
||||
|
||||
|
||||
class _FakeToolFileManager:
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
class _FakeToolFileManager(ToolFileManager):
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
tool_file = ToolFile(
|
||||
user_id=kwargs["user_id"],
|
||||
tenant_id=kwargs["tenant_id"],
|
||||
conversation_id=kwargs["conversation_id"],
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_key=f"tools/{uuid4().hex}",
|
||||
mimetype=kwargs["mimetype"],
|
||||
mimetype=mimetype,
|
||||
original_url=None,
|
||||
name=kwargs.get("filename") or "file.bin",
|
||||
size=len(kwargs["file_binary"]),
|
||||
name=filename or "file.bin",
|
||||
size=len(file_binary),
|
||||
)
|
||||
tool_file.id = str(uuid4())
|
||||
with session_factory.create_session() as session:
|
||||
session.add(tool_file)
|
||||
session.commit()
|
||||
return SimpleNamespace(
|
||||
id=tool_file.id,
|
||||
size=len(kwargs["file_binary"]),
|
||||
mimetype=kwargs["mimetype"],
|
||||
)
|
||||
return tool_file
|
||||
|
||||
|
||||
@pytest.fixture(autouse=True)
|
||||
@ -95,7 +100,6 @@ def _tables() -> Generator[None, None, None]:
|
||||
AgentConfigSnapshot,
|
||||
AgentConfigDraft,
|
||||
AgentConfigRevision,
|
||||
AgentRuntimeSession,
|
||||
ToolFile,
|
||||
Tag,
|
||||
TagBinding,
|
||||
@ -106,7 +110,8 @@ def _tables() -> Generator[None, None, None]:
|
||||
WorkflowAgentNodeBinding,
|
||||
)
|
||||
for model in models:
|
||||
model.__table__.create(bind=engine, checkfirst=True)
|
||||
table = cast(Table, model.__table__)
|
||||
table.create(bind=engine, checkfirst=True)
|
||||
_seed_agent()
|
||||
yield
|
||||
with session_factory.create_session() as session:
|
||||
@ -455,17 +460,6 @@ def test_sync_assistant_model_config_updates_debugger_draft() -> None:
|
||||
updated_by=USER,
|
||||
)
|
||||
session.add(draft)
|
||||
runtime_session = AgentRuntimeSession(
|
||||
tenant_id=TENANT,
|
||||
app_id=agent.backing_app_id,
|
||||
owner_type=AgentRuntimeSessionOwnerType.CONVERSATION,
|
||||
agent_id=agent.id,
|
||||
agent_config_snapshot_id=draft.id,
|
||||
conversation_id=str(uuid4()),
|
||||
session_snapshot="{}",
|
||||
status=AgentRuntimeSessionStatus.ACTIVE,
|
||||
)
|
||||
session.add(runtime_session)
|
||||
session.flush()
|
||||
|
||||
SkillManagementService._sync_assistant_model_config(
|
||||
@ -479,7 +473,6 @@ def test_sync_assistant_model_config_updates_debugger_draft() -> None:
|
||||
assert updated_draft.model is not None
|
||||
assert updated_draft.model.model_provider == "langgenius/tongyi/tongyi"
|
||||
assert updated_draft.model.model == "qwen3.7-plus"
|
||||
assert runtime_session.status == AgentRuntimeSessionStatus.CLEANED
|
||||
|
||||
|
||||
def test_sync_assistant_model_config_updates_draft_without_active_snapshot() -> None:
|
||||
@ -1148,9 +1141,26 @@ def test_publish_archive_contains_synced_skill_md() -> None:
|
||||
captured: dict[str, bytes] = {}
|
||||
|
||||
class CapturingToolFileManager(_FakeToolFileManager):
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
captured["archive"] = kwargs["file_binary"]
|
||||
return super().create_file_by_raw(**kwargs)
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
captured["archive"] = file_binary
|
||||
return super().create_file_by_raw(
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_binary=file_binary,
|
||||
mimetype=mimetype,
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
service = SkillManagementService(tool_file_manager=CapturingToolFileManager())
|
||||
created = service.create_skill(
|
||||
@ -1173,9 +1183,26 @@ def test_list_versions_includes_publisher_name_and_version_detail_files() -> Non
|
||||
captured: dict[str, bytes] = {}
|
||||
|
||||
class CapturingToolFileManager(_FakeToolFileManager):
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
captured["archive"] = kwargs["file_binary"]
|
||||
return super().create_file_by_raw(**kwargs)
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
captured["archive"] = file_binary
|
||||
return super().create_file_by_raw(
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_binary=file_binary,
|
||||
mimetype=mimetype,
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
service = SkillManagementService(tool_file_manager=CapturingToolFileManager())
|
||||
created = service.create_skill(
|
||||
@ -1607,9 +1634,26 @@ def test_duplicate_skill_copies_latest_published_content_without_history() -> No
|
||||
captured: dict[str, bytes] = {}
|
||||
|
||||
class CapturingToolFileManager(_FakeToolFileManager):
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
captured["archive"] = kwargs["file_binary"]
|
||||
return super().create_file_by_raw(**kwargs)
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
captured["archive"] = file_binary
|
||||
return super().create_file_by_raw(
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_binary=file_binary,
|
||||
mimetype=mimetype,
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
service = SkillManagementService(tool_file_manager=CapturingToolFileManager())
|
||||
created = service.create_skill(
|
||||
@ -1834,9 +1878,26 @@ def test_publish_and_export_include_binary_tool_files() -> None:
|
||||
captured: dict[str, bytes] = {}
|
||||
|
||||
class CapturingToolFileManager(_FakeToolFileManager):
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
captured["archive"] = kwargs["file_binary"]
|
||||
return super().create_file_by_raw(**kwargs)
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
captured["archive"] = file_binary
|
||||
return super().create_file_by_raw(
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_binary=file_binary,
|
||||
mimetype=mimetype,
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
service = SkillManagementService(tool_file_manager=CapturingToolFileManager())
|
||||
created = service.create_skill(tenant_id=TENANT, user_id=USER, payload=SkillCreatePayload(name="finance-sop"))
|
||||
@ -1883,9 +1944,26 @@ def test_restore_version_replaces_draft_and_creates_new_published_version() -> N
|
||||
captured: list[bytes] = []
|
||||
|
||||
class CapturingToolFileManager(_FakeToolFileManager):
|
||||
def create_file_by_raw(self, **kwargs):
|
||||
captured.append(kwargs["file_binary"])
|
||||
return super().create_file_by_raw(**kwargs)
|
||||
@override
|
||||
def create_file_by_raw(
|
||||
self,
|
||||
*,
|
||||
user_id: str,
|
||||
tenant_id: str,
|
||||
conversation_id: str | None,
|
||||
file_binary: bytes,
|
||||
mimetype: str,
|
||||
filename: str | None = None,
|
||||
) -> ToolFile:
|
||||
captured.append(file_binary)
|
||||
return super().create_file_by_raw(
|
||||
user_id=user_id,
|
||||
tenant_id=tenant_id,
|
||||
conversation_id=conversation_id,
|
||||
file_binary=file_binary,
|
||||
mimetype=mimetype,
|
||||
filename=filename,
|
||||
)
|
||||
|
||||
service = SkillManagementService(tool_file_manager=CapturingToolFileManager())
|
||||
created = service.create_skill(tenant_id=TENANT, user_id=USER, payload=SkillCreatePayload(name="finance-sop"))
|
||||
|
||||
Loading…
Reference in New Issue
Block a user