getaimeter 0.7.9 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/tray.ps1 +9 -4
- package/watcher.js +56 -5
package/package.json
CHANGED
package/tray.ps1
CHANGED
|
@@ -55,10 +55,15 @@ $dashboard.Add_Click({ Start-Process "https://getaimeter.com/dashboard" })
|
|
|
55
55
|
$logs = $menu.Items.Add("View Logs")
|
|
56
56
|
$viewerScript = Join-Path (Split-Path $MyInvocation.MyCommand.Path) 'log-viewer.ps1'
|
|
57
57
|
$logs.Add_Click({
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
# Launch log viewer directly via PowerShell — avoids VBS quoting issues with paths containing spaces
|
|
59
|
+
Start-Process "powershell" -ArgumentList @(
|
|
60
|
+
"-NoProfile",
|
|
61
|
+
"-ExecutionPolicy", "Bypass",
|
|
62
|
+
"-STA",
|
|
63
|
+
"-WindowStyle", "Hidden",
|
|
64
|
+
"-File", $viewerScript,
|
|
65
|
+
"-LogPath", $LogPath
|
|
66
|
+
) -WindowStyle Hidden
|
|
62
67
|
})
|
|
63
68
|
|
|
64
69
|
$menu.Items.Add("-")
|
package/watcher.js
CHANGED
|
@@ -67,8 +67,28 @@ function detectSource(filePath) {
|
|
|
67
67
|
}
|
|
68
68
|
|
|
69
69
|
if (normalized.includes('.copilot/') || normalized.includes('/copilot/')) {
|
|
70
|
-
|
|
71
|
-
|
|
70
|
+
// Check session.start or vscode.metadata.json to detect CLI vs VS Code
|
|
71
|
+
let copilotSource = 'copilot_cli';
|
|
72
|
+
try {
|
|
73
|
+
// Check for vscode.metadata.json alongside events.jsonl
|
|
74
|
+
const dir = path.dirname(filePath);
|
|
75
|
+
if (fs.existsSync(path.join(dir, 'vscode.metadata.json'))) {
|
|
76
|
+
copilotSource = 'copilot_vscode';
|
|
77
|
+
} else {
|
|
78
|
+
// Read first line for session.start producer field
|
|
79
|
+
const fd = fs.openSync(filePath, 'r');
|
|
80
|
+
const buf = Buffer.alloc(Math.min(1024, fs.fstatSync(fd).size));
|
|
81
|
+
fs.readSync(fd, buf, 0, buf.length, 0);
|
|
82
|
+
fs.closeSync(fd);
|
|
83
|
+
const firstLine = buf.toString('utf8').split('\n')[0];
|
|
84
|
+
const meta = JSON.parse(firstLine);
|
|
85
|
+
if (meta.type === 'session.start' && meta.data?.producer === 'copilot-agent') {
|
|
86
|
+
copilotSource = 'copilot_vscode'; // VS Code agent sessions have "copilot-agent" producer
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
} catch {}
|
|
90
|
+
_sourceCache.set(filePath, copilotSource);
|
|
91
|
+
return copilotSource;
|
|
72
92
|
}
|
|
73
93
|
if (normalized.includes('.gemini/') || normalized.includes('/gemini/')) {
|
|
74
94
|
_sourceCache.set(filePath, 'gemini_cli');
|
|
@@ -236,8 +256,7 @@ function extractNewUsage(filePath) {
|
|
|
236
256
|
continue;
|
|
237
257
|
}
|
|
238
258
|
|
|
239
|
-
// ── Copilot
|
|
240
|
-
// Copilot events: { type: "token_usage", input_tokens, output_tokens, reasoning_tokens, model }
|
|
259
|
+
// ── Copilot format (old: token_usage, new: session.shutdown with modelMetrics) ──
|
|
241
260
|
if (obj.type === 'token_usage' && (obj.input_tokens !== undefined || obj.output_tokens !== undefined)) {
|
|
242
261
|
const copilotModel = obj.model || 'copilot';
|
|
243
262
|
const hashKey = `${filePath}:${lineOffset}:copilot:${obj.input_tokens || 0}:${obj.output_tokens || 0}`;
|
|
@@ -247,7 +266,7 @@ function extractNewUsage(filePath) {
|
|
|
247
266
|
usageEvents.push({
|
|
248
267
|
provider: 'github',
|
|
249
268
|
model: copilotModel,
|
|
250
|
-
source:
|
|
269
|
+
source: detectSource(filePath),
|
|
251
270
|
inputTokens: obj.input_tokens || 0,
|
|
252
271
|
outputTokens: obj.output_tokens || 0,
|
|
253
272
|
thinkingTokens: obj.reasoning_tokens || 0,
|
|
@@ -257,6 +276,38 @@ function extractNewUsage(filePath) {
|
|
|
257
276
|
continue;
|
|
258
277
|
}
|
|
259
278
|
|
|
279
|
+
// GitHub Copilot agent: session.shutdown has per-model usage in data.modelMetrics
|
|
280
|
+
if (obj.type === 'session.shutdown' && obj.data?.modelMetrics) {
|
|
281
|
+
for (const [model, metrics] of Object.entries(obj.data.modelMetrics)) {
|
|
282
|
+
const u = metrics.usage || {};
|
|
283
|
+
const inputTokens = u.inputTokens || 0;
|
|
284
|
+
const outputTokens = u.outputTokens || 0;
|
|
285
|
+
if (inputTokens === 0 && outputTokens === 0) continue;
|
|
286
|
+
|
|
287
|
+
const hashKey = `${filePath}:copilot-shutdown:${model}:${inputTokens}:${outputTokens}`;
|
|
288
|
+
const hash = crypto.createHash('md5').update(hashKey).digest('hex');
|
|
289
|
+
if (isDuplicate(hash)) continue;
|
|
290
|
+
|
|
291
|
+
// Determine provider from model name
|
|
292
|
+
let provider = 'github';
|
|
293
|
+
if (model.includes('claude') || model.includes('anthropic')) provider = 'anthropic';
|
|
294
|
+
else if (model.includes('gpt') || model.includes('o3') || model.includes('o4')) provider = 'openai';
|
|
295
|
+
else if (model.includes('gemini')) provider = 'google';
|
|
296
|
+
|
|
297
|
+
usageEvents.push({
|
|
298
|
+
provider,
|
|
299
|
+
model,
|
|
300
|
+
source: detectSource(filePath),
|
|
301
|
+
inputTokens,
|
|
302
|
+
outputTokens,
|
|
303
|
+
thinkingTokens: 0,
|
|
304
|
+
cacheReadTokens: u.cacheReadTokens || 0,
|
|
305
|
+
cacheWriteTokens: u.cacheWriteTokens || 0,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
continue;
|
|
309
|
+
}
|
|
310
|
+
|
|
260
311
|
// ── Gemini CLI format ─────────────────────────────────────────
|
|
261
312
|
// Gemini events may contain usageMetadata: { promptTokenCount, candidatesTokenCount, totalTokenCount }
|
|
262
313
|
if (obj.usageMetadata && (obj.usageMetadata.promptTokenCount || obj.usageMetadata.candidatesTokenCount)) {
|