Skip to content

Improve overlay feedback, Edit Mode capture, and Codex command routing#408

Open
tarushvkodes wants to merge 7 commits into
altic-dev:mainfrom
tarushvkodes:codex/lower-visualizer-threshold
Open

Improve overlay feedback, Edit Mode capture, and Codex command routing#408
tarushvkodes wants to merge 7 commits into
altic-dev:mainfrom
tarushvkodes:codex/lower-visualizer-threshold

Conversation

@tarushvkodes

@tarushvkodes tarushvkodes commented Jun 23, 2026

Copy link
Copy Markdown

Summary

This PR includes a focused set of user-facing improvements to FluidVoice's overlay, Edit Mode, and Command Mode.

Overlay feedback

  • Lowers the default visualizer noise threshold from 0.4 to 0.12.
  • This makes the waveform respond to quieter but valid microphone input, so the overlay no longer looks inactive while FluidVoice is listening.
  • Adds an integration test covering the more sensitive default.

Edit Mode reliability

  • Improves selected-text capture when apps do not expose highlighted text through Accessibility APIs.
  • Adds a clipboard-preserving Cmd+C fallback after AXSelectedText / selected-range capture fails.
  • Extends the fallback wait window for Google Docs and similar browser-based rich editors, which can update the pasteboard more slowly.
  • Tracks the original target app PID when Edit Mode captures selection context.
  • Routes accepted rewrites through a reliable paste path so rich web editors, especially Google Docs, replace the selected text more consistently than with synthetic direct typing.

Command Mode to Codex

  • Adds an optional CommandModeRouteToCodex setting, defaulting off, so existing Command Mode behavior remains unchanged unless enabled.
  • Adds two Codex handoff styles:
    • Notch: keeps FluidVoice's Command Mode notch UX, runs the bundled Codex CLI in the background, and displays the result in the notch without focusing the Codex app.
    • App: activates the Codex desktop app and pastes/submits the spoken command there.
  • Exposes compact Codex controls in the Command Mode UI.
  • Bypasses chat-provider readiness checks when Codex routing is enabled.
  • Stabilizes expanded command-notch presentation so the notch opens smoothly and stays visible for Codex output.

Why

A few real-world workflows were failing or feeling confusing:

  • Quiet microphone input could be heard by the app, but the waveform barely moved, making the overlay look broken.
  • In Google Docs and other rich/browser editors, Edit Mode could fail to see selected text or fail to replace the selected text cleanly.
  • Command Mode is useful as a voice handoff into Codex, but focusing the Codex app can be intrusive. The notch handoff keeps the interaction in FluidVoice's overlay instead.

The changes are preference-backed and conservative: normal dictation and default Command Mode behavior are preserved unless the user enables the Codex route.

Validation

Validated locally on macOS with Xcode:

  • swiftc -parse $(rg --files Sources/Fluid -g '*.swift')
  • git diff --check
  • plutil -lint Fluid.xcodeproj/project.pbxproj Info.plist Fluid.entitlements
  • xcodebuild clean build -project Fluid.xcodeproj -scheme Fluid -destination 'platform=macOS,arch=arm64' CODE_SIGN_IDENTITY='' CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
  • Manual install/sign/run of /Applications/FluidVoice.app
  • Manual Codex CLI smoke test with the bundled Codex binary

Notes

  • This branch has been rebased onto upstream main at v1.6.1 (49e91c0).
  • The earlier Package.resolved-only MCP SDK bump was dropped during rebase because upstream removed that dependency.
  • GitHub Actions may require upstream approval to run on the fork PR.

@tarushvkodes tarushvkodes changed the title [codex] Lower default visualizer threshold [codex] Improve overlay capture and Codex command routing Jun 24, 2026
@tarushvkodes

Copy link
Copy Markdown
Author

Update: improved Edit Mode replacement for Google Docs and similar browser editors.\n\n- Captures the original target PID when selected text is captured, so accepting a rewrite can return to the document instead of aiming at the FluidVoice overlay.\n- Routes Edit Mode acceptance through the reliable paste path, which web rich-text editors handle better than synthetic direct typing.\n- Gives clipboard-based selection capture a longer window for Google Docs/browser editors that update the pasteboard more slowly after Cmd+C.\n\nValidated locally:\n- swiftc parse over Sources/Fluid Swift files\n- git diff --check\n- plutil lint for project/Info/entitlements\n- xcodebuild clean build for macOS arm64\n- installed and ad-hoc signed local /Applications/FluidVoice.app

@tarushvkodes tarushvkodes force-pushed the codex/lower-visualizer-threshold branch from 003a852 to 314f9c7 Compare June 28, 2026 15:25
@tarushvkodes

Copy link
Copy Markdown
Author

Update: rebased this branch onto upstream main at v1.6.1 (49e91c0) and reinstalled a fresh local build.\n\nNotes:\n- Dropped the old Package.resolved-only MCP SDK bump during rebase because upstream removed that dependency.\n- Preserved the visualizer threshold, Codex command mode, notch output, and Google Docs/Edit Mode replacement changes.\n- PR head is now 314f9c7 and reports mergeable.\n\nValidated locally:\n- swiftc parse over Sources/Fluid Swift files\n- git diff --check\n- plutil lint for project/Info/entitlements\n- xcodebuild clean build for macOS arm64\n- installed and ad-hoc signed /Applications/FluidVoice.app

@tarushvkodes tarushvkodes changed the title [codex] Improve overlay capture and Codex command routing Improve overlay feedback, Edit Mode capture, and Codex command routing Jun 28, 2026
@tarushvkodes tarushvkodes marked this pull request as ready for review June 28, 2026 15:26
Copilot AI review requested due to automatic review settings June 28, 2026 15:26

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

This PR improves FluidVoice’s user-facing feedback and reliability across three flows: overlay waveform responsiveness, Edit Mode selection capture + rewrite insertion, and optional Command Mode routing to Codex (notch or app handoff).

Changes:

  • Makes the overlay visualizer respond to quieter mic input by lowering the default noise threshold and adds an integration test for the new default.
  • Improves Edit Mode reliability by adding clipboard-based selected-text capture fallback and forcing a “reliable paste” insertion path for accepted rewrites, with PID tracking.
  • Adds an opt-in Command Mode “Route to Codex” setting with notch/app handoff styles, updates UI controls, and stabilizes expanded notch output behavior.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Tests/FluidDictationIntegrationTests/DictationE2ETests.swift Adds an integration test asserting the new, more sensitive default visualizer noise threshold.
Sources/Fluid/Views/CommandModeView.swift Adds Codex routing UI controls and adjusts readiness/notch-output behavior based on routing settings.
Sources/Fluid/UI/SettingsView.swift Updates the visualizer threshold reset behavior to use the new default constant.
Sources/Fluid/Services/TypingService.swift Introduces a “force reliable paste” path (typeTextReliably) and plumbs it through the insertion pipeline.
Sources/Fluid/Services/TextSelectionService.swift Adds clipboard-preserving Cmd+C fallback for selected-text capture when AX APIs fail.
Sources/Fluid/Services/RewriteModeService.swift Tracks target PID for Edit Mode context and routes accepted rewrites via the reliable paste path.
Sources/Fluid/Services/NotchOverlayManager.swift Stabilizes expanded command-notch presentation state transitions and cleanup behavior.
Sources/Fluid/Services/CommandModeService.swift Adds Codex routing branch and notch sync behavior for Codex “notch” handoff.
Sources/Fluid/Services/CodexHandoffService.swift New service that runs Codex CLI for notch output or activates/pastes into the Codex app.
Sources/Fluid/Persistence/SettingsStore+CommandMode.swift Bypasses command readiness issues when Codex routing is enabled.
Sources/Fluid/Persistence/SettingsStore.swift Adds default visualizer threshold constant and persists Codex routing + handoff-style settings.
Sources/Fluid/ContentView.swift Routes rewrite acceptance through RewriteModeService.acceptRewrite(...) with PID targeting.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

}

private func pasteAndSubmit(_ text: String) async -> Bool {
Self.pasteboardSessionSemaphore.wait()
Comment on lines +175 to +197
pasteboard.clearContents()
guard pasteboard.setString(text, forType: .string) else {
self.restorePasteboardSnapshot(snapshot, to: pasteboard)
Self.pasteboardSessionSemaphore.signal()
return false
}

guard self.sendCommandKey("v") else {
self.restorePasteboardSnapshot(snapshot, to: pasteboard)
Self.pasteboardSessionSemaphore.signal()
return false
}

try? await Task.sleep(nanoseconds: 100_000_000)
guard self.sendReturnKey() else {
self.restorePasteboardSnapshot(snapshot, to: pasteboard)
Self.pasteboardSessionSemaphore.signal()
return false
}

try? await Task.sleep(nanoseconds: 1_000_000_000)
self.restorePasteboardSnapshot(snapshot, to: pasteboard)
Self.pasteboardSessionSemaphore.signal()
Comment on lines +170 to +188
let deadline = Date().addingTimeInterval(1.0)
var copiedText: String?
repeat {
if pasteboard.changeCount != clearedChangeCount,
let text = pasteboard.string(forType: .string),
!text.isEmpty
{
copiedText = text
break
}
usleep(15_000)
} while Date() < deadline

self.restorePasteboardSnapshot(snapshot, to: pasteboard)

guard let copiedText else {
self.diag("Clipboard fallback failed: clipboard did not receive selected text")
return nil
}
func captureSelectedText() -> Bool {
let targetPID = TypingService.captureSystemFocusedPID()
?? NSWorkspace.shared.frontmostApplication?.processIdentifier
if let text = textSelectionService.getSelectedText(), !text.isEmpty {
.outputDelivered,
properties: [
"mode": AnalyticsMode.rewrite.rawValue,
"method": AnalyticsOutputMethod.typed.rawValue,
self.asr.typeTextToActiveField(
self.rewriteModeService.rewrittenText,
preferredTargetPID: typingTarget.pid
self.rewriteModeService.acceptRewrite(

@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: 314f9c7e81

ℹ️ 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 +371 to +373
if self.shouldSyncCommandNotchState {
NotchContentState.shared.addCommandMessage(role: result.success ? .assistant : .status, content: result.message)
NotchContentState.shared.setCommandProcessing(false)

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 Capture notch sync state for Codex cleanup

When a Codex notch handoff starts, the earlier block can set isCommandProcessing to true, but this completion block recomputes shouldSyncCommandNotchState after the async Codex run. If the user toggles Codex routing off or changes the handoff style while Codex is still running, cleanup is skipped and the expanded notch can remain stuck in a processing/disabled state even though isProcessing is false; capture the initial sync decision or always clear command processing on completion.

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.

2 participants