Skip to content

fix(stats): persist cache totals + lastPromptTokens across resume#384

Merged
esengine merged 1 commit into
mainfrom
fix/364-resume-cache-context
May 7, 2026
Merged

fix(stats): persist cache totals + lastPromptTokens across resume#384
esengine merged 1 commit into
mainfrom
fix/364-resume-cache-context

Conversation

@esengine

@esengine esengine commented May 7, 2026

Copy link
Copy Markdown
Owner

Closes #364.

Why

SessionMeta only carried totalCostUsd and turnCount. On every resume /status showed:

  • 0 contextsummary.lastPromptTokens came from turns[0]?.usage, and turns is empty before the first live turn fires.
  • 0% cache hitaggregateCacheHitRatio summed turns[] only, so it was undefined / 0 immediately after resume.

The next API call still hit the cached prefix and answered correctly (the user's transcript shows 366,976 / 367,085 cache hits on turn 1), but the status panel claimed "no context" until that call landed.

What changes

src/memory/session.ts — extend SessionMeta:

cacheHitTokens?: number;
cacheMissTokens?: number;
lastPromptTokens?: number;

src/telemetry/stats.tsseedCarryover accepts the three new fields. aggregateCacheHitRatio now seeds hit / miss from carryover before summing live turns. summary().lastPromptTokens falls back to the carryover when no live turn exists yet.

src/loop.tsseedCarryover call on resume passes the new fields.

src/cli/ui/App.tsxpatchSessionMeta after assistant_final now writes:

cacheHitTokens: (m.cacheHitTokens ?? 0) + u.promptCacheHitTokens,
cacheMissTokens: (m.cacheMissTokens ?? 0) + u.promptCacheMissTokens,
lastPromptTokens: u.promptTokens, // only when truthy

Tests

  • tests/telemetry.test.ts — 5 new cases: ratio with carryover-only, ratio with carryover + live, lastPromptTokens fallback + override, seedCarryover ignores zero/negative.
  • tests/session.test.ts — new case: CacheFirstLoop resume preloads cache + lastPromptTokens through the meta → stats path.

Test plan

  • npm run verify — 133 files / 2138 passed / 1 skipped (was 2132, +6 new)
  • Manual: chat one turn → exit → resume → /status shows the prior context bar and a non-zero cache hit %, not the previous 0/0 state

`SessionMeta` only carried `totalCostUsd` and `turnCount`, so on every
resume `/status` showed:

- 0 context — `lastPromptTokens` came from `turns[0]?.usage`, and
  `turns` is empty before the first live turn fires
- 0% cache hit — `aggregateCacheHitRatio` summed `turns[]` only

The next API call would still read the cached prefix and answer
correctly (turn 1 in the user's log shows 366,976 / 367,085 cache
hits), but the panel reported "no context" until that call landed.

Persist the missing fields after each turn (`patchSessionMeta`) and
seed them on resume (`stats.seedCarryover`). `aggregateCacheHitRatio`
and `summary().lastPromptTokens` now fall through to the carryover
when no live turn has run yet.
@esengine esengine merged commit 7edcb07 into main May 7, 2026
3 checks passed
@esengine esengine deleted the fix/364-resume-cache-context branch May 7, 2026 13:46
@esengine esengine mentioned this pull request May 7, 2026
6 tasks
ChasLui pushed a commit to ChasLui/DeepSeek-Reasonix that referenced this pull request May 23, 2026
…engine#364) (esengine#384)

`SessionMeta` only carried `totalCostUsd` and `turnCount`, so on every
resume `/status` showed:

- 0 context — `lastPromptTokens` came from `turns[0]?.usage`, and
  `turns` is empty before the first live turn fires
- 0% cache hit — `aggregateCacheHitRatio` summed `turns[]` only

The next API call would still read the cached prefix and answer
correctly (turn 1 in the user's log shows 366,976 / 367,085 cache
hits), but the panel reported "no context" until that call landed.

Persist the missing fields after each turn (`patchSessionMeta`) and
seed them on resume (`stats.seedCarryover`). `aggregateCacheHitRatio`
and `summary().lastPromptTokens` now fall through to the carryover
when no live turn has run yet.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cache and expense stat reset when exit

1 participant