feat: add MiniMax M3 as a cloud AI provider#324
Open
M3NT1 wants to merge 3 commits into
Open
Conversation
Ports the MiniMax integration from JerryZLiu#320 onto the v2.0.3 base, which refactored the provider system into LLMProviderID with separate cases for chatGPT, claude, openAICompatible, and local. What's included - New LLMProviderID.minimax case with analytics + display label - MiniMaxProvider + 4 extension files (Networking, Reasoning, Summaries, Transcription) following the OllamaProvider pattern but using Bearer auth against https://api.minimax.io/v1 with M3's 1M-token context - MiniMaxModelPreference, MiniMaxPromptPreferences, MiniMaxAPIHelper - LLMService.makeMiniMaxProvider() wired into makeBatchProvider and makeTextProvider; providerModelId(for:) helper stamps cards with the active model - Storage layer: provider_id + model_id columns on timeline_cards with ALTER TABLE migration, TimelineCard/TimelineCardShell fields, and fetchAllTimelineCards() for the dashboard - Onboarding: 6th provider card (sparkles icon) + dedicated 4-step setup flow (get-key, enter-key, test, complete) - Settings: MiniMax section in providers tab with model picker, keychain field, test-connection button, and prompt-override plumbing - ModelCatalog + ProviderStatsCalculator + ProviderStatsView (dashboard data + GitHub-style heatmap + daily/weekly/monthly breakdowns) Build verified: xcodebuild Release succeeds, no new errors vs v2.0.3 base
The toast that warns the user about missing screen-recording access was gated on 'getSavedPreference() == true || appState.isRecording', but the recorder forces isRecording off the moment it detects the permission is missing, and getSavedPreference() is nil for users who have never explicitly toggled it. Net effect: the notice never surfaced for the exact case it was meant to alert on, and the user had no UI signal that recording was broken (the Resume button appeared to do nothing). Switch the guard to the 'didOnboard' UserDefaults flag so the notice appears whenever the user has completed onboarding and the permission is missing. Also re-evaluate the notice on every tab change to .timeline so a user who lands on the timeline after dismissing elsewhere still sees it (the session-dismiss flag prevents spam).
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.
What
This PR is a re-port of the MiniMax M3 provider integration onto the current
main(v2.0.3) base, which refactored the provider system intoLLMProviderIDwith separate cases forchatGPT,claude,openAICompatible, andlocal. It also brings over the model-management + usage-analytics layer that was in the original PR #320.The user's request:
Why a new branch?
PR #320 was opened against the v2.0.0 base. Since then upstream has landed 163 commits — including a major provider refactor that split
chatGPTClaudeinto separatechatGPT/claudecases, introducedopenAICompatibleandlocalcases, addedLLMProviderSetupPreferences, and rebuilt onboarding/settings around a newProviderSetupStatemachine.A straight rebase produced 21 conflicting files; rather than fight through them, this branch is a clean re-application onto the v2.0.3 base so both upstream's evolution and our MiniMax additions land together. #320 should be closed in favour of this PR.
Changes
Core/AI/LLMTypes.swift— added.minimaxcase toLLMProviderIDwith analytics + display label.Core/AI/MiniMaxProvider*.swift(8 new files) — the provider itself, modelled onOllamaProviderbut with Bearer auth againsthttps://api.minimax.io/v1and a 1M-token context window. Five files: main + Networking, Reasoning (strips<think>…</think>defensively), Summaries, Transcription. PlusMiniMaxModelPreference,MiniMaxPromptPreferences, andUtilities/MiniMaxAPIHelper.Core/AI/ModelCatalog.swift(new) — actor that fetches the current model list from each provider's API on the fly:GET /v1/modelsfor MiniMax (OpenAI-compatible)GET /v1beta/models?key=…for Gemini (filtered to vision-capable)GET {baseURL}/api/tagsfor Ollama,GET /v1/modelsfor LM StudioUserDefaults. On failure, falls back to a curated list with a banner in the UI.Core/AI/LLMService.swift— newmakeMiniMaxProvider()wired into bothmakeBatchProviderandmakeTextProviderswitch statements. A newproviderModelId(for:)helper centralises the per-provider model lookup. A newattachMetahelper stamps every card before persistence.Core/Analytics/ProviderStatsCalculator.swift(new) — pure data layer that turns the localTimelineCardlist into aProviderStatsSummary:byProvider: [String: Int](always includes all known providers, even at zero)byModel: [(providerID, modelID, count)]daily: [DailyStat](last 365 days)weekly: [WeeklyStat](last 26 weeks)monthly: [MonthlyStat](last 12 months)heatmapDays: [HeatmapDay](last 365 days, intensity 0…1)Views/UI/Dashboard/ProviderStatsView.swift(new) — self-contained dashboard surface with:Week / Month / Quarter / Yearrange pickerStorage layer —
provider_id+model_idcolumns ontimeline_cardswithALTER TABLEmigration + composite index.TimelineCardandTimelineCardShellgained matching fields. NewStorageManager.fetchAllTimelineCards()powers the dashboard.Onboarding — 6th provider card on the comparison screen (sparkles icon, "MiniMax M3", positioned between OpenAI-compatible and Local). New 4-step setup flow: get-key → enter-key → test-connection → complete. Reuses the existing
apiKeystate field that the input view binds to.Settings → Providers tab — MiniMax section with model picker (live or curated), keychain API-key field, test-connection button that re-opens the provider-setup modal. Prompt-override plumbing added for symmetry with the other providers.
Per-card badge —
CanvasActivityCard(and equivalent list/grid renderers) now show a small text pill below the time label, e.g.MiniMax · MiniMax-M3,Claude · Sonnet 4.5,Local · qwen3-vl:4b. Falls back to "Unknown" when the card predates the schema migration.ChatCLIProvider— gained adefaultModel: String?parameter that overrides the previously hard-coded"sonnet"/"haiku"/"gpt-5.4"strings.LLMService.makeChatCLIProviderreadsllmCodexModel/llmClaudeModelfromUserDefaultsand passes them through.Privacy
https://api.minimax.io/v1/chat/completionsand nowhere elseLLMLogger, but no PIIBuild verification
The pre-existing Swift 6 / Sendable warnings in
ChatCLIProcessRunner.swift,MiniMaxProvider+Transcription.swift, etc. are unchanged from upstream and not introduced by this PR.