Skip to content

feat: add Doubao Coding Plan usage#1841

Merged
steipete merged 32 commits into
mainfrom
maintainer/doubao-coding-plan
Jul 2, 2026
Merged

feat: add Doubao Coding Plan usage#1841
steipete merged 32 commits into
mainfrom
maintainer/doubao-coding-plan

Conversation

@steipete

@steipete steipete commented Jul 2, 2026

Copy link
Copy Markdown
Owner

Recreates and improves #1727 on a maintainer-owned branch because the contributor branch does not allow maintainer edits.

Summary

  • add signed Volcengine AK/SK/region support for GetCodingPlanUsage
  • map Coding Plan session, weekly, and monthly quota windows
  • preserve Ark bearer-token behavior and fallback
  • surface structured Volcengine authorization errors
  • add maintainer changelog credit for @LeoLin990405

Contributor commits are preserved through the commit's Co-authored-by trailer.

Proof

  • swift test --filter 'Doubao|ProviderConfigEnvironmentTests|ConfigValidationTests' — 90/90 passed
  • make check — documentation links, locales, SwiftFormat, and SwiftLint passed
  • make test — all 45 shards passed
  • autoreview — clean, no actionable findings

Live authenticated proof and official CLI cross-check remain documented in #1727.

ss251 and others added 24 commits July 1, 2026 23:46
console.sakana.ai/billing always server-renders "Resets on <date>" in
UTC (confirmed via the raw HTML's embedded "timeZone":"UTC" hydration
payload marker, and Sakana's own "Weekly usage resets every Monday at
00:00 UTC" copy elsewhere on the page). The browser only corrects that
text to the viewer's local timezone client-side, after JS hydration --
which this HTML-only fetcher never runs.

SakanaUsageFetcher.parseResetDate parsed the raw string using
TimeZone.current instead, so every non-UTC user got a reset time off
by exactly their UTC offset -- 5.5h early on an IST machine, verified
by building main into the codexbar CLI and running it against a real
account: the tool's own JSON output landed 5.5h before the true reset
instant shown in a browser on the same page at the same moment.

Removes the timeZone parameter entirely (it no longer has a legitimate
caller-supplied value; the source data is always UTC) and hardcodes
UTC in parseResetDate. Updates the existing fixture-based tests, which
previously asserted the buggy local-timezone interpretation as if it
were correct, and adds a regression test pinned to a literal Unix
timestamp independent of the date-building helper.

Fixes #1826.
- The UTC regression test didn't actually pin the fix: on a UTC CI
  runner, the pre-fix TimeZone.current code would coincidentally
  still produce the correct instant, so the test would pass either
  way. Force NSTimeZone.default to UTC+14 for the test's duration
  (same pattern as BedrockUsageStatsTests) so it only passes when the
  parser genuinely ignores the device timezone. Verified by
  temporarily reverting the fix locally and confirming the test now
  fails with the expected 5.5h-off result before restoring it.
- docs/sakana.md still said reset dates use the device's local time
  zone (TimeZone.current) -- exactly the behavior this PR removes.
  Updated to describe the actual UTC parsing and why, linking #1826.
clawsweeper's re-review flagged that the new NSTimeZone.default
override test lives in a non-serialized suite, unlike the existing
BedrockUsageStatsTests that uses the same pattern -- unrelated
parallel Swift Testing cases could observe UTC+14 and fail
nondeterministically. Mark @suite(.serialized), matching Bedrock's
precedent exactly.
Move remaining provider UI copy through localization helpers and add Traditional Chinese translations.

Preserve existing personal-info redaction behavior while localizing the visible placeholders and usage labels.
Keep stored OpenAI dashboard and Codex credits cached failure envelopes in English so CodexUIErrorMapper can parse the Cached values from marker.

Add zh-Hant regression coverage for localized user-facing cached error messages.
Route the Claude Code sign-in menu label through localization and add English, zh-Hant, and strict-locale catalog entries.

Add a zh-Hant regression test for the Claude account action.
Add the Claude Code sign-in label to localization catalogs covered by strict parity tests so CI passes after the menu action was localized.
CrossModel (https://crossmodel.ai) is a multi-provider, OpenAI- and
Anthropic-compatible API aggregation platform billed against a prepaid
USD wallet. This adds it as an API-key usage provider, modeled on the
OpenRouter provider since the data shape is nearly identical (wallet
balance + daily/weekly/monthly spend).

Data source (two read-only endpoints, integer micro units):
- GET /v1/credits -> balance_micro, uncollected_micro
- GET /v1/usage   -> daily/weekly/monthly cost_micro + tokens + counts

Display: balance in the identity line (and optional menu bar), today/
this week/this month spend in the menu card, and a shared inline
dashboard. No quota meter (prepaid wallet, no per-key limit).

Auth: CROSSMODEL_API_KEY env var or Settings/CLI config. Base URL
override via CROSSMODEL_API_URL (loopback HTTP allowed for local
testing).

Tests: CrossModelUsageStatsTests (decode, micro->USD, best-effort
usage, 401, redaction, round-trip) and a ProviderConfigEnvironment
regression covering Settings/CLI-saved keys.
CrossModel's balance lives in crossModelUsage, not the generic
credits path, so the fallback creditsHint text ("Wallet balance
from the CrossModel API") rendered as a misleading Credits row.
Suppress it the same way OpenRouter's balance-only card does.
Co-authored-by: LeoLin <leolin990405@gmail.com>
@clawsweeper

clawsweeper Bot commented Jul 2, 2026

Copy link
Copy Markdown

Codex review: found issues before merge. Reviewed July 2, 2026, 9:52 AM ET / 13:52 UTC.

Summary
The PR adds Doubao Volcengine AK/SK/region settings, signed GetCodingPlanUsage fetching, Coding Plan window mapping, Ark fallback preservation, structured Volcengine errors, and focused regression tests.

Reproducibility: not applicable. as a bug reproduction: this is a feature PR for a new Doubao Coding Plan fetch path. The related PR discussion includes redacted live CodexBarCLI output showing the signed path rendering real Coding Plan windows.

Review metrics: 3 noteworthy metrics.

  • Diff surface: 16 files, +1075/-36. The PR spans provider runtime, settings/config projection, signing, menu labels, and tests, so auth behavior is the main review surface.
  • Credential aliases: 4 access-key, 5 secret-key, 4 region aliases. Broad env alias support affects how existing Volcengine and Ark environments resolve signed Coding Plan versus bearer fallback.
  • Regression coverage: 4 test files, +478/-1. Focused tests cover parser/signing, config validation, credential projection, labels, and fallback behavior.

Root-cause cluster
Relationship: fixed_by_candidate
Canonical: #1724
Summary: This PR is a maintainer-owned candidate implementation for the open Doubao Coding Plan usage issue and overlaps the contributor PR it recreates.

Members:

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

Merge readiness
Overall: 🐚 platinum hermit
Proof: 🦞 diamond lobster
Patch quality: 🐚 platinum hermit
Result: ready for maintainer review.

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

Rank-up moves:

  • Update docs/doubao.md, docs/providers.md, and the README provider entry for AK/SK/region Coding Plan setup.
  • Record maintainer approval for the long-term AK/SK credential path or request the desired auth shape.

Risk before merge

  • [P1] Merging intentionally adds a long-term Volcengine AK/SK credential path for Doubao, so maintainers need to accept that auth and storage boundary.
  • [P2] The new credential precedence can select signed Coding Plan before Ark fallback in mixed Volcengine/Ark environments, even though the PR adds targeted compatibility tests.
  • [P1] The signer currently supports long-term AK/SK only; SSO or temporary STS credentials still need a follow-up or clear docs.

Maintainer options:

  1. Approve the AK/SK path deliberately (recommended)
    Maintainers can accept long-term Volcengine AK/SK support for Doubao and merge after checks, treating STS/session-token support as follow-up work.
  2. Require explicit auth/docs before merge
    If automatic AKLT detection or setup copy is not the desired UX, request a narrow update to auth-mode wording and Doubao docs first.
  3. Pause long-term key support
    If long-term Volcengine secrets should not live in CodexBar, pause or close this branch and keep the linked issue for a different auth design.

Next step before merge

  • Manual review is appropriate because the remaining blocker is auth/product boundary approval, with only a small docs follow-up.

Security
Cleared: No concrete security or supply-chain defect was found; the new AK/SK credential surface is tracked as merge risk for maintainer acceptance.

Review findings

  • [P3] Update Doubao docs for AK/SK setup — Sources/CodexBar/Providers/Doubao/DoubaoProviderImplementation.swift:40-56
Review details

Best possible solution:

Have a maintainer explicitly accept or reject the Doubao AK/SK credential path; if accepted, update Doubao docs and merge after required checks, leaving STS support as follow-up.

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

Not applicable as a bug reproduction: this is a feature PR for a new Doubao Coding Plan fetch path. The related PR discussion includes redacted live CodexBarCLI output showing the signed path rendering real Coding Plan windows.

Is this the best way to solve the issue?

Technically yes: the implementation is focused on GetCodingPlanUsage, preserves Ark fallback, and has targeted compatibility tests. Product-wise it still needs maintainer acceptance of the AK/SK credential surface and a docs update.

Full review comments:

  • [P3] Update Doubao docs for AK/SK setup — Sources/CodexBar/Providers/Doubao/DoubaoProviderImplementation.swift:40-56
    The new settings expose an access-key ID, secret access key, and region for Coding Plan usage, but docs/doubao.md, docs/providers.md, and README.md still describe only Ark API-key chat-completions probing. Users following the docs will not know how to configure the signed path or why it differs from an Ark bearer key.
    Confidence: 0.91

Overall correctness: patch is correct
Overall confidence: 0.88

AGENTS.md: found and applied where relevant.

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

Label changes

Label justifications:

  • P2: This is a normal-priority provider usage feature with limited blast radius but meaningful auth/config review needs.
  • merge-risk: 🚨 compatibility: The diff changes Doubao labels and credential precedence for existing config/environment combinations.
  • merge-risk: 🚨 auth-provider: The diff adds Volcengine AK/SK/region authentication alongside the existing Ark bearer-token path.
  • merge-risk: 🚨 security-boundary: The diff introduces an additional long-term secret field and signed request path that maintainers should explicitly accept.
  • rating: 🐚 platinum hermit: Overall readiness is 🐚 platinum hermit; proof is 🦞 diamond lobster and patch quality is 🐚 platinum hermit.
  • status: 👀 ready for maintainer look: ClawSweeper has no concrete contributor-facing blocker left for this PR. Not applicable: The maintainer-authored PR is outside the external-contributor proof gate; it references the source PR's redacted live signed-path CodexBarCLI proof.
Evidence reviewed

What I checked:

Likely related people:

  • LeoLin990405: Authored the original merged Qwen/Doubao provider PR and the open source PR that this maintainer branch recreates, with co-authored provenance on the current Doubao Coding Plan commit. (role: introduced behavior and source implementation contributor; confidence: high; commits: 6eb3699ec977, 970b938750ed, da34262edb44; files: Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift, Sources/CodexBarCore/Providers/Doubao/DoubaoProviderDescriptor.swift, Sources/CodexBar/Providers/Doubao/DoubaoProviderImplementation.swift)
  • steipete: Merged the original Doubao provider PR, authored the unavailable-quota behavior this feature builds on, and owns the current maintainer branch. (role: recent area contributor and merger; confidence: high; commits: 6eb3699ec977, 4a6fa81c3e1f, da34262edb44; files: Sources/CodexBarCore/Providers/Doubao/DoubaoUsageFetcher.swift, Tests/CodexBarTests/DoubaoMenuCardModelTests.swift, Sources/CodexBarCore/Config/ProviderConfigEnvironment.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 proof: sufficient Contributor real behavior proof is sufficient. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels Jul 2, 2026
@clawsweeper clawsweeper Bot added P2 Normal priority bug or improvement with limited blast radius. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 auth-provider 🚨 Merging this PR could break OAuth, tokens, provider routing, model choice, or credentials. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. labels Jul 2, 2026
@clawsweeper clawsweeper Bot removed the proof: sufficient Contributor real behavior proof is sufficient. label Jul 2, 2026
@steipete steipete merged commit 44f0949 into main Jul 2, 2026
17 of 19 checks passed
@steipete

steipete commented Jul 2, 2026

Copy link
Copy Markdown
Owner Author

Maintainer verification on exact head a5b4446533dad196cf6efcee5ed3e30088beb092:

  • Reviewed the contributor's real signed AK/SK proof and the Volcengine request-signing implementation.
  • Verified Coding Plan session, weekly, and monthly usage parsing plus authentication, request signing, configuration, menu, CLI, and diagnostics coverage.
  • Focused Doubao tests: 90 passed. Combined provider/localization/parser proof: 121 passed across 15 suites.
  • make check: passed.
  • make test: all 45 shards passed; one unrelated flaky shard passed on the automatic retry.
  • Autoreview: clean.
  • GitHub Actions: 10/10 checks passed on the exact landed head.

This maintainer replacement preserves @LeoLin990405's co-author credit and changelog thanks because the original branch did not allow maintainer edits. Thanks for the contribution.

LeoLin990405 pushed a commit to LeoLin990405/CodexBar that referenced this pull request Jul 2, 2026
…del/doubao-coding-plan conflicts)

Second conflict resolution after upstream landed Doubao Coding Plan (steipete#1841),
qoder, and crossmodel providers. Resolutions across the shared registration
surfaces (Providers enum + IconStyle + cookie-import props, ProviderDescriptor,
ProviderImplementationRegistry, UsageStore/CostUsageScanner switches,
docs/configuration.md regenerated in enum order) keep all providers; longcat
retained alongside qoder/crossmodel. CodexParserHash regenerated.
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. merge-risk: 🚨 compatibility 🚨 Merging this PR could break existing users, config, migrations, defaults, or upgrades. merge-risk: 🚨 security-boundary 🚨 Merging this PR could weaken sandboxing, authorization, credentials, or sensitive data. P2 Normal priority bug or improvement with limited blast radius. rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants