Skip to content

Commit a98a04d

Browse files
Copilotrajbos
andcommitted
Add Environmental Impact and Fluency Score views to Visual Studio extension (#483)
* Initial plan * Implement environmental and maturity views for Visual Studio extension Co-authored-by: rajbos <6085745+rajbos@users.noreply.github.com> Agent-Logs-Url: https://github.com/rajbos/github-copilot-token-usage/sessions/07d7e46e-e18f-417b-9794-3e80d4083899 * Add Environmental Impact and Fluency Score views to Visual Studio extension Co-authored-by: rajbos <6085745+rajbos@users.noreply.github.com> Agent-Logs-Url: https://github.com/rajbos/github-copilot-token-usage/sessions/07d7e46e-e18f-417b-9794-3e80d4083899 * update gitignore to fix merge conflicts * Add maturity.js to CopilotTokenTracker webview for enhanced functionality * Enhance error handling in CLI bridge and stats retrieval for improved robustness * Implement structure for code changes tracking * Refactor GetUsageStatsAsync to prevent duplicate CLI calls by reusing in-flight tasks * Add dashboard view fallback in TokenTrackerControl and update postMessage handling in vscode-shim * Bump cache version and enhance SessionData structure; add loading and error HTML builders for improved user feedback * feat: Enhance Copilot Token Tracker with new CLI commands and UI improvements - Added `chart` command to output daily token usage data in JSON format. - Introduced `usage-analysis` command for detailed usage analysis stats. - Updated ToolbarInfoCommand to reset the view to details instead of refreshing. - Modified CopilotTokenTrackerPackage.vsct to reflect changes in tooltip text. - Implemented caching mechanism in TokenTrackerControl to improve loading times. - Added methods to fetch chart and usage analysis data from the CLI. - Enhanced error handling and logging in TokenTrackerControl. - Improved HTML rendering in ThemedHtmlBuilder to hide unsupported views in Visual Studio. - Created GitHub Actions workflow for building and packaging the Visual Studio extension. * feat: Add npm build and compile commands to auto-approve settings * feat: Enhance usage analysis with model tier classification and unified tool display across periods * Docs updates * Fix initial load --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: rajbos <6085745+rajbos@users.noreply.github.com> Co-authored-by: Rob Bos <raj.bos@gmail.com>
1 parent 6f28d90 commit a98a04d

File tree

32 files changed

+52193
-521
lines changed

32 files changed

+52193
-521
lines changed

.github/instructions/visualstudio-extension.instructions.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,39 @@ Or from the repo root:
2929
./build.ps1 -Project visualstudio
3030
```
3131

32+
## Build Validation
33+
34+
VSIX projects require Visual Studio's MSBuild toolchain — **not `dotnet build`**.
35+
36+
### Correct way: use `build.ps1`
37+
38+
Always build the VS extension via the root orchestrator:
39+
```powershell
40+
# From the repo root:
41+
./build.ps1 -Project visualstudio
42+
```
43+
44+
This uses `vswhere.exe` to locate the correct `MSBuild.exe` from the Visual Studio install. Running `dotnet build` against the `.csproj` directly **always fails** with:
45+
```
46+
error MSB4018: The "GenerateResourceAndCtoFileManifests" task failed unexpectedly.
47+
```
48+
That error is a `dotnet build` / VSSDK incompatibility, **not a code error** — ignore it if seen.
49+
50+
### Checking for C# compiler errors without a full build
51+
52+
```powershell
53+
# From the repo root:
54+
./build.ps1 -Project visualstudio 2>&1 | Select-String -Pattern "error CS|FAILED"
55+
# No "error CS" lines = no compiler errors
56+
```
57+
58+
- The language server (Roslyn / `get_errors` tool) surfaces C# errors in the IDE without a build run.
59+
- After editing C# files, call `get_errors` on the changed files first, then run `./build.ps1 -Project visualstudio` to confirm a clean MSBuild result.
60+
61+
### C# interpolated verbatim strings (`$@"..."`) — escaping `{` / `}`
62+
63+
HTML templates in `ThemedHtmlBuilder.cs` use C# `$@"..."` strings. Literal `{` and `}` characters inside embedded JavaScript **must** be doubled (`{{` / `}}`) to avoid being treated as interpolation holes. Forgetting this produces `CS1073`, `CS1012`, `CS1011` errors at the JS lines.
64+
3265
## Session File Discovery
3366

3467
Visual Studio Copilot Chat stores sessions as MessagePack-encoded binary files:

.github/workflows/cli-build.yml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,14 @@ jobs:
111111
working-directory: cli
112112
run: node dist/cli.js diagnostics
113113

114+
- name: Validate chart command
115+
working-directory: cli
116+
run: node dist/cli.js chart --json
117+
118+
- name: Validate usage-analysis command
119+
working-directory: cli
120+
run: node dist/cli.js usage-analysis --json
121+
114122
- name: Build production bundle
115123
working-directory: cli
116124
run: npm run build:production
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
name: Visual Studio Extension - Build & Package
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
paths:
7+
- 'visualstudio-extension/**'
8+
- 'cli/**'
9+
- 'vscode-extension/src/sessionDiscovery.ts'
10+
- 'vscode-extension/src/sessionParser.ts'
11+
- 'vscode-extension/src/tokenEstimation.ts'
12+
- 'vscode-extension/src/maturityScoring.ts'
13+
- 'vscode-extension/src/usageAnalysis.ts'
14+
- 'vscode-extension/src/opencode.ts'
15+
- 'vscode-extension/src/visualstudio.ts'
16+
- 'vscode-extension/src/types.ts'
17+
- 'vscode-extension/src/tokenEstimators.json'
18+
- 'vscode-extension/src/modelPricing.json'
19+
- 'vscode-extension/src/toolNames.json'
20+
- '.github/workflows/visualstudio-build.yml'
21+
pull_request:
22+
branches: [ main, develop ]
23+
paths:
24+
- 'visualstudio-extension/**'
25+
- 'cli/**'
26+
- 'vscode-extension/src/sessionDiscovery.ts'
27+
- 'vscode-extension/src/sessionParser.ts'
28+
- 'vscode-extension/src/tokenEstimation.ts'
29+
- 'vscode-extension/src/maturityScoring.ts'
30+
- 'vscode-extension/src/usageAnalysis.ts'
31+
- 'vscode-extension/src/opencode.ts'
32+
- 'vscode-extension/src/visualstudio.ts'
33+
- 'vscode-extension/src/types.ts'
34+
- 'vscode-extension/src/tokenEstimators.json'
35+
- 'vscode-extension/src/modelPricing.json'
36+
- 'vscode-extension/src/toolNames.json'
37+
- '.github/workflows/visualstudio-build.yml'
38+
workflow_dispatch:
39+
inputs:
40+
publish_marketplace:
41+
description: 'Publish to VS Marketplace after packaging'
42+
required: false
43+
default: false
44+
type: boolean
45+
46+
permissions:
47+
contents: read
48+
49+
jobs:
50+
build:
51+
name: Build & Package
52+
# Windows required: Node.js SEA (bundle-exe.ps1) and MSBuild/VSSDK are Windows-only
53+
runs-on: windows-latest
54+
55+
steps:
56+
- name: Harden the runner (Audit all outbound calls)
57+
uses: step-security/harden-runner@fa2e9d605c4eeb9fcad4c99c224cee0c6c7f3594 # v2.16.0
58+
with:
59+
egress-policy: audit
60+
61+
- name: Checkout code
62+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
63+
64+
- name: Setup Node.js
65+
uses: actions/setup-node@53b83947a5a98c8d113130e565377fae1a50d02f # v6.3.0
66+
with:
67+
node-version: '22.x'
68+
69+
# ── Install dependencies ────────────────────────────────────────────────
70+
71+
- name: Install vscode-extension dependencies
72+
run: npm ci
73+
working-directory: vscode-extension
74+
75+
- name: Install CLI dependencies
76+
run: npm ci
77+
working-directory: cli
78+
79+
# ── Build & validate CLI (js bundle) ───────────────────────────────────
80+
81+
- name: Build CLI (production bundle)
82+
working-directory: cli
83+
run: npm run build:production
84+
85+
- name: Validate CLI --help
86+
working-directory: cli
87+
run: node dist/cli.js --help
88+
89+
- name: Validate CLI new commands
90+
working-directory: cli
91+
run: |
92+
node dist/cli.js chart --json
93+
node dist/cli.js usage-analysis --json
94+
95+
# ── Bundle CLI as Windows .exe (Node.js SEA) ───────────────────────────
96+
97+
- name: Bundle CLI as single executable
98+
working-directory: cli
99+
shell: pwsh
100+
run: |
101+
& pwsh -NoProfile -File bundle-exe.ps1 -SkipBuild
102+
if ($LASTEXITCODE -ne 0) { throw "bundle-exe.ps1 failed" }
103+
104+
- name: Verify CLI exe was produced
105+
working-directory: cli
106+
shell: pwsh
107+
run: |
108+
$exe = "dist\copilot-token-tracker.exe"
109+
if (-not (Test-Path $exe)) { throw "CLI exe not found at $exe" }
110+
$sizeMB = [math]::Round((Get-Item $exe).Length / 1MB, 1)
111+
Write-Host "✅ CLI exe: $exe ($sizeMB MB)"
112+
113+
# ── Copy CLI bundle into VS extension project ──────────────────────────
114+
115+
- name: Copy CLI exe + wasm to cli-bundle/
116+
shell: pwsh
117+
run: |
118+
$vsCliDir = "visualstudio-extension\src\CopilotTokenTracker\cli-bundle"
119+
New-Item -ItemType Directory -Path $vsCliDir -Force | Out-Null
120+
Copy-Item "cli\dist\copilot-token-tracker.exe" "$vsCliDir\copilot-token-tracker.exe" -Force
121+
Copy-Item "cli\dist\sql-wasm.wasm" "$vsCliDir\sql-wasm.wasm" -Force
122+
Write-Host "✅ Copied cli-bundle assets"
123+
124+
# ── Build webview bundles (chart.js, usage.js, etc.) ──────────────────
125+
126+
- name: Build VS Code extension webview bundles
127+
working-directory: vscode-extension
128+
run: npm run package
129+
130+
- name: Copy webview bundles to VS extension project
131+
shell: pwsh
132+
run: |
133+
$src = "vscode-extension\dist\webview"
134+
$dst = "visualstudio-extension\src\CopilotTokenTracker\webview"
135+
if (Test-Path $dst) { Remove-Item $dst -Recurse -Force }
136+
Copy-Item $src $dst -Recurse -Force
137+
Write-Host "✅ Copied webview bundles:"
138+
Get-ChildItem $dst -Filter "*.js" | ForEach-Object { Write-Host " $($_.Name)" }
139+
140+
# ── Build Visual Studio extension (MSBuild / VSSDK) ───────────────────
141+
142+
- name: Add MSBuild to PATH
143+
uses: microsoft/setup-msbuild@6fb02220983dee41ce7ae257b6f4d8f9bf5ed4ce # v2.0.0
144+
145+
- name: Restore NuGet packages
146+
working-directory: visualstudio-extension
147+
run: nuget restore CopilotTokenTracker.sln
148+
149+
- name: Build solution (Release)
150+
working-directory: visualstudio-extension
151+
run: msbuild CopilotTokenTracker.sln /p:Configuration=Release /t:Build /v:minimal
152+
153+
# ── Collect the produced .vsix ─────────────────────────────────────────
154+
155+
- name: Find .vsix artifact
156+
id: vsix
157+
shell: pwsh
158+
run: |
159+
$vsix = Get-ChildItem -Path "visualstudio-extension" -Filter "*.vsix" -Recurse |
160+
Sort-Object LastWriteTime -Descending |
161+
Select-Object -First 1
162+
if (-not $vsix) { throw "No .vsix file produced" }
163+
$sizeMB = [math]::Round($vsix.Length / 1MB, 1)
164+
Write-Host "✅ VSIX: $($vsix.FullName) ($sizeMB MB)"
165+
echo "vsix_path=$($vsix.FullName)" >> $env:GITHUB_OUTPUT
166+
echo "vsix_name=$($vsix.Name)" >> $env:GITHUB_OUTPUT
167+
168+
- name: Upload .vsix as artifact
169+
uses: actions/upload-artifact@bbbca2ddaa5d8feaa63e36b76fdaad77386f024f # v7.0.0
170+
with:
171+
name: copilot-token-tracker-vs-${{ github.sha }}
172+
path: ${{ steps.vsix.outputs.vsix_path }}
173+
retention-days: 30
174+
175+
# ── (Optional) Publish to VS Marketplace ──────────────────────────────
176+
177+
- name: Publish to Visual Studio Marketplace
178+
if: github.event_name == 'workflow_dispatch' && inputs.publish_marketplace == true
179+
shell: pwsh
180+
env:
181+
VS_MARKETPLACE_PAT: ${{ secrets.VS_MARKETPLACE_PAT }}
182+
run: |
183+
if (-not $env:VS_MARKETPLACE_PAT) {
184+
Write-Error "❌ VS_MARKETPLACE_PAT secret is not configured."
185+
exit 1
186+
}
187+
$vsix = "${{ steps.vsix.outputs.vsix_path }}"
188+
Write-Host "Publishing $vsix to Visual Studio Marketplace..."
189+
& npx @vscode/vsce publish --packagePath $vsix --pat $env:VS_MARKETPLACE_PAT
190+
if ($LASTEXITCODE -ne 0) { throw "Marketplace publish failed" }
191+
Write-Host "✅ Published to Visual Studio Marketplace"
192+
193+
# ── Summary ────────────────────────────────────────────────────────────
194+
195+
- name: Build summary
196+
if: always()
197+
shell: pwsh
198+
run: |
199+
$vsixName = "${{ steps.vsix.outputs.vsix_name }}"
200+
if ($vsixName) {
201+
@"
202+
## ✅ Visual Studio Extension Built Successfully
203+
204+
| Item | Value |
205+
|------|-------|
206+
| VSIX | ``$vsixName`` |
207+
| Trigger | ``${{ github.event_name }}`` |
208+
| Commit | ``${{ github.sha }}`` |
209+
"@ >> $env:GITHUB_STEP_SUMMARY
210+
} else {
211+
"## ❌ Build failed — no .vsix produced" >> $env:GITHUB_STEP_SUMMARY
212+
}

.gitignore

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,12 @@ node_modules
99
.github/scripts/scraped-models.json
1010
example.json
1111
log-example.txt
12-
13-
# Visual Studio extension generated files
14-
visualstudio-extension/**/obj/
15-
visualstudio-extension/**/bin/
1612
visualstudio-extension/.vs/
17-
visualstudio-extension/**/obj/**
18-
visualstudio-extension/**/bin/**
19-
20-
# Accidental nested Visual Studio extension workspace/build output
21-
visualstudio-extension/visualstudio-extension/
22-
visualstudio-extension/src/CopilotTokenTracker/bin/Release/net472/MessagePack.Annotations.dll
23-
visualstudio-extension/src/CopilotTokenTracker/bin/Release/net472/System.Buffers.dll
24-
25-
# Bundled CLI exe (build artifact copied from cli/dist/)
13+
visualstudio-extension/src/CopilotTokenTracker/bin/
14+
visualstudio-extension/src/CopilotTokenTracker/obj/
2615
visualstudio-extension/src/CopilotTokenTracker/cli-bundle/
27-
28-
# Node.js SEA build artifacts
29-
cli/dist/sea-prep.blob
30-
cli/dist/copilot-token-tracker.exe
16+
visualstudio-extension/src/CopilotTokenTrackerRunner/bin/
17+
visualstudio-extension/src/CopilotTokenTrackerRunner/obj/
18+
visualstudio-extension/src/CopilotTokenTrackerRunner/cli-bundle/
19+
visualstudio-extension/visualstudio-extension/src/CopilotTokenTrackerRunner/obj/
20+
visualstudio-extension/src/CopilotTokenTracker/obj/project.nuget.cache

.vscode/settings.json

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@
2424
"approve": true,
2525
"matchCommandLine": true
2626
},
27-
"npx eslint": true
27+
"npx eslint": true,
28+
"dotnet build": true,
29+
".\\build.ps1": true,
30+
"npm run build": true,
31+
"npm run compile": true
2832
}
2933
}

0 commit comments

Comments
 (0)