Oversized plain-text tool results now spill to a session-scoped file and return a bounded preview plus the spill path, so a verbose result stays readable via `read` without consuming the next model request in full. - dsh-spill: minimal SpillFiles seam (saveText → session-scoped SpillPath) - dsh-spill-local: private 0700 session dirs, traversal-safe names, exclusive owner-only writes - dsh-spill-policy: tools/post-execute transformer; no-op unless maxInlineBytes is set; skips read; best-effort on save failure (never turns a success into an isError) web_fetch is the showcase — no tool-specific spill code. The coding-agent example loads the stack so its keyless Loader smoke guards the namespace-plugin export shape. Snapshot gap for a transcript-visible web_fetch spill is recorded in the RFC's Consequences (ACP replay is keyless and cannot hit the web).
2.5 KiB
@deepseek-ai/dsh-spill-policy
The tool-result spill policy: a tools/post-execute transformer that keeps oversized plain-text tool results out of the model's context. When a final result exceeds maxInlineBytes, it saves the FULL text to a session-scoped spill file via ctx.spillFiles and replaces the model-facing result with a bounded head/tail preview plus the spill path — the model reads the complete result later with the existing read tool.
This plugin registers no service and owns no storage or preview mechanics: preview is @deepseek-ai/dsh-retention (TextRetainer), storage is ctx.spillFiles. It only decides WHEN to spill and composes the notice.
Config
| Key | Default | Meaning |
|---|---|---|
maxInlineBytes |
(omitted) | Model-facing context cap for a plain-text result, in UTF-8 bytes. Omitted disables the policy entirely (the plugin registers nothing). When set, a larger result is spilled and replaced with a preview derived from the same budget (head/tail split). |
Behavior
-
Let the tool run (delegates via
next(), so it bounds whatever a downstream hook accepted). -
Skip
read(avoids aread → spill file → read againloop) and any non-acceptdecision (ablock's corrective feedback passes through). -
Flatten the accepted content only when it is plain text (all
textblocks); a result with any non-text block is left untouched. -
If its UTF-8 size is
≤ maxInlineBytes, leave it unchanged. -
Otherwise save the full text and replace the result with a preview + this notice:
<retained head/tail preview> (Omitted N bytes. Full formatted result saved to: /…/session-…/…-web_fetch.txt. Use read with offset/limit to inspect it.)
Best-effort: no session owner, no ctx.spillFiles backend, or a saveText rejection ⇒ the policy logs a warning and returns the original result. A spill failure never turns a successful call into an isError or hides the inline result.
Scope
The policy sees only the FINAL formatted tool result — not a tool's internal resource. If a provider already truncated (e.g. web-fetch-local.maxBodyChars), the spill file holds the full formatted result the tool returned, not the full original source. Provider/resource caps stay mandatory and separate. Tool-owned early spill (bash streams, subagent rollouts) is future work — see the tool output spill RFC.