@vibe-cafe/vibe-usage 0.7.8 → 0.7.9
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/README.md +1 -1
- package/package.json +1 -1
- package/src/api.js +13 -6
package/README.md
CHANGED
|
@@ -64,7 +64,7 @@ npx @vibe-cafe/vibe-usage status # Show config & detected tools
|
|
|
64
64
|
- Parses local session logs from each AI coding tool
|
|
65
65
|
- Aggregates token usage into 30-minute buckets
|
|
66
66
|
- Extracts session metadata from all parsers: active time (AI generation time, excluding queue/TTFT wait), total duration, message counts
|
|
67
|
-
- Uploads buckets + sessions to your vibecafe.ai dashboard
|
|
67
|
+
- Uploads buckets + sessions to your vibecafe.ai dashboard (gzip-compressed when ≥ 1 KB, ~94% smaller)
|
|
68
68
|
- Stateless: computes full totals from local logs each sync (idempotent, no state files)
|
|
69
69
|
- For continuous syncing, use `npx @vibe-cafe/vibe-usage daemon` or the [Vibe Usage Mac app](https://github.com/vibe-cafe/vibe-usage-app)
|
|
70
70
|
|
package/package.json
CHANGED
package/src/api.js
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import https from 'node:https';
|
|
2
2
|
import http from 'node:http';
|
|
3
3
|
import { URL } from 'node:url';
|
|
4
|
+
import { gzipSync } from 'node:zlib';
|
|
4
5
|
|
|
5
6
|
const MAX_RETRIES = 3;
|
|
6
7
|
const INITIAL_DELAY = 1000;
|
|
8
|
+
const GZIP_MIN_BYTES = 1024;
|
|
7
9
|
|
|
8
10
|
export async function ingest(apiUrl, apiKey, buckets, opts, sessions) {
|
|
9
11
|
let lastError;
|
|
@@ -30,18 +32,23 @@ function _send(apiUrl, apiKey, buckets, onProgress, sessions) {
|
|
|
30
32
|
const url = new URL('/api/usage/ingest', apiUrl);
|
|
31
33
|
const payload = { buckets };
|
|
32
34
|
if (sessions && sessions.length > 0) payload.sessions = sessions;
|
|
33
|
-
const
|
|
35
|
+
const raw = Buffer.from(JSON.stringify(payload));
|
|
36
|
+
const useGzip = raw.length >= GZIP_MIN_BYTES;
|
|
37
|
+
const body = useGzip ? gzipSync(raw) : raw;
|
|
34
38
|
const totalBytes = body.length;
|
|
35
39
|
const mod = url.protocol === 'https:' ? https : http;
|
|
36
40
|
|
|
41
|
+
const headers = {
|
|
42
|
+
'Content-Type': 'application/json',
|
|
43
|
+
'Authorization': `Bearer ${apiKey}`,
|
|
44
|
+
'Content-Length': totalBytes,
|
|
45
|
+
};
|
|
46
|
+
if (useGzip) headers['Content-Encoding'] = 'gzip';
|
|
47
|
+
|
|
37
48
|
const req = mod.request(url, {
|
|
38
49
|
method: 'POST',
|
|
39
50
|
timeout: 60_000,
|
|
40
|
-
headers
|
|
41
|
-
'Content-Type': 'application/json',
|
|
42
|
-
'Authorization': `Bearer ${apiKey}`,
|
|
43
|
-
'Content-Length': totalBytes,
|
|
44
|
-
},
|
|
51
|
+
headers,
|
|
45
52
|
}, (res) => {
|
|
46
53
|
let data = '';
|
|
47
54
|
res.on('data', (chunk) => { data += chunk; });
|