Skip to content

Feat/codex rate limits pill toggle#9

Merged
urbanlama merged 3 commits into
offbyone1:masterfrom
urbanlama:feat/codex-rate-limits-pill-toggle
May 8, 2026
Merged

Feat/codex rate limits pill toggle#9
urbanlama merged 3 commits into
offbyone1:masterfrom
urbanlama:feat/codex-rate-limits-pill-toggle

Conversation

@urbanlama
Copy link
Copy Markdown
Collaborator

What

  • Widget: Codex rate-limits in the always-on-top pill (single + dual mode), real Anthropic / OpenAI brand glyphs,
    side-by-side Claude/Codex grid in the expanded panel
  • Backend: Codex JSONL loader (events + rate limits), token bucket fix (split cached input out of fresh input so
    cache reads don't get double-counted)
  • Dashboard: hot-path perf fix in buildDashboardData (Intl.DateTimeFormat hoisted out of per-event loop — 87×
    faster on 33k events), inline brand PNG so the header matches the widget, inline favicon
  • Tauri: set-position + available-monitors capabilities for persistent drag position, skipTaskbar: true,
    RIGHT_MARGIN: 0 to snap to screen edge

Why

Why are these changes needed?

Checklist

  • npm run build succeeds
  • New loader? Added to src/loaders/index.ts and src/types.ts
  • Updated README.md if user-facing changes

@urbanlama
Copy link
Copy Markdown
Collaborator Author

Hey @urbanlama — quick heads-up before you continue review.

Master has had a fairly large audit-fix sweep over the past 24h (commits 62f794d through 9f406a7, ~10 commits, all CI-green on Linux/macOS/Windows × Node 20/22/24). Several of the 7 ultrareview findings I fixed in this branch are now resolved differently — and better — on master. To avoid merge churn, a rebase before further review would help.

Ultrareview-bug status against current master

# Bug Status
1 Codex output double-counting reasoning ⚠️ Overlaps with master 8abd0a1 (codex.ts now drops invalid timestamps) + 9adf0ea (exports subtractUsage with unit tests). The reasoning-subtraction logic should still apply but the diff context will conflict — please reconcile.
2 inline-dashboard-icon.mjs never auto-ran ❌ Obsolete — master 79c0f4c introduced scripts/run-tests.mjs and the build chain runs the icon inliner via prebuild. Drop the prelint/pretest hooks.
3 Tauri 2 Monitor API migration ✅ Widget-only, keep as-is.
4 Node 20 import.meta.dirname compat ❌ Irrelevant on current master — scripts/inline-dashboard-icon.mjs already uses fileURLToPath. Drop the commit.
9 Pill position not persisted ✅ Widget-only, keep.
13 Source-toggle state machine ✅ Widget-only, keep.
14 renderError source-aware ⚠️ Conflicts with master fd4368c (C16: lastUsageJson reset on error). Both fixes are correct in different ways — please merge them so both behaviours hold.

Suggested action

git fetch origin
git rebase origin/master
# resolve conflicts in widget/src/main.ts, src/loaders/codex.ts,
# package.json — the rest should be clean

Once rebased, the PR will be much smaller (obsolete commits can be dropped during interactive rebase) and conflict-free.

Happy to help with the rebase if useful — just let me know.

urbanlama and others added 3 commits May 8, 2026 02:04
…refresh

Adds `loadCodexRateLimits()` which scans ~/.codex/sessions newest-first
for the most recent token_count event with a `rate_limits` payload, then
projects it into a `CodexRateLimits` snapshot consumed by the dashboard
and the desktop widget. Stale snapshots (resets_at in the past) are
zeroed so a quiet user doesn't see a near-100% utilization that has
silently rolled over since Codex last wrote to disk.

`buildDashboardData` accepts the snapshot as a second arg and surfaces
it on `DashboardData.codexRateLimits`. The CLI no longer persists Codex
events to the store (they're cumulative-totals re-derived on every
scan, so persisting double-counts) — `mergeFreshSourceEvents` overlays
fresh Codex events on top of the persisted store at read time.

Reconciled with master's audit-sweep work:
- keeps `isValidTimestamp` in the codex loader entrypoint
- exports `normalizeUsage` / `subtractUsage` / `RawUsage` for testing
- preserves `writeJsonAndExit` (Bun --compile stdout flush on Windows)

Test coverage:
- normalizeUsage / subtractUsage unit tests (master)
- loadCodexRateLimits integration tests covering staleness, missing
  rate_limits, plan_type=null (API-key auth)
- loadCodexEvents integration test for cumulative-delta + cached-input
  splitting
- aggregator pass-through smoke tests for codexRateLimits

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds `CodexUsage` + `CodexWindowUsage` mirrors of the TS interfaces in
`src/types.ts`, projected from the sidecar's `codexRateLimits` JSON
into `LocalUsageSummary.codex_usage`. The frontend reads this through
the existing `fetch_local_usage` Tauri command — no new round-trip.

Schema-drift safety: deserialization failures log to stderr instead of
silently dropping the field, so a sidecar shape change surfaces as a
"why is the Codex toggle null?" debug clue rather than a mystery.

Re-applies the C16 widget error-recovery fix from master `fd4368c` —
the backup branch I rebased from didn't include it, so the manual
restore here is just a safety net (net-zero diff vs master for that
hunk).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…mark

The dashboard header rendered a stylized "T-coin in flames" SVG glyph
that didn't match the widget's actual brand mark (the photoreal PNG in
widget/src/assets/tokenbbq-icon.png). Embed the PNG at build time and
serve it as a base64 data URL so the dashboard ships a single source
of truth for the brand without depending on a runtime file path —
external file paths don't survive Bun --compile (same constraint as
the existing scripts/inline-wasm.mjs).

- New `scripts/inline-dashboard-icon.mjs` reads the widget PNG and
  writes `src/dashboard-icon.ts` (gitignored). Uses
  `fileURLToPath(import.meta.url)` so it runs on Node 20.0+ — the CI
  matrix tests Node 20/22/24, and `import.meta.dirname` only landed
  in 20.11.
- The build chain integrates the inliner the same way it integrates
  inline-wasm.mjs (chained `&&` in build/dev/lint/test/build:sidecar)
  rather than via prebuild/predev hooks, matching the existing pattern
  on master.
- `dashboard.ts` drops the inline SVG glyph in favor of `<img>` with
  `DASHBOARD_BRAND_ICON_DATA_URL` (TOKENBBQ_LOGO_PATH override still
  wins). A small inline SVG favicon link replaces /favicon.ico 404s.

Bundle grows ~1.8 MB; user-facing the dashboard now matches the widget.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@urbanlama urbanlama force-pushed the feat/codex-rate-limits-pill-toggle branch from ae3771d to 21343b8 Compare May 8, 2026 00:20
@urbanlama urbanlama merged commit 3b3c338 into offbyone1:master May 8, 2026
5 checks passed
urbanlama pushed a commit that referenced this pull request May 8, 2026
`dateKey` and `monthKey` used `new Date(ts).toISOString().slice(0, N)`,
which is UTC-formatted. For any user east of UTC, events recorded
after local midnight ended up in the previous day's bucket; for users
west of UTC, in the next day's. The heatmap and daily/monthly tables
were silently shifted by one row.

Replaced with local-time getters (`getFullYear`, `getMonth`, `getDate`)
so each bucket carries the same calendar date the user would write
down for the event. urbanlama had this fix on the fork branch as
c7b0f30 but it was dropped during the PR #9 rebase.

Verified: lint clean, 57/57 tests pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
urbanlama pushed a commit that referenced this pull request May 8, 2026
Minor bump rather than patch — three behavior changes are technically
breaking, even if pre-1.0 makes that less load-bearing:
  • Server now binds 127.0.0.1 instead of 0.0.0.0 (LAN access removed)
  • Tauri SettingsDisplay no longer ships the plaintext session_key
    field to the renderer
  • Pricing returns 0 for unknown models instead of fuzzy-matched
    or input-rate-fallback prices

Plus the Codex rate-limits + dual-mode pill feature from PR #9 and
~14 audit-driven correctness/security fixes since v0.4.9.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant