diff --git a/README.md b/README.md index 3cabec7..966da83 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ The installer automatically exposes scripts from the `scripts/` directory as glo - **`blob_glass [on|off|toggle]`**: A quick toggle to enable or disable window transparency on the fly. - **`blob_boot [path]`**: Safely updates your Plymouth boot splash image (defaults to `branding/boot_flash.png`) and rebuilds the `initramfs` (GRUB compatible via `mkinitcpio`). - **`blob_wifi`**: A streamlined script to connect to the GMU Eduroam Wi-Fi network using `iwd` and `systemd-resolved` (replaces NetworkManager). -- **`blob_key [NAME] [VALUE]`**: Stores secrets/env values for widgets and services, e.g. `blob_key set ANTHROPIC_ADMIN_KEY sk-ant-admin01-...` for the Claude Code Usage card in the quick settings panel. +- **`blob_key [NAME] [VALUE]`**: Stores secrets/env values for widgets and services, e.g. `blob_key set SOME_TOKEN value`. ## Installation diff --git a/ags/lib/claude-usage.sh b/ags/lib/claude-usage.sh index 35d7ea3..f5246ed 100755 --- a/ags/lib/claude-usage.sh +++ b/ags/lib/claude-usage.sh @@ -1,34 +1,25 @@ #!/bin/bash -KEY_FILE="$HOME/.config/ags/secrets/ANTHROPIC_ADMIN_KEY" +PROJECTS_DIR="$HOME/.claude/projects" +TODAY=$(date -u '+%Y-%m-%d') -if [ ! -f "$KEY_FILE" ]; then - echo '{"available":false,"tokens":0,"costUsd":0}' +if [ ! -d "$PROJECTS_DIR" ]; then + echo '{"available":false,"tokens":0,"messages":0}' exit 0 fi -ADMIN_KEY=$(cat "$KEY_FILE") -TODAY_START=$(date -u '+%Y-%m-%dT00:00:00Z') -TODAY_END=$(date -u -d tomorrow '+%Y-%m-%dT00:00:00Z') +FILES=$(find "$PROJECTS_DIR" -name "*.jsonl" -newermt "$TODAY") -USAGE_JSON=$(curl -fsS --max-time 6 \ - -H "anthropic-version: 2023-06-01" \ - -H "x-api-key: $ADMIN_KEY" \ - "https://api.anthropic.com/v1/organizations/usage_report/messages?starting_at=${TODAY_START}&ending_at=${TODAY_END}&bucket_width=1d") - -COST_JSON=$(curl -fsS --max-time 6 \ - -H "anthropic-version: 2023-06-01" \ - -H "x-api-key: $ADMIN_KEY" \ - "https://api.anthropic.com/v1/organizations/cost_report?starting_at=${TODAY_START}&ending_at=${TODAY_END}&bucket_width=1d") - -if [ -z "$USAGE_JSON" ] || [ -z "$COST_JSON" ]; then - echo '{"available":false,"tokens":0,"costUsd":0}' +if [ -z "$FILES" ]; then + echo '{"available":true,"tokens":0,"messages":0}' exit 0 fi -TOKENS=$(echo "$USAGE_JSON" | jq '[(.data // [])[].results[]? | (.uncached_input_tokens // 0) + (.cache_read_input_tokens // 0) + (.cache_creation.ephemeral_1h_input_tokens // 0) + (.cache_creation.ephemeral_5m_input_tokens // 0) + (.output_tokens // 0)] | add // 0') - -COST_CENTS=$(echo "$COST_JSON" | jq '[(.data // [])[].results[]?.amount | tonumber] | add // 0') - -jq -n --argjson tokens "$TOKENS" --argjson costCents "$COST_CENTS" \ - '{available: true, tokens: $tokens, costUsd: ($costCents / 100)}' +jq -s --arg today "$TODAY" ' + [.[] | select(.timestamp != null and (.timestamp | startswith($today)) and .message.usage != null) | .message.usage] as $usages + | { + available: true, + tokens: ([$usages[] | (.input_tokens // 0) + (.output_tokens // 0) + (.cache_creation_input_tokens // 0) + (.cache_read_input_tokens // 0)] | add // 0), + messages: ($usages | length) + } +' $FILES 2>/dev/null || echo '{"available":false,"tokens":0,"messages":0}' diff --git a/ags/style.css b/ags/style.css index b63c92c..d41b488 100644 --- a/ags/style.css +++ b/ags/style.css @@ -349,44 +349,37 @@ font-size: 13px; } -.qs-divider { - min-width: 1px; - background-color: alpha(@foreground, 0.15); -} - .qs-side-panel { - min-width: 160px; + min-width: 170px; } -.side-card { - background-color: alpha(@color0, 0.6); - border-radius: 10px; +.widget-card { padding: 10px; } -.side-card-icon { +.widget-card-icon { color: @accent; font-size: 14px; } -.side-card-title { +.widget-card-title { font-size: 12px; font-weight: bold; color: @foreground; } -.side-card-label { +.widget-card-label { font-size: 12px; opacity: 0.8; } -.side-card-value { +.widget-card-value { font-size: 13px; font-weight: bold; color: @foreground; } -.side-card-empty { +.widget-card-empty { font-size: 12px; opacity: 0.6; } diff --git a/ags/widget/ClaudeUsage.tsx b/ags/widget/ClaudeUsage.tsx index f94a0dc..3c8e49c 100644 --- a/ags/widget/ClaudeUsage.tsx +++ b/ags/widget/ClaudeUsage.tsx @@ -5,18 +5,18 @@ import { shell } from "../lib/utils" type ClaudeUsage = { available: boolean tokens: number - costUsd: number + messages: number } const usage = createPoll( - { available: false, tokens: 0, costUsd: 0 }, + { available: false, tokens: 0, messages: 0 }, 60000, shell("bash $HOME/.config/ags/lib/claude-usage.sh"), (stdout) => { try { return JSON.parse(stdout.trim()) } catch { - return { available: false, tokens: 0, costUsd: 0 } + return { available: false, tokens: 0, messages: 0 } } }, ) @@ -29,26 +29,26 @@ function formatTokens(tokens: number) { export function ClaudeUsageCard() { return ( - + - diff --git a/ags/widget/QuickSettings.tsx b/ags/widget/QuickSettings.tsx index dba4174..9b32b3f 100644 --- a/ags/widget/QuickSettings.tsx +++ b/ags/widget/QuickSettings.tsx @@ -313,12 +313,12 @@ const uptime = createPoll("", 60000, shell("uptime -p"), (stdout) => function UptimeCard() { return ( - + - - ) } @@ -329,19 +329,19 @@ const weather = createPoll("Loading...", 600000, shell("omarchy-weather-status") function WeatherCard() { return ( - + - - ) } function LeftPanel() { return ( - + @@ -350,7 +350,7 @@ function LeftPanel() { function RightPanel() { return ( - + ) @@ -371,10 +371,9 @@ export default function QuickSettings() { visible={false} application={app} > - + - - +
@@ -382,7 +381,6 @@ export default function QuickSettings() { -