Skip to content

Conversation

@ComputelessComputer
Copy link
Collaborator

Overview

  • Added a hook to validate local speech-to-text (STT) models
  • Improved model selection and validation process

Changes

  • Implemented validation mechanism for local STT models
  • Enhanced model selection logic

@netlify
Copy link

netlify bot commented Dec 22, 2025

Deploy Preview for hyprnote ready!

Name Link
🔨 Latest commit 49de27c
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote/deploys/69492d6a29e44c0008693a39
😎 Deploy Preview https://deploy-preview-2469--hyprnote.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 22, 2025

Warning

Rate limit exceeded

@ComputelessComputer has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 8 minutes and 21 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between cc890c9 and 49de27c.

📒 Files selected for processing (3)
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
📝 Walkthrough

Walkthrough

This PR adds model validation for locally-downloaded STT models, automatically clearing selections when models become unavailable. It also refines the model display logic to filter by download status and adds user hints for hyprnote models, alongside text description updates for Parakeet v2 and v3 models.

Changes

Cohort / File(s) Summary
STT Configuration & Selection UI
apps/desktop/src/components/settings/ai/stt/configure.tsx, apps/desktop/src/components/settings/ai/stt/select.tsx
Updated Parakeet v2/v3 descriptions for Apple Silicon. Integrated model validation hook to auto-clear invalid selections. Enhanced model filtering to show only downloaded models for non-hyprnote providers and cloud for hyprnote. Added UI hints (Download/Trial) for non-downloaded hyprnote models. Adjusted provider-model mapping logic based on platform availability.
Model Validation Hook
apps/desktop/src/hooks/useValidateSttModel.ts
New hook that validates local STT models via TanStack Query polling (2s interval). Performs download status checks and triggers onClearModel callback for invalid selections. Returns isModelValid flag for UI state.

Sequence Diagram

sequenceDiagram
    participant UI as Select Component
    participant Hook as useValidateSttModel Hook
    participant Query as TanStack Query
    participant Storage as Form/Storage
    
    Note over UI,Storage: Component Initializes
    UI->>Hook: Call with provider, model, onClearModel
    
    rect rgb(200, 220, 255)
        Note over Hook,Query: Validation Cycle (every 2s)
        Hook->>Query: Check isModelDownloaded<br/>[stt-model-downloaded, model]
        Query-->>Hook: Downloaded status
    end
    
    alt Model is local & not downloaded
        Hook->>Storage: onClearModel() callback
        Storage->>Storage: Reset form field & storage
        Hook-->>UI: isModelValid = false
    else Model valid (cloud or downloaded)
        Hook-->>UI: isModelValid = true
    end
    
    UI->>UI: Update model Select<br/>enable/disable & show hints
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

  • useValidateSttModel hook: Verify TanStack Query configuration, error handling, and the side-effect logic for clearing invalid selections
  • Model filtering logic in select.tsx: Ensure correct conditional filtering based on provider type and downloaded status for each model
  • Integration of validation with UI: Confirm validation state properly controls model Select availability and hint display
  • Hyprnote-specific logic: Review the conditional model inclusion for Apple Silicon paths and download/trial hint presentation

Possibly related PRs

Suggested reviewers

  • yujonglee

Pre-merge checks and finishing touches

❌ 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%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title 'Validate local stt models' directly summarizes the main change: implementing validation for local speech-to-text models, which is the primary focus across all modified files.
Description check ✅ Passed The description accurately describes the main changes: adding a validation hook for STT models and improving model selection logic, which aligns with the changeset modifications.

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.

@netlify
Copy link

netlify bot commented Dec 22, 2025

Deploy Preview for hyprnote-storybook ready!

Name Link
🔨 Latest commit 49de27c
🔍 Latest deploy log https://app.netlify.com/projects/hyprnote-storybook/deploys/69492d6bd3a97900083a2612
😎 Deploy Preview https://deploy-preview-2469--hyprnote-storybook.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
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)
apps/desktop/src/hooks/useValidateSttModel.ts (1)

49-50: Consider more conservative polling interval.

The refetchInterval: 2000 will continuously poll every 2 seconds while the query is enabled. For a file system check (model download status), this may be more aggressive than necessary.

Consider increasing to 5000ms (5 seconds) or higher, unless there's a specific user experience requirement for near-real-time updates.

🔎 Suggested adjustment
-    refetchInterval: 2000,
-    staleTime: 500,
+    refetchInterval: 5000,
+    staleTime: 2000,
apps/desktop/src/components/settings/ai/stt/select.tsx (2)

55-65: Memoize getValidatedModel to prevent unnecessary recalculations.

The getValidatedModel function is called during form initialization (line 70) but isn't memoized. Since it accesses configuredProviders which is derived from a query, this function will execute on every render of SelectProviderAndModel.

🔎 Wrap in useCallback
+  const getValidatedModel = useCallback(() => {
-  const getValidatedModel = () => {
     if (!current_stt_provider || !current_stt_model) return "";
 
     const providerModels =
       configuredProviders[current_stt_provider as ProviderId]?.models ?? [];
     const isModelValid = providerModels.some(
       (model) => model.id === current_stt_model && model.isDownloaded,
     );
 
     return isModelValid ? current_stt_model : "";
-  };
+  }, [current_stt_provider, current_stt_model, configuredProviders]);

331-336: Consolidate duplicate isAppleSilicon check.

The am-whisper-large-v3 model is added in a separate isAppleSilicon block (lines 331-336) immediately after the first isAppleSilicon block (lines 318-329). These can be combined for better code organization.

🔎 Merge into single isAppleSilicon block
         if (isAppleSilicon) {
           models.push(
             {
               id: "am-parakeet-v2",
               isDownloaded: p2.data ?? false,
             },
             {
               id: "am-parakeet-v3",
               isDownloaded: p3.data ?? false,
             },
+            {
+              id: "am-whisper-large-v3",
+              isDownloaded: whisperLargeV3.data ?? false,
+            },
           );
         }
 
-        if (isAppleSilicon) {
-          models.push({
-            id: "am-whisper-large-v3",
-            isDownloaded: whisperLargeV3.data ?? false,
-          });
-        }
-
         models.push(
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6cf957d and cc890c9.

📒 Files selected for processing (3)
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
🧰 Additional context used
📓 Path-based instructions (5)
**/*

📄 CodeRabbit inference engine (AGENTS.md)

Format using dprint fmt from the root. Do not use cargo fmt.

Files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
**/*.{ts,tsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx}: Avoid creating a bunch of types/interfaces if they are not shared. Especially for function props. Just inline them.
Never do manual state management for form/mutation. Use useForm from tanstack-form and useQuery/useMutation from tanstack-query for 99% cases.

Files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
**/*.{ts,tsx,rs,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

By default, avoid writing comments at all. If you write one, it should be about 'Why', not 'What'.

Files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
**/*.{ts,tsx,js,jsx}

📄 CodeRabbit inference engine (AGENTS.md)

**/*.{ts,tsx,js,jsx}: If there are many classNames with conditional logic, use cn (import from @hypr/utils). Always pass an array and split by logical grouping.
Use motion/react instead of framer-motion.

Files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
  • apps/desktop/src/hooks/useValidateSttModel.ts
  • apps/desktop/src/components/settings/ai/stt/configure.tsx
**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

**/*.ts: Agent implementations should use TypeScript and follow the established architectural patterns defined in the agent framework
Agent communication should use defined message protocols and interfaces

Files:

  • apps/desktop/src/hooks/useValidateSttModel.ts
🧠 Learnings (2)
📚 Learning: 2025-12-16T07:24:36.000Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-16T07:24:36.000Z
Learning: Applies to **/*.{ts,tsx} : Never do manual state management for form/mutation. Use `useForm` from tanstack-form and `useQuery`/`useMutation` from tanstack-query for 99% cases.

Applied to files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
📚 Learning: 2025-11-24T16:32:19.706Z
Learnt from: CR
Repo: fastrepl/hyprnote PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-11-24T16:32:19.706Z
Learning: Applies to **/*.{ts,tsx} : Never do manual state management for form/mutation. Use useForm (from tanstack-form) and useQuery/useMutation (from tanstack-query) for 99% of cases instead of setError and similar patterns.

Applied to files:

  • apps/desktop/src/components/settings/ai/stt/select.tsx
🧬 Code graph analysis (2)
apps/desktop/src/components/settings/ai/stt/select.tsx (2)
apps/desktop/src/components/settings/ai/stt/shared.tsx (2)
  • ProviderId (197-197)
  • displayModelId (31-84)
apps/desktop/src/hooks/useValidateSttModel.ts (1)
  • useValidateSttModel (22-61)
apps/desktop/src/hooks/useValidateSttModel.ts (1)
crates/transcribe-proxy/src/routes/mod.rs (1)
  • provider (38-40)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (9)
  • GitHub Check: Redirect rules - hyprnote-storybook
  • GitHub Check: Header rules - hyprnote-storybook
  • GitHub Check: Pages changed - hyprnote-storybook
  • GitHub Check: fmt
  • GitHub Check: desktop_ci (linux, depot-ubuntu-24.04-8)
  • GitHub Check: desktop_ci (linux, depot-ubuntu-22.04-8)
  • GitHub Check: Redirect rules - hyprnote
  • GitHub Check: Header rules - hyprnote
  • GitHub Check: Pages changed - hyprnote
🔇 Additional comments (7)
apps/desktop/src/components/settings/ai/stt/configure.tsx (1)

121-121: LGTM! Improved model descriptions.

The updated descriptions provide clearer guidance to users about when to use each model. "Optimized for English" and "Better for European languages" are more actionable than the previous wording.

Also applies to: 126-126

apps/desktop/src/hooks/useValidateSttModel.ts (1)

53-58: Ensure onClearModel callback is stable.

The useEffect depends on onClearModel. If the caller doesn't memoize this callback (e.g., with useCallback), the effect will run on every render, potentially causing unnecessary model clearing or performance issues.

Verified in select.tsx that handleClearModel is properly wrapped with useCallback (lines 90-93), so this is correctly handled. Good implementation!

apps/desktop/src/components/settings/ai/stt/select.tsx (5)

90-93: LGTM! Properly memoized callback.

The handleClearModel callback is correctly wrapped with useCallback and includes all necessary dependencies, ensuring stable reference for useValidateSttModel.


95-99: LGTM! Validation hook integration.

The useValidateSttModel hook is correctly integrated, passing the current provider, model, and the stable handleClearModel callback. This will automatically clear invalid model selections when models become unavailable.


199-207: LGTM! Improved model filtering logic.

The new filtering logic correctly shows all models for hyprnote (allowing users to see what's available to download) while only showing downloaded models for other providers. The cloud model is always shown regardless of download status, which is appropriate.


227-237: LGTM! Enhanced user feedback for unavailable models.

The UI now provides helpful hints ("Start trial" for cloud, "Download model" for local models) when hovering over unavailable hyprnote models. The group class and opacity transition create a polished user experience.


338-347: Verify intended model availability for non-Apple Silicon platforms.

The code now unconditionally adds QuantizedTinyEn and QuantizedSmallEn models to the list (lines 338-347), regardless of platform. Previously, based on configure.tsx (lines 154-167), these models were shown for non-Apple Silicon platforms.

This appears intentional but represents a behavior change: these models are now available on all platforms for the hyprnote provider in the model selector.

Please confirm this is the intended behavior - that QuantizedTinyEn and QuantizedSmallEn should be available for selection on all platforms (both Apple Silicon and non-Apple Silicon).

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