mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
refactor(dify-builder): drop the resource conflict policy
The resource-recommendation step made the user pick a "conflict policy" that never decided anything. Remove it end to end: the ConflictPolicyOption card option, ResourceSelectCard's conflict_policy_options field, the third bind_resources() parameter across the port/placeholder/LLM-agent implementations, and the dead conflict_policy field on the (unused) ResourcesPayload contract type. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
583f7fa55f
commit
e8b14b50ff
13 files changed
+24
-48
No files matched your search
@@ -394,15 +394,6 @@ class SessionView:
|
||||
app_revision: AppRevision | None = None
|
||||
|
||||
|
||||
@dataclass
|
||||
class ConflictPolicyOption:
|
||||
"""One selectable conflict-resolution policy in a ``resource_select`` card."""
|
||||
|
||||
id: str
|
||||
label: str
|
||||
recommended: bool = False
|
||||
|
||||
|
||||
@dataclass
|
||||
class PreflightIssue:
|
||||
"""One checklist finding in a ``preflight_context`` card.
|
||||
@@ -592,14 +583,11 @@ class ChallengeCard(_Card):
|
||||
|
||||
@dataclass
|
||||
class ResourceSelectCard(_Card):
|
||||
"""Resource discovery: multi-select ``recommended`` resources +
|
||||
single-select ``conflict_policy_options``.
|
||||
"""
|
||||
"""Resource discovery: multi-select ``recommended`` resources."""
|
||||
|
||||
kind: ClassVar[CardKind] = CardKind.RESOURCE_SELECT
|
||||
|
||||
recommended: list[ResourceOption] = field(default_factory=list)
|
||||
conflict_policy_options: list[ConflictPolicyOption] = field(default_factory=list)
|
||||
|
||||
|
||||
@dataclass
|
||||
@@ -737,7 +725,6 @@ class EditRulesPayload:
|
||||
|
||||
@dataclass
|
||||
class ResourcesPayload:
|
||||
conflict_policy: str
|
||||
resource_ids: list[str] = field(default_factory=list)
|
||||
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ from core.dify_builder.contract import (
|
||||
ChallengeCard,
|
||||
ChangeSetCard,
|
||||
CheckpointCard,
|
||||
ConflictPolicyOption,
|
||||
DecisionItem,
|
||||
ErrorCard,
|
||||
ExecutionProgress,
|
||||
@@ -266,10 +265,6 @@ def handle_initial_plan(env: Env, turn: Turn, s: Session, fc: DifyBuilderContext
|
||||
fc,
|
||||
ResourceSelectCard(
|
||||
recommended=options,
|
||||
conflict_policy_options=[
|
||||
ConflictPolicyOption(id="audited", label="Prefer audited", recommended=True),
|
||||
ConflictPolicyOption(id="ask", label="Ask each time"),
|
||||
],
|
||||
),
|
||||
)
|
||||
if not options:
|
||||
@@ -322,16 +317,12 @@ def handle_resource_recommendation(env: Env, turn: Turn, s: Session, fc: DifyBui
|
||||
fc.checkpoint_seq = fc.next_seq
|
||||
|
||||
resource_ids: list[str] = []
|
||||
conflict_policy = ""
|
||||
if turn.action is not None and isinstance(turn.action.payload, dict):
|
||||
raw_ids = turn.action.payload.get("resource_ids")
|
||||
if isinstance(raw_ids, list):
|
||||
resource_ids = [r for r in raw_ids if isinstance(r, str)]
|
||||
cp = turn.action.payload.get("conflict_policy")
|
||||
if isinstance(cp, str):
|
||||
conflict_policy = cp
|
||||
fc.resource_selection = {"resource_ids": resource_ids, "conflict_policy": conflict_policy}
|
||||
fc.plan_items = env.agent.bind_resources(list(fc.plan_items), resource_ids, conflict_policy)
|
||||
fc.resource_selection = {"resource_ids": resource_ids}
|
||||
fc.plan_items = env.agent.bind_resources(list(fc.plan_items), resource_ids)
|
||||
fc.plan_version_tag = "v2"
|
||||
|
||||
progress.activate("build-create-checkpoint")
|
||||
|
||||
@@ -127,7 +127,7 @@ class PlaceholderAgent:
|
||||
)
|
||||
]
|
||||
|
||||
def bind_resources(self, plan_items: list[str], resource_ids: list[str], conflict_policy: str) -> list[str]:
|
||||
def bind_resources(self, plan_items: list[str], resource_ids: list[str]) -> list[str]:
|
||||
return [
|
||||
"Ingest source documents",
|
||||
"Retrieve from Company Knowledge Base",
|
||||
|
||||
@@ -85,7 +85,7 @@ class DifyBuilderAgent(Protocol):
|
||||
|
||||
def discover_resources(self, plan_items: list[str]) -> list[ResourceOption]: ...
|
||||
|
||||
def bind_resources(self, plan_items: list[str], resource_ids: list[str], conflict_policy: str) -> list[str]: ...
|
||||
def bind_resources(self, plan_items: list[str], resource_ids: list[str]) -> list[str]: ...
|
||||
|
||||
def build_nodes(self, plan_items: list[str], resource_ids: list[str] | None = None) -> BuildNodesResult: ...
|
||||
|
||||
|
||||
@@ -168,9 +168,7 @@ def discover_resources(
|
||||
]
|
||||
|
||||
|
||||
def bind_resources(
|
||||
model, tenant_id: str, plan_items: list[str], resource_ids: list[str], conflict_policy: str
|
||||
) -> list[str]:
|
||||
def bind_resources(model, tenant_id: str, plan_items: list[str], resource_ids: list[str]) -> list[str]:
|
||||
inv = resources.list_tenant_resources(tenant_id)
|
||||
by_id = {r.id: r for r in (*inv.datasets, *inv.tools, *inv.models)}
|
||||
labels = [by_id[rid].label for rid in resource_ids if rid in by_id]
|
||||
|
||||
@@ -125,8 +125,8 @@ class LlmBuilderAgent:
|
||||
self._reasoning_for("discover-resources"),
|
||||
)
|
||||
|
||||
def bind_resources(self, plan_items, resource_ids, conflict_policy):
|
||||
return build.bind_resources(self.model_or_none(), self._tenant_id, plan_items, resource_ids, conflict_policy)
|
||||
def bind_resources(self, plan_items, resource_ids):
|
||||
return build.bind_resources(self.model_or_none(), self._tenant_id, plan_items, resource_ids)
|
||||
|
||||
def build_nodes(self, plan_items, resource_ids=None):
|
||||
return build.build_nodes(self._tenant_id, self._model_config, plan_items, resource_ids or ())
|
||||
|
||||
@@ -418,7 +418,7 @@ class StubAgent:
|
||||
def discover_resources(self, _plan_items):
|
||||
return []
|
||||
|
||||
def bind_resources(self, _plan_items, _resource_ids, _conflict_policy):
|
||||
def bind_resources(self, _plan_items, _resource_ids):
|
||||
return []
|
||||
|
||||
def build_nodes(self, _plan_items, _resource_ids=None):
|
||||
|
||||
@@ -175,7 +175,7 @@ def test_initial_plan_find_resources_advances_to_resource_recommendation():
|
||||
assert res.next == PcState.BUILD_RESOURCE_RECOMMENDATION
|
||||
rs = next(i for i in res.items if i.kind == "resource_select")
|
||||
assert rs.payload["recommended"][0]["readiness"] == "ready"
|
||||
assert len(rs.payload["conflict_policy_options"]) == 2
|
||||
assert "conflict_policy_options" not in rs.payload
|
||||
|
||||
|
||||
def test_resource_recommendation_confirm_creates_checkpoint_and_plan_v2():
|
||||
@@ -189,7 +189,7 @@ def test_resource_recommendation_confirm_creates_checkpoint_and_plan_v2():
|
||||
turn = Turn(
|
||||
action=Action(
|
||||
kind="confirm_resources",
|
||||
payload={"resource_ids": ["kb-company"], "conflict_policy": "audited"},
|
||||
payload={"resource_ids": ["kb-company"]},
|
||||
base_version=1,
|
||||
),
|
||||
actor=_actor(),
|
||||
@@ -198,7 +198,7 @@ def test_resource_recommendation_confirm_creates_checkpoint_and_plan_v2():
|
||||
|
||||
assert res.next == PcState.BUILD_PLAN_APPROVAL
|
||||
assert res.context.plan_version_tag == "v2"
|
||||
assert res.context.resource_selection == {"resource_ids": ["kb-company"], "conflict_policy": "audited"}
|
||||
assert res.context.resource_selection == {"resource_ids": ["kb-company"]}
|
||||
assert res.context.checkpoint_id
|
||||
assert res.context.last_structure_fingerprint != ""
|
||||
cp, _snap = repo.get_checkpoint(res.context.checkpoint_id)
|
||||
@@ -1010,7 +1010,7 @@ def test_full_build_flow_goal_to_complete():
|
||||
assert out.current_state == PcState.BUILD_RESOURCE_RECOMMENDATION
|
||||
|
||||
# 4) confirm_resources -> build.plan_approval
|
||||
confirm_payload = {"resource_ids": ["kb-company"], "conflict_policy": "audited"}
|
||||
confirm_payload = {"resource_ids": ["kb-company"]}
|
||||
confirm_action = Action(kind="confirm_resources", payload=confirm_payload, base_version=out.version)
|
||||
out = runner.advance(s.id, Turn(action=confirm_action, actor=_actor()))
|
||||
assert out.current_state == PcState.BUILD_PLAN_APPROVAL
|
||||
@@ -1082,7 +1082,7 @@ def test_full_build_flow_keep_draft_reaches_complete_without_publish():
|
||||
reqs_action = Action(kind="submit_requirements", base_version=out.version)
|
||||
out = runner.advance(s.id, Turn(action=reqs_action, actor=_actor()))
|
||||
out = runner.advance(s.id, Turn(action=Action(kind="find_resources", base_version=out.version), actor=_actor()))
|
||||
confirm_payload = {"resource_ids": ["kb-company"], "conflict_policy": "audited"}
|
||||
confirm_payload = {"resource_ids": ["kb-company"]}
|
||||
confirm_action = Action(kind="confirm_resources", payload=confirm_payload, base_version=out.version)
|
||||
out = runner.advance(s.id, Turn(action=confirm_action, actor=_actor()))
|
||||
out = runner.advance(s.id, Turn(action=Action(kind="approve_repair", base_version=out.version), actor=_actor()))
|
||||
@@ -1123,7 +1123,7 @@ def test_review_continue_adjusting_then_reapprove_is_idempotent():
|
||||
reqs_action = Action(kind="submit_requirements", base_version=out.version)
|
||||
out = runner.advance(s.id, Turn(action=reqs_action, actor=_actor()))
|
||||
out = runner.advance(s.id, Turn(action=Action(kind="find_resources", base_version=out.version), actor=_actor()))
|
||||
confirm_payload = {"resource_ids": ["kb-company"], "conflict_policy": "audited"}
|
||||
confirm_payload = {"resource_ids": ["kb-company"]}
|
||||
confirm_action = Action(kind="confirm_resources", payload=confirm_payload, base_version=out.version)
|
||||
out = runner.advance(s.id, Turn(action=confirm_action, actor=_actor()))
|
||||
|
||||
@@ -1263,7 +1263,7 @@ def test_execution_revert_then_retry_after_revert_reapprove_is_idempotent():
|
||||
s.id, Turn(action=Action(kind="submit_requirements", base_version=out.version), actor=_actor())
|
||||
)
|
||||
out = runner.advance(s.id, Turn(action=Action(kind="find_resources", base_version=out.version), actor=_actor()))
|
||||
confirm_payload = {"resource_ids": ["kb-company"], "conflict_policy": "audited"}
|
||||
confirm_payload = {"resource_ids": ["kb-company"]}
|
||||
out = runner.advance(
|
||||
s.id,
|
||||
Turn(
|
||||
|
||||
@@ -132,7 +132,7 @@ def test_propose_plan_v1_and_bind_resources_return_ordered_strings():
|
||||
v1 = a.propose_plan_v1({"currency": "USD"})
|
||||
assert v1
|
||||
assert all(isinstance(x, str) for x in v1)
|
||||
v2 = a.bind_resources(v1, ["kb-company"], "audited")
|
||||
v2 = a.bind_resources(v1, ["kb-company"])
|
||||
assert v2
|
||||
assert all(isinstance(x, str) for x in v2)
|
||||
|
||||
|
||||
@@ -125,7 +125,7 @@ class _StubAgent:
|
||||
def discover_resources(self, _plan_items):
|
||||
return []
|
||||
|
||||
def bind_resources(self, _plan_items, _resource_ids, _conflict_policy):
|
||||
def bind_resources(self, _plan_items, _resource_ids):
|
||||
return []
|
||||
|
||||
def build_nodes(self, _plan_items, _resource_ids=None):
|
||||
|
||||
@@ -143,7 +143,7 @@ def test_discover_resources_keeps_only_ids_the_model_actually_picked(monkeypatch
|
||||
def test_bind_resources_names_bound_label(monkeypatch):
|
||||
monkeypatch.setattr(build.resources, "list_tenant_resources", lambda t: resources.TenantResources( # noqa: ARG005
|
||||
models=[], datasets=[resources.ResourceRef(id="kb-1", label="Company KB")], tools=[]))
|
||||
out = build.bind_resources(None, "t1", ["Retrieve knowledge"], ["kb-1"], "audited")
|
||||
out = build.bind_resources(None, "t1", ["Retrieve knowledge"], ["kb-1"])
|
||||
assert any("Company KB" in item for item in out)
|
||||
|
||||
|
||||
|
||||
@@ -61,8 +61,8 @@ def test_remaining_build_methods_thread_model_and_tenant_args(monkeypatch):
|
||||
seen["discover_resources"] = (model, tenant_id, plan_items)
|
||||
return []
|
||||
|
||||
def mock_bind_resources(model, tenant_id, plan_items, resource_ids, conflict_policy):
|
||||
seen["bind_resources"] = (model, tenant_id, plan_items, resource_ids, conflict_policy)
|
||||
def mock_bind_resources(model, tenant_id, plan_items, resource_ids):
|
||||
seen["bind_resources"] = (model, tenant_id, plan_items, resource_ids)
|
||||
return []
|
||||
|
||||
def mock_build_nodes(tenant_id, model_config, plan_items, resource_ids=()):
|
||||
@@ -89,8 +89,8 @@ def test_remaining_build_methods_thread_model_and_tenant_args(monkeypatch):
|
||||
agent.discover_resources(["step"])
|
||||
assert seen["discover_resources"] == ("MODEL", "t1", ["step"])
|
||||
|
||||
agent.bind_resources(["step"], ["rid"], "audited")
|
||||
assert seen["bind_resources"] == ("MODEL", "t1", ["step"], ["rid"], "audited")
|
||||
agent.bind_resources(["step"], ["rid"])
|
||||
assert seen["bind_resources"] == ("MODEL", "t1", ["step"], ["rid"])
|
||||
|
||||
agent.build_nodes(["step"])
|
||||
assert seen["build_nodes"] == ("t1", model_config, ["step"], ())
|
||||
|
||||
@@ -97,7 +97,7 @@ def test_context_round_trips_build_fields():
|
||||
requirements={"currency": "USD", "prefer_audited": True},
|
||||
plan_items=["Retrieve", "Summarize", "Emit"],
|
||||
plan_version_tag="v2",
|
||||
resource_selection={"resource_ids": ["kb-company"], "conflict_policy": "audited"},
|
||||
resource_selection={"resource_ids": ["kb-company"]},
|
||||
built_node_ids=["start", "llm", "end"],
|
||||
)
|
||||
out = context_from_dict(context_to_dict(fc))
|
||||
|
||||
Reference in new issue
Block a user