Skip to content

Add OAuth login providers - #820

Draft
Elemperor1 wants to merge 9 commits into
altic-dev:mainfrom
Elemperor1:add-oauth-providers
Draft

Add OAuth login providers#820
Elemperor1 wants to merge 9 commits into
altic-dev:mainfrom
Elemperor1:add-oauth-providers

Conversation

@Elemperor1

@Elemperor1 Elemperor1 commented Aug 9, 2026

Copy link
Copy Markdown

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

  • 🐞 Bug fix
  • ✨ New feature
  • 💥 Breaking change
  • 🧹 Chore
  • 📝 Documentation update

Related Issue or Discussion

Closes #819

Testing

  • Tested on Intel Mac
  • Tested on Apple Silicon Mac (M3 Pro)
  • Tested on macOS version: 26.5.2
  • Ran linter locally: swiftlint --strict --config .swiftlint.yml Sources Tests/FluidDictationIntegrationTests/LLMClientRequestBodyTests.swift (0 violations across 143 files)
  • Ran formatter locally on all files changed by the latest remediation (0 files required changes); repository-wide formatter lint still reports pre-existing drift in 58 untouched source files
  • Ran tests locally: 223 tests passed with 0 failures and 0 skips using the unsigned CI-equivalent command; the focused request-body suite passed 46 tests; ./build.sh unsigned succeeded before review remediation, and the final full test run rebuilt the app successfully

Screenshots / Video

OAuth and API-key providers shown together

  • No UI/visual changes; screenshots/video are not applicable.

Notes

  • Existing OpenAI, Anthropic, Google, and xAI API-key providers remain available.
  • FluidVoice-owned Grok and ChatGPT OAuth sessions are stored in dedicated Keychain items.
  • Claude and Gemini imports remain read-only. FluidVoice does not copy or refresh their refresh tokens.
  • Review remediation preserves Grok identity across opaque refreshes, verifies the provider that completed browser sign-in with a bundled default model, scopes opaque Responses and Gemini tool continuation state to its originating provider/account, replays complete required terminal arguments, coalesces concurrent Codex and Grok token refreshes, cancels and awaits refreshes before removing or replacing a FluidVoice-owned login, disables parallel tool calls for the single-call Command Mode consumer, caches Gemini Code Assist project discovery per credential, preserves task cancellation through OAuth polling, and rejects failed, incomplete, empty, Anthropic-error, or Gemini-error official-login responses in streaming and non-streaming paths.
  • The PR is opened from Elemperor1/FluidVoice:add-oauth-providers because the authenticated account does not have direct push access to the upstream repository.

@github-actions github-actions Bot added needs PR template Pull request is missing required template content. needs screenshots Pull request needs screenshot or video evidence. labels Aug 9, 2026
@github-actions

github-actions Bot commented Aug 9, 2026

Copy link
Copy Markdown

The PR Policy check is blocking this PR because required template information is missing.

Please update the PR description with:

  • Description
  • Type of Change
  • Related Issue or Discussion
  • Testing
  • Screenshots / Video

Visual files detected:

  • .github/screenshots/oauth-login-providers.jpeg
  • Sources/Fluid/ContentView.swift
  • Sources/Fluid/Persistence/SettingsStore+CommandMode.swift
  • Sources/Fluid/Persistence/SettingsStore.swift
  • Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift
  • Sources/Fluid/UI/AISettingsView+AIConfiguration.swift

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.

@Elemperor1
Elemperor1 force-pushed the add-oauth-providers branch from 7053160 to e59e0c3 Compare August 9, 2026 21:38
@github-actions github-actions Bot removed needs PR template Pull request is missing required template content. needs screenshots Pull request needs screenshot or video evidence. labels Aug 9, 2026
@Elemperor1
Elemperor1 marked this pull request as ready for review August 9, 2026 21:39
Copilot AI lite review requested due to automatic review settings August 9, 2026 21:39
@greptile-apps

greptile-apps Bot commented Aug 9, 2026

Copy link
Copy Markdown

Greptile Summary

Adds subscription-based OAuth providers alongside existing API-key providers and updates shared LLM routing, persistence, verification, and settings UI to support them.

  • Adds browser/device authorization for ChatGPT and Grok, plus read-only official-client credential imports for Claude and Gemini.
  • Routes official-provider credentials and protocol-specific requests through the shared LLM client.
  • Preserves provider/account-scoped continuation state and adds focused authentication, request-body, cancellation, and refresh tests.

Confidence Score: 5/5

The PR appears safe to merge because the previously reported Grok refresh identity failure is fixed and no blocking failure remains.

The refresh path now passes the stored Grok user ID and email into token decoding, opaque refresh responses retain those values, and the retained user ID is used for both required proxy routing headers; no blocking failure remains.

Reviews (9): Last reviewed commit: "Validate Responses continuations" | Re-trigger Greptile

Comment thread Sources/Fluid/Services/GrokSubscriptionAuth.swift Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

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 LLMClient to 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

  • setupLabel uses lowercase "guide", but existing UI icon logic checks label.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

  • setupLabel uses lowercase "guide", but existing UI icon logic checks label.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

  • setupLabel uses lowercase "guide", but existing UI icon logic checks label.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.

Comment thread Sources/Fluid/Services/OfficialProviderAuth.swift Outdated

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

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

case "response.output_item.added", "response.output_item.done":
guard let item = event["item"] as? [String: Any],
item["type"] as? String == "function_call"
else { continue }

P1 Badge Preserve encrypted reasoning across Codex tool turns

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

Comment thread Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift Outdated
Comment thread Sources/Fluid/Services/GrokSubscriptionAuth.swift
Comment thread Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift Outdated

Copy link
Copy Markdown
Author

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 reasoning.encrypted_content, Command Mode keeps it in memory for the active turn, and the next store: false request replays the reasoning item before the function call and function result. The continuation data is intentionally not persisted to chat history.

Validation on the final commit:

  • swiftformat --config .swiftformat Sources
  • swiftlint --strict --config .swiftlint.yml Sources — 0 violations across 142 source files
  • unsigned CI-equivalent Xcode suite — 206 passed, 0 failed, 0 skipped
  • focused regressions cover opaque Grok refresh identity, encrypted Codex reasoning replay/order, and official-provider guide labels

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift Outdated

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/CommandModeService.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/CodexSubscriptionAuth.swift Outdated

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/OfficialProviderAuth.swift Outdated
Comment thread Sources/Fluid/Services/GrokSubscriptionAuth.swift Outdated
Comment thread Sources/Fluid/Services/CodexSubscriptionAuth.swift
@Elemperor1

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/CodexSubscriptionAuth.swift
Comment thread Sources/Fluid/Services/LLMClient.swift Outdated
Comment thread Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift Outdated
@Elemperor1

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/CodexSubscriptionAuth.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
@Elemperor1

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
@Elemperor1

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/CommandModeService.swift
@Elemperor1

Copy link
Copy Markdown
Author

@codex review

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

Copy link
Copy Markdown

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: 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".

Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/Services/LLMClient.swift
Comment thread Sources/Fluid/UI/AISettings/AIEnhancementSettingsViewModel.swift
Comment thread Sources/Fluid/ContentView.swift
Comment thread Sources/Fluid/Services/OfficialProviderAuth.swift
@altic-dev

Copy link
Copy Markdown
Owner

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.

@Elemperor1

Copy link
Copy Markdown
Author

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.

@altic-dev
altic-dev marked this pull request as draft August 10, 2026 00:30
@altic-dev

Copy link
Copy Markdown
Owner

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!

@Elemperor1

Copy link
Copy Markdown
Author

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?

@altic-dev

Copy link
Copy Markdown
Owner

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.

@Elemperor1

Copy link
Copy Markdown
Author

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.

@altic-dev

altic-dev commented Aug 10, 2026 via email

Copy link
Copy Markdown
Owner

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.

[FEATURE] grok oauth for ai providers

3 participants