Conversation
|
You have reached your Codex rate limits. Please try again later. |
There was a problem hiding this comment.
Pull request overview
This PR reintroduces a Manus usage provider on top of current main, adding the core fetch/parsing stack, app-side settings UI wiring, tests, and documentation/assets so Manus can be enabled like other providers.
Changes:
- Add CodexBarCore Manus provider implementation (cookie/env resolution, optional browser import on macOS, credits API fetch + mapping).
- Wire Manus into app registries/settings and adjust UI presentation to reflect Manus-specific quota semantics.
- Add Manus-focused tests plus docs/README updates and an official Manus SVG icon.
Reviewed changes
Copilot reviewed 23 out of 24 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| Tests/CodexBarTests/ManusProviderTests.swift | Adds strategy/fallback/cache tests for Manus fetching and resolution behavior. |
| Tests/CodexBarTests/ManusCookieHeaderTests.swift | Adds cookie-header parsing tests and macOS cookie object extraction test. |
| Sources/CodexBarWidget/CodexBarWidgetViews.swift | Adds Manus display name + color for widget UI components. |
| Sources/CodexBarWidget/CodexBarWidgetProvider.swift | Ensures Manus is treated as unsupported in widgets (mapping returns nil). |
| Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift | Excludes Manus from cost-usage scanning (empty report). |
| Sources/CodexBarCore/TokenAccountSupportCatalog+Data.swift | Declares Manus token account support semantics (session_id cookie header). |
| Sources/CodexBarCore/Providers/ProviderSettingsSnapshot.swift | Adds Manus settings snapshot types and builder/enum wiring. |
| Sources/CodexBarCore/Providers/Providers.swift | Adds .manus to UsageProvider and IconStyle. |
| Sources/CodexBarCore/Providers/ProviderDescriptor.swift | Registers ManusProviderDescriptor in the descriptor registry. |
| Sources/CodexBarCore/Providers/Manus/ManusUsageFetcher.swift | Implements credits API fetch + parsing + mapping to UsageSnapshot. |
| Sources/CodexBarCore/Providers/Manus/ManusSettingsReader.swift | Reads Manus session token from environment variables / cookie header env. |
| Sources/CodexBarCore/Providers/Manus/ManusProviderDescriptor.swift | Adds Manus provider descriptor + web fetch strategy and token resolution logic. |
| Sources/CodexBarCore/Providers/Manus/ManusCookieImporter.swift | Implements macOS browser cookie import via SweetCookieKit for Manus. |
| Sources/CodexBarCore/Providers/Manus/ManusCookieHeader.swift | Implements session_id extraction from raw token/cookie header/HTTPCookie array. |
| Sources/CodexBarCore/Logging/LogCategories.swift | Adds Manus-specific logging categories. |
| Sources/CodexBarCLI/TokenAccountCLI.swift | Adds Manus settings snapshot wiring for CLI token accounts/config. |
| Sources/CodexBar/UsageStore.swift | Adds Manus placeholder debug-log support and routes provider through unimplemented path. |
| Sources/CodexBar/Resources/ProviderIcon-manus.svg | Adds official Manus glyph SVG resource. |
| Sources/CodexBar/Providers/Shared/ProviderImplementationRegistry.swift | Registers ManusProviderImplementation in app provider catalog. |
| Sources/CodexBar/Providers/Manus/ManusSettingsStore.swift | Adds SettingsStore accessors + snapshot contribution for Manus settings. |
| Sources/CodexBar/Providers/Manus/ManusProviderImplementation.swift | Adds app-side settings UI for Manus cookie source + manual cookie entry. |
| Sources/CodexBar/MenuCardView.swift | Adds Manus-specific detail/reset display behavior and hides cost section for Manus. |
| README.md | Updates supported provider list + permissions note to include Manus. |
| docs/providers.md | Documents Manus data sources and API endpoint in provider overview docs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| _ = tokenOverride | ||
| return ProviderSettingsSnapshot.ManusProviderSettings( | ||
| cookieSource: self.manusCookieSource, | ||
| manualCookieHeader: self.manusManualCookieHeader) |
|
|
||
| @MainActor | ||
| func observeSettings(_ settings: SettingsStore) { | ||
| _ = settings.manusCookieSource | ||
| _ = settings.manusManualCookieHeader | ||
| } | ||
|
|
||
| @MainActor | ||
| func settingsSnapshot(context: ProviderSettingsSnapshotContext) -> ProviderSettingsSnapshotContribution? { | ||
| .manus(context.settings.manusSettingsSnapshot(tokenOverride: context.tokenOverride)) | ||
| } |
|
|
||
| #expect(attempts.snapshot() == ["browser-token", "env-token"]) |
| @Test | ||
| func `browser token populates cache after successful fetch`() async throws { | ||
| try await self.withIsolatedCacheStore { | ||
| #if os(macOS) | ||
| let browserCookie = try #require(HTTPCookie(properties: [ | ||
| .domain: "manus.im", | ||
| .path: "/", | ||
| .name: "session_id", | ||
| .value: "browser-token", | ||
| .secure: "TRUE", | ||
| ])) | ||
| ManusCookieImporter.importSessionOverrideForTesting = { _, _ in | ||
| ManusCookieImporter.SessionInfo(cookies: [browserCookie], sourceLabel: "Chrome") | ||
| } | ||
| ManusCookieImporter.importSessionsOverrideForTesting = nil | ||
| defer { | ||
| ManusCookieImporter.importSessionOverrideForTesting = nil | ||
| ManusCookieImporter.importSessionsOverrideForTesting = nil | ||
| } | ||
| #endif | ||
|
|
||
| let strategy = ManusWebFetchStrategy() | ||
| let settings = ProviderSettingsSnapshot.make( | ||
| manus: ProviderSettingsSnapshot.ManusProviderSettings( | ||
| cookieSource: .auto, | ||
| manualCookieHeader: nil)) | ||
| let context = self.makeContext(settings: settings) | ||
| let fetchOverride: @Sendable (String, Date) async throws -> ManusCreditsResponse = { token, _ in | ||
| #expect(token == "browser-token") | ||
| return self.stubResponse() | ||
| } | ||
|
|
||
| _ = try await ManusUsageFetcher.$fetchCreditsOverride.withValue(fetchOverride, operation: { | ||
| try await strategy.fetch(context) | ||
| }) | ||
|
|
||
| let cached = CookieHeaderCache.load(provider: .manus) | ||
| #expect(cached?.cookieHeader == "session_id=browser-token") | ||
| } |
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 28d4e952c7
ℹ️ 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".
| if let direct = try? decoder.decode(ManusCreditsResponse.self, from: data) { | ||
| return direct |
There was a problem hiding this comment.
Decode envelope before permissive direct payload
parseResponse tries a direct ManusCreditsResponse decode first, but that type’s custom decoder defaults all missing numeric fields to 0, so almost any JSON object (including wrapped payloads like { "data": { ... } }) decodes successfully. That means the envelope branch is skipped and wrapped responses are silently interpreted as zero credits, producing incorrect usage percentages and balances.
Useful? React with 👍 / 👎.
| func manusSettingsSnapshot(tokenOverride: TokenAccountOverride?) -> ProviderSettingsSnapshot.ManusProviderSettings { | ||
| _ = tokenOverride | ||
| return ProviderSettingsSnapshot.ManusProviderSettings( | ||
| cookieSource: self.manusCookieSource, | ||
| manualCookieHeader: self.manusManualCookieHeader) |
There was a problem hiding this comment.
Honor token-account override for Manus snapshot
This snapshot path discards tokenOverride and always returns the persisted Manus cookie settings, so selecting a Manus token account does not affect runtime fetch credentials. In the same commit, Manus is added to TokenAccountSupportCatalog+Data.swift as manual cookie-header token-account support, so users can configure accounts but the selected account is never propagated into the provider settings used by fetch.
Useful? React with 👍 / 👎.
- Swap parseResponse decode order: try envelope first to avoid permissive direct decoder silently returning zero credits for wrapped payloads - Honor tokenOverride in ManusSettingsStore snapshot, mirroring Cursor pattern - Add tokenAccountsVisibility/applyTokenAccountCookieSource to wire up token account UI properly - Wrap macOS-only browser cookie tests in #if os(macOS) for Linux CI compat Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
Hi @ratulsarna — thanks for flagging the Copilot/Codex review! I've gone through all the suggestions and they were solid catches. Just pushed a fix addressing each one:
All 12 Manus tests passing locally. Ready for another look when you get a chance! |
|
Hi @ratulsarna — I pulled the latest Verified on my side:
Since this PR is meant to be the clean replacement for the old #476 direction, a quick maintainer sanity check on whether the overall approach fits the repo would help a lot before I spend more time polishing follow-up details. Thanks! |
# Conflicts: # README.md # Sources/CodexBar/UsageStore.swift # Sources/CodexBarCore/Vendored/CostUsage/CostUsageScanner.swift # docs/providers.md
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2505c1be1a
ℹ️ 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".
| self.totalCredits = container.decodeLossyDoubleIfPresent(forKey: .totalCredits) ?? 0 | ||
| self.freeCredits = container.decodeLossyDoubleIfPresent(forKey: .freeCredits) ?? 0 | ||
| self.periodicCredits = container.decodeLossyDoubleIfPresent(forKey: .periodicCredits) ?? 0 |
There was a problem hiding this comment.
Validate decoded Manus payload before accepting zero defaults
ManusCreditsResponse defaults missing numeric keys to 0, so parseResponse can treat unrelated HTTP 200 JSON (for example, an error object without credit fields) as a successful usage response and surface a fake “0 credits” state instead of a fetch/parsing error. This can silently mask backend/auth failures and mislead users into thinking their balance is exhausted; add a required-field validation path (or explicit envelope success checks) before accepting the decoded payload.
Useful? React with 👍 / 👎.
| - [Droid](docs/factory.md) — Browser cookies + WorkOS token flows for Factory usage + billing. | ||
| - [Copilot](docs/copilot.md) — GitHub device flow + Copilot internal usage API. | ||
| - [z.ai](docs/zai.md) — API token (Keychain) for quota + MCP windows. | ||
| - [Manus](docs/manus.md) — Browser `session_id` auth for credit balance, monthly credits, and daily refresh tracking. |
There was a problem hiding this comment.
Update README Manus docs link to an existing file
The new README entry links to docs/manus.md, but that file is not present in the repository, so the provider documentation link is broken for readers. Point this link to an existing page (or add the missing docs file) to avoid dead navigation from the main project page.
Useful? React with 👍 / 👎.
- Reject Manus API payloads lacking expected credits fields so unrelated 200 responses (e.g. error objects) no longer decode into a bogus zero-credit snapshot via the permissive defaults. - Add docs/manus.md so the README link resolves, covering setup, cookie sources, API endpoint, and troubleshooting. - Extend parseResponse tests for the rejection path and the envelope wrapper shape.
|
Hi @ratulsarna — thanks for kicking off another Codex pass. Addressed both suggestions in 03d7547:
Verified locally:
Ready for another look whenever you have a moment. |
@steipete @ratulsarna
I found a Manus provider issue and completed a full local rework on top of current
main.Summary
This PR adds a clean Manus provider implementation for current
main, including:Sources/CodexBar/Providers/Manus/ManusProviderImplementation.swiftSources/CodexBarCore/Providers/Manus/*Tests/CodexBarTests/ManusProviderTests.swiftTests/CodexBarTests/ManusCookieHeaderTests.swiftWhy
This is intended as a clean replacement for the old PR #476 direction, not a continuation of that drifted branch.
The older attempt no longer fits current
mainsafely, and it also had behavioral problems:This PR fixes that by aligning Manus with the current provider architecture and rendering Manus-specific semantics:
BalanceMonthly creditsDaily refreshValidation
swift test --filter Manuspassedpnpm checkpassed./Scripts/compile_and_run.shpassedsession_idand liveGetAvailableCreditsresponseNotes
The icon uses the official Manus glyph asset rather than the boxed icon asset, because CodexBar currently renders provider SVGs as template images; the boxed icon collapses into a white square in that pipeline, while the official glyph renders correctly.
Related