Sync upstream CrossModel provider#44
Merged
Merged
Conversation
* 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Upstream range
Syncs Pete upstream
daba50847e1823b83c0835e1d22a68e31b7e4ac6..0a18391e1838ee9d110395f3409f785bfbca7c99.Included upstream commit:
0a18391e1Add 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:
SyncCrossModelUsage, Mac mapper, ghost-record handling, iOS detail card, SwiftData cache blob, CloudKit merge preservation, and mobile provider palette parity.UPSTREAM_VERSION=v0.36.1; advancedUPSTREAM_MONITOR_BASEto0a18391e1838ee9d110395f3409f785bfbca7c99.QuotaKit adaptations
~/.codexbarprimary config to QuotaKit~/.quotakit/config.json, retaining legacy~/.codexbar/config.jsononly as compatibility fallback in docs.e92fd56571a54d44.Validation
Local validation passed:
swift buildswift 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 lintxcodebuild -project CodexBarMobile/CodexBarMobile.xcodeproj -scheme CodexBarMobile -destination 'generic/platform=iOS Simulator' CODE_SIGNING_ALLOWED=NO build./Scripts/check_upstreams.shreports 0 new upstream commits since0a18391e1838ee9d110395f3409f785bfbca7c99~/.codexbar/config.jsonfallback 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.