Skip to content

Commit 4f1e399

Browse files
committed
fix(sidebar): drop tokens row from Current session — show messages + age only
The token count in the session block was reading the local Cursor JSONL transcript through a chars/3.5 heuristic. Two problems: - The local transcript only contains compact message envelopes — the expanded tool results and file reads that dominate Cursor's real context budget never land in that file. Our number was 3.8k when Cursor's own Context panel showed 43.5k for the same chat. - There is no public API to read Cursor's authoritative counter (researched the Cursor docs API, forum threads, GitHub, Reddit — nothing exposes the per-chat context breakdown to third-party extensions, and Cursor staff's only comment is a vague "more visibility coming"). User picked Variant B from the menu of options: drop the token row entirely, keep the two signals we CAN measure accurately — Messages (count) and Started (age). The session warning now fires on either >=50 messages OR >=2h elapsed, which roughly maps to "approaching Cursor's ~50% auto-summarize threshold" without claiming a token number we can't see. ActiveSession.tokens is still computed for any future use, just not rendered. #!axme pr=none repo=AxmeAI/axme-code
1 parent e4ee9e1 commit 4f1e399

1 file changed

Lines changed: 27 additions & 23 deletions

File tree

extension/src/sidebar-webview.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,10 @@ import { log } from "./log.js";
3333
*/
3434
const SESSION_POLL_MS = 3_000;
3535

36-
/** Threshold above which we warn the user to close the session. Chosen
37-
* to match the upper end of Cursor's reported auto-summarize trigger
38-
* (~50–60% of context window for 200k models) so the user has a chance
39-
* to close cleanly via our handoff flow BEFORE Cursor's lossy condense
40-
* fires. */
41-
const SESSION_WARN_TOKENS = 200_000;
36+
// (Old SESSION_WARN_TOKENS dropped — we no longer display a token number
37+
// in the session block. See "Live session block" comment in the render
38+
// code for the rationale. Threshold is now message-count + duration in
39+
// the render code itself: >50 messages OR >2h triggers the warning.)
4240

4341
export interface SidebarState {
4442
/** Is the workspace initialised (`.axme-code/` exists)? */
@@ -55,10 +53,10 @@ export interface SidebarState {
5553
hooksOk: boolean;
5654
/** Are we running in Cursor (vs other host)? */
5755
isCursor: boolean;
58-
/** Live snapshot of the active chat session — tokens, messages, age. */
56+
/** Live snapshot of the active chat session — messages, age (tokens are
57+
* collected but no longer displayed; see "Live session block" comment
58+
* in the render code for the rationale). */
5959
session: ActiveSession | null;
60-
/** Warn threshold (passed to webview so it can hide its own UI). */
61-
warnTokens: number;
6260
}
6361

6462
export type SidebarMessage =
@@ -85,7 +83,7 @@ export class AxmeSidebarProvider implements vscode.WebviewViewProvider {
8583

8684
constructor(
8785
private readonly context: vscode.ExtensionContext,
88-
private readonly initialState: Omit<SidebarState, "counts" | "backlog" | "auditorKeyConfigured" | "session" | "warnTokens">,
86+
private readonly initialState: Omit<SidebarState, "counts" | "backlog" | "auditorKeyConfigured" | "session">,
8987
) {}
9088

9189
attach(workspaceRoot: string | undefined, binary: string): void {
@@ -152,7 +150,6 @@ export class AxmeSidebarProvider implements vscode.WebviewViewProvider {
152150
counts,
153151
backlog,
154152
hooksOk: hooksAreInstalled(),
155-
warnTokens: SESSION_WARN_TOKENS,
156153
...this.pendingState,
157154
});
158155
this.pendingState = {};
@@ -441,7 +438,7 @@ select, input[type=text], input[type=password] {
441438

442439
const SIDEBAR_JS = `
443440
const vscode = acquireVsCodeApi();
444-
let S = { setupDone: false, counts: { memories:0, decisions:0, safety:0, backlog:0, questions:0 }, backlog: [], auditorMode: "cooperative", auditorKeyConfigured: false, hooksOk: false, isCursor: true, session: null, warnTokens: 200000 };
441+
let S = { setupDone: false, counts: { memories:0, decisions:0, safety:0, backlog:0, questions:0 }, backlog: [], auditorMode: "cooperative", auditorKeyConfigured: false, hooksOk: false, isCursor: true, session: null };
445442
446443
function formatDuration(ms) {
447444
if (ms <= 0) return "just now";
@@ -453,11 +450,8 @@ function formatDuration(ms) {
453450
const rm = m % 60;
454451
return h + "h " + (rm ? rm + "m" : "");
455452
}
456-
function formatTokens(n) {
457-
if (n < 1000) return n + "";
458-
if (n < 100000) return (n / 1000).toFixed(1).replace(/\\.0$/, "") + "k";
459-
return Math.round(n / 1000) + "k";
460-
}
453+
// formatTokens was used by the old Tokens row in the session block.
454+
// Variant B dropped that row — function removed to keep dead code out.
461455
462456
function send(msg) { vscode.postMessage(msg); }
463457
function cmd(id) { send({ type: "command", commandId: id }); }
@@ -554,22 +548,32 @@ function render() {
554548
});
555549
556550
// Live session block — driven by readActiveSession on the host side.
551+
// We deliberately do NOT show a token count: our only data source is the
552+
// local Cursor JSONL transcript which contains compact message envelopes,
553+
// not the expanded tool results that dominate Cursor's actual context
554+
// budget. Showing "3.8k" while Cursor's own Context panel shows 43.5k
555+
// confused users more than it helped. Instead we show two signals we CAN
556+
// measure honestly: messages (count) and duration (age).
557+
//
558+
// Warning threshold uses both. >50 messages OR >2h is a reasonable
559+
// proxy for "you're heading toward Cursor's ~50–60% auto-summarize
560+
// trigger" without lying about a token number we can't see.
557561
const sess = S.session;
558562
let sessionHtml = '<p class="muted">No active chat detected. Tools will record activity when an MCP call lands.</p>';
559563
if (sess && sess.hasData) {
560564
const startedMs = Date.parse(sess.startedAt);
561565
const ageMs = Number.isFinite(startedMs) ? Date.now() - startedMs : 0;
562-
const overWarn = sess.tokens >= S.warnTokens;
566+
const ageHours = ageMs / 3_600_000;
567+
const overWarn = sess.messages >= 50 || ageHours >= 2;
563568
sessionHtml = \`
564569
<div class="row"><span class="k">Started</span><span class="v">\${formatDuration(ageMs)} ago</span></div>
565-
<div class="row"><span class="k">Tokens</span><span class="v">\${formatTokens(sess.tokens)}</span></div>
566570
<div class="row"><span class="k">Messages</span><span class="v">\${sess.messages}</span></div>
567571
\${overWarn ? \`
568572
<div class="warning-banner">
569-
Approaching Cursor's auto-summarize threshold. Cursor will compress
570-
your conversation around here and quality often degrades after that.
571-
Ask the agent in the chat to <b>close the session</b> — it will
572-
extract memories / decisions / safety inline and give you a
573+
Session is getting long (\${sess.messages} messages, \${formatDuration(ageMs)}).
574+
Cursor auto-summarizes around the ~50% context mark and quality often
575+
regresses after that. Ask the agent to <b>close the session</b> —
576+
it will extract memories / decisions / safety inline and give you a
573577
startup prompt for a fresh chat with zero context loss.
574578
</div>\` : ""}
575579
\`;

0 commit comments

Comments
 (0)