fix(dify-builder): ground model on all model-bearing nodes, carry branch handles, clean test lint

Final consolidated fix wave from whole-branch review of the Real Build +
Edit Cognition slice:

- _ground now overwrites the model dict on ANY create_node whose config
  carries a model dict (llm, question-classifier, parameter-extractor),
  not just "llm", so a drifted/hallucinated provider/name on those other
  node types no longer flows through ungrounded.
- to_intents now carries a generator edge's sourceHandle/targetHandle
  into the connect intent's args (source_handle/target_handle) so
  branching nodes (if-else, question-classifier) wire onto the correct
  port instead of collapsing onto the default handle; edges without
  handles still produce bare {from_node, to_node} args.
- Cleared the 17 ruff errors (PT018/E302/E306/E501) across the slice's
  test files by splitting composite asserts, adding missing blank
  lines, and wrapping long lines -- no assertions weakened, no noqa.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Charles YaoandClaude Opus 4.8 committed 2026-08-29 14:22:19 -07:00
1 parent a07dc0e766
commit cd5fb6bbf0
7 files changed
+130 -18

No files matched your search

+7 -3
View File
@@ -169,14 +169,18 @@ def _ground(intents: list[MutationIntent], mc: ModelConfig, tenant_id: str, plan
if intent.op != "create_node":
continue
config = intent.args.get("config") or {}
if intent.args.get("node_type") == "llm":
if isinstance(config.get("model"), dict):
# Ground ONLY provider+name (the real, configured model); preserve whatever
# mode/completion_params the generator produced -- never fabricate params.
model = dict(config.get("model") or {})
# Applies to ANY node type that carries a model block (llm,
# question-classifier, parameter-extractor, ...), not just "llm" --
# otherwise a drifted/hallucinated model on those node types flows
# through ungrounded.
model = dict(config["model"])
model["provider"] = mc.provider
model["name"] = mc.name
model.setdefault("mode", mode)
config["model"] = model
elif intent.args.get("node_type") == "knowledge-retrieval":
if intent.args.get("node_type") == "knowledge-retrieval":
config["dataset_ids"] = list(matched) # independent copy per node -- never share one list
intent.args["config"] = config
@@ -45,9 +45,16 @@ def to_intents(graph: dict[str, Any]) -> list[MutationIntent]:
src, tgt = edge.get("source"), edge.get("target")
if not src or not tgt:
continue
connects.append(MutationIntent(op="connect", args={
args: dict[str, Any] = {
"from_node": remap.get(str(src), str(src)),
"to_node": remap.get(str(tgt), str(tgt)),
}))
}
source_handle = edge.get("sourceHandle")
if source_handle:
args["source_handle"] = source_handle
target_handle = edge.get("targetHandle")
if target_handle:
args["target_handle"] = target_handle
connects.append(MutationIntent(op="connect", args=args))
return creates + connects