Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 25 additions & 10 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,13 +102,14 @@ interface ModeUsage {
}

interface ContextReferenceUsage {
file: number; // #file references
selection: number; // #selection references
symbol: number; // #symbol references
codebase: number; // #codebase references
workspace: number; // @workspace references
terminal: number; // @terminal references
vscode: number; // @vscode references
file: number; // #file references
selection: number; // #selection references
implicitSelection: number; // Implicit selections via inputState.selections
symbol: number; // #symbol references
codebase: number; // #codebase references
workspace: number; // @workspace references
terminal: number; // @terminal references
vscode: number; // @vscode references
}

interface McpToolUsage {
Expand Down Expand Up @@ -194,7 +195,7 @@ interface SessionLogData {

class CopilotTokenTracker implements vscode.Disposable {
// Cache version - increment this when making changes that require cache invalidation
private static readonly CACHE_VERSION = 8; // Skip sessions with 0 models in avg calculation (2026-02-02)
private static readonly CACHE_VERSION = 9; // Added implicitSelection to ContextReferenceUsage (2026-02-02)

private diagnosticsPanel?: vscode.WebviewPanel;
// Tracks whether the diagnostics panel has already received its session files
Expand Down Expand Up @@ -980,6 +981,7 @@ class CopilotTokenTracker implements vscode.Disposable {
contextReferences: {
file: 0,
selection: 0,
implicitSelection: 0,
symbol: 0,
codebase: 0,
workspace: 0,
Expand Down Expand Up @@ -1079,6 +1081,7 @@ class CopilotTokenTracker implements vscode.Disposable {
// Merge context references
period.contextReferences.file += analysis.contextReferences.file;
period.contextReferences.selection += analysis.contextReferences.selection;
period.contextReferences.implicitSelection += analysis.contextReferences.implicitSelection || 0;
period.contextReferences.symbol += analysis.contextReferences.symbol;
period.contextReferences.codebase += analysis.contextReferences.codebase;
period.contextReferences.workspace += analysis.contextReferences.workspace;
Expand Down Expand Up @@ -1359,6 +1362,7 @@ class CopilotTokenTracker implements vscode.Disposable {
contextReferences: {
file: 0,
selection: 0,
implicitSelection: 0,
symbol: 0,
codebase: 0,
workspace: 0,
Expand Down Expand Up @@ -1392,13 +1396,23 @@ class CopilotTokenTracker implements vscode.Disposable {
// Handle VS Code incremental format - detect mode from session header
if (event.kind === 0 && event.v?.inputState?.mode?.kind) {
sessionMode = event.v.inputState.mode.kind;

// Detect implicit selections in initial state
if (event.v?.inputState?.selections && Array.isArray(event.v.inputState.selections) && event.v.inputState.selections.length > 0) {
analysis.contextReferences.implicitSelection++;
}
}

// Handle mode changes (kind: 1 with mode update)
if (event.kind === 1 && event.k?.includes('mode') && event.v?.kind) {
sessionMode = event.v.kind;
}

// Detect implicit selections in updates to inputState.selections
if (event.kind === 1 && event.k?.includes('selections') && Array.isArray(event.v) && event.v.length > 0) {
analysis.contextReferences.implicitSelection++;
}

// Handle VS Code incremental format - count requests as interactions
if (event.kind === 2 && event.k?.[0] === 'requests' && Array.isArray(event.v)) {
for (const request of event.v) {
Expand Down Expand Up @@ -1763,6 +1777,7 @@ class CopilotTokenTracker implements vscode.Disposable {
contextReferences: {
file: 0,
selection: 0,
implicitSelection: 0,
symbol: 0,
codebase: 0,
workspace: 0,
Expand Down Expand Up @@ -1805,7 +1820,7 @@ class CopilotTokenTracker implements vscode.Disposable {
modified: stat.mtime.toISOString(),
interactions: 0,
contextReferences: {
file: 0, selection: 0, symbol: 0, codebase: 0,
file: 0, selection: 0, implicitSelection: 0, symbol: 0, codebase: 0,
workspace: 0, terminal: 0, vscode: 0
},
firstInteraction: null,
Expand Down Expand Up @@ -2266,7 +2281,7 @@ class CopilotTokenTracker implements vscode.Disposable {
*/
private createEmptyContextRefs(): ContextReferenceUsage {
return {
file: 0, selection: 0, symbol: 0, codebase: 0,
file: 0, selection: 0, implicitSelection: 0, symbol: 0, codebase: 0,
workspace: 0, terminal: 0, vscode: 0
};
}
Expand Down
5 changes: 4 additions & 1 deletion src/webview/usage/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ type ModeUsage = { ask: number; edit: number; agent: number };
type ContextReferenceUsage = {
file: number;
selection: number;
implicitSelection: number;
symbol: number;
codebase: number;
workspace: number;
Expand Down Expand Up @@ -67,7 +68,7 @@ function escapeHtml(text: string): string {
}

function getTotalContextRefs(refs: ContextReferenceUsage): number {
return refs.file + refs.selection + refs.symbol + refs.codebase +
return refs.file + refs.selection + refs.implicitSelection + refs.symbol + refs.codebase +
refs.workspace + refs.terminal + refs.vscode;
}

Expand Down Expand Up @@ -205,6 +206,7 @@ function renderLayout(stats: UsageAnalysisStats): void {
padding: 12px;
box-shadow: 0 2px 4px rgba(0,0,0,0.2);
}
.stat-card[title] { cursor: help; }
.stat-label { font-size: 11px; color: #b8b8b8; margin-bottom: 4px; }
.stat-value { font-size: 20px; font-weight: 700; color: #f6f6f6; }
.bar-chart {
Expand Down Expand Up @@ -320,6 +322,7 @@ function renderLayout(stats: UsageAnalysisStats): void {
<div class="stats-grid">
<div class="stat-card"><div class="stat-label">📄 #file</div><div class="stat-value">${stats.month.contextReferences.file}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.file}</div></div>
<div class="stat-card"><div class="stat-label">✂️ #selection</div><div class="stat-value">${stats.month.contextReferences.selection}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.selection}</div></div>
<div class="stat-card" title="Text selected in your editor providing passive context to Copilot"><div class="stat-label">✨ Implicit Selection</div><div class="stat-value">${stats.month.contextReferences.implicitSelection}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.implicitSelection}</div></div>
<div class="stat-card"><div class="stat-label">🔤 #symbol</div><div class="stat-value">${stats.month.contextReferences.symbol}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.symbol}</div></div>
<div class="stat-card"><div class="stat-label">🗂️ #codebase</div><div class="stat-value">${stats.month.contextReferences.codebase}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.codebase}</div></div>
<div class="stat-card"><div class="stat-label">📁 @workspace</div><div class="stat-value">${stats.month.contextReferences.workspace}</div><div style="font-size: 10px; color: #999; margin-top: 4px;">Today: ${stats.today.contextReferences.workspace}</div></div>
Expand Down
Loading