Skip to content

MiniMax: Token Plan API usage, weekly-cap handling, collapsible menu & settings UI#742

Open
cskeleton wants to merge 12 commits intosteipete:mainfrom
cskeleton:cursor/minimax-multi-model-usage-ef73
Open

MiniMax: Token Plan API usage, weekly-cap handling, collapsible menu & settings UI#742
cskeleton wants to merge 12 commits intosteipete:mainfrom
cskeleton:cursor/minimax-multi-model-usage-ef73

Conversation

@cskeleton
Copy link
Copy Markdown

Summary

  • Usage: Show full MiniMax Token Plan API usage in the menu bar card and in provider settings. Legacy plans without a weekly cap omit weekly-limit rows.
  • UI: MiniMax menu card supports grouped section collapse and in-card scrolling; settings mirror grouped sections with scrolling.
  • Sync: Branch includes a merge of current upstream/main to reduce conflicts.

Implementation notes

  • New helpers: MiniMaxMenuCardViews, MiniMaxSectionCollapseStore, MiniMaxUILayoutMetrics, UsageMenuCardViewModel+MiniMax; MiniMaxUsageFetcher extended accordingly.
  • Post-merge: AppGroupSupportTests snapshot paths isolated to temp dirs; ClickToCopy overlay split to MenuCardClickToCopy.swift for SwiftLint file length.

Verification

  • swift test
  • ./Scripts/lint.sh lint

Made with Cursor

cursoragent and others added 5 commits April 18, 2026 19:19
Co-authored-by: c.skeleton <cskeleton@users.noreply.github.com>
- Show full MiniMax Token Plan API usage in menu bar card and provider settings; hide weekly cap rows when the plan has no weekly limit (legacy plans).\n- MiniMax menu card: section collapse defaults, in-card scrolling, layout metrics; Preferences mirrors grouped sections with scrolling.\n- Extend MiniMaxUsageFetcher parsing, tests, and docs/minimax.md; note behavior in AGENTS.md.

Made-with: Cursor
Resolve conflicts: keep upstream async URLSession challenge handlers; use waitForResult in OpenAIDashboardNavigationDelegateTests.

Made-with: Cursor
- AppGroupSupportTests: override snapshot URLs with temp paths so migration tests do not touch real Group Containers.\n- Move ClickToCopy overlay types to MenuCardClickToCopy.swift to satisfy SwiftLint file_length.

Made-with: Cursor
Copy link
Copy Markdown

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

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: 26d7044213

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


static func miniMaxDetailLine(model: MiniMaxModelUsage) -> String? {
guard let total = model.availablePrompts else { return nil }
let used = model.currentPrompts ?? max(0, total - (model.remainingPrompts ?? 0))
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 Avoid inferring full usage when remaining count is missing

In miniMaxDetailLine, the fallback model.remainingPrompts ?? 0 turns a missing remaining count into zero and reports used == total, which can render rows as fully consumed even when the API payload simply omitted current_interval_usage_count. This creates incorrect usage text (and disagrees with percent/reset fields that already treat missing counts as unknown), so rows with partial interval data should avoid deriving used from an assumed zero remaining value.

Useful? React with 👍 / 👎.

Avoid treating missing remaining as zero (full usage). Show em dash over total when neither current nor remaining is available. Adds XCTest coverage. Addresses Codex review on PR steipete#742.

Made-with: Cursor
@cskeleton
Copy link
Copy Markdown
Author

Addressed the P2 inline review on miniMaxDetailLine: we no longer treat missing remainingPrompts as 0 when deriving used count. If both currentPrompts and remainingPrompts are absent, the line shows —/<total> instead of implying full consumption. Pushed as f952a432.

Remove .cursor/hooks/state and .specstory from the repo tree; add gitignore rules so IDE-local data is not committed again.

Made-with: Cursor
@ratulsarna
Copy link
Copy Markdown
Collaborator

@codex review

Copy link
Copy Markdown

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

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: 32fc946c9d

ℹ️ 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 thread docs/minimax.md Outdated
Comment on lines 3 to 7
## summary: "MiniMax provider data sources: API token or browser cookies + coding plan remains API."
read_when:
- Debugging MiniMax usage parsing
- Updating MiniMax cookie handling or coding plan scraping
- Adjusting MiniMax provider UI/menu behavior
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3 Badge Restore valid YAML front matter in MiniMax docs

The top metadata block is no longer valid front matter: summary was turned into a markdown heading (## summary) and the block is missing its closing ---, so Scripts/docs-list.mjs now classifies this file as malformed and cannot extract summary/read_when metadata for documentation discovery workflows.

Useful? React with 👍 / 👎.

Resolve conflict in StatusItemController+Menu by remeasuring both menu cards and overview rows using rendered menu width; restore valid YAML front matter in docs/minimax.md.

Made-with: Cursor
Resolve the post-merge sizing regression by using instance-based remeasurement during menu refresh, so long MiniMax usage content can collapse correctly and the menu window shrinks as expected.

Made-with: Cursor
@cskeleton
Copy link
Copy Markdown
Author

Follow-up update pushed in 3f5c1200 (plus prior local merge sync):

  • Addresses Codex feedback in this PR (MiniMax detail-line inference fix was already pushed earlier in f952a432).
  • Resolves latest upstream merge conflict in StatusItemController+Menu.
  • Fixes menu sizing regression after merge: long MiniMax usage sections now collapse correctly and the menu height shrinks as expected (instance-based remeasure in refreshMenuCardHeights).

Also includes upstream sync commit d411a8e7 with the docs front-matter repair in docs/minimax.md.

@cskeleton
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

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

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: 3f5c120096

ℹ️ 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 +49 to +50
let used = model.usedPercent ?? 0
let barPercent = percentStyle == .used ? used : (100 - used)
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 unknown usage percent when interval counts are absent

When MiniMax omits current_interval_usage_count (a case this patch explicitly handles in miniMaxDetailLine), model.usedPercent is nil, but this code coerces it to 0 and computes barPercent from that synthetic value. That renders rows as 0% used / 100% left even though usage is actually unknown, which can mislead users about remaining quota. Keep the percent unknown instead of defaulting to zero before deriving the progress value.

Useful? React with 👍 / 👎.

Comment on lines +39 to +40
Button {
self.collapseStore.toggle(sectionTitle: section.title, rowCount: rowCount)
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 Avoid row-selection side effects on MiniMax collapse button taps

This new in-card Button is rendered inside overview rows, which are still wrapped by makeMenuCardItem(..., onClick:) in StatusItemController+Menu.swift and therefore have a row-level click recognizer for provider selection. Tapping the collapse header can trigger the row selection path and switch providers instead of just toggling the section, making collapse/expand unreliable in Overview for MiniMax rows.

Useful? React with 👍 / 👎.

Keep MiniMax progress unknown when interval usage counts are missing, and suppress overview row selection when users tap in-card controls like section collapse buttons.

Made-with: Cursor
@cskeleton
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

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

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

ℹ️ 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 +657 to +660
for candidate in candidates {
let trimmed = candidate?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !trimmed.isEmpty { return trimmed }
}
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 Ensure MiniMax row IDs are unique across repeated models

modelIdentifier returns the first non-empty label directly, so rows that share model_type/name can get the same identifier when model_name is missing or duplicated. Those IDs flow into MiniMaxRow.id and are consumed by SwiftUI ForEach, where duplicate identities can cause row reuse glitches (missing/incorrectly updated rows after refresh or collapse toggles). Use a collision-safe ID (for example, include index or a stable unique field) when building identifiers.

Useful? React with 👍 / 👎.

Comment thread Sources/CodexBar/MenuCardView.swift Outdated
Comment on lines +145 to +146
static func miniMaxUsageScrollMaxHeight() -> CGFloat {
MiniMaxUILayoutMetrics.menuUsageScrollMaxHeight(visibleScreenHeight: NSScreen.main?.visibleFrame.height)
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 Compute MiniMax scroll cap from the menu display, not NSScreen.main

This cap uses NSScreen.main, which tracks the key-window screen rather than the status-item menu’s actual display and can be nil when no key window exists. On multi-monitor setups that yields the wrong max height (or fallback), so the MiniMax card can still be mis-sized and obscure lower menu actions. Thread the current menu/button screen height into this calculation instead of reading global main screen state here.

Useful? React with 👍 / 👎.

Make model-remains row IDs collision-safe for SwiftUI diffing and compute MiniMax menu scroll caps from the menu/status-item display screen instead of global NSScreen.main.

Made-with: Cursor
@cskeleton
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

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

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

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

]
for candidate in primary {
let trimmed = candidate?.trimmingCharacters(in: .whitespacesAndNewlines) ?? ""
if !trimmed.isEmpty { return "\(trimmed)#\(index)" }
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Preserve unsuffixed MiniMax identifiers for model lookups

This now returns "\(trimmed)#\(index)" for every non-empty model key, so a normal row like model_name: "text-gen" no longer has identifier text-gen but text-gen#0. That breaks consumers that match rows by API model identifier (including the new parser tests in this commit that look up text-gen, image-01, and coding-model), so lookups fail even on valid payloads. Please only suffix when disambiguation is actually needed (or keep a separate UI-only key) so identifier-based matching remains reliable.

Useful? React with 👍 / 👎.

Preserve unsuffixed model identifiers for lookup compatibility while appending #n only when duplicate IDs appear within the same payload.

Made-with: Cursor
@cskeleton
Copy link
Copy Markdown
Author

@codex review

Copy link
Copy Markdown

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

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: 4fa0330dbb

ℹ️ 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 +645 to +646
hasWeeklyQuota: weeklyTotal != nil || weeklyRemaining != nil,
hasIntervalQuota: total != nil || remaining != 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 Treat 0/0 interval placeholders as non-interval quotas

MiniMax can return weekly-limited rows where current_interval_* is present only as a 0/0 placeholder; with the current nil-check (total != nil || remaining != nil), those placeholders are treated as a real interval quota. In that case classifyWindowKind will never emit .weekly, so weekly-only rows are grouped under Daily/Other even though their interval line is suppressed, which mislabels the quota window in both menu and settings sections. Compute hasIntervalQuota from meaningful interval data (e.g., exclude the placeholder 0/0 case) before classifying.

Useful? React with 👍 / 👎.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants