mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Machine-produced by `pnpm run rescope-vendor --apply` plus the regeneration it prints: `pnpm install` for the lockfile, `pnpm run gen-third-party-notices`, `verify-translation-pairing --write` for the touched bilingual pairs, `gen-doc-graphs`, and one typert snapshot whose ids embed character offsets. `pnpm run rescope-vendor --check` verifies the result. Renames nine vendored packages (cordis, cosmokit, schemastery and the six @cordisjs plugins) and every reference that resolves them: manifest names and dependency keys, module specifiers including declare-module merges, cordis.yml plugin names, tsconfig paths, every Markdown fence, and `docs/` prose. Directory names, upstream versions, and dependency ranges are unchanged, so vendor/README.md still reads as an upstream snapshot; its manifest table gains an upstream-name column so THIRD_PARTY_NOTICES keeps MIT attribution pointed at each fork's origin. The tutorial tier follows the rename end to end: its yaml fences named plugins the Loader can no longer resolve, its `ts ignore-check` fences disagreed with the compiled fences beside them, and its prose quoted both. The contracts that told readers to keep upstream names — the root convention and the vendoring cookbook's tree comment and manifest invariant — now say to rescope instead. Two rules read `@deepseek-ai/` as "another workspace plugin": the client bundle purity gate now names the vendored libraries a browser bundle inlines, and the files where a bare `cordis` is an agent-preset id keep that product data.
63 lines
4.0 KiB
Markdown
63 lines
4.0 KiB
Markdown
# @deepseek-ai/dsh-compact-tool-result-prune
|
|
|
|
English | [中文](README.zh.md)
|
|
|
|
The replay-safe model-free pruning service (`ctx.toolResultPrune`). It rewrites over-budget `tool/result` surface nodes to a bounded head, a fixed omission marker, and a bounded tail while retaining the full original event in the append-only session log.
|
|
|
|
This is a concrete companion to [`dsh-compact-basic`](../compact-basic/README.md), not a compaction backend or model-facing tool. Compact-basic reads it through optional `ctx.get('toolResultPrune')`, so either package remains independently composable.
|
|
|
|
## Service API
|
|
|
|
`pruneSession(session)` scans one stable snapshot of the current surface. Every over-budget tool result is replaced by one newly appended `tool/result` carrying `{ surfaceOp: { op: 'replace', start: originalSeq, end: originalSeq }, sourceEventSeqs: [originalSeq] }`. The replacement spreads the complete original data and changes only `content`, preserving `turn`, `step`, `callId`, error fields, `meta`, and later data additions. The original event remains available for persistence, replay, and exact-log inspection.
|
|
|
|
The method throws synchronously when the session rejects a replacement. Replacements committed earlier in the pass remain durable.
|
|
|
|
`measureContent(blocks)` counts Unicode code points in `text` blocks. `pruneContent(blocks)` returns the bounded replacement or `null` when content is already within the threshold. Non-text blocks are retained at their original relative positions; text slicing never splits a UTF-16 surrogate pair, though it can split a multi-code-point grapheme cluster.
|
|
|
|
Every emitted result has exactly the configured head budget, fixed marker, and tail budget in text code points, is no larger than `thresholdChars`, and is strictly smaller than the triggering input. A second pass therefore emits no replacement.
|
|
|
|
## Config
|
|
|
|
Unrecognized keys fail at plugin construction. Resolved config is detached and deeply immutable.
|
|
|
|
| Key | Required | Meaning |
|
|
|---|---|---|
|
|
| `thresholdChars` | no (default `8192`) | Prune when combined text exceeds this many Unicode code points. |
|
|
| `headChars` | no (default `4096`) | Leading Unicode code points retained. |
|
|
| `tailChars` | no (default `1024`) | Trailing Unicode code points retained. |
|
|
|
|
All values are integers; the threshold is positive and head/tail are non-negative. `headChars + marker + tailChars` must fit within `thresholdChars`, so a valid configuration can prune every over-budget result without growth or repeated rewriting.
|
|
|
|
## Usage
|
|
|
|
```ts
|
|
import type { Context } from '@deepseek-ai/cordis'
|
|
import ToolResultPruneService from '@deepseek-ai/dsh-compact-tool-result-prune'
|
|
|
|
export function apply(ctx: Context): void {
|
|
ctx.plugin(ToolResultPruneService)
|
|
}
|
|
```
|
|
|
|
## Model Experience
|
|
|
|
### Pruned tool result
|
|
|
|
#### What the model sees
|
|
|
|
Once a compaction trigger qualifies, future requests see the retained head, `\n\n[... tool result middle pruned ...]\n\n`, and retained tail in place of the removed text. Rich blocks keep their order. The model does not see a second copy of the original.
|
|
|
|
#### Token effect
|
|
|
|
Each rewritten tool result has at most `thresholdChars` text code points. Pruning itself makes no model call; compact-basic skips summarization when the remeasured request falls below pressure, otherwise the summarizer reads the pruned surface.
|
|
|
|
#### KV Cache effect
|
|
|
|
Replacing an earlier result invalidates reuse from the first changed token. The pruned prefix is eligible for reuse while its route, envelope, and preceding history remain identical.
|
|
|
|
## Known Limitations and Deferred Work
|
|
|
|
- **Character budgets are not token budgets** — provider token density varies, so `ctx.tokenMeter` remains the authority for deciding whether pruning relieved request pressure.
|
|
- **Pruning is syntactic** — it retains the beginning and end without interpreting which middle lines are semantically important.
|
|
- **Grapheme clusters can split** — code-point slicing protects surrogate pairs but does not perform locale-aware grapheme segmentation.
|