Polish pass
This commit is contained in:
@@ -61,9 +61,9 @@
|
|||||||
"margin-bottom": 16,
|
"margin-bottom": 16,
|
||||||
"margin-left": 16,
|
"margin-left": 16,
|
||||||
"margin-right": 16,
|
"margin-right": 16,
|
||||||
"modules-left": ["gamemode", "battery", "temperature", "cpu", "memory", "network"],
|
"modules-left": ["gamemode", "battery", "temperature", "cpu", "memory", "network", "custom/codex-primary", "custom/codex-secondary"],
|
||||||
"modules-center": [],
|
"modules-center": [],
|
||||||
"modules-right": ["mpris", "pulseaudio", "custom/output-device", "custom/openai-rate", "backlight", "idle_inhibitor", "clock"],
|
"modules-right": ["mpris", "pulseaudio", "custom/output-device", "backlight", "idle_inhibitor", "clock"],
|
||||||
"clock": {
|
"clock": {
|
||||||
"format": "{:%a %b %d %I:%M %p}",
|
"format": "{:%a %b %d %I:%M %p}",
|
||||||
"tooltip": false
|
"tooltip": false
|
||||||
@@ -155,13 +155,19 @@
|
|||||||
"exec": "flatpak remote-ls --updates --app | wc -l",
|
"exec": "flatpak remote-ls --updates --app | wc -l",
|
||||||
"exec-if": "test $(flatpak remote-ls --updates --app | wc -l) -gt 0"
|
"exec-if": "test $(flatpak remote-ls --updates --app | wc -l) -gt 0"
|
||||||
},
|
},
|
||||||
"custom/openai-rate": {
|
"custom/codex-primary": {
|
||||||
"interval": 15,
|
"interval": 15,
|
||||||
"return-type": "json",
|
"return-type": "json",
|
||||||
"exec": "$HOME/.config/waybar/scripts/openai-rate.py",
|
"exec": "$HOME/.config/waybar/scripts/openai-rate.py --window primary",
|
||||||
"exec-if": "test -r ~/.codex/auth.json",
|
"exec-if": "test -r ~/.codex/auth.json",
|
||||||
"max-length": 90,
|
"format": "5h {}"
|
||||||
"format": "{}"
|
},
|
||||||
|
"custom/codex-secondary": {
|
||||||
|
"interval": 15,
|
||||||
|
"return-type": "json",
|
||||||
|
"exec": "$HOME/.config/waybar/scripts/openai-rate.py --window secondary",
|
||||||
|
"exec-if": "test -r ~/.codex/auth.json",
|
||||||
|
"format": "W {}"
|
||||||
},
|
},
|
||||||
"custom/backup": {
|
"custom/backup": {
|
||||||
"interval": 60,
|
"interval": 60,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import urllib.error
|
import urllib.error
|
||||||
import urllib.request
|
import urllib.request
|
||||||
|
from argparse import ArgumentParser
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
@@ -107,6 +108,16 @@ def reset_text(seconds):
|
|||||||
return f"{round(hours / 24)}d"
|
return f"{round(hours / 24)}d"
|
||||||
|
|
||||||
|
|
||||||
|
def usage_class(used, limit_reached=False):
|
||||||
|
if limit_reached or used >= 95:
|
||||||
|
return "critical"
|
||||||
|
if used >= 90:
|
||||||
|
return "warning"
|
||||||
|
if used >= 75:
|
||||||
|
return "regular"
|
||||||
|
return "good"
|
||||||
|
|
||||||
|
|
||||||
def format_window(name, window):
|
def format_window(name, window):
|
||||||
if not isinstance(window, dict):
|
if not isinstance(window, dict):
|
||||||
return None
|
return None
|
||||||
@@ -121,7 +132,13 @@ def format_window(name, window):
|
|||||||
tooltip = f"{name} {label}: {used}% used"
|
tooltip = f"{name} {label}: {used}% used"
|
||||||
if reset:
|
if reset:
|
||||||
tooltip += f", resets in {reset}"
|
tooltip += f", resets in {reset}"
|
||||||
return {"text": f"{left}% {label}", "used": used, "tooltip": tooltip}
|
return {
|
||||||
|
"label": label,
|
||||||
|
"left": left,
|
||||||
|
"text": f"{left}% {label}",
|
||||||
|
"used": used,
|
||||||
|
"tooltip": tooltip,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
def credit_text(credits):
|
def credit_text(credits):
|
||||||
@@ -158,11 +175,19 @@ def spend_control_text(spend_control):
|
|||||||
return text
|
return text
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def selected_window_output(data, source, selector):
|
||||||
token, account_id, source = load_auth()
|
|
||||||
data = fetch_usage(token, account_id)
|
|
||||||
rate_limit = data.get("rate_limit") or {}
|
rate_limit = data.get("rate_limit") or {}
|
||||||
|
window = format_window(selector, rate_limit.get(f"{selector}_window"))
|
||||||
|
if not window:
|
||||||
|
waybar("n/a", "warning", f"No {selector} usage window returned\nsource: {source}")
|
||||||
|
|
||||||
|
klass = usage_class(window["used"], rate_limit.get("limit_reached"))
|
||||||
|
tooltip = [window["tooltip"], f"{window['left']}% remaining", f"source: {source}"]
|
||||||
|
waybar(f"{window['left']}%", klass, "\n".join(tooltip))
|
||||||
|
|
||||||
|
|
||||||
|
def combined_output(data, source):
|
||||||
|
rate_limit = data.get("rate_limit") or {}
|
||||||
windows = [
|
windows = [
|
||||||
format_window("primary", rate_limit.get("primary_window")),
|
format_window("primary", rate_limit.get("primary_window")),
|
||||||
format_window("secondary", rate_limit.get("secondary_window")),
|
format_window("secondary", rate_limit.get("secondary_window")),
|
||||||
@@ -178,7 +203,7 @@ def main():
|
|||||||
waybar("AI n/a", "warning", f"No displayable usage data\nsource: {source}")
|
waybar("AI n/a", "warning", f"No displayable usage data\nsource: {source}")
|
||||||
|
|
||||||
worst_used = max(window["used"] for window in windows) if windows else 0
|
worst_used = max(window["used"] for window in windows) if windows else 0
|
||||||
klass = "critical" if rate_limit.get("limit_reached") or worst_used >= 95 else "warning" if worst_used >= 90 else "good"
|
klass = usage_class(worst_used, rate_limit.get("limit_reached"))
|
||||||
|
|
||||||
tooltip = [window["tooltip"] for window in windows]
|
tooltip = [window["tooltip"] for window in windows]
|
||||||
spend = spend_control_text(data.get("spend_control"))
|
spend = spend_control_text(data.get("spend_control"))
|
||||||
@@ -191,5 +216,27 @@ def main():
|
|||||||
waybar(f"AI {' '.join(parts)}", klass, "\n".join(tooltip))
|
waybar(f"AI {' '.join(parts)}", klass, "\n".join(tooltip))
|
||||||
|
|
||||||
|
|
||||||
|
def parse_args():
|
||||||
|
parser = ArgumentParser(description="Waybar Codex rate-limit widget")
|
||||||
|
parser.add_argument(
|
||||||
|
"--window",
|
||||||
|
choices=("primary", "secondary", "all"),
|
||||||
|
default="all",
|
||||||
|
help="usage window to display",
|
||||||
|
)
|
||||||
|
return parser.parse_args()
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
args = parse_args()
|
||||||
|
token, account_id, source = load_auth()
|
||||||
|
data = fetch_usage(token, account_id)
|
||||||
|
|
||||||
|
if args.window == "all":
|
||||||
|
combined_output(data, source)
|
||||||
|
else:
|
||||||
|
selected_window_output(data, source, args.window)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
main()
|
main()
|
||||||
|
|||||||
@@ -238,13 +238,22 @@ window#waybar.fullscreen #window {
|
|||||||
color: #ebdbb2;
|
color: #ebdbb2;
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
}
|
}
|
||||||
#custom-openai-rate {
|
#custom-codex-primary,
|
||||||
|
#custom-codex-secondary {
|
||||||
padding: 0 1em;
|
padding: 0 1em;
|
||||||
|
color: rgba(235, 219, 178, 0.2);
|
||||||
|
}
|
||||||
|
#custom-codex-primary.regular,
|
||||||
|
#custom-codex-secondary.regular {
|
||||||
color: #ebdbb2;
|
color: #ebdbb2;
|
||||||
}
|
}
|
||||||
#custom-openai-rate.warning {
|
#custom-codex-primary.warning,
|
||||||
|
#custom-codex-secondary.warning {
|
||||||
color: #fabd2f;
|
color: #fabd2f;
|
||||||
}
|
}
|
||||||
#custom-openai-rate.critical {
|
#custom-codex-primary.critical,
|
||||||
color: #fb4934;
|
#custom-codex-secondary.critical {
|
||||||
|
color: #282828;
|
||||||
|
background: #fb4934;
|
||||||
|
border-radius: 8px;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user