a2zusage 1.0.8 → 1.0.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 +21 -1
- package/package.json +1 -1
- package/scripts/gemini-wrapper.sh +87 -0
package/README.md
CHANGED
|
@@ -78,7 +78,7 @@ a2zusage supports **14+ AI coding tools** out of the box:
|
|
|
78
78
|
| **Cline / Roo Code** | VS Code extension storage | ✅ Exact token counts (when stored by the extension) |
|
|
79
79
|
| **OpenCode** | Local JSON files | ✅ Exact token counts (when present in session/message usage fields) |
|
|
80
80
|
| **OpenAI Codex** | OpenAI Usage API | ✅ Exact token counts (requires API key + org access) |
|
|
81
|
-
|
|
81
|
+
|| **Gemini CLI** | Local telemetry (`~/.gemini/`) | ✅ Exact token counts with wrapper (see [Gemini CLI Setup](#gemini-cli-setup)) |
|
|
82
82
|
| **Amazon Q Developer** | Local logs | ⚠️ Best-effort: logs may not contain token totals |
|
|
83
83
|
| **Tabnine** | Local logs | ⚠️ Partial: uses explicit token fields when present; no invented prompt/context tokens |
|
|
84
84
|
| **Gemini Code Assist** | Google Cloud | ⚠️ Not implemented in this repo yet |
|
|
@@ -141,6 +141,26 @@ a2zusage -v # Verbose mode with data sources
|
|
|
141
141
|
]
|
|
142
142
|
```
|
|
143
143
|
|
|
144
|
+
## Tool-Specific Setup
|
|
145
|
+
|
|
146
|
+
### Gemini CLI Setup
|
|
147
|
+
|
|
148
|
+
Gemini CLI stores conversation data in encrypted protobuf files. To get accurate token tracking, use our wrapper script that captures the `usageMetadata` from the `--output-format stream-json` output:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
# 1. Copy the wrapper script
|
|
152
|
+
curl -o ~/.local/bin/gemini-wrapper https://raw.githubusercontent.com/aezizhu/a2zaiusage/main/scripts/gemini-wrapper.sh
|
|
153
|
+
chmod +x ~/.local/bin/gemini-wrapper
|
|
154
|
+
|
|
155
|
+
# 2. Create an alias (add to your .bashrc or .zshrc)
|
|
156
|
+
alias gemini="~/.local/bin/gemini-wrapper"
|
|
157
|
+
|
|
158
|
+
# 3. Use gemini as normal - token data is now tracked!
|
|
159
|
+
gemini "Your prompt here"
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The wrapper creates `~/.gemini/a2zusage-telemetry.jsonl` with exact token counts for each request.
|
|
163
|
+
|
|
144
164
|
## Why This Tool?
|
|
145
165
|
|
|
146
166
|
### 🎯 Built for Hiring AI-Native Developers
|
package/package.json
CHANGED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Gemini CLI Wrapper for a2zusage
|
|
3
|
+
# This script wraps the Gemini CLI to capture usage statistics
|
|
4
|
+
#
|
|
5
|
+
# Installation:
|
|
6
|
+
# 1. Make this script executable: chmod +x gemini-wrapper.sh
|
|
7
|
+
# 2. Add alias to your shell: alias gemini='/path/to/gemini-wrapper.sh'
|
|
8
|
+
# Or symlink: ln -s /path/to/gemini-wrapper.sh /usr/local/bin/gemini-tracked
|
|
9
|
+
|
|
10
|
+
USAGE_FILE="${HOME}/.gemini/a2zusage-telemetry.jsonl"
|
|
11
|
+
REAL_GEMINI=$(which -a gemini | grep -v "gemini-wrapper" | head -1)
|
|
12
|
+
|
|
13
|
+
# If no real gemini found, try common paths
|
|
14
|
+
if [ -z "$REAL_GEMINI" ]; then
|
|
15
|
+
for path in /opt/homebrew/bin/gemini /usr/local/bin/gemini ~/.local/bin/gemini; do
|
|
16
|
+
if [ -x "$path" ]; then
|
|
17
|
+
REAL_GEMINI="$path"
|
|
18
|
+
break
|
|
19
|
+
fi
|
|
20
|
+
done
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
if [ -z "$REAL_GEMINI" ]; then
|
|
24
|
+
echo "Error: Could not find gemini CLI" >&2
|
|
25
|
+
exit 1
|
|
26
|
+
fi
|
|
27
|
+
|
|
28
|
+
# Create usage file directory if needed
|
|
29
|
+
mkdir -p "$(dirname "$USAGE_FILE")"
|
|
30
|
+
|
|
31
|
+
# Check if user wants raw output (non-interactive mode)
|
|
32
|
+
if [[ "$*" == *"--output-format"* ]]; then
|
|
33
|
+
# User specified format, run as-is
|
|
34
|
+
exec "$REAL_GEMINI" "$@"
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
# Run gemini with stream-json and process output
|
|
38
|
+
"$REAL_GEMINI" --output-format stream-json "$@" 2>&1 | while IFS= read -r line; do
|
|
39
|
+
# Check if line is JSON
|
|
40
|
+
if echo "$line" | grep -q '^{'; then
|
|
41
|
+
# Parse the JSON event type
|
|
42
|
+
event_type=$(echo "$line" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('type',''))" 2>/dev/null)
|
|
43
|
+
|
|
44
|
+
case "$event_type" in
|
|
45
|
+
"init")
|
|
46
|
+
# Extract model info
|
|
47
|
+
model=$(echo "$line" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('model','unknown'))" 2>/dev/null)
|
|
48
|
+
session_id=$(echo "$line" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('session_id',''))" 2>/dev/null)
|
|
49
|
+
;;
|
|
50
|
+
"message")
|
|
51
|
+
# Display user/assistant messages
|
|
52
|
+
role=$(echo "$line" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('role',''))" 2>/dev/null)
|
|
53
|
+
content=$(echo "$line" | python3 -c "import sys,json; d=json.loads(sys.stdin.read()); print(d.get('content',''))" 2>/dev/null)
|
|
54
|
+
if [ "$role" = "assistant" ]; then
|
|
55
|
+
echo -n "$content"
|
|
56
|
+
fi
|
|
57
|
+
;;
|
|
58
|
+
"result")
|
|
59
|
+
# This is the usage data - log it!
|
|
60
|
+
timestamp=$(date -u +"%Y-%m-%dT%H:%M:%SZ")
|
|
61
|
+
stats=$(echo "$line" | python3 -c "
|
|
62
|
+
import sys, json
|
|
63
|
+
d = json.loads(sys.stdin.read())
|
|
64
|
+
stats = d.get('stats', {})
|
|
65
|
+
print(json.dumps({
|
|
66
|
+
'timestamp': '$timestamp',
|
|
67
|
+
'model': '${model:-unknown}',
|
|
68
|
+
'input_tokens': stats.get('input_tokens', stats.get('input', 0)),
|
|
69
|
+
'output_tokens': stats.get('output_tokens', stats.get('output', 0)),
|
|
70
|
+
'total_tokens': stats.get('total_tokens', 0),
|
|
71
|
+
'cached_tokens': stats.get('cached', 0),
|
|
72
|
+
'duration_ms': stats.get('duration_ms', 0),
|
|
73
|
+
'tool_calls': stats.get('tool_calls', 0)
|
|
74
|
+
}))
|
|
75
|
+
" 2>/dev/null)
|
|
76
|
+
|
|
77
|
+
if [ -n "$stats" ]; then
|
|
78
|
+
echo "$stats" >> "$USAGE_FILE"
|
|
79
|
+
fi
|
|
80
|
+
echo "" # Final newline after response
|
|
81
|
+
;;
|
|
82
|
+
esac
|
|
83
|
+
else
|
|
84
|
+
# Non-JSON output (errors, loading messages, etc.)
|
|
85
|
+
echo "$line" >&2
|
|
86
|
+
fi
|
|
87
|
+
done
|