Skip to content

Commit 2bd1910

Browse files
rajbosCopilot
andcommitted
fix: use actual API token count in diagnostics; add sortable columns
- Use actualTokens (real LLM API count) when available, falling back to estimated tokens — fixes vastly under-reported counts in the table - Make Size, Tokens, Interactions, and Context Refs columns sortable (click to sort desc/asc, indicator arrow shows active sort) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent 4863e44 commit 2bd1910

2 files changed

Lines changed: 38 additions & 26 deletions

File tree

vscode-extension/src/extension.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3138,13 +3138,14 @@ class CopilotTokenTracker implements vscode.Disposable {
31383138
lastInteraction = stat.mtime.toISOString();
31393139
}
31403140

3141-
// Reconstruct SessionFileDetails from cache
3141+
// Reconstruct SessionFileDetails from cache.
3142+
// Prefer actualTokens (real API count) when available; fall back to estimated tokens.
31423143
const details: SessionFileDetails = {
31433144
file: sessionFile,
31443145
size: cached.size || stat.size,
31453146
modified: stat.mtime.toISOString(),
31463147
interactions: cached.interactions,
3147-
tokens: cached.tokens || 0,
3148+
tokens: cached.actualTokens || cached.tokens || 0,
31483149
contextReferences: cached.usageAnalysis.contextReferences,
31493150
firstInteraction: cached.firstInteraction || null,
31503151
lastInteraction: lastInteraction,
@@ -3171,8 +3172,9 @@ class CopilotTokenTracker implements vscode.Disposable {
31713172
// Get existing cache entry if available
31723173
const existingCache = this.getCachedSessionData(sessionFile);
31733174

3174-
// Enrich details with token count from existing cache (populated by main stats calculation)
3175-
details.tokens = existingCache?.tokens || 0;
3175+
// Enrich details with token count from existing cache (populated by main stats calculation).
3176+
// Prefer actualTokens (real API count) when available; fall back to estimated tokens.
3177+
details.tokens = existingCache?.actualTokens || existingCache?.tokens || 0;
31763178

31773179
// Create or update cache entry
31783180
const cacheEntry: SessionFileCache = {

vscode-extension/src/webview/diagnostics/main.ts

Lines changed: 32 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ const vscode = acquireVsCodeApi<DiagnosticsViewState>();
103103
const initialData = window.__INITIAL_DIAGNOSTICS__;
104104

105105
// Sorting and filtering state
106-
let currentSortColumn: "lastInteraction" = "lastInteraction";
106+
let currentSortColumn: "lastInteraction" | "size" | "tokens" | "interactions" | "contextRefs" = "lastInteraction";
107107
let currentSortDirection: "asc" | "desc" = "desc";
108108
let currentEditorFilter: string | null = null; // null = show all
109109
let currentContextRefFilter: keyof ContextReferenceUsage | null = null; // null = show all
@@ -418,28 +418,38 @@ function getEditorIcon(editor: string): string {
418418

419419
function sortSessionFiles(files: SessionFileDetails[]): SessionFileDetails[] {
420420
return [...files].sort((a, b) => {
421-
const aVal = a.lastInteraction;
422-
const bVal = b.lastInteraction;
423-
424-
// Handle null values - push them to the end
425-
if (!aVal && !bVal) {
421+
let aNum: number;
422+
let bNum: number;
423+
424+
if (currentSortColumn === "lastInteraction") {
425+
const aVal = a.lastInteraction;
426+
const bVal = b.lastInteraction;
427+
if (!aVal && !bVal) { return 0; }
428+
if (!aVal) { return 1; }
429+
if (!bVal) { return -1; }
430+
aNum = new Date(aVal).getTime();
431+
bNum = new Date(bVal).getTime();
432+
} else if (currentSortColumn === "size") {
433+
aNum = a.size || 0;
434+
bNum = b.size || 0;
435+
} else if (currentSortColumn === "tokens") {
436+
aNum = a.tokens || 0;
437+
bNum = b.tokens || 0;
438+
} else if (currentSortColumn === "interactions") {
439+
aNum = a.interactions || 0;
440+
bNum = b.interactions || 0;
441+
} else if (currentSortColumn === "contextRefs") {
442+
aNum = getTotalContextRefs(a.contextReferences);
443+
bNum = getTotalContextRefs(b.contextReferences);
444+
} else {
426445
return 0;
427446
}
428-
if (!aVal) {
429-
return 1;
430-
}
431-
if (!bVal) {
432-
return -1;
433-
}
434-
435-
const aTime = new Date(aVal).getTime();
436-
const bTime = new Date(bVal).getTime();
437447

438-
return currentSortDirection === "desc" ? bTime - aTime : aTime - bTime;
448+
return currentSortDirection === "desc" ? bNum - aNum : aNum - bNum;
439449
});
440450
}
441451

442-
function getSortIndicator(column: "lastInteraction"): string {
452+
function getSortIndicator(column: typeof currentSortColumn): string {
443453
if (currentSortColumn !== column) {
444454
return "";
445455
}
@@ -634,10 +644,10 @@ function renderSessionTable(
634644
<th>Editor</th>
635645
<th>Title</th>
636646
<th>Repository</th>
637-
<th>Size</th>
638-
<th>Tokens</th>
639-
<th>Interactions</th>
640-
<th>Context Refs</th>
647+
<th class="sortable" data-sort="size">Size${getSortIndicator("size")}</th>
648+
<th class="sortable" data-sort="tokens">Tokens${getSortIndicator("tokens")}</th>
649+
<th class="sortable" data-sort="interactions">Interactions${getSortIndicator("interactions")}</th>
650+
<th class="sortable" data-sort="contextRefs">Context Refs${getSortIndicator("contextRefs")}</th>
641651
<th class="sortable" data-sort="lastInteraction">Last Interaction${getSortIndicator("lastInteraction")}</th>
642652
<th>Actions</th>
643653
</tr>
@@ -1575,7 +1585,7 @@ function renderLayout(data: DiagnosticsData): void {
15751585
header.addEventListener("click", () => {
15761586
const sortColumn = (header as HTMLElement).getAttribute(
15771587
"data-sort",
1578-
) as "lastInteraction";
1588+
) as typeof currentSortColumn;
15791589
if (sortColumn) {
15801590
// Toggle direction if same column, otherwise default to desc
15811591
if (currentSortColumn === sortColumn) {

0 commit comments

Comments
 (0)