Files
deepseek-harness/docs/core-data-structures/spill.md
T

3.6 KiB

Spill Storage

The spill storage seam — a capability seam that persists a tool's oversized text and returns a model-facing locator plus retrieval guidance, split across packages: interface (dsh-spill, ctx.spillStore), implementation (dsh-spill-local, private session-scoped files on the host filesystem), and consumer (dsh-spill-policy, the tools/post-execute policy). Spill is one optional capability, not part of the agent-loop spine — so its vocabulary lives here, not in core.md. Preview mechanics stay in dsh-retention; this seam only saves the final text the policy hands it.

Source: packages/spill/spill/src/types.ts

The save request

saveText is the whole seam: persist content verbatim, return an opaque locator, a backend-supplied retrieval hint, and the exact byte count. The request carries the save-time storage namespace (owner), WHERE it came from (source, descriptive provenance for naming and inspection — not access control), and a suggestedName the backend may use as a naming hint (it is not a path).

interface SaveTextSpill {
  owner: SpillOwner
  source: SpillSource
  suggestedName: string
  content: string
}
interface SpillOwner {
  sessionId: SessionId
}

SpillOwner.sessionId is the save-time storage namespace. Forked sessions inherit existing spill locators from the seeded log; those artifacts are not copied or re-owned, and spills produced after the fork use the child session id. A retention-period cleanup may expire old locators with other old session artifacts; the spill seam does not define a per-session cleanup policy.

interface SpillSource {
  toolName: string
  callId: CallId
  label: string
}

The result

interface SpillRef {
  locator: SpillLocator
  bytes: number
  retrievalHint: string
}

SpillLocator is a branded model-facing handle returned by the backend. The local backend renders it as a filesystem path; a remote or database backend can render a URI, key, or command token. Consumers treat it as opaque and render it with retrievalHint instead of assuming read is always the right retrieval mechanism.

type SpillLocator = Branded<'SpillLocator'>

The service

SpillStore (ctx.spillStore, defined in packages/spill/spill/src/index.ts) is a one-method abstract service: saveText(input) → Promise<SpillRef>. It persists the FULL content and REJECTS on a real storage failure (permissions, ENOSPC, backend unavailable). The seam owns storage only: no retention policy, no tool-result replacement, no retrieval/search API.

The local backend (dsh-spill-local) writes under <root>/session-<hash>/<random>-<safeName> — a configured or lazily-created private (0700) root, a sha256(sessionId) session subdir, and an exclusive owner-only (open(path, 'wx', 0o600)) write so a planted symlink cannot redirect it. Its locator is the local path and its retrievalHint tells the model to use read or grep on that path. The policy consumer (dsh-spill-policy) replaces an over-maxInlineBytes plain-text final result with a retention-library head/tail preview plus the spill reference, best-effort: a save failure keeps the original inline result rather than turning a successful call into an isError.