Skip to content

feat: Add voice mode patch (tengu_amber_quartz + tengu_sotto_voce)#587

Merged
georpar merged 7 commits intoPiebald-AI:mainfrom
TyceHerrman:feat/voice-mode-patch
Mar 8, 2026
Merged

feat: Add voice mode patch (tengu_amber_quartz + tengu_sotto_voce)#587
georpar merged 7 commits intoPiebald-AI:mainfrom
TyceHerrman:feat/voice-mode-patch

Conversation

@TyceHerrman
Copy link
Copy Markdown
Contributor

@TyceHerrman TyceHerrman commented Mar 5, 2026

Force-enable the /voice slash command by bypassing the tengu_amber_quartz feature gate, and optionally enable the tengu_sotto_voce concise output mode for voice interactions.

Summary by CodeRabbit

  • New Features
    • Added "Voice mode" (accessible via /voice) with two toggles: enableVoiceMode (default off) and enableVoiceSottoVoce (default on).
    • Settings UI updated to control these voice options.
  • Tests
    • Added automated tests validating voice-mode behavior and gating logic.

Force-enable the /voice slash command by bypassing the tengu_amber_quartz
feature gate, and optionally enable the tengu_sotto_voce concise output
mode for voice interactions.

Requires Claude.ai OAuth login and SoX (or native audio capture binary).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 5, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Adds a new "voice mode" feature: two misc settings, UI defaults and types, a new patch module that force-enables voice gates (amber_quartz and optional sotto voce), tests for the patcher, and integration of the patch into the patch pipeline.

Changes

Cohort / File(s) Summary
Configuration & Types
src/defaultSettings.ts, src/types.ts, src/ui/components/MiscView.tsx
Adds two boolean flags to misc: enableVoiceMode (default false) and enableVoiceSottoVoce (default true); updates types and UI controls.
Voice Mode Implementation & Tests
src/patches/voiceMode.ts, src/patches/voiceMode.test.ts
New patch module exporting writeVoiceMode(file, enableSottoVoce) with patchAmberQuartz and conditional patchSottoVoce; includes unit tests for transformations and failure cases.
Patch System Integration
src/patches/index.ts
Registers voice-mode patch: imports writeVoiceMode, adds patch definition/implementation, and gates execution by config.settings.misc?.enableVoiceMode.

Sequence Diagram

sequenceDiagram
    participant Config as Configuration (misc flags)
    participant PatchIndex as Patch System
    participant VoicePatch as Voice Mode Module
    participant File as File/Source

    Config->>PatchIndex: Read enableVoiceMode & enableVoiceSottoVoce
    alt enableVoiceMode = true
        PatchIndex->>VoicePatch: writeVoiceMode(file, enableVoiceSottoVoce)
        VoicePatch->>VoicePatch: patchAmberQuartz(file) — inject unconditional return
        alt enableVoiceSottoVoce = true
            VoicePatch->>VoicePatch: patchSottoVoce(file) — replace gate with if(!0)
        end
        VoicePatch-->>PatchIndex: Return modified file
        PatchIndex->>File: Write modified file
    else
        PatchIndex-->>File: Skip voice-mode patch
    end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Suggested reviewers

  • bl-ue

Poem

🐰
I hopped through code and left a trail,
Flipped the gates so whispers sail,
Amber true and sotto low,
Tiny hops make features grow,
Carrots celebrate the tale 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and specifically describes the main change: adding a voice mode patch that handles two feature gates (tengu_amber_quartz and tengu_sotto_voce), which aligns with the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@TyceHerrman TyceHerrman marked this pull request as ready for review March 5, 2026 20:46
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
src/patches/voiceMode.ts (3)

28-28: Circular import through re-export.

Importing showDiff from ./index creates a circular dependency (index.ts imports from voiceMode.ts, voiceMode.ts imports from index.ts). While this works because showDiff is a static function re-exported from ./patchDiffing, importing directly from the source module would be cleaner and avoid potential initialization order issues.

🔧 Suggested change
-import { showDiff } from './index';
+import { showDiff } from './patchDiffing';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/patches/voiceMode.ts` at line 28, voiceMode.ts currently imports showDiff
from ./index which creates a circular import with index.ts; change the import to
pull showDiff directly from its original module (the export source, e.g.,
./patchDiffing) so voiceMode.ts imports showDiff from the concrete module that
defines it (symbol: showDiff) instead of re-export via index to avoid
initialization-order issues.

51-75: Consider using minified boolean form for consistency.

Line 60 uses if(true) but line 41 uses return !0; (minified form). For consistency with minified code style and to avoid potential detection by any minification-aware tooling, consider using the minified form.

🔧 Suggested change for consistency
-  const replacement = 'if(true)';
+  const replacement = 'if(!0)';
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/patches/voiceMode.ts` around lines 51 - 75, The replacement string in
patchSottoVoce currently uses "if(true)" which is inconsistent with the minified
boolean style elsewhere (e.g., "return !0;"); update the replacement constant
inside the patchSottoVoce function to use the minified form "if(!0)" (and ensure
showDiff is still passed the same replacement variable) so the patched output
matches the existing minified code style.

30-49: Consider adding word boundary anchor for regex performance.

The regex starts with function which works but may be slower than anchoring with a literal character. Per coding guidelines, starting patterns with , ; } { can significantly improve matching performance. Since function declarations typically follow } or ; in minified code, consider:

🔧 Optional performance improvement
-  const pattern = /function [$\w]+\(\)\{return [$\w]+\("tengu_amber_quartz"/;
+  const pattern = /[;}]function ([$\w]+)\(\)\{return [$\w]+\("tengu_amber_quartz"/;

Note: If the function could appear at the start of a chunk, the current pattern is acceptable.

As per coding guidelines: "Use , ; } { literal characters at regex start instead of \b for performance in patch patterns"

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/patches/voiceMode.ts` around lines 30 - 49, The regex in patchAmberQuartz
uses /^function / without a leading literal anchor which can be slower in
minified patches; update the pattern variable so it expects a preceding literal
character or start-of-string (for example, prepend a non-capturing optional
group like (?:[,\;{}\n]|^) before the existing function token) so the match is
anchored to a nearby literal delimiter while still allowing the function to
appear at the start of the chunk; keep the rest of the logic (insertIndex,
insertion, showDiff, return newFile) unchanged and ensure the updated pattern is
referenced where pattern is used to compute insertIndex.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/ui/components/MiscView.tsx`:
- Around line 84-85: The defaultMisc object defines enableVoiceMode and
enableVoiceSottoVoce but the items array in MiscView (the MiscItem entries)
lacks corresponding UI toggles; add two MiscItem entries to the items array
following the same pattern used for other boolean feature flags (e.g., the
existing enableWorktreeMode/enableContextLimitOverride entries) with keys/ids
matching enableVoiceMode and enableVoiceSottoVoce, user-facing labels (e.g.,
"Enable Voice Mode" and "Enable Sotto Voce"), and boolean toggle behavior so
users can change them via the UI; if these flags are intentionally hidden mark
them with a short inline comment near defaultMisc explaining why instead of
adding UI controls.

---

Nitpick comments:
In `@src/patches/voiceMode.ts`:
- Line 28: voiceMode.ts currently imports showDiff from ./index which creates a
circular import with index.ts; change the import to pull showDiff directly from
its original module (the export source, e.g., ./patchDiffing) so voiceMode.ts
imports showDiff from the concrete module that defines it (symbol: showDiff)
instead of re-export via index to avoid initialization-order issues.
- Around line 51-75: The replacement string in patchSottoVoce currently uses
"if(true)" which is inconsistent with the minified boolean style elsewhere
(e.g., "return !0;"); update the replacement constant inside the patchSottoVoce
function to use the minified form "if(!0)" (and ensure showDiff is still passed
the same replacement variable) so the patched output matches the existing
minified code style.
- Around line 30-49: The regex in patchAmberQuartz uses /^function / without a
leading literal anchor which can be slower in minified patches; update the
pattern variable so it expects a preceding literal character or start-of-string
(for example, prepend a non-capturing optional group like (?:[,\;{}\n]|^) before
the existing function token) so the match is anchored to a nearby literal
delimiter while still allowing the function to appear at the start of the chunk;
keep the rest of the logic (insertIndex, insertion, showDiff, return newFile)
unchanged and ensure the updated pattern is referenced where pattern is used to
compute insertIndex.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2674a2e3-1a43-4e0c-9935-7dc7a14d8ad7

📥 Commits

Reviewing files that changed from the base of the PR and between 18aacb4 and 604562d.

📒 Files selected for processing (5)
  • src/defaultSettings.ts
  • src/patches/index.ts
  • src/patches/voiceMode.ts
  • src/types.ts
  • src/ui/components/MiscView.tsx

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/patches/voiceMode.test.ts`:
- Around line 29-35: The test should both assert the error path and ensure the
spy is always restored: add an expectation that the console.error spy
(consoleError) was called after invoking writeVoiceMode('const x=1;', false),
and make the mock cleanup failure-safe by restoring the spy in a finally block
(or move the spy setup/restore into an afterEach). Specifically, in the test
that calls writeVoiceMode, add expect(consoleError).toHaveBeenCalled() (or a
toHaveBeenCalledWith if you want to verify the message) and wrap the call and
assertions in try { ... } finally { consoleError.mockRestore(); } (or use
afterEach to call consoleError.mockRestore()) so mockRestore always runs.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: ee766c53-76fc-41cc-83ef-2d1ba769aaad

📥 Commits

Reviewing files that changed from the base of the PR and between 604562d and e5640ed.

📒 Files selected for processing (2)
  • src/patches/voiceMode.test.ts
  • src/patches/voiceMode.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/patches/voiceMode.ts

@TyceHerrman
Copy link
Copy Markdown
Contributor Author

All coderabbit comments addressed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
src/patches/voiceMode.test.ts (1)

6-28: Consider adding a test for enableSottoVoce=false when both gates are present.

The current tests verify:

  • Both gates + enableSottoVoce=true → both patched
  • Only amber_quartz + enableSottoVoce=false → amber_quartz patched

Missing scenario: both gates present but enableSottoVoce=false — this would confirm the flag correctly leaves sotto_voce unchanged while still patching amber_quartz.

Optional test case
it('patches only amber quartz when sotto voce is disabled', () => {
  const file =
    'const x=1;' +
    'function qX_(){return A9("tengu_amber_quartz",!1)}' +
    'if(A9("tengu_sotto_voce",!1))return`# Output efficiency...`';

  const result = writeVoiceMode(file, false);

  expect(result).not.toBeNull();
  expect(result).toContain('function qX_(){return !0;return A9(');
  expect(result).toContain('if(A9("tengu_sotto_voce",!1))'); // unchanged
});
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/patches/voiceMode.test.ts` around lines 6 - 28, Add a unit test that
covers the missing scenario where both gates appear in the source but
enableSottoVoce is false: call writeVoiceMode(file, false) on the same input
used in the first test (both tengu_amber_quartz and tengu_sotto_voce present)
and assert that amber_quartz is patched (e.g., contains the '!0' replacement in
the function body) while sotto_voce remains unchanged (e.g., still contains the
original A9("tengu_sotto_voce",!1) check); place this new test alongside the
existing tests in src/patches/voiceMode.test.ts and use the same file string and
assertion style as the other cases to keep consistency.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@src/patches/voiceMode.test.ts`:
- Around line 6-28: Add a unit test that covers the missing scenario where both
gates appear in the source but enableSottoVoce is false: call
writeVoiceMode(file, false) on the same input used in the first test (both
tengu_amber_quartz and tengu_sotto_voce present) and assert that amber_quartz is
patched (e.g., contains the '!0' replacement in the function body) while
sotto_voce remains unchanged (e.g., still contains the original
A9("tengu_sotto_voce",!1) check); place this new test alongside the existing
tests in src/patches/voiceMode.test.ts and use the same file string and
assertion style as the other cases to keep consistency.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3dce3102-c1d7-48e1-a33f-55db9dfe9769

📥 Commits

Reviewing files that changed from the base of the PR and between 5e358c0 and 8e197a9.

📒 Files selected for processing (1)
  • src/patches/voiceMode.test.ts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@georpar
Copy link
Copy Markdown
Member

georpar commented Mar 7, 2026

@TyceHerrman will you please rename enableVoiceSottoVoce to something like enableVoiceConciseOutput? It's more consistent with the other feature flag patches.

@TyceHerrman
Copy link
Copy Markdown
Contributor Author

@georpar, done!

@georpar georpar merged commit 036f07b into Piebald-AI:main Mar 8, 2026
2 checks passed
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