mirror of
https://github.com/bytedance/deer-flow.git
synced 2026-06-10 17:35:57 +00:00
* fix(#3189): prevent write_file streaming timeout on long reports Adds a layered defense against StreamChunkTimeoutError caused by oversized single-shot write_file tool calls: - factory: default stream_chunk_timeout to 240s for OpenAI-compatible clients (overridable via ModelConfig.stream_chunk_timeout in config.yaml) - sandbox/tools: server-side 80 KB length guard on non-append write_file calls (configurable via DEERFLOW_WRITE_FILE_MAX_BYTES env var, 0 disables); rejects oversized payloads with a structured error pointing the model at str_replace or append=True - middleware: classify StreamChunkTimeoutError as transient but cap retries at 1 via per-exception _RETRY_BUDGET_OVERRIDES (same-payload retry on a chunk-gap timeout buffers the same way upstream; full 3-attempt loop would stack 6-12 min of dead air) - middleware: surface an actionable user-facing message for stream-drop exceptions instead of leaking the raw langchain stack - prompts: add a routing-style File Editing Workflow hint to both lead_agent and general_purpose subagent prompts, pointing the model at str_replace for incremental edits (mirrors Claude Code's Edit / Codex's apply_patch) - tests: behavioural coverage for size guard, retry budget override, stream-drop user message, factory default injection Refs #3189 * fix(#3189): drop stream_chunk_timeout for non-OpenAI providers Address CR feedback on PR #3195: - factory: pop `stream_chunk_timeout` from kwargs for any model_use_path other than `langchain_openai:ChatOpenAI` instead of returning early. `ModelConfig.stream_chunk_timeout` is part of the shared schema, so a user-supplied value on a non-OpenAI provider would otherwise be forwarded to its constructor and raise `TypeError: unexpected keyword argument`. - factory: rewrite docstring to describe the actual `exclude_none=True` behaviour (explicit null is excluded and falls back to the default) instead of the misleading "None falling out via exclude_none=True keeps its value". - tests: add regression coverage asserting the kwarg is stripped before reaching a non-OpenAI provider's constructor. Refs: bytedance#3189 * fix(#3189): restrict stream-drop user copy to StreamChunkTimeoutError only Per CR on #3195: narrow _STREAM_DROP_EXCEPTIONS to StreamChunkTimeoutError. Generic httpx RemoteProtocolError / ReadError fall back to the standard 'temporarily unavailable' copy, since they routinely fire on transient network blips where the 'split the output' guidance is misleading. Retry/backoff classification is unchanged — both remain transient/retriable. Tests updated to reflect new copy, plus a symmetric regression test for ReadError. --------- Co-authored-by: Willem Jiang <willem.jiang@gmail.com>
This commit is contained in:
@@ -373,3 +373,44 @@ def test_warm_enabled_skills_cache_logs_on_timeout(monkeypatch, caplog):
|
||||
|
||||
assert warmed is False
|
||||
assert "Timed out waiting" in caplog.text
|
||||
|
||||
|
||||
def test_system_prompt_template_contains_file_editing_workflow_rule():
|
||||
"""The File Editing Workflow rule must remain in the system prompt
|
||||
template so the planner picks the right tool (str_replace for edits,
|
||||
write_file + append=True for long new content) and avoids mid-stream
|
||||
chunk-gap timeouts on oversized single-shot writes. See issue #3189
|
||||
/ PR #3195.
|
||||
|
||||
We deliberately do NOT assert on any specific byte / word threshold
|
||||
here — that would re-introduce the docstring-lock-in pattern the
|
||||
reviewers flagged. The numeric cap lives in the server-side guard
|
||||
(see test_write_file_tool_size_guard.py), which is where it belongs.
|
||||
"""
|
||||
template = prompt_module.SYSTEM_PROMPT_TEMPLATE
|
||||
# Section anchor — keeps the rule discoverable in the assembled prompt.
|
||||
assert "File Editing Workflow" in template
|
||||
# Behavioural anchors — if either of these disappears, the model will
|
||||
# silently regress to single-shot write_file calls for long content.
|
||||
assert "str_replace" in template
|
||||
assert "append=True" in template
|
||||
|
||||
|
||||
def test_system_prompt_template_preserves_placeholders():
|
||||
"""Ensure the chunking-rule edit didn't drop any f-string placeholder
|
||||
consumed by apply_prompt_template(). A missing placeholder would
|
||||
crash prompt rendering at runtime.
|
||||
"""
|
||||
template = prompt_module.SYSTEM_PROMPT_TEMPLATE
|
||||
for ph in (
|
||||
"{agent_name}",
|
||||
"{soul}",
|
||||
"{self_update_section}",
|
||||
"{subagent_thinking}",
|
||||
"{skills_section}",
|
||||
"{deferred_tools_section}",
|
||||
"{subagent_section}",
|
||||
"{acp_section}",
|
||||
"{subagent_reminder}",
|
||||
):
|
||||
assert ph in template, f"placeholder {ph} accidentally removed"
|
||||
|
||||
Reference in New Issue
Block a user