Repository navigation
fix(api): stop JSON.stringify-ing messages before estimateTokens (restores #8368 image estimate) - #8599
Closed
Prudhvivuda wants to merge 0 commit into
Conversation
This was referenced Jul 25, 2026
diegosouzapw
force-pushed
the
fix/8594-estimatetokens-image-bypass
branch
from
July 27, 2026 02:53
0fbb8a5 to
ed7db3e
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
Six production call sites pre-
JSON.stringify()the messages/body before passing them toestimateTokens(), forcing the char/4 text path and undoing the #8368 inline-base64-image bounded estimate for those paths.estimateTokens(string)takesMath.ceil(str.length / CHARS_PER_TOKEN); the image-detection walk (extractImageTokens) only runs for the object overload introduced by #8368. Stringifying first strips the structural type information the fix depends on.Impact — for any Chat Completions request carrying inline base64 images (
{ type: 'image_url', image_url: { url: 'data:image/...' } }) that triggers compression:compressContextover-estimates (a ~500 KB image → ≈125 000 tokens via base64-as-text instead of the correct ~1 200-token estimate) → thinks the context is way over the limit and enters aggressive compression.purifyHistorybinary-search prunes image-bearing turns unnecessarily → silent context loss.combo.tsfallback compression fires for requests that fit comfortably.Fix
Pass the structured object directly at all six sites —
estimateTokensalready handles both thestringandobjectoverloads; the object path walks the structure for inline base64 image blocks, substitutes the bounded per-image estimate, then measures the remainder as text.Sites fixed:
open-sse/services/contextManager.ts—compressContextinitial estimate + after Layers 1/2/3, and thepurifyHistorybinary-search candidate check (5 sites).open-sse/services/combo.ts— fallback compression threshold check (1 site).Test plan
New TDD guard
tests/unit/8594-compress-image-token-stringify.test.tsdrivescompressContextdirectly (fails before the fix, passes after):purifyHistoryretains all image-bearing turns when they fit;Validated on Node v22.8.0 (supported range):
4053e2314, confirming reproduction).#8368image-token suite: 8/8 pass (no regression).npm run typecheck:coreclean;eslintclean on all changed files.Closes #8594
Refs #8368, #8560