Skip to content

Add Qoder usage provider#1736

Open
Yuxin-Qiao wants to merge 11 commits into
steipete:mainfrom
Yuxin-Qiao:add-qoder-provider
Open

Add Qoder usage provider#1736
Yuxin-Qiao wants to merge 11 commits into
steipete:mainfrom
Yuxin-Qiao:add-qoder-provider

Conversation

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor

Summary

  • add a Qoder provider backed by the documented big_model_credits usage endpoint
  • support automatic browser cookie import, manual Cookie headers, and token-account Cookie header overrides
  • register Qoder metadata, icon style/resource, widget exclusion, debug-log fallback, and focused provider/fetcher tests

Closes #1590.

Tests

  • swiftformat Sources/CodexBarCore/Providers/Qoder Sources/CodexBar/Providers/Qoder Tests/CodexBarTests/QoderProviderTests.swift Tests/CodexBarTests/QoderUsageFetcherTests.swift Sources/CodexBarCore/Logging/LogCategories.swift Sources/CodexBarCore/Providers/Providers.swift Sources/CodexBarCore/Providers/ProviderDescriptor.swift Sources/CodexBarCore/Providers/ProviderSettingsSnapshot.swift Sources/CodexBarCore/TokenAccountSupportCatalog+Data.swift Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift Sources/CodexBar/Providers/Shared/ProviderImplementationRegistry.swift Sources/CodexBar/UsageStore.swift Sources/CodexBarWidget/CodexBarWidgetViews.swift Sources/CodexBarWidget/CodexBarWidgetProvider.swift
  • git diff --cached --check
  • HOME=/Users/yuxinqiao/Documents/Codex/Codexbar-bugfix1/CodexBar-main/.codex-home CLANG_MODULE_CACHE_PATH=/Users/yuxinqiao/Documents/Codex/Codexbar-bugfix1/CodexBar-main/.build/module-cache swift test --filter 'Qoder|ProviderRegistryTests|ProviderIconResourcesTests|ProviderLabelMetadataCharacterizationTests' (passed in the full local source tree used for implementation)\n\nNote: I also attempted the same focused swift test on this pushed branch after expanding the partial clone, but SwiftPM stalled downloading the Sparkle binary artifact before compilation produced any Qoder errors.

@clawsweeper

clawsweeper Bot commented Jun 24, 2026

Copy link
Copy Markdown

Codex review: needs changes before merge. Reviewed June 25, 2026, 6:51 AM ET / 10:51 UTC.

Summary
Adds a Qoder web usage provider with browser/manual cookie auth, token-account Cookie overrides, provider metadata/icon/docs, widget exclusion, CLI/app integration, and focused tests.

Reproducibility: yes. for the review findings: source inspection shows Qoder totals still flow through resetDescription into a standard menu path that does not whitelist Qoder, manual cookies are always labeled qoder.com, and invalid auto-cookie retry advances only once. No unrequested live provider or Keychain validation was run under AGENTS.md guidance.

Review metrics: 2 noteworthy metrics.

  • Provider Surface: 31 files changed, +1154/-35. The PR spans app, CLI, core provider code, widget exclusions, docs, resources, and tests, so cross-surface provider behavior matters before merge.
  • Real Proof Artifacts: 1 redacted live CLI output. The contributor supplied a real qoder.com.cn Chrome-cookie fetch result, which materially improves endpoint and auth confidence.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #1590
Summary: This PR is the candidate implementation for the open Qoder provider request; the broader custom-provider feature request is adjacent but does not supersede this first-class provider work.

Members:

Proposal only: this assessment does not dispatch repair, suppress jobs, mutate sibling items, close, or merge anything.

Merge readiness
Overall: 🦐 gold shrimp
Proof: 🦞 diamond lobster
Patch quality: 🦐 gold shrimp
Result: needs maintainer review before merge.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix the three Qoder rendering and cookie-routing findings.
  • Keep the redacted live proof in the PR body or discussion for maintainer review.
  • Get maintainer acceptance for the new cookie-auth provider scope after repairs.

Risk before merge

  • [P1] The PR adds browser-cookie import, manual Cookie headers, and token-account Cookie routing for a new authenticated provider, so maintainers still need to accept the auth/privacy behavior before release.
  • [P1] As written, standard menu rendering can mislabel Qoder credit totals as reset text, and valid credentials can be skipped for manual qoder.com.cn cookies or multi-profile stale-cookie cases.

Maintainer options:

  1. Fix Qoder Auth Edges Before Merge (recommended)
    Repair the standard menu detail path, manual qoder.com.cn routing, and all-candidate retry behavior before maintainer auth-provider acceptance.
  2. Accept Cookie-Auth Scope
    Maintainers may accept the new browser-cookie/manual-cookie provider scope after the correctness fixes and existing redacted proof are reviewed.
  3. Pause Provider Acceptance
    If Qoder's cookie-auth or domain contract is not product-approved yet, keep this PR open or close it until the provider direction is explicit.

Next step before merge

  • [P2] A focused repair can address the three source-level bugs; maintainer auth-provider acceptance remains a separate decision after repairs.

Security
Cleared: No new dependencies, workflows, package-resolution changes, install scripts, or supply-chain execution paths were added; cookie-auth privacy is tracked as merge risk rather than a concrete security defect.

Review findings

  • [P2] Handle Qoder totals in the standard menu path — Sources/CodexBarCore/Providers/Qoder/QoderUsageSnapshot.swift:33
  • [P2] Route manual China cookies to the China endpoint — Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift:98
  • [P2] Retry all imported Qoder cookie candidates — Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift:75-85
Review details

Best possible solution:

Land Qoder after credit-detail rendering is consistent across menu/card/CLI paths, cookie resolution handles both Qoder domains through all imported candidates, and maintainers accept the new cookie-auth provider behavior.

Do we have a high-confidence way to reproduce the issue?

Yes for the review findings: source inspection shows Qoder totals still flow through resetDescription into a standard menu path that does not whitelist Qoder, manual cookies are always labeled qoder.com, and invalid auto-cookie retry advances only once. No unrequested live provider or Keychain validation was run under AGENTS.md guidance.

Is this the best way to solve the issue?

No, not yet: the provider shape and proof are promising, but the maintainable solution still needs consistent detail rendering, domain-aware manual cookie handling, full candidate retry, and maintainer acceptance for cookie-auth scope.

Full review comments:

  • [P2] Handle Qoder totals in the standard menu path — Sources/CodexBarCore/Providers/Qoder/QoderUsageSnapshot.swift:33
    This PR still stores Qoder's credit total in primary.resetDescription. MenuCardView and CLIRenderer special-case Qoder, but MenuDescriptor only strips resetDescription for other providers, so the standard menu path can render a balance as reset text; add descriptor coverage or move the balance to a proper detail field.
    Confidence: 0.9
  • [P2] Route manual China cookies to the China endpoint — Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift:98
    After adding qoder.com.cn support, the manual Cookie path still labels every manual header as qoder.com. A pasted qoder.com.cn Cookie header or token-account Cookie will be sent to qoder.com and fail instead of using the China endpoint.
    Confidence: 0.86
  • [P2] Retry all imported Qoder cookie candidates — Sources/CodexBarCore/Providers/Qoder/QoderProviderDescriptor.swift:75-85
    The invalid-credentials handler clears the cache and tries only one alternate imported source. If that second source is also anonymous or expired, the error escapes and later valid Qoder sessions from other profiles or domains are never attempted.
    Confidence: 0.84

Overall correctness: patch is incorrect
Overall confidence: 0.86

AGENTS.md: found and applied where relevant.

Codex review notes: model internal, reasoning high; reviewed against ada3660e9d61.

Label changes

Label justifications:

  • P2: This is a normal-priority optional provider addition with bounded but merge-relevant integration bugs.
  • merge-risk: 🚨 auth-provider: The PR adds browser-cookie import, manual Cookie headers, and token-account routing for a new authenticated provider.
  • rating: 🦐 gold shrimp: Overall readiness is 🦐 gold shrimp; proof is 🦞 diamond lobster and patch quality is 🦐 gold shrimp.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (live_output): The contributor posted redacted live CLI output from a real Qoder China account showing Chrome cookie import, endpoint fetch, JSON usage output, and a secret-pattern check with no matches.
  • proof: sufficient: Contributor real behavior proof is sufficient. The contributor posted redacted live CLI output from a real Qoder China account showing Chrome cookie import, endpoint fetch, JSON usage output, and a secret-pattern check with no matches.
Evidence reviewed

Acceptance criteria:

  • [P1] swift test --filter 'Qoder|MenuDescriptor|CLISnapshotTests|CLIEntryTests'.
  • [P1] swiftformat Sources/CodexBarCore/Providers/Qoder Sources/CodexBar/Providers/Qoder Tests/CodexBarTests/QoderProviderTests.swift Tests/CodexBarTests/QoderUsageFetcherTests.swift Tests/CodexBarTests/QoderProviderBehaviorTests.swift.
  • [P1] make check.

What I checked:

  • Repository policy read: AGENTS.md was read in full; its Chrome-only cookie import, provider data siloing, focused test, and no unrequested live Keychain/browser-cookie validation guidance applies to this provider PR. (AGENTS.md:1, ada3660e9d61)
  • Vision sign-off context: VISION.md says new provider support can merge by default when it follows existing patterns, but changes affecting provider auth, data storage, or user privacy need sign-off. (VISION.md:3, ada3660e9d61)
  • Current main has no Qoder provider: A current-main source search found no Qoder references, so this PR is not obsolete on main. (ada3660e9d61)
  • Live behavior proof: The contributor posted redacted live CLI output from a real Qoder China account showing Chrome cookie import, qoder.com.cn endpoint fetch, JSON usage output, and a secret-pattern check with no matches. (6ed44d1c6f57)
  • Qoder totals still use resetDescription: The proposed Qoder snapshot stores the credit total in primary.resetDescription with no reset date. (Sources/CodexBarCore/Providers/Qoder/QoderUsageSnapshot.swift:33, 6ed44d1c6f57)
  • Standard menu path omits Qoder detail handling: Current main's MenuDescriptor treats resetDescription as non-reset detail for several providers, but Qoder is not in that allow-list. (Sources/CodexBar/MenuDescriptor.swift:155, ada3660e9d61)

Likely related people:

  • steipete: Git blame ties the current MenuDescriptor detail handling, provider cookie defaults, and token-account scaffolding to Peter Steinberger, and he asked for endpoint/auth/fixture details on the linked Qoder request. (role: current provider/settings area contributor and issue participant; confidence: high; commits: f380287041b8; files: Sources/CodexBar/MenuDescriptor.swift, Sources/CodexBarCore/Providers/Providers.swift, Sources/CodexBarCLI/TokenAccountCLI.swift)
  • BAKEZQ: Recent z.ai BigModel work touched TokenAccountCLI and ProviderSettingsSnapshot near the same provider account-routing surface. (role: recent adjacent provider-settings contributor; confidence: medium; commits: 2435c93453fe; files: Sources/CodexBarCLI/TokenAccountCLI.swift, Sources/CodexBarCore/Providers/ProviderSettingsSnapshot.swift)
  • Yuxin-Qiao: Beyond authoring this PR, repository history shows prior merged provider, cookie, keychain, and menu/display work in adjacent areas. (role: recent provider, cookie, and menu-area contributor; confidence: medium; commits: 6d906d375d2e, 050b13925da4, f561834141ac; files: Sources/CodexBarCore/Providers/Poe/PoeUsageFetcher.swift, Sources/CodexBarCore/Providers/MiMo/MiMoCookieImporter.swift, Sources/CodexBarCore/KeychainAccessGate.swift)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. labels Jun 24, 2026

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

Copy link
Copy Markdown

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: 7d94f1fef0

ℹ️ 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 +100 to +103
let usedValue: Int
let limitValue: Int
let remainingValue: Int
let usagePercentage: Int

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 Decode Qoder credit values as decimals

When Qoder returns fractional credit balances (for example after a 0.35-credit usage event), these Int fields make JSONDecoder throw a type-mismatch and the provider shows a parse error instead of usage. The snapshot already stores Doubles, so the wire model should accept decimal values for used/limit/remaining/percentage rather than requiring integral JSON numbers.

Useful? React with 👍 / 👎.

.crof: CrofProviderDescriptor.descriptor,
.venice: VeniceProviderDescriptor.descriptor,
.commandcode: CommandCodeProviderDescriptor.descriptor,
.qoder: QoderProviderDescriptor.descriptor,

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 Wire Qoder into CLI cookie settings

Registering Qoder exposes it through the CLI provider flow, but TokenAccountCLI.makeCookieBackedSnapshot has no .qoder case and makeSnapshot has no qoder parameter. In CLI contexts, a configured manual Cookie header or selected Qoder token account therefore never populates ProviderSettingsSnapshot.qoder, so codexbar usage qoder --account .../manual config falls back to auto browser cookies or missing credentials instead of using the supplied header.

Useful? React with 👍 / 👎.

Comment on lines +50 to +53
#if os(macOS)
return true
#else
return false

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 Allow manual Qoder cookies off macOS

For non-macOS CLI builds, this makes the strategy unavailable before resolveCookieHeader can consume settings.qoder.cookieSource == .manual, and fetch also compiles to missingCredentials. Manual Cookie headers and token-account Cookie overrides should work without browser import, as the HTTP fetcher itself is platform-neutral; only the automatic browser import/cache path needs to be macOS-gated.

Useful? React with 👍 / 👎.

Comment on lines +43 to +47
for source in sources where !source.records.isEmpty {
let cookies = BrowserCookieClient.makeHTTPCookies(source.records, origin: query.origin)
guard !cookies.isEmpty else { continue }
self.emit("Found \(cookies.count) cookies in \(source.label)", logger: logger)
return SessionInfo(cookies: cookies, sourceLabel: source.label)

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 Try later Qoder cookie sources after stale cookies

When automatic import finds any cookies in the first browser/profile, it returns them immediately without checking for an auth cookie or preserving later candidates. If that first source only has anonymous or expired qoder.com cookies, the fetch gets invalidCredentials, clears the cache, then re-imports and retries the same bad source, so a valid Qoder session in a later profile/browser is never used.

Useful? React with 👍 / 👎.

case crof
case venice
case commandcode
case qoder

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 Update config docs for Qoder provider ID

Adding .qoder to UsageProvider.allCases also requires updating docs/configuration.md's Provider IDs list; ConfigurationDocsProviderIDTests reads that section and expects it to exactly match enum order. As committed, the docs list jumps from commandcode to stepfun, so the documentation test fails for this provider addition.

Useful? React with 👍 / 👎.

let cookieSource = context.settings?.qoder?.cookieSource ?? .auto
do {
let (cookieHeader, sourceLabel) = try Self.resolveCookieHeader(context: context, allowCached: true)
let snapshot = try await QoderUsageFetcher.fetchUsage(cookieHeader: cookieHeader)

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 Honor the Qoder web timeout setting

Qoder fetches ignore context.webTimeout here because fetchUsage has no timeout parameter and always uses the fetcher's hard-coded 15 seconds. In CLI runs with a larger --web-timeout or app refreshes that pass 60 seconds, a slow Qoder API response can still fail early even though the caller explicitly allowed more time.

Useful? React with 👍 / 👎.

toggleTitle: "Show Qoder usage",
cliName: "qoder",
defaultEnabled: false,
isPrimaryProvider: false,

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 Qoder's default cookie import Chrome-only

Using ProviderBrowserCookieDefaults.defaultImportOrder makes automatic Qoder refresh probe every default browser, so enabling this provider can trigger unrelated Safari/Firefox/Chromium keychain prompts. The repository guidance for cookie imports is to default Chrome-only when possible, and Qoder still has manual Cookie headers/token accounts for non-Chrome sessions.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown

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: 7adc20978d

ℹ️ 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".

let totalQuota: QoderQuotaContainer?

private enum CodingKeys: String, CodingKey {
case totalQuota = "total_quota"

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 Match Qoder's documented quota JSON shape

Qoder's documented Get member quota payload (https://docs.qoder.com/account/teams/openapi/members#get-member-quota) uses the camelCase path totalQuota.quotaSummary with usedValue/limitValue/unit, while this decoder looks for total_quota.quota_summary and then requires derived fields the documented response does not send. Any account returning the documented quota schema will hit the missing total_quota.quota_summary parse error instead of showing usage; accept the documented camelCase shape and derive remaining/percentage from used/limit.

Useful? React with 👍 / 👎.

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

Copy link
Copy Markdown

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: 42b4921c53

ℹ️ 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".

usedPercent: min(100, max(0, self.usagePercentage)),
windowMinutes: nil,
resetsAt: nil,
resetDescription: creditSummary)

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 Stop using resetDescription for Qoder totals

For any successful Qoder response, creditSummary is not a reset time, but the normal menu/CLI renderers call UsageFormatter.resetLine for primary windows and prefix a non-empty resetDescription with Resets. That makes Qoder display Resets 125 / 500 credits even though there is no reset, so the credit total should be carried as provider-specific detail or left out of resetDescription instead of being attached here.

Useful? React with 👍 / 👎.

let primary = RateWindow(
usedPercent: min(100, max(0, self.usagePercentage)),
windowMinutes: nil,
resetsAt: nil,

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 Qoder quota reset dates

When Qoder returns the documented quota payload with nextResetAt/lastResetAt, this always sets resetsAt to nil, so the menu/CLI cannot show the monthly reset countdown even though reset metadata was available. Decode nextResetAt in the fetcher and pass it through here as the primary window's reset date.

Useful? React with 👍 / 👎.

@Yuxin-Qiao Yuxin-Qiao force-pushed the add-qoder-provider branch from eb2e136 to d9e4f73 Compare June 25, 2026 03:36
@clawsweeper clawsweeper Bot added status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. status: 🛠️ actively grinding The PR author has acted after the latest ClawSweeper review and work remains. labels Jun 25, 2026

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

Copy link
Copy Markdown

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: d9e4f73651

ℹ️ 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".

throw QoderUsageError.parseFailed("invalid JSON: \(error.localizedDescription)")
}

guard let summary = response.totalQuota?.quotaSummary else {

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 Include shared Qoder credits in quota totals

For team accounts that receive sharedQuota in Qoder's member quota response, totalQuota is only the plan plus resource-pack quota. Reading only this field drops shared add-on credits; for example, an exhausted personal quota with 1,000 shared credits still available displays as 100% used and 0 remaining. Decode sharedQuota and fold it into the displayed total/remaining when present.

Useful? React with 👍 / 👎.

providerID: .qoder,
accountEmail: nil,
accountOrganization: nil,
loginMethod: "\(Self.formatCredits(self.remainingCredits)) credits remaining")

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 Stop storing Qoder remaining credits as loginMethod

For every successful Qoder snapshot, this value is consumed by UsageMenuCardView.Model.plan and CLIRenderer.appendIdentityAndNotes as plan/login text, so the UI/CLI show a bogus line such as Plan: 375 Credits Remaining. Remaining credits are quota detail, not identity or plan data; leave loginMethod nil or expose the value through a Qoder-specific detail field.

Useful? React with 👍 / 👎.

Yuxin-Qiao and others added 2 commits June 25, 2026 12:10
Fold optional sharedQuota into displayed totals, keep remaining credits out
of loginMethod, and align fixtures with the schema from CodexBar#1590.

Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>

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

Copy link
Copy Markdown

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: c2cde4dd94

ℹ️ 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 +80 to +83
let snapshot = try await QoderUsageFetcher.fetchUsage(
cookieHeader: cookieHeader,
timeout: context.webTimeout)
return self.makeResult(usage: snapshot.toUsageSnapshot(), sourceLabel: sourceLabel)

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 Continue past every stale Qoder source

When automatic import has more than one unauthenticated/expired Qoder cookie set before a valid profile, this retry fetch is attempted only once; if the second candidate also returns invalidCredentials, the error escapes and later imported sessions are never tried. Fresh evidence in this version is that the invalid-credential catch resolves and fetches exactly one alternate source here, with no loop/catch around that second request.

Useful? React with 👍 / 👎.

@Yuxin-Qiao

Copy link
Copy Markdown
Contributor Author

Added real Qoder behavior proof from a free Qoder China account.

What I ran on the PR branch after adding qoder.com.cn support:

$ GIT_OPTIONAL_LOCKS=0 swift run CodexBarCLI usage --provider qoder --source web --format json --pretty > /tmp/qoder-proof.json
Build of product 'CodexBarCLI' complete!

$ rg -n "Cookie|Authorization|sid=|token|secret|password|Bearer|qoder-account-token" /tmp/qoder-proof.json
# no matches

$ python3 -m json.tool /tmp/qoder-proof.json
[
    {
        "provider": "qoder",
        "source": "Chrome Default / qoder.com.cn",
        "usage": {
            "identity": {
                "providerID": "qoder"
            },
            "primary": {
                "resetDescription": "0 / 300 credits",
                "usedPercent": 0
            },
            "secondary": null,
            "tertiary": null,
            "updatedAt": "2026-06-25T10:40:58Z"
        }
    }
]

This confirms the provider can import a real Chrome session for qoder.com.cn, call the Qoder usage endpoint, and render the credit total without writing raw cookies or sensitive auth material to the proof file.

@clawsweeper re-review

@clawsweeper

clawsweeper Bot commented Jun 25, 2026

Copy link
Copy Markdown

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

@clawsweeper clawsweeper Bot added proof: sufficient Contributor real behavior proof is sufficient. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. labels Jun 25, 2026
@clawsweeper clawsweeper Bot added rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 25, 2026

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

Copy link
Copy Markdown

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: 6ed44d1c6f

ℹ️ 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".

guard let manual = CookieHeaderNormalizer.normalize(context.settings?.qoder?.manualCookieHeader) else {
throw QoderUsageError.missingCredentials
}
return (manual, Self.sourceLabel(browserLabel: "manual", site: .international))

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 Route manual Qoder China cookies to the China host

When a user pastes a Cookie header or cURL capture from qoder.com.cn, this branch always labels the manual credentials as qoder.com, and site(for:) then sends the request to the international https://qoder.com/... endpoint. Because the importer explicitly supports qoder.com.cn sessions but manual mode has no way to select that site, China-domain manual cookies/token accounts will be sent to the wrong host and fail even though the same session works through automatic import.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. P2 Normal priority bug or improvement with limited blast radius. proof: sufficient Contributor real behavior proof is sufficient. rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add supplier - qoder

1 participant