From 25a7e2c04f5fe7841e71e29b05676f647238bd11 Mon Sep 17 00:00:00 2001
From: Arturo Carretero Calvo <10163049+ArtCC@users.noreply.github.com>
Date: Wed, 26 Aug 2026 10:51:59 +0200
Subject: [PATCH 01/14] Calibrate chat context usage from LiteLLM token reports
- Preserve LiteLLM prompt-token usage when streaming or agent responses report it, and estimate response tokens separately
- Fall back to local context estimation when prompt usage is unavailable or the model has no usable capacity
- Ignore prompt-token calibration for memory mutation agent calls to keep estimated context usage unchanged
- Add shared helpers to compare normalized chat request content and retain context usage across persisted conversation merges
- Cover prompt-usage propagation, context calibration, normalized attachment matching, and zero-capacity model behavior with tests
- Bump marketing version and update changelog, README badge, and TestFlight notes to 1.6.35
---
CHANGELOG.md | 6 +
README.md | 2 +-
TestFlight/WhatToTest.en-US.txt | 8 +-
.../Chat/AgentStreamUseCaseContextTests.swift | 27 +++
.../Features/Chat/ChatMessageTests.swift | 50 +++++
.../ChatViewModelTests+ContextUsage.swift | 207 ++++++++++++++++++
.../Chat/ChatViewModelTests+Persistence.swift | 50 -----
.../Chat/ContextWindowBuilderTests.swift | 16 ++
openclient-llm.xcodeproj/project.pbxproj | 20 +-
.../Features/Chat/Models/ChatMessage.swift | 16 ++
.../Chat/UseCases/AgentStreamUseCase.swift | 9 +-
.../Chat/ViewModels/ChatViewModel+Agent.swift | 73 ++++--
.../ViewModels/ChatViewModel+Helpers.swift | 28 ++-
.../ViewModels/ChatViewModel+Streaming.swift | 68 ++++--
specs/version.instructions.md | 2 +-
15 files changed, 468 insertions(+), 114 deletions(-)
create mode 100644 openclient-llm-test/Features/Chat/ChatMessageTests.swift
create mode 100644 openclient-llm-test/Features/Chat/ChatViewModelTests+ContextUsage.swift
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3a5119a2..c05c26ec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Contributions are welcome — see [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.
+## [1.6.35-build-86] - 2026-08-26
+
+### Fixed
+
+- Chat context usage now retains LiteLLM's reported prompt-token count and estimates only the newly generated response, falling back to local estimation when usage is unavailable
+
## [1.6.30-build-85] - 2026-08-23
### Added
diff --git a/README.md b/README.md
index 0f4342fe..056238c5 100644
--- a/README.md
+++ b/README.md
@@ -8,7 +8,7 @@
-
+
V6DGfpp@7^EqJvZ!%qCZdIx%fR6K@6Tl*m&!Z*e57X7*eHhgt~|^
zD%d}9s0>XB1!*mq8l~-#2WAF7?xOxe>~-h9lo`-DCU#EhH%xi)X!9tTZxfy!oUa2O
zvl&|ievy4Dy~j(f2)ISN$xsT=4|>kwxo|qTTZj4_X;?-RWcSy`?sF&&LlZ~Vb@CG~
zuHA;pAe`KS)?E&eE*e^p*(_#wFp)2w9?(V{OpzlWqW>xPw@@xa&efgnyPILWMshhz
zT?7ub^l3xAtN|yUS29T|tE|R!e6YMto~Eh@XF7M%cU7LnC+9akVC0>AKCEH5&=g
zvHFqlN8LlqbKplLa-w*wcH^_`+)T`)q@Sl%>#-GIaSII3Go-Vh)>$qNEQPTu!D~@&
z-#y@DFYLlYbxNDD{fQh9F7yw-x42H*@}0T+I_{&a{KxP}&BxAe@cr~h*nl%PuVAC~
z!NLZf;uq4{KMQ5qBG(ZO){Qwl01H%QB)oeh!;iZtoUxd6LOBj17kZTsrqg||wqIWk
zHOFgp-yc}Yr+7nJ2W=$0>Ub{My2PB(!B=oS?laBU0s=-5$`16^1!Wr2$NN~yJ1QyA
zrXB%|1|(rCkKI9ZaR^H*;)m9-&vG?#glvV~9Ieb2wNA?Y4wDeSA8H6(VggM1f@xNx
z92&*Quun%yX4`Jd*8H7f`>y;SqOaiTCtG|%FS^}uDJ@Sa^i3!Ut6@#4e8(&WAEmy3
z5%!z-E)|aA#a|~1DzusqoI*jR3d 2g(x=cZ;&7!3`^ScsDM
z!$(T0OmofH3l53T$;~>R815T1@xV=#5yhzNs=Pbf{S$^ag^^c%XAh?=;51ifMB$CD
z8ifP9At&Gq2n;W-2fx-@w>#$r!p)@J2{T7ZMH#v-EjQO~MTzV_FwV~)A~SgOrE@Nl
zdzWT>GKUKt{cGDEKKQtRlv){>!nFcM^?q$cc^s!BDH`6GI;uiP)=Nzdt?!nrr}eM?
zfrx8)23x4wzsBG&XdZpqN~ct7G$yG!P4d7a(Qxc$e^s~m-=ns)i5_1QwXtem8ZJSk(+(c_{i=TXr?k7C&)HsW-(KJ
zKKMng_TGT_TP6%#z8J3n!g0-!%30BP=55f#H%z#Y3ITeFqwE#R=#DlnRc(g7WY<==
z-DvXu6$ZDm*Pe6@_TL7-n+!%lh0xQ7qU1hNTEh
*TBQ!Pi~VH0$8-)uZinujdy=E@bGl|fs9QP{$8Wejbnpo}9Dx~x&|P&K{>
z1UY!N;S+vn55sL0J-q3_KlHCfaebaNdb?3SX&1%^O*)a9lEf=g;r;e5*C}DOa-(B;
zo=ZU*d4#V
a!8#Xs6H(O(xDJca?K<@DuDp$
zqCHLF0I=H)AJwGR9FNt$pGD-_>~8>xLSK6#^>tDm-)S}G$OffEUqX{`X-3jAAsx(t
zh=HW8F`bsuQx{q)kB*vF)pL$147Eg~A7o-2)sQte*-n3+#Oa*_ReU)Vu>MXYG26jj
zQI8Pv7n9(ka5cji2PR4N469pDK_LnNRv+8%AejfZXS)RwDb2}89S4jM^pZAD8Sk{{
z_je2WPhHE#NQ*~QJ%Fo+$)u-`=7q;#9
j8{<6W2_3+Ylj!bJl_%A8#z
zj9#t>%V?Igwms-oP6`UUAKmN4jXEah>35H=m=ZhUWg6?d>(iOOjtJHjZNz-mT+U~a
z!d++j=Y-9lGegMqw-$$J|0z@vVx4ksl1W~QQx)~li}xGB;0?m4`t;n7Z*M@Dyo%(g
zW>a{g&V8vc0K&jm2u==H5f-tQp&TbWcm&-Zn(Dn3o{3y!u?NL55Gkn*gzX(BpkNX!
zLIccM95GHF2x7RpUO7@_5Fe(sc~V+In7xu`FS_R3Si24F8iTC{s5_?hCZ;%~6f2%{
z
RTZc2-ZIOzO{(6NLoU?m+{1%
zKLOC(&`wL<7LqD?!0Gb@(y`;zK-pG)zzwI*qftwE-dwxkBX}a8ojIp-Hib4m_S2KA
zJ-G58tmlO!R`{g8SPY%;ZBGJ#9Ez*Dc#GU#7D&|zSun4W1E#<(H)Gu;1+!6%*~><5
z{iog4``~ZkrR~JkZp1%hI}%$1Z@(+eVifZ6BrUC&hVq_(+N8aG1t-HbY6%4|=U^}E
z!o2l1GC&RAaHlU?e7Tr$;%%-cG*9Fzau|Gd%umA(Yl&-COXO8z#Bv6R9}bh3Gw39K
zCXv639Ax6xbGLPCZ$8*ZAOPeygi&HXaDi*sN!zc){^4UYFB`pgxBgu3VtqPnVV=Eq
zl5w|6nAo@@E<3P_`ivm>Em_cv4_Wc2;9ysLnUkhLIZ1B7Yv2A*ME%xJg*o<$28KQp
zU)TSaTxI^zxcdd+aW9`ay`yk0Q2RPV!`m|k{^}8+`qD9J&e+>8(n7G-le53{p1hS;
za0Pf2m%BjQd@C|{I@P{Vq_8>P)o>C2Ftw`5Ea}!%Q-yYv9Gp#AWtB!w??pMeJ@}?}
zc-yzWi+8r~Pd3%k$U~s|@U*8_7EY^lbe`TFd3o{slW@@_U29{VKWjaNYDH?Eu^%n4
zo)w66C9R2qul6sIU-75&$MqgO!6ntc{&p48rjKcR?hY?On!n2lsB|TUihzE#GJyyY
z%^W`S!e9)arD1agB%?}8ha7X+`HMblure{LbQS%gpt7yKWKJBG;=EPWJsI
tv}BIQd*}q
zm!Zh$4QpDA&JE+M_;P36gKy<3`Fs!RETeiE)WoOzlzXZUj&l^YH;jWt6Y7JpX^6(0
z*0GwN?+I-w37$<~F0gA9s>)5c3{vLJ*&aRXtcj#=3(T^Uk5FhZ$z$Nr4V%5VmUY_O
z=^v4%EFFl0!oi%K(u<b+va;C{y!J4FXqa9HxA-_lsRffoSDBh8@
zNW1gw;4z$F%GlSsI+