Skip to content

Commit 429481e

Browse files
authored
Merge pull request #510 from rajbos/team-dashboard
team dashboard
2 parents 7bdfe49 + ffaa01f commit 429481e

File tree

12 files changed

+703
-72
lines changed

12 files changed

+703
-72
lines changed

.claude/settings.local.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"permissions": {
3+
"allow": [
4+
"Bash(xargs grep:*)"
5+
]
6+
}
7+
}

.github/workflows/cli-publish.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,10 +71,13 @@ jobs:
7171

7272
- name: Determine trigger type
7373
id: trigger_type
74+
env:
75+
EVENT_NAME: ${{ github.event_name }}
76+
GIT_REF: ${{ github.ref }}
7477
run: |
75-
if [[ "$GITHUB_EVENT_NAME" == "push" && "$GITHUB_REF" == refs/tags/cli/v* ]]; then
78+
if [[ "$EVENT_NAME" == "push" && "$GIT_REF" == refs/tags/cli/v* ]]; then
7679
echo "is_tag=true" >> "$GITHUB_OUTPUT"
77-
TAG_VERSION=${GITHUB_REF#refs/tags/cli/v}
80+
TAG_VERSION=${GIT_REF#refs/tags/cli/v}
7881
echo "tag_version=$TAG_VERSION" >> "$GITHUB_OUTPUT"
7982
echo "Triggered by tag push: cli/v$TAG_VERSION"
8083
else

vscode-extension/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "copilot-token-tracker",
33
"displayName": "AI Engineering Fluency",
4-
"description": "Track your AI Engineering Fluency — daily and monthly token usage, cost estimates, and productivity insights in VS Code.",
4+
"description": "Track your AI Engineering Fluency — daily and monthly token usage, cost estimates, and AI fluency insights in VS Code.",
55
"version": "0.0.24",
66
"publisher": "RobBos",
77
"icon": "assets/logo.png",

vscode-extension/src/backend/facade.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ export interface BackendFacadeDeps {
7373
modelUsage: ModelUsage;
7474
timestamp: number;
7575
}>;
76+
// Crush session handling (per-project crush.db virtual paths)
77+
isCrushSession?: (sessionFile: string) => boolean;
78+
getCrushSessionData?: (sessionFile: string) => Promise<{
79+
tokens: number;
80+
interactions: number;
81+
modelUsage: ModelUsage;
82+
timestamp: number;
83+
}>;
84+
// Visual Studio session detection (binary MessagePack — cannot be parsed as JSON)
85+
isVSSessionFile?: (sessionFile: string) => boolean;
7686
}
7787

7888
export class BackendFacade {
@@ -126,6 +136,9 @@ export class BackendFacade {
126136
statSessionFile: deps.statSessionFile,
127137
isOpenCodeSession: deps.isOpenCodeSession,
128138
getOpenCodeSessionData: deps.getOpenCodeSessionData,
139+
isCrushSession: deps.isCrushSession,
140+
getCrushSessionData: deps.getCrushSessionData,
141+
isVSSessionFile: deps.isVSSessionFile,
129142
},
130143
this.credentialService,
131144
this.dataPlaneService,
@@ -441,6 +454,18 @@ export class BackendFacade {
441454
return result;
442455
}
443456

457+
/**
458+
* Backfill historical data to Azure Table Storage.
459+
* Scans ALL local session files (ignoring the mtime-based age filter) and upserts daily
460+
* rollups for every day within the given lookback window (default 365 days).
461+
* Use this when the normal sync has missed data due to the mtime filter.
462+
*/
463+
public async backfillHistoricalData(maxLookbackDays = 365, onProgress?: (processed: number, total: number, daysFound: number) => void): Promise<void> {
464+
const settings = this.getSettings();
465+
await this.syncService.backfillSync(settings, this.isConfigured(settings), maxLookbackDays, onProgress);
466+
this.clearQueryCache();
467+
}
468+
444469
public async tryGetBackendDetailedStatsForStatusBar(
445470
settings: BackendSettings,
446471
): Promise<any | undefined> {

vscode-extension/src/backend/services/dataPlaneService.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -309,11 +309,13 @@ export class DataPlaneService {
309309
const dsPrefix = `ds:${datasetId}`;
310310
const uPrefix = `u:${userId}`;
311311

312-
const startDate = new Date(startDayKey);
313-
const endDate = new Date(endDayKey);
314-
endDate.setUTCHours(23, 59, 59, 999);
315-
316-
const filter = `Timestamp ge datetime'${startDate.toISOString()}' and Timestamp le datetime'${endDate.toISOString()}'`;
312+
// Filter by PartitionKey range instead of system Timestamp.
313+
// PartitionKey format is "ds:{datasetId}|d:{YYYY-MM-DD}".
314+
// Using system Timestamp would miss entities written by older syncs (e.g. written March 1
315+
// for day "2026-03-15") because their Timestamp predates the startDayKey.
316+
const pkStart = buildAggPartitionKey(datasetId, startDayKey);
317+
const pkEnd = buildAggPartitionKey(datasetId, endDayKey);
318+
const filter = `PartitionKey ge '${pkStart}' and PartitionKey le '${pkEnd}'`;
317319

318320
this.log(
319321
`Deleting entities for user "${userId}" in dataset "${datasetId}" (${startDayKey} to ${endDayKey})`,

0 commit comments

Comments
 (0)