Skip to content

fix(web): keep context usage live on the v2 engine#1601

Merged
kermanx merged 2 commits into
mainfrom
fix/web-context-usage-v2
Jul 13, 2026
Merged

fix(web): keep context usage live on the v2 engine#1601
kermanx merged 2 commits into
mainfrom
fix/web-context-usage-v2

Conversation

@kermanx

@kermanx kermanx commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

No linked issue — the problem is explained below.

Problem

On the web UI connected to the v2 engine (kap-server), the composer's context usage indicator stays at 0:

  • During a new session's first turn it never leaves 0: the v2 server's v1-compatible agent.status.updated bridge reported the measured-only context token count, which is 0 until the first model response completes (v1 reports the live measured + estimated size, so it grows from the first request).
  • After reopening a session or reloading the session list (e.g. via sidebar search), a previously correct reading drops back to 0: the client replaces the cached session with the wire record wholesale, and both engines return an all-zero placeholder for the record's usage field; for an idle session nothing repairs it until the next select.

What changed

  • packages/kap-server (legacyStatus bridge): report max(live measured+estimated size, measured tokens) — the live size matches the REST /status rollup and v1 semantics, while the measured total floors the transient window where a post-step context fold leaves the context shorter than the measured prefix (every real shrink — undo/clear/compaction — rebases the measured model first, so the max only wins in that window). The derived model also watches context-append Ops so the status line moves as soon as a prompt or step event lands.
  • apps/kimi-web: add isPlaceholderSessionUsage and preserve the accumulated live usage whenever an incoming session record carries the placeholder — in snapshot sync (mirroring the existing model preservation) and in wholesale session-list replaces (initial load + search-triggered full reload).
  • Tests: two regression cases in apps/kimi-web/test/workspace-state.test.ts covering list-reload usage preservation. The server-side fix was verified live against a kap-server instance: frames go 0 (empty context) → single-digit estimate on prompt append → measured total after the response, with no zero frames after the first non-zero one and no end-of-turn dip.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue, or explained the problem above.
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

The v2 server's v1-compatible status bridge reported the measured-only
context token count, which reads 0 until the first model response of a
session completes; v1 reports the live (measured + estimated) size. The
web client then compounded this by replacing cached sessions with wire
records whose usage is an all-zero placeholder on snapshot syncs and
session-list reloads.

- kap-server legacyStatus: report max(live size, measured) and watch
  context-append Ops so the status line moves as soon as a prompt lands
- kimi-web: preserve the accumulated live usage when an incoming session
  record carries the placeholder (snapshot sync + list reloads)
@changeset-bot

changeset-bot Bot commented Jul 13, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 056717d

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 2 packages
Name Type
@moonshot-ai/kap-server Patch
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@pkg-pr-new

pkg-pr-new Bot commented Jul 13, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@056717d
npx https://pkg.pr.new/@moonshot-ai/kimi-code@056717d

commit: 056717d

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 830cdfb08e

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

// The wire session's usage is a placeholder (both engines return zeros
// for the heavy fields); keep the live usage folded in from /status and
// the WS status stream instead of zeroing it on every snapshot sync.
usage: isPlaceholderSessionUsage(snap.session.usage) ? s.usage : snap.session.usage,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Refresh status when preserving placeholder snapshots

When syncSessionFromSnapshot is invoked from the WS resync path (onResync/snapshotSyncRunner) rather than through selectSession, the cached s.usage can be the stale value precisely because the volatile status frames were missed. Since the snapshot's session usage is the all-zero placeholder, this line keeps that stale usage and the resync path does not run the sidecar status refresh that selectSession runs after snapshots; after a reconnect/buffer overflow following a turn, compaction, or undo with no later status event, the context ring can remain at the pre-resync value indefinitely. Please refresh /status (or otherwise fetch live usage) when preserving placeholder usage on resync paths.

Useful? React with 👍 / 👎.

…r usage

The resync and stale-socket recovery paths reach syncSessionFromSnapshot
without selectSession's sidecar refresh, and the volatile status frames
that would update usage are exactly what the resync replaced. Re-read
/status after applying a snapshot whose usage is the all-zero placeholder
so a preserved-but-stale reading converges on the live value.
@kermanx

kermanx commented Jul 13, 2026

Copy link
Copy Markdown
Collaborator Author

@codex

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. More of your lovely PRs please.

Reviewed commit: 056717d79d

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

@kermanx kermanx merged commit dc309a7 into main Jul 13, 2026
10 checks passed
@kermanx kermanx deleted the fix/web-context-usage-v2 branch July 13, 2026 10:01
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.

1 participant