a2zusage 1.0.8 → 1.0.11
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 +4 -3
- package/package.json +1 -1
- package/scripts/gemini-wrapper.sh +87 -0
package/README.md
CHANGED
|
@@ -28,8 +28,9 @@
|
|
|
28
28
|
├────────────────┼──────────┼───────────────┼─────────────┼─────────────┼───────────────┤
|
|
29
29
|
│ Claude Code │ ✓ Active │ 321K tokens │ 1.4M tokens │ 6.1M tokens │ 24.2M tokens │
|
|
30
30
|
│ Cursor │ ✓ Active │ - │ - │ - │ 32.5K tokens │
|
|
31
|
-
│ Windsurf │ ✓ Active │
|
|
31
|
+
│ Windsurf │ ✓ Active │ 1 req │ 1 req │ 1 req │ 21 reqs │
|
|
32
32
|
│ Warp AI │ ✓ Active │ - │ - │ 8.2M tokens │ 167.1M tokens │
|
|
33
|
+
│ Gemini CLI │ ✓ Active │ - │ 72K tokens │ 101K tokens │ 48.1M tokens │
|
|
33
34
|
│ GitHub Copilot │ ○ N/A │ - │ - │ - │ - │
|
|
34
35
|
│ ... │ ... │ ... │ ... │ ... │ ... │
|
|
35
36
|
╰────────────────┴──────────┴───────────────┴─────────────┴─────────────┴───────────────╯
|
|
@@ -73,12 +74,12 @@ a2zusage supports **14+ AI coding tools** out of the box:
|
|
|
73
74
|
| **Claude Code** | Local JSONL (`~/.claude/projects/`) | ✅ Exact token counts (input/output + cache tokens when present) |
|
|
74
75
|
| **Cursor** | SQLite database | ✅ Exact token counts (when present in DB) |
|
|
75
76
|
| **GitHub Copilot** | GitHub API + Local logs | ⚠️ Usage count / requests only (GitHub does not expose reliable token totals here) |
|
|
76
|
-
|
|
77
|
+
|| **Windsurf** | Cascade sessions (`~/.codeium/`) | ℹ️ Session count only (token data encrypted). Visit windsurf.ai for detailed usage. |
|
|
77
78
|
| **Warp AI** | SQLite database | ✅ Total tokens (Warp does not expose a reliable input/output split) |
|
|
78
79
|
| **Cline / Roo Code** | VS Code extension storage | ✅ Exact token counts (when stored by the extension) |
|
|
79
80
|
| **OpenCode** | Local JSON files | ✅ Exact token counts (when present in session/message usage fields) |
|
|
80
81
|
| **OpenAI Codex** | OpenAI Usage API | ✅ Exact token counts (requires API key + org access) |
|
|
81
|
-
|
|
82
|
+
|| **Gemini CLI** | Native sessions (`~/.gemini/tmp/`) | ✅ Exact token counts from native session files (no setup required) |
|
|
82
83
|
| **Amazon Q Developer** | Local logs | ⚠️ Best-effort: logs may not contain token totals |
|
|
83
84
|
| **Tabnine** | Local logs | ⚠️ Partial: uses explicit token fields when present; no invented prompt/context tokens |
|
|
84
85
|
| **Gemini Code Assist** | Google Cloud | ⚠️ Not implemented in this repo yet |
|
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
|