Skip to content

Sync upstream CrossModel provider#44

Merged
ColumbusLabs merged 3 commits into
mainfrom
codex/upstream-sync-crossmodel-20260702
Jul 2, 2026
Merged

Sync upstream CrossModel provider#44
ColumbusLabs merged 3 commits into
mainfrom
codex/upstream-sync-crossmodel-20260702

Conversation

@ColumbusLabs

Copy link
Copy Markdown
Owner

Upstream range

Syncs Pete upstream daba50847e1823b83c0835e1d22a68e31b7e4ac6..0a18391e1838ee9d110395f3409f785bfbca7c99.

Included upstream commit:

  • 0a18391e1 Add CrossModel provider (#1747)

No upstream-sync issue existed for this live tail.

Review notes

Risk classification: medium/high because this adds a new API-key provider across provider registry, settings, CLI diagnostics, menu/status rendering, docs, widget enumeration, parser hash, and shared/mobile sync surfaces.

Reviewed areas:

  • CrossModel API token resolution, endpoint override validation, HTTP redirect/error handling, optional usage-window timeout behavior, and diagnostic redaction.
  • Menu/status/CLI rendering for CrossModel wallet balance plus daily/weekly/monthly spend windows.
  • QuotaKit identity preservation in public docs, settings copy, config paths, site metadata, social image, and release/appcast ownership.
  • iCloud/iOS parity for CrossModel: added SyncCrossModelUsage, Mac mapper, ghost-record handling, iOS detail card, SwiftData cache blob, CloudKit merge preservation, and mobile provider palette parity.
  • Preserved iOS/Mac build numbers and UPSTREAM_VERSION=v0.36.1; advanced UPSTREAM_MONITOR_BASE to 0a18391e1838ee9d110395f3409f785bfbca7c99.

QuotaKit adaptations

  • Kept QuotaKit/Columbus Labs public identity and QuotaKit docs/site framing.
  • Changed CrossModel settings copy/docs from upstream ~/.codexbar primary config to QuotaKit ~/.quotakit/config.json, retaining legacy ~/.codexbar/config.json only as compatibility fallback in docs.
  • Added CrossModel shared/mobile sync payload so iOS gets structured wallet and usage-window data instead of an empty generic card.
  • Added CrossModel to Mac/iOS ghost filtering, account identity grouping, model-estimation switch handling, and mobile palette parity.
  • Regenerated the parser hash to e92fd56571a54d44.

Validation

Local validation passed:

  • swift build
  • swift test --no-parallel --filter 'CrossModelUsageStatsTests|MenuDescriptorCrossModelTests|ProviderConfigEnvironmentTests|ProviderDiagnosticExportTests|CLIDiagnoseCommandTests|CLIOutputTests|UsageStorePathDebugTests|StatusItemBalanceDisplayTests|SettingsStoreAdditionalTests|SyncCrossModelMapperTests|V036SnapshotsCodableTests|SyncWireFormatRoundTripTests' (160 tests)
  • PARSER_LINT_BASE=origin/main ./Scripts/lint.sh lint
  • xcodebuild -project CodexBarMobile/CodexBarMobile.xcodeproj -scheme CodexBarMobile -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build
  • ./Scripts/check_upstreams.sh reports 0 new upstream commits since 0a18391e1838ee9d110395f3409f785bfbca7c99
  • Branding/config scan found only intentional legacy ~/.codexbar/config.json fallback mentions.

Note: Xcode still reports this Mac's CoreSimulator framework is out of date while loading simulator devices, but the generic simulator build completed successfully.

hujuncheng and others added 2 commits July 2, 2026 06:41
* fix(sakana): parse weekly/5-hour reset time as UTC, not device-local

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.

* address clawsweeper review: strengthen regression test, fix stale docs

- 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.

* test(sakana): serialize suite with process-global timezone mutation

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.

* Localize provider menu strings

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.

* fix(codex): keep cached error envelopes parseable

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.

* fix(claude): localize Claude Code sign-in action

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.

* fix(localization): complete Claude sign-in catalog parity

Add the Claude Code sign-in label to localization catalogs covered by strict parity tests so CI passes after the menu action was localized.

* Add CrossModel provider

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.

* Fix CrossModel menu metrics and diagnostics

* fix: harden CrossModel provider integration

* fix: suppress generic credits bar for CrossModel menu card

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.

* fix: repair CrossModel currency handling

* fix: normalize CrossModel redirect ports

* docs: update CrossModel provider count

* fix: respect CrossModel optional usage setting

* fix: render CrossModel CLI usage

* docs: note Sakana reset timezone fix

* test: align Sakana fixture with raw UTC HTML

* fix: preserve hidden identity behavior

* docs: note localization completion

* fix: preserve CrossModel balance without usage

* fix: expose CrossModel diagnostics

---------

Co-authored-by: ss251 <ss251@uw.edu>
Co-authored-by: Shun Min Chang <ji394m6y7@gmail.com>
Co-authored-by: Peter Steinberger <steipete@gmail.com>
@ColumbusLabs ColumbusLabs merged commit a951df4 into main Jul 2, 2026
10 checks passed
@ColumbusLabs ColumbusLabs deleted the codex/upstream-sync-crossmodel-20260702 branch July 2, 2026 15:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants