Skip to content

refactor(vscode): harden context-usage display with trusted token limits#2875

Merged
tanzhenxin merged 4 commits intofix/2847-vscode-new-session-minimalfrom
fix/2847-vscode-new-session-reset-context
Apr 7, 2026
Merged

refactor(vscode): harden context-usage display with trusted token limits#2875
tanzhenxin merged 4 commits intofix/2847-vscode-new-session-minimalfrom
fix/2847-vscode-new-session-reset-context

Conversation

@yiliang114
Copy link
Copy Markdown
Collaborator

Summary

Follow-up to #2874. Adds defensive hardening so the context-usage bar behaves correctly even when the ACP server omits tokenLimit from its responses.

  • knownTokenLimit() in core/tokenLimits.ts: a new export that returns undefined for unrecognized models (unlike tokenLimit() which always falls back to a default). This lets callers distinguish "known limit" from "guessed default".
  • acpModelInfo.ts: derives _meta.contextLimit from the known-model table when the ACP payload omits a numeric limit, with a clear priority chain (legacy numeric > meta numeric > derived > explicit null > undefined).
  • computeContextUsage(): extracted from the 45-line inline block in App.tsx into a standalone tested module. Returns null when no trusted numeric limit is available — the UI hides the context bar instead of showing a misleading default.
  • Removes the last @qwen-code/qwen-code-core runtime import from App.tsx, keeping the webview bundle free of Node-only dependencies.

Files changed

File Change
core/tokenLimits.ts Add findTokenLimit() + knownTokenLimit() export, refactor tokenLimit() to reuse
acpModelInfo.ts Derive contextLimit from known model table when ACP omits it
contextUsage.ts (new) Pure function extracted from App.tsx, no default fallback
App.tsx Replace 45-line inline block with computeContextUsage() call
+ 3 test files Cover all new behaviors

Test plan

  • tokenLimits.test.tsknownTokenLimit returns values for known models, undefined for unknown
  • acpModelInfo.test.ts — derives contextLimit when payload omits it, preserves explicit null
  • contextUsage.test.ts — null without trusted limit, prefers usageStats over meta, inputTokens/promptTokens compat
  • imageSupport.bundle.test.ts — App webview bundle has no core runtime imports

Depends on #2874

The webview context-usage bar did not clear when the user started a new
session because the old code always fell back to DEFAULT_TOKEN_LIMIT,
producing a stale percentage even after usageStats and modelInfo were
both cleared.

Key changes:
- Extract `knownTokenLimit()` in core/tokenLimits.ts that returns
  `undefined` for unrecognized models instead of a default, keeping
  `tokenLimit()` behavior unchanged.
- In acpModelInfo.ts, derive `_meta.contextLimit` from the known-model
  table when the ACP payload omits a numeric limit.
- Extract `computeContextUsage()` into its own module, which returns
  `null` when no trusted numeric limit is available — the UI then
  correctly hides the context bar.
- Remove the `@qwen-code/qwen-code-core` runtime import from App.tsx
  so the webview bundle stays free of Node-only dependencies.

Closes #2847
@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Apr 4, 2026

📋 Review Summary

This PR adds defensive hardening for the context-usage display in the VS Code extension, ensuring correct behavior when the ACP server omits tokenLimit from responses. The implementation introduces a new knownTokenLimit() function that distinguishes between "known limit" and "guessed default," extracts context usage computation into a testable module, and removes the last runtime dependency on @qwen-code/qwen-code-core from the webview bundle. Overall, this is a well-structured refactoring with comprehensive test coverage.

🔍 General Feedback

  • Strong separation of concerns: The extraction of computeContextUsage() from the 45-line inline block in App.tsx significantly improves testability and maintainability.
  • Clear priority chain: The context limit resolution order (legacy numeric > meta numeric > derived > explicit null > undefined) is well-documented and logically sound.
  • Excellent test coverage: All new functions have corresponding tests covering edge cases, including unknown models, null handling, and fallback behaviors.
  • Clean dependency management: Removing the @qwen-code/qwen-code-core runtime import from App.tsx is a positive architectural improvement for the webview bundle.
  • Consistent patterns: The refactoring of tokenLimit() to reuse knownTokenLimit() follows DRY principles without sacrificing clarity.

🎯 Specific Feedback

🔵 Low

  • File: packages/vscode-ide-companion/src/utils/acpModelInfo.ts:66-73 - The priority chain comment is helpful, but consider extracting the context limit derivation logic into a named helper function (e.g., resolveContextLimit()) to improve readability and make the priority chain self-documenting:

    const contextLimit = resolveContextLimit(legacyLimit, metaLimit, derivedLimit);
  • File: packages/vscode-ide-companion/src/webview/utils/contextUsage.ts:24 - The limit assignment could benefit from an explicit comment about why DEFAULT_TOKEN_LIMIT is intentionally NOT used as a fallback here (unlike in tokenLimit()), since this distinction is the core purpose of this PR.

  • File: packages/core/src/core/tokenLimits.ts:190-200 - The findTokenLimit() function is declared but not exported. Consider adding a JSDoc comment explaining its internal-only status to prevent future accidental exports.

✅ Highlights

  • packages/core/src/core/tokenLimits.ts - The refactoring of tokenLimit() to compose over knownTokenLimit() is elegant and maintains backward compatibility while enabling the new "unknown model" detection pattern.

  • packages/vscode-ide-companion/src/webview/utils/contextUsage.ts - The pure function design with no default fallback is exactly what's needed for the webview context. Returning null when no trusted limit is available prevents misleading UI states.

  • Test files - All three test files (tokenLimits.test.ts, acpModelInfo.test.ts, contextUsage.test.ts) demonstrate thorough coverage of edge cases, including the critical "unknown model returns undefined" behavior and the inputTokens/promptTokens compatibility handling.

  • packages/vscode-ide-companion/src/utils/acpModelInfo.ts - The explicit handling of null vs undefined for context limits ("limit intentionally unknown" vs "not provided") shows thoughtful API design that respects server intent.

Copy link
Copy Markdown
Collaborator

@tanzhenxin tanzhenxin left a comment

Choose a reason for hiding this comment

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

Review: refactor(vscode): harden context-usage display with null guards and session reset

Overview

Three interrelated improvements: extracting computeContextUsage() into a standalone tested utility (removing the last core runtime import from the webview bundle), adding knownTokenLimit() to core, and passing { forceNew: true } for explicit new-session actions.


Issues

1. forceNew session without resetting currentConversationId causes data mixing (High)

SessionMessageHandler.ts creates a fresh ACP session with forceNew: true, but neither that path nor WebViewProvider.ts resets currentConversationId. When the user sends the first prompt, SessionMessageHandler skips createConversation() because the old id is still present, and appends the new chat to the previous conversation record. This is a real data-mixing bug introduced by this change.

2. Context-usage reset incomplete — stale token usage after "New Session" (Medium)

The new-session flows only emit conversationCleared, but useWebViewMessages.ts does not clear usageStats. Since App.tsx derives the footer from retained usageStats, an empty fresh chat can still display the old session's context consumption until a new request produces updated metadata.

3. Silent behavioral change in token field priority (Medium)

Old code: usageStats?.usage?.promptTokens ?? 0
New code: usageStats?.usage?.inputTokens ?? usageStats?.usage?.promptTokens ?? 0

The new priority preferring inputTokens over promptTokens is arguably more correct (SDK primary vs legacy compat), but it's a silent behavioral change not called out in the PR description. If both fields are present with different values, displayed usage will change. Worth documenting as intentional.


Positives

  • Clean extraction of computeContextUsage as a pure, testable function.
  • Bundle test (imageSupport.bundle.test.ts) is a clever integration safeguard.
  • Well-documented priority chain in acpModelInfo.ts.
  • knownTokenLimit / findTokenLimit extraction is well-structured.
  • Solid test coverage for new paths.

Verdict

REQUEST_CHANGES — The currentConversationId not being reset on forceNew (#1) is a data-mixing bug that needs fixing before merge. The stale usage display (#2) should also be addressed.

@yiliang114
Copy link
Copy Markdown
Collaborator Author

Related context: this is very much in the same direction as #2902, in that both reduce frontend-side coupling to @qwen-code/qwen-code-core. The scope is different though: this PR is focused on the vscode webview path, while #2902 is focused on the published webui package and its release/build path.

@yiliang114
Copy link
Copy Markdown
Collaborator Author

yiliang114 commented Apr 5, 2026

Addressed the review feedback in follow-up commits:

  • reset stale currentConversationId on forceNew in both SessionMessageHandler and WebViewProvider
  • clear retained usageStats when the webview handles conversationCleared
  • document that computeContextUsage() intentionally avoids DEFAULT_TOKEN_LIMIT and prefers inputTokens over legacy promptTokens
  • add regression coverage for stale conversation reset and cleared webview state

Verification run locally:

  • npm test --workspace=packages/vscode-ide-companion
  • npm run build --workspace=packages/vscode-ide-companion

@yiliang114 yiliang114 requested a review from tanzhenxin April 5, 2026 11:04
Copy link
Copy Markdown
Collaborator

@wenshao wenshao left a comment

Choose a reason for hiding this comment

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

No issues found. LGTM! ✅

Reviewed by glm-5.1 via Qwen Code /review

@yiliang114
Copy link
Copy Markdown
Collaborator Author

@codex review it

Copy link
Copy Markdown
Collaborator

@tanzhenxin tanzhenxin left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@tanzhenxin tanzhenxin merged commit c2f3c96 into fix/2847-vscode-new-session-minimal Apr 7, 2026
1 check passed
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.

3 participants