Skip to content

fix: read OpenCode Go usage from local data#1021

Open
sopenlaz0 wants to merge 2 commits into
steipete:mainfrom
sopenlaz0:codex/fix-opencode-go-local-usage
Open

fix: read OpenCode Go usage from local data#1021
sopenlaz0 wants to merge 2 commits into
steipete:mainfrom
sopenlaz0:codex/fix-opencode-go-local-usage

Conversation

@sopenlaz0
Copy link
Copy Markdown

@sopenlaz0 sopenlaz0 commented May 18, 2026

Summary

Fix OpenCode Go usage refreshes for local OpenCode Go users by reading OpenCode's local auth/history before falling back to the existing web-cookie dashboard fetch.

Affected users currently see OpenCode Go cookie header is invalid. when CodexBar cannot import or reuse an opencode.ai browser cookie, even though OpenCode Go usage is available locally. OpenUsage handles this successfully by reading OpenCode's local auth.json and SQLite history, so this PR adds the same local-first path to CodexBar without changing the UI.

What changed

  • Add a macOS OpenCodeGoLocalUsageReader.
  • Detect local OpenCode Go auth at ~/.local/share/opencode/auth.json.
  • Read ~/.local/share/opencode/opencode.db and aggregate assistant messages where providerID == "opencode-go".
  • Support both OpenCode history shapes:
    • message-level data.cost
    • part rows where data.type == "step-finish" and the message only stores metadata
  • Avoid double-counting when both message-level cost and step-finish part cost exist for the same message.
  • Compute the existing OpenCode Go windows:
    • rolling 5-hour usage against $12
    • weekly usage against $30
    • monthly usage against $60, anchored to the first local usage timestamp
  • Prefer the local strategy in automatic mode when usable local history exists.
  • Preserve optional Zen balance in automatic mode when local usage succeeds and a valid dashboard cookie/workspace is available.
  • Keep the existing web-cookie fetcher for explicit web mode and as fallback when local OpenCode Go state/history is not available.
  • Preserve the original monthly anchor when a 29th-31st anchor is clamped in shorter months.

Screenshots / Evidence

No UI changes. This is a provider data-source fix, so screenshots/GIFs are not applicable.

Before this change, an affected setup reports OpenCode Go cookie header is invalid. in CodexBar while OpenUsage can still show Session, Weekly, and Monthly usage from local OpenCode data. After this change, automatic mode uses that local-data path first when local history is present.

Local runtime verification with a freshly built app returns OpenCode Go usage from the local source:

{
  "provider": "opencodego",
  "source": "local"
}

Issue

No matching open issue found; this PR is self-contained.

Validation

  • make check
  • swift test --filter OpenCodeGo
  • swift test --filter OpenCodeGoLocalUsageReaderTests
  • ./Scripts/compile_and_run.sh
  • .build/debug/CodexBarCLI usage --provider opencodego --source auto --format json --pretty --no-color
  • CodexBar.app/Contents/Helpers/CodexBarCLI usage --provider opencodego --source auto --format json --pretty --no-color

The focused tests cover:

  • local OpenCode Go history aggregation into 5-hour, weekly, and monthly windows
  • auth-only installs without local history falling through so the web strategy can still run
  • auth plus unreadable/empty SQLite history falling through so the web strategy can still run
  • missing auth/history falling through so the existing web strategy can still run
  • step-finish part rows when message rows only store metadata
  • avoiding double-counting when both message and part rows report cost for the same message
  • optional Zen balance fetch behavior, including the local strategy helper's cookie normalization and workspace override path
  • monthly reset boundaries when the original anchor day is clamped by a shorter month
  • existing OpenCode Go web parser/fetcher behavior

@sopenlaz0 sopenlaz0 changed the title [codex] Fix OpenCode Go local usage fix: read OpenCode Go usage from local data May 18, 2026
@sopenlaz0 sopenlaz0 marked this pull request as ready for review May 18, 2026 09:28
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 751e680c6e

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

nowComponents = calendar.dateComponents([.year, .month], from: previous)
start = self.anchoredMonth(calendar: calendar, month: nowComponents, anchor: anchorComponents)
}
let end = calendar.date(byAdding: .month, value: 1, to: start) ?? start
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Re-anchor the monthly window end

When the first local OpenCode Go usage falls on the 29th–31st, anchoredMonth clamps shorter months to their last day, but this line then advances from that clamped date instead of from the original anchor. For example, with a Jan 31 anchor and now on Mar 29, the start becomes Feb 28 and adding one month makes the end Mar 28, so the monthly reset is reported as already expired and Mar 29–30 usage is excluded; compute the next boundary by anchoring the following calendar month with the original anchor components instead of adding a month to the clamped start.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 64d6b15c by computing the monthly reset from the original anchor applied to the following calendar month, plus a regression test for the Jan 31 -> Feb clamp -> Mar reset case.

@sopenlaz0
Copy link
Copy Markdown
Author

@codex review

@sopenlaz0
Copy link
Copy Markdown
Author

Verified locally with a freshly built CodexBar.app. OpenCode Go now loads from local usage data instead of failing on the invalid cookie path. Screenshot evidence to follow.

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 64d6b15c85

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +45 to +46
if hasAuth {
return Self.emptySnapshot(now: now)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Fall back instead of accepting empty local usage

When auth.json exists but this hard-coded DB path is absent (for example a new local login with no history yet, or OpenCode using a channel/OPENCODE_DB database), this returns a successful zeroed snapshot. In auto mode the local strategy runs before the web strategy and the fetch pipeline stops on the first success, so users with valid dashboard cookies/current remote usage will now see 0% bars instead of the existing web result; treat missing/unreadable local history as fallback-eligible until the web path fails, rather than succeeding here.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 87169850. Missing, empty, or unreadable local history now throws a fallback-eligible local error, so automatic mode can still use the existing web-cookie strategy when valid remote usage is available. I also updated the tests to cover the fallback behavior and re-ran swift test --filter OpenCodeGo, make check, and a rebuilt CLI verification that still reports source: "local" when local history is present.

@sopenlaz0
Copy link
Copy Markdown
Author

Screenshot 2026-05-18 at 6 30 00 in the evening

@sopenlaz0 sopenlaz0 force-pushed the codex/fix-opencode-go-local-usage branch from 64d6b15 to 8716985 Compare May 18, 2026 11:33
@sopenlaz0
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 87169850d5

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +78 to +82
FROM message
WHERE json_valid(data)
AND json_extract(data, '$.providerID') = 'opencode-go'
AND json_extract(data, '$.role') = 'assistant'
AND json_type(data, '$.cost') IN ('integer', 'real')
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Read OpenCode step-finish usage rows

When OpenCode histories use the newer SQLite shape where usage/cost is emitted on part rows with data.type == 'step-finish' and the message row only contains metadata, this query returns no rows and auto mode falls through to the web-cookie strategy. That leaves the local-only users this change targets still seeing the cookie error despite having usable local usage in opencode.db; the local reader should also aggregate the step-finish part usage rather than only message.data.cost.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 8f403b74. The local reader now supports OpenCode part rows where data.type == "step-finish", joined back to assistant message metadata for providerID == "opencode-go". It keeps message-level data.cost as the source of truth when present and only uses step-finish part cost when the message does not already have cost, so mixed histories do not double-count. Added regression tests for part-only histories and mixed message+part histories; swift test --filter OpenCodeGo, swift test --filter OpenCodeGoLocalUsageReaderTests, make check, and a real local CLI check all pass.

@sopenlaz0 sopenlaz0 force-pushed the codex/fix-opencode-go-local-usage branch from 8716985 to 8f403b7 Compare May 18, 2026 12:16
@sopenlaz0
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 8f403b74f1

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +62 to +65
let snapshot = try OpenCodeGoLocalUsageReader().fetch()
return self.makeResult(
usage: snapshot.toUsageSnapshot(),
sourceLabel: "local")
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve Zen balance when local usage succeeds

When automatic mode has any local OpenCode Go history, this strategy succeeds and the fetch pipeline returns before OpenCodeGoUsageFetchStrategy runs. The local reader never uses context.includeOptionalUsage or fetches zenBalanceUSD, so users who enable optional extra usage lose the Zen balance section that the existing web strategy populated; this only shows up for local-history users in auto mode.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in 7bdad24740. The local OpenCode Go strategy now preserves optional Zen balance when optional usage is enabled by reusing the existing cookie/workspace resolution and fetching the balance non-fatally after local SQLite usage succeeds. If cookies/workspace are unavailable or the optional fetch fails, local usage still returns normally so the original invalid-cookie failure does not reappear.

Validation:

  • swift test --filter OpenCodeGo
  • make check
  • .build/debug/CodexBarCLI usage --provider opencodego --source auto --format json --pretty --no-color

@sopenlaz0 sopenlaz0 force-pushed the codex/fix-opencode-go-local-usage branch from 8f403b7 to 7bdad24 Compare May 18, 2026 12:35
@sopenlaz0
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7bdad24740

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +86 to +89
let zenBalance = try await OpenCodeGoUsageFetcher.fetchOptionalZenBalance(
cookieHeader: cookieHeader,
timeout: context.webTimeout,
workspaceIDOverride: workspaceOverride)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Keep optional Zen lookup from blocking local usage

In auto mode with local history present, this path turns an otherwise synchronous SQLite read into a web-dependent refresh whenever optional usage is enabled and cookies are available. If no workspace override is configured, fetchOptionalZenBalance first resolves the workspace with context.webTimeout and then loads the balance page, so a slow/unreachable opencode.ai can delay the local result for the full web timeout (or at least the 5s balance timeout) before the error is swallowed. The web fetcher already bounds this optional lookup with completedOptionalZenBalance; the local strategy should apply the same grace/timeout behavior or skip it so local usage remains fast/offline.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Fixed in ff8057a6. The local strategy no longer resolves/imports browser cookies or waits on the full web timeout for optional Zen balance. It only uses an already manual or cached OpenCode Go cookie, starts the Zen balance lookup as optional work, and joins it through the existing completedOptionalZenBalance grace path. Non-cancellation failures return nil, so the SQLite usage result stays fast/offline.

Validation:

  • swift test --filter OpenCodeGo
  • make check
  • .build/debug/CodexBarCLI usage --provider opencodego --source auto --format json --pretty --no-color

@sopenlaz0 sopenlaz0 force-pushed the codex/fix-opencode-go-local-usage branch from 7bdad24 to ff8057a Compare May 18, 2026 12:46
@sopenlaz0
Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector
Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Another round soon, please!

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

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