Skip to content

feat: connect OpenAI and Anthropic API usage monitors - #43

Open
pekth wants to merge 6 commits into
mainfrom
feat/openai-api-usage
Open

pekth wants to merge 6 commits into
mainfrom
feat/openai-api-usage

Conversation

@pekth

@pekth pekth commented Sep 27, 2026 •

Copy link
Copy Markdown
Owner

What changed

OpenAI and Anthropic organization API monitors show reported spend and tokens for today and the last 30 UTC calendar days, separate from coding-assistant quotas and local estimates. Settings provides masked key entry, endpoint tests, saved connections in MeterUsage-owned macOS Keychain items, and recovery without re-entering an unreadable saved key. OpenAI API spend also appears in the side notch without a quota percentage.

This branch is rebased onto main at 79a6cc9, preserving its accent themes and Codex pricing changes. Successful Disconnect now invalidates queued saved-key recovery, so a delayed restore cannot reconnect using a launcher key.

Before and after

Before After
No organization API monitor Separate OpenAI and Anthropic reported usage and spend
Unreadable saved key requires recovery Restore saved connection retries storage without opening a key field
Queued recovery can reconnect after Disconnect The queued restore returns without reading or making reporting requests

Existing synthetic side-notch fixtures from the original feature implementation: Codex and OpenAI API. These are historical captures, not runtime proof for the rebased build. No new runtime capture was taken for this coordinator fix.

Verification

Validated source: 86be289a80a655e761ffdfe1b21c0d2960f5b778, against base 79a6cc90a9f496ad6d0c81b37789c511714dfe11.

  • On macOS arm64 over SSH, swift build passed, swift test passed all 412 tests, and bash Scripts/make-app.sh produced the release bundle and passed strict signature verification.
  • The new queued-recovery test failed eight assertions before the guard and passed afterward for both OpenAI and Anthropic. All 11 connection tests passed, including successful saved-key restoration, failed-save retry, replacement, failed storage operations, environment fallback, demo isolation, and stale responses.
  • The complete tracked-input digest matched between the development checkout and macOS validation copy: 986b24a57100d5672bf87b0e0e0f850bca9adbf347ee1452b5ca1c0cbaa3f34c.
  • git diff --check passed. GitHub reports the rebased branch has no base conflicts.
  • Normal tests use synthetic data and injected storage. The new candidate was not installed or tested with a real account. Prior native Keychain receipts remain historical evidence; no production Keychain item was changed in this update.

Risks or follow-up

  • GitHub CI passed for the pushed head (86be289), including Build and Test. Independent review completed against the current base/head and confirmed the queued-recovery fix and preservation of both sides during rebase. It returned a fix-then-ship verdict for the separate failed-delete finding below.
  • Independent review confirmed a separate P2: a pending replacement key survives a failed Disconnect deletion. It remains unresolved and prevents merge. This update addresses the supplied queued-recovery finding.
  • python3 scripts/documentation.py --check could not run because that script is absent from the repository.

Model(s): GPT-6.1-Sol (current update and independent review)

Harness: T3 Code through Codex

@pekth pekth changed the title feat: monitor OpenAI API usage and spend feat: monitor OpenAI and Anthropic API usage and spend Sep 27, 2026
@pekth pekth changed the title feat: monitor OpenAI and Anthropic API usage and spend feat: connect OpenAI and Anthropic API usage monitors Sep 28, 2026
@greptile-apps

greptile-apps Bot commented Oct 5, 2026 •

Copy link
Copy Markdown

RetriggerConfidence Score: 3/5

[Critical risk] Adds API key storage and retrieval for cloud provider billing APIs.

The PR should not merge until Disconnect reliably discards pending entry and prevents queued recovery from reconnecting.

Fix All in CodexFindings

  1. P1 Disconnect retains a pending key ▶
  2. P1 Queued recovery undoes Disconnect ▶
Fix with agent prompt
### Issue 1
Sources/MeterUsage/Core/AppCoordinator.swift:360-364
If saving a new key fails and Keychain deletion also fails when the user selects Disconnect, this early return leaves the submitted key in memory. The app still offers “Retry saving key,” which can later save a key the user tried to discard. Clear the pending entry on Disconnect even if the existing connection must remain intact.

### Issue 2
Sources/MeterUsage/Core/AppCoordinator.swift:372-380
If a saved-key read failed at launch and a launcher key is also present, the user can select Restore saved connection and then Disconnect before the restore task runs. This method does not check whether Disconnect invalidated that task. It can fall back to the launcher key and reconnect after the user disconnected.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Summary

The PR adds opt-in OpenAI and Anthropic organization-usage monitors, Keychain-backed connection controls, and an OpenAI spend entry in the side notch.

  • The new readers report provider costs and endpoint-specific tokens separately from local coding totals.
  • Disconnect needs to clear pending key entry on storage failure and invalidate queued recovery actions.
Diagram
%%{init: {'theme': 'neutral'}}%%
flowchart LR
  Entry[Masked key entry] --> Save[Save Keychain item]
  Save -->|success| Test[Test usage and cost endpoints]
  Save -->|failure| Pending[Pending key for retry]
  Pending --> Retry[Retry saving key]
  Saved[Saved item at launch] --> Restore[Restore connection]
  Restore --> Test
  Test --> Reading[Provider usage reading]
  Pending --> Disconnect[Disconnect]
  Restore --> Disconnect
  Disconnect --> Clear[Delete saved item and clear connection]
Loading

Reviews (1) · Last reviewed commit: "fix: recover saved API connections witho..."

Comment on lines +360 to +364
do { try apiKeys.set(nil, for: provider) }
catch {
apiConnectionErrors[provider] = APIKeySession.message(for: error)
return
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Disconnect retains a pending key

If saving a new key fails and Keychain deletion also fails when the user selects Disconnect, this early return leaves the submitted key in memory. The app still offers “Retry saving key,” which can later save a key the user tried to discard. Clear the pending entry on Disconnect even if the existing connection must remain intact.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/MeterUsage/Core/AppCoordinator.swift
Line: 360-364

Comment:
**Disconnect retains a pending key**

If saving a new key fails and Keychain deletion also fails when the user selects Disconnect, this early return leaves the submitted key in memory. The app still offers “Retry saving key,” which can later save a key the user tried to discard. Clear the pending entry on Disconnect even if the existing connection must remain intact.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

Comment on lines +372 to +380
func retrySavedAPIKey(_ provider: Provider) async {
guard provider.isOrganizationAPI, !isDemoMode,
!testingAPIProviders.contains(provider),
let source = usageSources.first(where: { $0.provider == provider }) else { return }
if let pendingKey = pendingAPIKeys[provider] {
await connectAPI(provider, key: pendingKey)
return
}
do { try apiKeys.restore(provider) }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Queued recovery undoes Disconnect

If a saved-key read failed at launch and a launcher key is also present, the user can select Restore saved connection and then Disconnect before the restore task runs. This method does not check whether Disconnect invalidated that task. It can fall back to the launcher key and reconnect after the user disconnected.

Prompt To Fix With AI
This is a comment left during a code review.
Path: Sources/MeterUsage/Core/AppCoordinator.swift
Line: 372-380

Comment:
**Queued recovery undoes Disconnect**

If a saved-key read failed at launch and a launcher key is also present, the user can select Restore saved connection and then Disconnect before the restore task runs. This method does not check whether Disconnect invalidated that task. It can fall back to the launcher key and reconnect after the user disconnected.

---

For each issue above, determine whether it is valid and should be fixed. If so, fix it directly.

Fix in Codex

@pekth
pekth force-pushed the feat/openai-api-usage branch from ce8d21e to 86be289 Compare October 5, 2026 02:09
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