mirror of
https://github.com/OpenWhispr/openwhispr.git
synced 2026-10-02 05:04:47 +08:00
* feat(onboarding): use-case intent capture, meeting step, and finish step Reworks the onboarding wizard around an id-keyed dynamic step machine: - New "Why are you here?" step: multi-select use-case cards (OptionCard) plus an optional note, persisted to settings and synced fire-and-forget to /api/onboarding-intent for signed-in users - Permission copy rewritten to explain outcomes; system audio badge flips to Recommended when the user came for meeting notes - New conditional meeting step introducing auto-detection and the existing meeting hotkey (shown when system audio is granted or meetings selected) - New finish step: OpenWhispr Cloud summary with Open Settings deep-link (Settings > Transcription) or Skip; local/BYOK variant for skip-auth users; registry-gated Corti partner screen for medical intent - All new strings translated across the 10 locale files * refactor(lint): fix react-refresh and hook-deps warnings, run formatter - Move pending-invitation token helpers out of AcceptInvitationModal into src/utils/pendingInvitationToken.ts so the component file only exports components (react-refresh/only-export-components) - Memoize the invitations fallback in ShareNoteDialog so its callback dependencies are stable (react-hooks/exhaustive-deps) - Prettier reflow in clipboard.js * fix(onboarding): add back-to-sign-in escape from email verification Without it, users who never receive the verification email are stuck on the polling screen with no way back to choose another email or sign-in method. * style(onboarding): match back-to-sign-in button to auth screen idiom Align the verification back button with AuthenticationStep's continue- without-account styling; prettier array reflow in zh locale files. * refactor(auth): use Button ghost variant for subtle text actions Replace bespoke raw buttons (back-to-sign-in, continue-without-account) with the design-system Button, gaining focus-visible rings and proper disabled styling. * feat(onboarding): broaden medical use case to healthcare, clarify multi-select - Rename use-case id medical -> healthcare; card now reads "Medical, clinical & therapy transcription / Dictate patient notes, session notes and reports" so therapy and psychology users self-identify - Add "Select all that apply" hint and switch OptionCard's selection indicator from radio circle to checkbox square so multi-select is obvious - Update Corti finish title to match; all 10 locales updated * fix(onboarding): allow proceeding with Corti credentials in setup step The Corti provider tab (#929) now appears in the onboarding transcription picker, but canProceed only recognized openai/groq/mistral/custom — a user selecting Corti was blocked on Next unless an OpenAI key happened to be set. Gate on client id + secret, matching shouldUseStreaming's readiness rule. * feat(onboarding): preselect Corti provider when opening settings from finish step The Corti finish screen's Set up in Settings CTA now sets cloudTranscriptionProvider to corti so the settings picker opens on the Corti tab with its credential fields. Safe for signed-in users — the provider only takes effect in BYOK mode. * feat(onboarding): inline Corti setup on the finish step Replace the settings detour with credentials entered in place: honest copy (clinical-grade, HIPAA compliant), a visible $50 free credit badge next to the create-account link, Client ID/Secret fields reusing ApiKeyInput, and a US/EU data-region select (defaults prefilled from the store). Use Corti activates the provider in BYOK mode and completes onboarding; Not now falls through to the default finish. * refactor(onboarding): remove quit button from title bar The power/quit button only ever rendered in onboarding (TitleBar's sole consumer) and duplicates OS-level quit (Cmd+Q, dock, window controls). Remove it end to end: TitleBar quit UI + confirm dialog, app-quit IPC handler, appQuit preload bridge and type, and the titleBar i18n block in all 10 locales. * feat(onboarding): link Corti homepage with UTM and add setup steps Point the create-account link at corti.ai with the partnership UTM params instead of the console, and add a three-step guide (sign up, create API credentials in the console, paste below) since the homepage no longer lands users on signup. * feat(onboarding): refine use-case step copy and move progress into macOS title bar - Subtext constrained to readable width and rewritten to say plainly that the user's picks set up the app and steer what we build next - Select-all hint restyled to the existing uppercase section-label idiom - Note placeholder reduced to "Optional" — no canned examples - TitleBar gains a centered no-drag slot; on macOS the step progress renders there (reclaiming the progress strip's height), Windows/Linux keep the strip alongside their window controls * feat(onboarding): add upload-audio use case and skip button for optional steps - New "Uploading audio files" use-case option (id: upload) with FileAudio icon - Skip button beside Next on optional steps (use case, voice agent, meeting) - Add common.skip and the upload option copy across all 10 locales * feat(transcription): add Corti provider icon Register the Corti logo in PROVIDER_ICONS so the Corti tab and provider chips show a real icon; monochrome (currentColor) like xai. * refactor(meetings): consolidate meeting detection into the notification toggle The meeting-detection notification was the only consumer of detection, so a detector running with notifications off did nothing but burn CPU. Drive the audio detector from the notification toggle (notificationsEnabled && notifyMeetingDetection) and remove the redundant standalone Audio Detection setting, its UI section, and the now-dead calendar.detection translations. * fix(settings): don't grab the mic when opening settings MicrophoneSettings called getUserMedia on mount to read device labels, which activates a mic input session and interrupts other audio (pauses music on macOS) every time Settings opens. Enumerate devices first and only fall back to getUserMedia when labels are missing (permission not yet granted). * feat: add UTM tracking to Corti 'get a key' link Point the Corti transcription provider's 'Get a key' link at the corti.ai home page with referral UTM params, matching the canonical CORTI_SIGNUP_URL used in onboarding instead of console.corti.app. * chore: apply prettier formatting to pre-existing files Format 21 docs, build scripts, and test files that were not prettier-compliant on main. Pure formatting, no logic changes. Kept separate from the onboarding feature work. * chore(release): 1.7.3 Bump version to 1.7.3 and document the onboarding upgrade, Corti provider polish, simplified meeting-detection setting, and the Settings microphone fix in the changelog. * docs(changelog): capture full 1.7.3 scope Expand the 1.7.3 entry to cover everything merged since v1.7.2, not just the onboarding branch: Corti BYOK and xAI transcription providers, Snippets, Voice Agent hotkey, dictionary redesign, notification controls, Linux PipeWire/paste fixes, new AI models, and the broader fix batch. * fix(onboarding): keep step progress labels on one line The stepper renders inside TitleBar's absolutely-positioned `left-1/2` center slot, whose shrink-to-fit width is capped at the space from center to edge. That squeezed the row and wrapped the longest label ("Voice Agent") onto two lines. Adding `whitespace-nowrap` lets the wrapper resolve to the content's full width and center it cleanly, fixing the layout across all platforms (shared StepProgress component). * fix(auth): recover stale-bearer cloud requests via session cookie The main process authenticates cloud requests with a single saved bearer token that only refreshes on sign-in. After an email/password login (which, unlike OAuth, never force-refreshes it) that token can go stale, so main-process requests 401 while the renderer stays signed in via its session cookie. onboarding-intent was the visible casualty: it fires right after the use-case step and failed silently, leaving intent unsaved. Retry cloud-api-request once with the window's session cookie when a bearer request returns 401. Cookie-only on retry, since a tagging-along bearer overwrites the cookie server-side. * fix(onboarding): hide voice agent step for continue-without-account users Continue-without-account users have no LLM configured, so the dictation agent can't run — skip the voice agent onboarding step for them and show it only to signed-in account users. * fix(i18n): add Hyprland hotkey locale strings * fix(clipboard): prevent stale clipboard restores during paste * fix(dictation-agent): reach cloud agent from voice hotkey without a selected model The voice agent hotkey resolved to "skip" for signed-in OpenWhispr cloud users because agentReachable required a non-empty dictationAgentModel, which cloud mode never sets — pasting the raw transcript instead of running the agent. Mirror the cleanup cloud fallback: the dictation agent is now reachable in cloud (openwhispr) and self-hosted (lan) modes without an explicit model, matching ReasoningService.processText's empty-model allowance, and the agent route forces provider "openwhispr" in cloud mode so it no longer depends on the cleanup scope. Also pass voiceAgentRequested on the streaming-STT path so the hotkey works there too. Reachability logic is extracted into a pure, tested helper (resolveDictationAgentReachability) alongside resolveDictationRouteKind. * feat(onboarding): preview the real meeting notification in the meeting step Replace the abstract "meeting detected" explainer with a faithful preview of the actual notification, rendered from a shared MeetingNotificationCard that MeetingNotificationOverlay now also consumes so the two never drift. Add the onboarding.meeting.notification.{title,body,cta} keys across all 10 locales. * fix(note-formatting): use cloud provider when no model is selected Note formatting passed no provider to processText, so cloud users fell back to getModelProvider(""), which resolves from the cleanup scope — throwing "No reasoning model selected" when cleanup uses a BYOK/local provider. Pin the provider to openwhispr in cloud mode for both enhancement and title generation. * feat(onboarding): temporarily hide the meeting step for all users * fix(dev): diagnose missing Electron binary * feat(transcription): dedicated Audio Upload speech-to-text settings Give audio upload its own transcription context, mirroring how Note Recording was split from Dictation. Adds an Audio Upload tab under Settings -> Speech-to-Text with independent upload* settings; the upload page is now settings-only (inline picker removed). A one-time migration copies existing users' dictation transcription preference into the new context; new users default to OpenWhispr Cloud. - store: 9 upload* keys, selectResolvedUploadTranscription (falls back to base dictation values), migrateUploadTranscription (runs after provider migration) - settings: new UploadTranscriptionPanel (openwhispr/providers/local) - upload page: read-only consumer of resolved upload settings; no-provider CTA routes to the Audio Upload tab - i18n: tabs.upload across all 10 locales; remove orphaned upload setup strings - fix cross-window boolean sync for meeting/upload useLocalWhisper (BOOLEAN_SETTINGS) - extract shared useStartOnboarding hook; drop dead uploadSetupComplete write * fix(history): inline discarded toggle and stop list flash on refresh Move the "Show Discarded" toggle inline to the left of "Clear All" in the first day header so the pair reveals together on hover; keep it reachable above the empty state. Gate the loading spinner on the initial load only (no data yet) so toggling discarded keeps the current list mounted and swaps in new data instead of unmounting to a spinner and flashing. * feat(upload): cancel button during audio-file transcription Add a Cancel transcription action beneath the progress bar on the upload page (shown for every transcription). Cancelling returns to the upload screen and discards the result so nothing is saved; a run-id token guards the async path so a cancelled or superseded run never persists a note. * docs(changelog): document late-breaking 1.7.3 changes * fix(onboarding): apply Corti to all transcription scopes on finish Choosing Corti during onboarding only set the dictation cloud provider, so note recording and audio upload kept their previous provider and every Settings tab still showed OpenWhispr Cloud — each tab displays the InferenceMode field, which was never updated. setCloudTranscriptionForAllScopes now applies the chosen provider to dictation, note recording, and audio upload, and sets each scope's InferenceMode via a shared deriveTranscriptionMode helper (also reused by the provider-settings migration). * refactor(corti): rework streaming close handshake with ack tracking Replace the single closeResolve callback with a pendingAck/waitForAck mechanism that resolves on the matching server ack (flushed/ended) or socket close, times out cleanly, and closes the socket with code 1000. * feat(onboarding): rename activation step to Dictation and add voice agent test area - Rename the activation onboarding step to "Dictation" in the progress nav and "Dictation Setup" in the step header - Rename the voice agent step header to "Voice Agent Setup" - Add a test area under the voice agent hotkey with example spoken commands and a textarea to try it - Add and translate the new strings across all 10 locales * fix(meeting): send true 24kHz sample rate to cloud streaming providers Meeting capture runs at 24kHz end-to-end, but Corti/Deepgram/AssemblyAI were told 16kHz, so they read the PCM ~1.5x too slow and degraded accuracy. Thread the real rate through the meeting connect path and teach cortiStreaming to honor options.sampleRate (matching Deepgram/AssemblyAI). OpenAI already declares 24kHz; dictation (16kHz) and the local downsample path are untouched. * fix(dictation-agent): default to OpenWhispr Cloud for signed-in users The dictation agent scope defaulted to "providers" (BYOK) with no model, unlike the cleanup and chat-agent scopes which default to OpenWhispr Cloud. As a result, a signed-in user who never explicitly configured the dictation agent had it unreachable, so the voice agent hotkey silently typed the raw transcript instead of running the command. Default dictationAgentMode and dictationAgentCloudMode to "openwhispr" so the voice agent works out of the box on Cloud. Users who explicitly chose BYOK, local, or self-hosted are unaffected (persisted values are read first). * perf(corti): pre-warm dictation socket to cut startup latency and first-word loss Corti dictation paid the full token-mint + socket-open + CONFIG_ACCEPTED cost at hotkey time (~1s), and audio captured before the socket existed was dropped. Give CortiStreaming a real warmup() that opens the socket and finishes the config handshake ahead of recording, keeps it alive with WS pings, and lets connect() promote the warm socket for an instant start — mirroring Deepgram/AssemblyAI. Falls back to a cold connect when no warm socket exists, so behavior is never worse than before. Meeting mode (fresh instance, no warmup) is unaffected.
43 lines
1.4 KiB
JavaScript
43 lines
1.4 KiB
JavaScript
const path = require("path");
|
||
const fs = require("fs");
|
||
const os = require("os");
|
||
|
||
// Clean build directories
|
||
console.log("🧹 Cleaning build directories...");
|
||
const dirsToClean = ["dist/", "src/dist/", "node_modules/.cache/"];
|
||
|
||
dirsToClean.forEach((dir) => {
|
||
if (fs.existsSync(dir)) {
|
||
fs.rmSync(dir, { recursive: true, force: true });
|
||
console.log(`✅ Cleaned: ${dir}`);
|
||
} else {
|
||
console.log(`ℹ️ Directory not found: ${dir}`);
|
||
}
|
||
});
|
||
|
||
// Clean development database
|
||
console.log("🗄️ Cleaning development database...");
|
||
try {
|
||
// Use the same logic as the database.js file to determine the user data path
|
||
const userDataPath =
|
||
process.platform === "darwin"
|
||
? path.join(os.homedir(), "Library", "Application Support", "open-whispr")
|
||
: process.platform === "win32"
|
||
? path.join(process.env.APPDATA || os.homedir(), "open-whispr")
|
||
: path.join(os.homedir(), ".config", "open-whispr");
|
||
|
||
const devDbPath = path.join(userDataPath, "transcriptions-dev.db");
|
||
|
||
// Clean development database
|
||
if (fs.existsSync(devDbPath)) {
|
||
fs.unlinkSync(devDbPath);
|
||
console.log(`✅ Development database cleaned: ${devDbPath}`);
|
||
} else {
|
||
console.log("ℹ️ No development database found to clean");
|
||
}
|
||
} catch (error) {
|
||
console.error("❌ Error cleaning database files:", error.message);
|
||
}
|
||
|
||
console.log("✨ Cleanup completed successfully!");
|