mirror of
https://github.com/langgenius/dify.git
synced 2026-10-04 13:47:55 +08:00
fix(dify-builder): cap the test-result card's rendered output
_terminal_output json.dumps'd a node's outputs with no length limit. Node outputs are only truncated upstream at ~100,000 chars per string, so a report-generating workflow -- the Builder's showcase case -- could push hundreds of KB of JSON into a dify_builder_conversation_items row, the SSE frame, and the localizer walk on every successful build. Cap the rendered output at 2000 chars with a visible truncation marker before it reaches TestResultCard. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
383d6d3624
commit
7ae152c5c2
2 files changed
+35
-2
No files matched your search
@@ -632,17 +632,31 @@ def handle_await_testdata(env: Env, turn: Turn, s: Session, fc: DifyBuilderConte
|
||||
return StepResult(next=PcState.BUILD_TEST_AND_REPAIR, context=fc)
|
||||
|
||||
|
||||
# Node outputs are only truncated upstream at ~100,000 chars per string, so a
|
||||
# report-generating workflow (the Builder's showcase case) can otherwise push
|
||||
# hundreds of KB of JSON into the conversation-item row, the SSE frame, and
|
||||
# the localizer walk on every successful build. The card is a preview, not a
|
||||
# download -- this cap keeps it one.
|
||||
_MAX_TERMINAL_OUTPUT_CHARS = 2000
|
||||
_TERMINAL_OUTPUT_TRUNCATED_MARKER = "\n… (truncated)"
|
||||
|
||||
|
||||
def _terminal_output(per_node: list[NodeOutput]) -> str:
|
||||
"""The last node that produced anything, as readable JSON, or "".
|
||||
|
||||
Deliberately status-agnostic: node status spellings differ by source
|
||||
("success" vs "succeeded"), and a status filter that silently misses is
|
||||
worse than showing the output of a run that ended badly -- showing what
|
||||
ran is the point of the card.
|
||||
ran is the point of the card. Capped at ``_MAX_TERMINAL_OUTPUT_CHARS``
|
||||
(see its comment) -- a big JSON blob is capped with a visible marker
|
||||
rather than silently dropped.
|
||||
"""
|
||||
for node in reversed(per_node):
|
||||
if node.outputs:
|
||||
return json.dumps(node.outputs, ensure_ascii=False, indent=2)
|
||||
rendered = json.dumps(node.outputs, ensure_ascii=False, indent=2)
|
||||
if len(rendered) > _MAX_TERMINAL_OUTPUT_CHARS:
|
||||
return rendered[:_MAX_TERMINAL_OUTPUT_CHARS] + _TERMINAL_OUTPUT_TRUNCATED_MARKER
|
||||
return rendered
|
||||
return ""
|
||||
|
||||
|
||||
|
||||
@@ -600,6 +600,25 @@ def test_a_passing_test_shows_what_the_workflow_produced():
|
||||
assert '"result": "42"' in test_result.payload["output"]
|
||||
|
||||
|
||||
def test_a_passing_test_caps_an_oversized_output_with_a_marker():
|
||||
"""Node outputs are only truncated upstream at ~100,000 chars per string,
|
||||
so an uncapped render (e.g. a report-generating workflow, the Builder's
|
||||
showcase case) could push hundreds of KB of JSON into the card, the SSE
|
||||
frame, and the localizer walk on every successful build. The card must
|
||||
cap the rendered output instead, with a visible truncation marker."""
|
||||
from core.dify_builder.handlers_build import _MAX_TERMINAL_OUTPUT_CHARS, handle_test_and_repair
|
||||
|
||||
env, _ = _new_env() # default FakeDifyPort; verify_pass=True by default
|
||||
env.dify.run_outputs = {"report": "x" * 50_000} # far beyond the cap once JSON-rendered
|
||||
s = _session(entry_mode=EntryMode.BUILD, current_state=PcState.BUILD_TEST_AND_REPAIR)
|
||||
fc = DifyBuilderContext(built_node_ids=["llm"])
|
||||
result = handle_test_and_repair(env, Turn(actor=_actor()), s, fc)
|
||||
test_result = next(i for i in result.items if i.kind == "test_result")
|
||||
output = test_result.payload["output"]
|
||||
assert len(output) < _MAX_TERMINAL_OUTPUT_CHARS + 100 # capped, not the ~50KB payload
|
||||
assert "truncated" in output
|
||||
|
||||
|
||||
def test_a_passing_test_with_no_output_shows_none():
|
||||
"""No output produced -> the card's output is "", not a stale/placeholder
|
||||
value -- a passing test that shows nothing is not evidence of anything,
|
||||
|
||||
Reference in new issue
Block a user