feat: show the Pro usage meter in eaSpot #83

Merged
xicv merged 11 commits from feat/easpot-publisher into main 2026-09-26 05:16:45 +00:00
xicv commented 2026-09-26 05:12:48 +00:00 (Migrated from github.com)

Shows the Pro usage meter in eaSpot, a macOS menu bar quota display, when it is installed. The menu bar then reads "ChatGPT · GPT-6 Pro weekly: 188 of 200 messages left".

What it does

  • Once IPC is up, the daemon looks for the easpot CLI every minute. It checks EASPOT_BIN first, then ~/.local/bin, /opt/homebrew/bin, /usr/local/bin, and eaSpot.app in /Applications or ~/Applications. When eaSpot isn't found it does nothing and never reads the meter.
  • When eaSpot is found, it reads the meter alone through the new broker.getProUsage() accessor. It then publishes gpt6ProWeek against the configured gpt6ProPerWeek allowance.
  • It publishes only when the count, the allowance or the reset changed, or every 20 minutes as a keep-alive, because eaSpot dims numbers older than an hour.
  • Only the broker on the default data directory publishes. Test brokers and other EGO_CHAT_DATA_DIR overrides never do.
  • The count is advisory and a lower bound, like the meter: ChatGPT use outside Ego Chat is not counted.

The reset time

eaSpot ignores a reading whose reset moved more than 30 minutes earlier, and it still reports success, so the published reset must never go backwards. It is:

  • the newest counted GPT-6 Pro Send plus 7 days, the time when every counted message has left the rolling week;
  • with nothing counted, a week after now, or after the earliest Send still waiting for its answer (oldestUnansweredSentAt), since that answer will count from its Send;
  • never lower than the last published reset, or at first the one eaSpot already holds (read with easpot status --json). This covers retention dropping the newest counted Send.

Other changes

  • computeProUsage adds gpt6ProNewestAt and oldestUnansweredSentAt.
  • config.mjs exports isDefaultDataDir().
  • The new module is embedded in rust/main.rs.
  • The A3K public boundary fixture is regenerated for the broker.mjs accessor.
  • TECH.md (Pro usage meter) and CONTINUITY.md are updated.

Compatibility

eaSpot 0.2.0 and later show the counts and the "ChatGPT" name. eaSpot 0.1.x accepts the same input and shows the percentage.

Testing

  • npm test: 1,540 pass. The test "an unexpected successor preparation failure retains its checkpoint…" fails now and then under full-suite load. It waits only 2 s for a restarted broker, never touches the publisher, and passes alone.
  • npm run lint is clean, and cargo check passes.
  • Checked end to end against eaSpot 0.2.0 and 0.1.1: a real easpot publish subprocess, including a slow first answer after an empty week.
Shows the Pro usage meter in [eaSpot](https://github.com/xicv/eaSpot), a macOS menu bar quota display, when it is installed. The menu bar then reads "ChatGPT · GPT-6 Pro weekly: 188 of 200 messages left". ## What it does - Once IPC is up, the daemon looks for the `easpot` CLI every minute. It checks `EASPOT_BIN` first, then `~/.local/bin`, `/opt/homebrew/bin`, `/usr/local/bin`, and `eaSpot.app` in `/Applications` or `~/Applications`. When eaSpot isn't found it does nothing and never reads the meter. - When eaSpot is found, it reads the meter alone through the new `broker.getProUsage()` accessor. It then publishes `gpt6ProWeek` against the configured `gpt6ProPerWeek` allowance. - It publishes only when the count, the allowance or the reset changed, or every 20 minutes as a keep-alive, because eaSpot dims numbers older than an hour. - Only the broker on the default data directory publishes. Test brokers and other `EGO_CHAT_DATA_DIR` overrides never do. - The count is advisory and a lower bound, like the meter: ChatGPT use outside Ego Chat is not counted. ## The reset time eaSpot ignores a reading whose reset moved more than 30 minutes earlier, and it still reports success, so the published reset must never go backwards. It is: - the newest counted GPT-6 Pro Send plus 7 days, the time when every counted message has left the rolling week; - with nothing counted, a week after now, or after the earliest Send still waiting for its answer (`oldestUnansweredSentAt`), since that answer will count from its Send; - never lower than the last published reset, or at first the one eaSpot already holds (read with `easpot status --json`). This covers retention dropping the newest counted Send. ## Other changes - `computeProUsage` adds `gpt6ProNewestAt` and `oldestUnansweredSentAt`. - `config.mjs` exports `isDefaultDataDir()`. - The new module is embedded in `rust/main.rs`. - The A3K public boundary fixture is regenerated for the `broker.mjs` accessor. - TECH.md (Pro usage meter) and CONTINUITY.md are updated. ## Compatibility eaSpot 0.2.0 and later show the counts and the "ChatGPT" name. eaSpot 0.1.x accepts the same input and shows the percentage. ## Testing - `npm test`: 1,540 pass. The test "an unexpected successor preparation failure retains its checkpoint…" fails now and then under full-suite load. It waits only 2 s for a restarted broker, never touches the publisher, and passes alone. - `npm run lint` is clean, and `cargo check` passes. - Checked end to end against eaSpot 0.2.0 and 0.1.1: a real `easpot publish` subprocess, including a slow first answer after an empty week.
Sign in to join this conversation.
No description provided.