mirror of
https://github.com/deepseek-ai/deepseek-harness
synced 2026-08-15 21:04:50 +00:00
Merge origin/master into codex/truncated-design
This commit is contained in:
@@ -31,3 +31,16 @@ This plugin registers **no service** and owns no storage or preview mechanics: p
|
||||
## 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 artifact 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](../../../docs/rfc/implemented/architecture/2026-07-08-tool-output-spill-files.md).
|
||||
|
||||
## Model Experience
|
||||
|
||||
### Oversized plain-text result
|
||||
|
||||
**What the model sees**: Results at or below `maxInlineBytes`, `read` results, blocked decisions, and results containing non-text blocks are unchanged. An oversized plain-text result becomes a bounded head/tail preview followed by `(Omitted <bytes> bytes. Full formatted result stored at: <locator>. <retrievalHint>)`; storage or ownership failures leave the original result visible.
|
||||
|
||||
**Token effect**: A successful replacement is at most `maxInlineBytes` UTF-8 bytes and remains in history until compaction; the full spill text is not resent to the model.
|
||||
|
||||
## Known Limitations and Deferred Work
|
||||
|
||||
- **Only final plain-text results are spillable** — mixed-content results, blocked feedback, and `read` pass through; provider truncation or tool-owned retention that happened earlier cannot be recovered here.
|
||||
- **A notice that cannot fit disables replacement for that call** — a tiny cap or long locator leaves the oversized original inline after the backend has already saved an unreferenced spill.
|
||||
|
||||
@@ -169,6 +169,6 @@ export function apply(ctx: Context, config: Config): void {
|
||||
return decision
|
||||
}
|
||||
const replaced: ContentBlock[] = [{ type: 'text', text: replacedText }]
|
||||
return { kind: 'accept', content: replaced, ...decision.additionalContext ? { additionalContext: decision.additionalContext } : {} }
|
||||
return { kind: 'accept', content: replaced, ...decision.additionalContexts ? { additionalContexts: decision.additionalContexts } : {} }
|
||||
})
|
||||
}
|
||||
|
||||
@@ -228,15 +228,15 @@ describe('composition', () => {
|
||||
expect(textOf(result.content)).toContain('Full formatted result stored at')
|
||||
})
|
||||
|
||||
it('preserves a downstream accept decision additionalContext when spilling', async () => {
|
||||
it('preserves downstream accept-decision contexts when spilling', async () => {
|
||||
const { ctx } = await setup({ maxInlineBytes: 200 })
|
||||
const context = { content: [{ type: 'text' as const, text: 'note' }], source: { kind: 'plugin' as const, plugin: 'test' } }
|
||||
ctx.on('tools/post-execute', async (_e, _r, _next) =>
|
||||
({ kind: 'accept', additionalContext: context }))
|
||||
({ kind: 'accept', additionalContexts: [context] }))
|
||||
ctx.tools.register(textTool('big', 'x'.repeat(1000)))
|
||||
const result = await ctx.tools.execute(exec('big'))
|
||||
expect(textOf(result.content)).toContain('Full formatted result stored at')
|
||||
expect(result.additionalContext).toEqual(context)
|
||||
expect(result.additionalContexts).toEqual([context])
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
Reference in New Issue
Block a user