Follow-up to #5833 after an independent review of the merged code.
- A malformed answer (deeply nested JSON raising RecursionError, or a
huge noul integer raising OverflowError outside the try) escaped the
fail-open path, and in the per-message task group it cancelled the
other messages' requests and dropped every flag of that tool call.
Parsing now happens inside the try, which also catches those errors.
- The 16 KiB response cap counted decoded bytes, so a compressed body
could expand far past it first. Requests now ask for identity encoding
and drop encoded responses.
- A plain-HTTP loopback endpoint followed HTTP_PROXY/ALL_PROXY, sending
the bearer key and excerpt to the proxy in cleartext. Such endpoints
now ignore proxy environment variables; HTTPS endpoints keep them.
Tests cover each case, including a real local server behind an
unreachable proxy, and pin previously untested behavior: independent
per-request deadlines, the sync hook without a task store, the >=
threshold and all four named remote tools, warnings for messages that
share a tool-call ID, consumed flags, and scanning past host messages.
The root README no longer says the excerpt is always PII-redacted, and
the example README documents the new limits and that the sync path's
deadline does not cover a stalled DNS lookup.
Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>
* feat(examples): add opt-in fetched-content screening extension
* fix(examples): screen sync and async results through supported middleware hooks
* fix(examples): preserve empty message IDs when applying screening warnings
* fix(examples): include screening policy in assembly identity
* feat(examples): load fetched-content screening through the extension entry
Package the screening example as a plugins: extension instead of an
operator-configured middleware. install() validates the private config
and, once enabled, contributes one TOOL_VISIBLE middleware for lead
agents and subagents. The package imports only deerflow_extension_api.
Extension tool wrappers are observational, so detection and the warning
use two supported contracts: the tool wrapper classifies the visible
result and records flagged tool-call IDs in the run's task store, and
before_model replaces the matching messages of the latest tool step by
ID. The excerpt sent to Jev is now the redacted, sanitized text the
model sees. Runs without a task store send nothing. Unexpected local
errors surface as isolation diagnostics; provider errors fail open.
Tests load the package through load_extensions() and the host isolation
wrapper and run real lead/subagent graphs with a task store bound as the
Gateway worker binds it. The README records what the example exercised
in the extension API and the gaps it found.
* fix(examples): classify each tool message of a screened result on its own
A Command result was classified as one concatenated excerpt and the flag
landed on its first text message, so a benign first result could take the
warning while an injected later result reached the model unmarked.
Each text message now gets its own bounded excerpt and Jev request, for at
most eight messages per tool call. The requests share one client and run
concurrently in a task group, each under its own deadline, so one slow or
failed request cannot hide another message's flag. Every flagged message's
tool-call ID is recorded. The message cap joins the declared policy, and the
README describes the per-message requests and data sharing.
---------
Co-authored-by: Totoro-qaq <279883115+Totoro-qaq@users.noreply.github.com>