getaimeter 0.4.0 → 0.5.0

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.
Files changed (3) hide show
  1. package/config.js +12 -0
  2. package/package.json +1 -1
  3. package/watcher.js +56 -0
package/config.js CHANGED
@@ -76,6 +76,18 @@ function getWatchPaths() {
76
76
  const codexHistory = path.join(os.homedir(), '.codex');
77
77
  if (fs.existsSync(codexHistory) && !paths.includes(codexHistory)) paths.push(codexHistory);
78
78
 
79
+ // 4. GitHub Copilot CLI sessions
80
+ const copilotSessions = path.join(os.homedir(), '.copilot', 'session-state');
81
+ if (fs.existsSync(copilotSessions)) paths.push(copilotSessions);
82
+
83
+ // 5. Gemini CLI sessions
84
+ const geminiDir = path.join(os.homedir(), '.gemini', 'tmp');
85
+ if (fs.existsSync(geminiDir)) {
86
+ // Gemini stores sessions under ~/.gemini/tmp/<project_hash>/chats/
87
+ // Watch the entire tmp dir and findJsonlFiles will recurse into it
88
+ paths.push(geminiDir);
89
+ }
90
+
79
91
  return paths;
80
92
  }
81
93
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "getaimeter",
3
- "version": "0.4.0",
3
+ "version": "0.5.0",
4
4
  "description": "Track your Claude AI usage across CLI, VS Code, and Desktop App. One command to start.",
5
5
  "bin": {
6
6
  "aimeter": "cli.js"
package/watcher.js CHANGED
@@ -65,6 +65,19 @@ function detectSource(filePath) {
65
65
  }
66
66
  }
67
67
 
68
+ if (normalized.includes('.copilot/') || normalized.includes('/copilot/')) {
69
+ _sourceCache.set(filePath, 'copilot_cli');
70
+ return 'copilot_cli';
71
+ }
72
+ if (normalized.includes('.gemini/') || normalized.includes('/gemini/')) {
73
+ _sourceCache.set(filePath, 'gemini_cli');
74
+ return 'gemini_cli';
75
+ }
76
+ if (normalized.includes('.codex/') || normalized.includes('/codex/')) {
77
+ _sourceCache.set(filePath, 'codex_cli');
78
+ return 'codex_cli';
79
+ }
80
+
68
81
  // Read first 10KB of the file to find entrypoint or IDE markers
69
82
  let source = 'cli'; // default
70
83
  try {
@@ -182,6 +195,49 @@ function extractNewUsage(filePath) {
182
195
  continue;
183
196
  }
184
197
 
198
+ // ── Copilot CLI format ────────────────────────────────────────
199
+ // Copilot events: { type: "token_usage", input_tokens, output_tokens, reasoning_tokens, model }
200
+ if (obj.type === 'token_usage' && (obj.input_tokens !== undefined || obj.output_tokens !== undefined)) {
201
+ const copilotModel = obj.model || 'copilot';
202
+ const hashKey = `${filePath}:${lineOffset}:copilot:${obj.input_tokens || 0}:${obj.output_tokens || 0}`;
203
+ const hash = crypto.createHash('md5').update(hashKey).digest('hex');
204
+ if (isDuplicate(hash)) continue;
205
+
206
+ usageEvents.push({
207
+ provider: 'github',
208
+ model: copilotModel,
209
+ source: 'copilot_cli',
210
+ inputTokens: obj.input_tokens || 0,
211
+ outputTokens: obj.output_tokens || 0,
212
+ thinkingTokens: obj.reasoning_tokens || 0,
213
+ cacheReadTokens: 0,
214
+ cacheWriteTokens: 0,
215
+ });
216
+ continue;
217
+ }
218
+
219
+ // ── Gemini CLI format ─────────────────────────────────────────
220
+ // Gemini events may contain usageMetadata: { promptTokenCount, candidatesTokenCount, totalTokenCount }
221
+ if (obj.usageMetadata && (obj.usageMetadata.promptTokenCount || obj.usageMetadata.candidatesTokenCount)) {
222
+ const um = obj.usageMetadata;
223
+ const geminiModel = obj.modelVersion || obj.model || 'gemini';
224
+ const hashKey = `${filePath}:${lineOffset}:gemini:${um.promptTokenCount || 0}:${um.candidatesTokenCount || 0}`;
225
+ const hash = crypto.createHash('md5').update(hashKey).digest('hex');
226
+ if (isDuplicate(hash)) continue;
227
+
228
+ usageEvents.push({
229
+ provider: 'google',
230
+ model: geminiModel,
231
+ source: 'gemini_cli',
232
+ inputTokens: um.promptTokenCount || 0,
233
+ outputTokens: um.candidatesTokenCount || 0,
234
+ thinkingTokens: um.thoughtsTokenCount || 0,
235
+ cacheReadTokens: um.cachedContentTokenCount || 0,
236
+ cacheWriteTokens: 0,
237
+ });
238
+ continue;
239
+ }
240
+
185
241
  continue;
186
242
  }
187
243