Skip to content

feat(macos): on-demand OpenCode rewrite shortcuts (last dictation and selection) - #63

Open
qretsar wants to merge 4 commits into
anomalyco:mainfrom
qretsar:feat/rewrite-last-dictation
Open

feat(macos): on-demand OpenCode rewrite shortcuts (last dictation and selection)#63
qretsar wants to merge 4 commits into
anomalyco:mainfrom
qretsar:feat/rewrite-last-dictation

Conversation

@qretsar

@qretsar qretsar commented Sep 1, 2026

Copy link
Copy Markdown

Closes #62

Summary

Two shortcuts built entirely on the existing OpenCode rewrite machinery, addressing the lost-flow-of-thought problem after accidental or messy captures (#62):

  1. Option-Shift-O, Rewrite last dictation (src/suppression.rs, src/parakeet.rs): re-submits the last completed transcript through Profiles::rewrite_cancellable (existing processor queue: bounded admission, ordered output, Escape cancellation) and pastes the result at the cursor. Always generates with the matching mode's configured model, even when the automatic mode-processing toggle is off. Failures paste nothing. The rewritten output never becomes the new last dictation, so Option-Shift-V keeps returning the original. Duplicate presses cancel-and-replace the in-flight rewrite.
  2. Option-Shift-R, Rewrite selected text: captures the current selection through Accessibility (the same call Voice Action uses) and does the same over the selection. Requires a non-empty selection and OpenCode; failures paste nothing.
  3. Keyboard layout serialization fix (src/keyboard.rs): concurrent TISCopyCurrentKeyboardLayoutInputSource calls abort the whole process (confirmed via a macOS crash report and reproduced by the new tests under parallel execution); TIS access is now serialized behind a lock and the cache is filled on cold misses.

Both shortcuts are user-configurable in Settings with the standard capture UI, conflict validation, and load-time disable when they would shadow an existing binding. History records rewrite outputs under a new Rewrite kind; AGENTS.md gains the matching invariant bullets.

Verification

  • New regression tests: rewrite model gate, generation-while-disabled, missing-transcript rejection, cancel-and-replace duplicate rejection, selection submission, RewriteLast/Selection paste semantics (Standalone, last-dictation untouched, Rewrite history kind), suppression matching, keyboard layout concurrency, Settings conflicts and voice-action interplay
  • Hardware (MacBook Pro M1, Right Command dictation): Option-Shift-O rewrites the last capture in place flow, Option-Shift-R replaces a text selection, Escape cancels cleanly
  • cargo fmt --check
  • cargo test --locked --bin voice-control (one pre-existing unrelated failure: personal_commands::tests::clean_workspace_provisioning_preserves_user_config_on_refresh, fails on clean main in this environment)
  • cargo clippy --locked --all-targets --all-features -- -D warnings
  • git diff --check

A note from me

I use HEX every single day and I am grateful for it, it genuinely changed how I work. I do not care about contributor credit at all; the feature is what matters to me. If you would rather design or land this yourselves, or if you would prefer I stop opening PRs on your repository, that is completely fine and there are no hard feelings. Happy to close this and keep using the app either way.

@qretsar
qretsar force-pushed the feat/rewrite-last-dictation branch from 1824897 to 8d594f9 Compare September 3, 2026 07:38
Add an Option-Shift-O shortcut that re-runs the last completed dictation
through OpenCode and pastes the cleaned-up result at the cursor. Unlike
live mode processing, the rewrite always generates with the matching
mode's configured model even when automatic processing is off; failures
paste nothing, the rewritten output never becomes the new last dictation,
and the job flows through the existing processor queue so ordering,
bounded admission, cancellation, and history capture are inherited.

The shortcut is user-configurable from Settings with conflict validation,
disables itself on load when it would shadow an existing binding, and
shows the processing indicator through the standard Submitted -> Stage
pipeline. Also fixes keyboard.rs layout-query concurrency (previous
commit) that the new tests surfaced.

AGENTS.md documents the invariant.
- Serialize HIToolbox keyboard-layout queries behind a lock: concurrent
  TISCopyCurrentKeyboardLayoutInputSource calls abort the process, which
  the new tests hit deterministically under parallel execution.
- Drop the stored processor sender before joining processor workers so
  shutdown cannot block forever on a channel that never disconnects.
- Publish Paste/Send text into the shared last-transcript mirror before
  the paste runs and restore it on failure, so a rewrite submitted while
  a paste is still in flight rewrites the transcript the user just heard.
- Reject a second rewrite while one is already generating instead of
  queueing duplicate generations of the same text.
- Report cancellation before the model gate, cover edit- and
  meeting-conflict cases in tests, and reword the normalized-settings
  log message.
- Surface user cancellation of a rewrite as a clean cancel instead of a
  failed rewrite (error tone) in the processor error path.
- Fill the keyboard layout cache on cold misses so every key_code_for
  caller benefits from the serialized TIS scan.
- Give rewrites their own DictationPhase::Rewritten so the activity feed
  no longer claims the dictation was merely pasted again.
- Cover RewriteLast in the Voice Action takeover test.
Add a user-configurable Option-Shift-R shortcut that captures the
selected text in the focused app (Accessibility, same as Voice Action),
runs it through the on-demand OpenCode rewrite pipeline, and pastes the
result over the selection. Requires a non-empty selection and OpenCode;
failures paste nothing and never touch the last dictation.

Also upgrades RewriteLast to cancel-and-replace: a second press cancels
the in-flight rewrite and starts a fresh one instead of erroring.
@qretsar
qretsar force-pushed the feat/rewrite-last-dictation branch from 8d594f9 to 0f88105 Compare September 3, 2026 20:42
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.

On-demand OpenCode rewrite: shortcut to rewrite the last dictation or the selected text

1 participant