Add OAuth login providers - #820
Conversation
|
The PR Policy check is blocking this PR because required template information is missing. Please update the PR description with:
Visual files detected:
Screenshots or video are required for UI, UX, settings, onboarding, overlay, menu bar, or visual behavior changes. If this PR has no visual changes, check the no-visual-change box in the template. If this remains incomplete for 48 hours after opening, the PR may be closed. |
7053160 to
e59e0c3
Compare
Greptile SummaryAdds subscription-based OAuth providers alongside existing API-key providers and updates shared LLM routing, persistence, verification, and settings UI to support them.
|
There was a problem hiding this comment.
Pull request overview
Adds first-party subscription login/OAuth providers (ChatGPT/Codex, Grok, Claude, Gemini) alongside existing API-key providers, wiring them through model selection, verification, and request building so FluidVoice can use official client sessions and transports.
Changes:
- Introduces official provider authentication adapters (device auth + Keychain storage where applicable; read-only imports for others).
- Extends
LLMClientto resolve official sessions, enforce Codex SSE streaming, and add Anthropic/Gemini wire-protocol request/response handling. - Updates settings UI + verification/fingerprinting to support “official login” providers in parallel with API-key providers, and adds/adjusts integration tests.
Reviewed changes
Copilot reviewed 16 out of 17 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| Tests/FluidDictationIntegrationTests/LLMClientRequestBodyTests.swift | Adds coverage for official provider credential decoding, streaming requirements, and request-body differences (Codex/Claude/Gemini/Grok). |
| Tests/FluidDictationIntegrationTests/DictationE2ETests.swift | Aligns E2E verification fingerprints with any existing Ollama API key in host-app test environments. |
| Sources/Fluid/UI/AISettingsView+AIConfiguration.swift | Adds “official client login” UI sections and allows model fetch/verify without API key for official providers. |
| Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift | Implements in-app sign-in flow orchestration, messaging/URL hints, disconnect, and official-provider verification path. |
| Sources/Fluid/Services/RewriteModeService.swift | Plumbs providerID into LLMClient.Config and updates fingerprinting via OfficialProviderAuth. |
| Sources/Fluid/Services/OfficialProviderAuth.swift | New shared resolver/decoder for official client sessions plus fingerprint strategy for official providers. |
| Sources/Fluid/Services/ModelRepository.swift | Registers official login providers as built-ins, supplies defaults (models/base URLs), and resolves official sessions before returning curated models. |
| Sources/Fluid/Services/LLMClient.swift | Adds providerID to config, official-session resolution, wire-protocol routing (Responses/Anthropic/Gemini), and Codex-specific request shaping. |
| Sources/Fluid/Services/GrokSubscriptionAuth.swift | New Grok device auth + Keychain-backed session storage, plus safe import of official Grok auth.json. |
| Sources/Fluid/Services/DictationPostProcessingService.swift | Allows official providers to run without API key and passes providerID into LLMClient.Config. |
| Sources/Fluid/Services/DictationAIPostProcessingGate.swift | Updates gating + fingerprinting to treat official providers as valid without API keys. |
| Sources/Fluid/Services/CommandModeService.swift | Passes providerID into LLMClient.Config so non-OpenAI wire protocols/official providers can work. |
| Sources/Fluid/Services/CodexSubscriptionAuth.swift | New ChatGPT/Codex device auth + Keychain-backed session storage and token decode/refresh support. |
| Sources/Fluid/Persistence/SettingsStore+CommandMode.swift | Switches fingerprinting to OfficialProviderAuth.configurationFingerprint to support official providers. |
| Sources/Fluid/Persistence/SettingsStore.swift | Allows official providers to be considered “configured” without API key; updates verification fingerprinting to use providerID-aware fingerprinting. |
| Sources/Fluid/ContentView.swift | Skips API-key requirement for official providers and passes providerID into LLMClient.Config (including fallback path). |
Suppressed comments (3)
Sources/Fluid/Services/OfficialProviderAuth.swift:129
setupLabeluses lowercase "guide", but existing UI icon logic checkslabel.contains("Guide")(case-sensitive), so official-provider links may render with the wrong icon (treated as a generic link instead of a guide). Consider capitalizing "Guide" for consistency with that UI contract.
setupLabel: "Claude login guide",
Sources/Fluid/Services/OfficialProviderAuth.swift:137
setupLabeluses lowercase "guide", but existing UI icon logic checkslabel.contains("Guide")(case-sensitive), so official-provider links may render with the wrong icon (treated as a generic link instead of a guide). Consider capitalizing "Guide" for consistency with that UI contract.
setupLabel: "Gemini login guide",
Sources/Fluid/Services/OfficialProviderAuth.swift:145
setupLabeluses lowercase "guide", but existing UI icon logic checkslabel.contains("Guide")(case-sensitive), so official-provider links may render with the wrong icon (treated as a generic link instead of a guide). Consider capitalizing "Guide" for consistency with that UI contract.
setupLabel: "Grok login guide",
💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.
There was a problem hiding this comment.
💡 Codex Review
FluidVoice/Sources/Fluid/Services/LLMClient.swift
Lines 976 to 979 in e59e0c3
When Command Mode receives a function call from a Codex reasoning model, the response includes the requested reasoning.encrypted_content, but this event handler retains only function_call items and Response has nowhere to carry the reasoning item. Because requests use store: false, the next tool-continuation request consequently replays the function call and result without the preceding encrypted reasoning item required for a stateless reasoning continuation, which can make Codex terminal-tool loops fail; retain these response items and replay them with the tool output.
ℹ️ 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".
|
Review remediation is published in e9b2e4e. In addition to the inline fixes, the Codex stateless tool-loop review is addressed: Responses API output parsing now retains Validation on the final commit:
|
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: e9b2e4ee51
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 221cb99cda
ℹ️ 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".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c60195d4cf
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ffef203e9b
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 013e2a0788
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b9bc97d77a
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 178a1e642a
ℹ️ 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".
|
@codex review |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 8865f4b0a0
ℹ️ 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".
|
Hey man, ~5000 lines seems excessive right now for to merge in while we're fixing reliablity issues for FV. Feel free to have a fork here if you want to keep testing it out while we figure out a way to come back to this soon! useful change but not in our current roadmap yet but much needed a little later once we do what we have in our plate rn! Thanks and appreciate the PR. |
Fair enough, I get it's a bit much. Thanks for the feedback! Is there a roadmap for contributions? I looked and didn't see anything. |
|
yeah, so we work usually based on requests time to time. But overall, all of these items are very sensitive to changes and since it goes out to 1000s of people - I am very careful about taking in bigger contributions at a time and looking for small bug and feature fixes so it's easy to verify and merge. Currently, we are focusing on fixing audio reliability issues. Since we ported to a new form of recording, which is the core audio, that has been a lot of problems and we've mostly fixed all of it. That is our current priority right now. Secondly, we've been working on rewriting our hotkey manager a little and also the clipboard pasting to make it all seamless. This would solve a lot of current issues. So some form of contribution if it's featured would be edit mode and command mode. Since it's separate from the dictation itself and it doesn't touch any of the main sensitive areas, I think this could be a good area to work with. Specifically, we are looking at how to add OCR to get context from the screenshots. If you're interested in that, I'm happy to take some help there. That is a little more than just asking your agent to code agent. You might need to look into a little more specifics on how to design it better. So that could be a good assignment if you're willing to take it. If you're interested, let me know, then we can talk further. Thanks! |
|
OpenAI has something similar to what you're looking for, I believe it's called app shots, is that what you want, but just local? |
|
AppShots reads the whole image and tries to understand it specifically. It's pretty much like taking a screenshot, right? But the current one is towards reading the text on the screen once you capture it and then get the important words from that. So we can use that to boost the current dictation. And this can be learned locally because you don't need a big model to understand what the image actually means. You just care about the text in the image. |
|
Ah, got it, so not really a local AppShots clone. More like: grab the current window, OCR the text locally, pull out the useful/unusual words, and use those to help the dictation. I was looking through the code and saw that FluidVoice already has vocabulary boosting through When you say “boost the current dictation,” do you mean temporarily feeding those OCR words into the ASR vocabulary for that recording? Like, if the screen has Or were you thinking the OCR text would only be used later during AI post-processing? If you mean the ASR side, I think the main thing to figure out is how to update that temporary vocabulary for each recording without having to reload the speech model every time. |
|
Yeah for each recording - or a session perhaps is what i was thinking.
I can do the AI post process part but thats a lil more involved
…On Sun, Aug 9, 2026 at 7:28 PM Jacob Rudolph ***@***.***> wrote:
*Elemperor1* left a comment (altic-dev/FluidVoice#820)
<#820 (comment)>
Ah, got it, so not really a local AppShots clone. More like: grab the
current window, OCR the text locally, pull out the useful/unusual words,
and use those to help the dictation.
I was looking through the code and saw that FluidVoice already has
vocabulary boosting through ParakeetVocabularyStore and
configureVocabularyBoosting.
When you say “boost the current dictation,” do you mean temporarily
feeding those OCR words into the ASR vocabulary for that recording?
Like, if the screen has SCScreenshotManager, FluidAudioProvider, or
someone’s unusual name, FluidVoice would temporarily boost those words so
they’re more likely to get transcribed correctly, then drop them after that
recording.
Or were you thinking the OCR text would only be used later during AI
post-processing?
If you mean the ASR side, I think the main thing to figure out is how to
update that temporary vocabulary for each recording without having to
reload the speech model every time.
—
Reply to this email directly, view it on GitHub
<#820?email_source=notifications&email_token=BVSOW2S6CLAVEQYEBUI3D6D5JEXNPA5CNFSNUABFM5UWIORPF5TWS5BNNB2WEL2JONZXKZKDN5WW2ZLOOQXTKMRTGUZDGMZUGI32M4TFMFZW63VHMNXW23LFNZ2KKZLWMVXHJLDGN5XXIZLSL5RWY2LDNM#issuecomment-5235233427>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/BVSOW2TAY7MKJUHFQOYFFPD5JEXNPAVCNFSNUABGKJSXA33TNF2G64TZHMYTANRRGMZDOMZRGE5US43TOVSTWNJRGA2DQNBRGU4TLILWAI>
.
You are receiving this because you commented.Message ID:
***@***.***>
|
Description
Adds official subscription login providers alongside the existing API-key providers. Grok and ChatGPT support direct browser/device authorization; Claude and Gemini safely reuse access tokens owned by their official clients. Each subscription adapter uses its provider's official transport and keeps API-key configuration available as a separate option.
The implementation also fixes two Codex subscription request incompatibilities found during live verification: Codex requires SSE streaming and rejects
max_output_tokens.Type of Change
Related Issue or Discussion
Closes #819
Testing
swiftlint --strict --config .swiftlint.yml Sources Tests/FluidDictationIntegrationTests/LLMClientRequestBodyTests.swift(0 violations across 143 files)./build.sh unsignedsucceeded before review remediation, and the final full test run rebuilt the app successfullyScreenshots / Video
Notes
Elemperor1/FluidVoice:add-oauth-providersbecause the authenticated account does not have direct push access to the upstream repository.