Skip to content

fix: show external Codex usage without inflating OpenCode Zen#2

Open
Daltonganger wants to merge 3 commits intomainfrom
fix/minimal-codex-lb-usage
Open

fix: show external Codex usage without inflating OpenCode Zen#2
Daltonganger wants to merge 3 commits intomainfrom
fix/minimal-codex-lb-usage

Conversation

@Daltonganger
Copy link
Copy Markdown
Owner

Summary

  • add codex-lb self-service /v1/usage support for external OpenAI API-key Codex accounts and map the returned limits into Codex quota data
  • keep OpenCode Zen from counting openai/* spend as pay-as-you-go when OpenCode routes OpenAI through provider.openai.options.baseURL
  • add focused TokenManager and decoding support for OpenAI API-key auth plus minimal regression tests for both flows

Testing

  • make lint-swift
  • xcodebuild -project "CopilotMonitor.xcodeproj" -scheme "CopilotMonitor" -configuration Debug build -quiet

@Daltonganger
Copy link
Copy Markdown
Owner Author

@copilot Review this critical!

let currentPath = components.path
if currentPath.hasSuffix("/api/codex/usage") {
components.path = String(currentPath.dropLast("/api/codex/usage".count)) + "/v1/usage"
} else if currentPath.hasSuffix("/usage") {
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔥 The Roast: This hasSuffix("/usage") check is about as precise as a blindfolded surgeon. If someone passes a URL that already ends with /v1/usage, the second condition catches it (because /v1/usage does end with /usage), drops the last 7 characters, and slaps /v1/usage back on — giving you the majestic /v1/v1/usage. Your URL just got a stutter.

🩹 The Fix: Add an explicit guard for /v1/usage before the broader /usage check:

Suggested change
} else if currentPath.hasSuffix("/usage") {
} else if currentPath.hasSuffix("/v1/usage") {
// Already a self-service endpoint; keep as-is
} else if currentPath.hasSuffix("/usage") {

📏 Severity: warning

@kilo-code-bot
Copy link
Copy Markdown

kilo-code-bot bot commented Apr 2, 2026

Code Review Roast 🔥

Verdict: No Issues Found | Recommendation: Merge

The previous review's warning about the URL double-injection (/v1/v1/usage) has been resolved. The fix adds an explicit /v1/usage check before the broader /usage catch-all, and two new tests confirm the behavior. The new init(from:) decoder on SelfServiceUsageResponse handles the missing limits key gracefully with try? ?? [].

Overview

Severity Count
🚨 critical 0
⚠️ warning 0
💡 suggestion 0
🤏 nitpick 0

Resolved Issues

File Line Status
CodexProvider.swift 514 → 523 ✅ Fixed — /v1/usage branch added before /usage catch-all

🏆 Best part: The fix is surgical — one else if branch and two targeted tests. No over-engineering, no unrelated changes. That's the kind of PR I'd stamp in under 30 seconds.

💀 Worst part: Line 525 (components.path = currentPath) is technically a no-op reassignment, but I'd need to manufacture outrage to care about it.

📊 Overall: Like someone actually reading the code review and doing exactly what was asked. I'm not used to this.

Files Reviewed (2 files incremental)
  • CopilotMonitor/CopilotMonitor/Providers/CodexProvider.swift - 0 new issues (1 previous issue resolved)
  • CopilotMonitor/CopilotMonitorTests/CodexProviderTests.swift - 0 issues

Reviewed by mimo-v2-pro-20260318 · 156,021 tokens

…le /v1 URL injection

Agent-Logs-Url: https://github.com/Daltonganger/opencode-bar/sessions/2672ff4d-23d5-4e27-9d06-5c3ec83b03b4

Co-authored-by: Daltonganger <17501732+Daltonganger@users.noreply.github.com>
Copy link
Copy Markdown

Copilot AI commented Apr 2, 2026

@copilot Review this critical!

Critical review complete. Two bugs were found and fixed in commit 2e213e1:

1. SelfServiceUsageResponse.limits decodes as non-optional
limits: [SelfServiceLimit] had no fallback — if the self-service API ever omits the key (or returns null), the decoder threw a keyNotFound error and the account fetch silently failed. Fixed by adding a custom init(from:) that defaults to []:

limits = (try? container.decodeIfPresent([SelfServiceLimit].self, forKey: .limits)) ?? []

2. URL path rewrite could produce double /v1/
The second else if currentPath.hasSuffix("/usage") branch stripped only /usage and appended /v1/usage, which turned /api/v1/usage into /api/v1/v1/usage. Fixed by inserting a hasSuffix("/v1/usage") guard above it so any path that already terminates with /v1/usage is passed through unchanged.

Three regression tests were added to cover both fixes.

Other observations (no code changes needed):

  • --models without a count argument is intentional — needed so all model names are visible for openai/* prefix filtering.
  • API-key accounts added to the accounts list when endpoint mode is directChatGPT fail gracefully (logged warning, fetch silently skipped) — acceptable behavior.
  • @testable import CopilotMonitor in the new test file matches the pre-existing pattern in AntigravityProviderVarintTests.swift.

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.

2 participants