feat(retain): expose processed_content_tokens on RetainResult#1217
Merged
Conversation
Delta retain already knows, at chunk-level granularity, which content
was new vs unchanged on an upsert to an existing document_id. Surface
that signal to post-retain hooks so extensions can reason about "how
much content actually went through the extraction pipeline" without
re-implementing the dedup logic.
New field `RetainResult.processed_content_tokens: int | None`:
* None — the retain went through the full (non-delta) path or has
no dedup signal. Consumers should treat this as "the full
submitted payload was processed."
* 0 — the submission matched prior content exactly; no chunks
went through extraction (metadata-only update).
* N>0 — only N tokens of content+context were actually re-extracted.
The remainder matched existing chunks by content_hash and
was skipped.
Populated in three places:
* Streaming / full retain path → None
* `_try_delta_retain` no-changes fallthrough (`_delta_metadata_only`)
→ 0
* `_try_delta_retain` partial-delta success → sum of
count_tokens(content) + count_tokens(context) across the chunks
built for extraction (delta_contents)
Sub-batch aggregation propagates None if any sub-batch bypassed dedup,
so callers never accidentally undercount when only part of a large
batch was eligible for delta processing.
Tests exercise the full path, unchanged-resubmit, appended-content,
and no-document-id cases plus a unit check on the aggregation helper.
cdbartholomew
force-pushed
the
feat/retain-processed-content-tokens
branch
from
April 22, 2026 21:09
e9b7440 to
17b892e
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Delta retain (PR #701) already computes, at chunk-level granularity, which content on an upsert is new vs. a duplicate of existing chunks. This PR surfaces that signal to post-retain hooks so extensions can reason about "how much content actually went through the extraction pipeline" without re-implementing the dedup logic themselves.
New field on
RetainResult:with these semantics:
None0content_hash). No chunks went through LLM extraction — metadata-only update.N > 0Ntokens of content+context were actually re-extracted. Remaining chunks matched existingcontent_hashand were skipped.Motivation
Clients that append to a growing document on each call (e.g. a session transcript that's upserted under a stable
document_idas turns accumulate) already benefit from chunk-level dedup inside the retain pipeline — unchanged chunks don't re-enter LLM extraction. But the post-retain hook currently sees only the submitted content list, with no signal about how much of it was genuinely new.Surfacing
processed_content_tokenslets a metering or rate-limiting extension charge / account for the actually-new portion without shadowing the dedup state table.Where it's populated
None(no per-chunk dedup was performed)._try_delta_retain"no changes" fallthrough (_delta_metadata_only) →0._try_delta_retainpartial-delta success → sum ofcount_tokens(content) + count_tokens(context)across the items built for extraction (delta_contents). Chunks matched bycontent_hashcontribute zero.retain_batch_asyncwhen the payload is auto-chunked) →Noneif any sub-batch bypassed dedup, otherwise sum. Conservative so callers never undercount when only part of a large batch was eligible for delta processing.retain_batchapplies the sameNone-propagating merge rule.Backward compatibility
RetainResultgains a new field with aNonedefault — existing extensions compile and run unchanged.retain_batch/_retain_batch_async_internalchanges from(unit_ids, usage)to(unit_ids, usage, processed_content_tokens). The publicretain_batch_asyncreturn (and itsreturn_usage=Trueform) is unchanged — the new signal is delivered only via theRetainResulthook.Test plan
document_id→processed_content_tokens is None.document_id→processed_content_tokens == 0.processed_content_tokensis either a positive value strictly less than submitted tokens, orNone(if the chunker forced a full-retain fallback). Both are legitimate signals.document_id→processed_content_tokens is None.uv run ruff checkclean.