Repository navigation
feat(code): prompt for microphone permission for custom completion sounds - #2136
jamesefhawkins wants to merge 13 commits into
Conversation
Introduces a top-level mode toggle above the nav list. Work mode is an empty shell — placeholder for an upcoming feature set built during the hackathon. Generated-By: PostHog Code Task-Id: bd0f6387-4ee8-42a4-b17d-80927d214463
Generated-By: PostHog Code Task-Id: 770a6aff-7419-424e-a0b0-893d6a1f9b3b
Adds icon assets and BRAND_ICONS entries for Gmail, Granola, Asana, and the Google Workspace apps (Calendar, Drive, Docs, Sheets, Slides) so the marketplace renders them once the backend catalog includes matching templates. The asana.svg is the wordmark for now — a square brand mark wasn't available from public sources and should be swapped in later. Generated-By: PostHog Code Task-Id: 7540ef3b-b0e0-43a2-bb62-5e1836d85765
…Google Calendar/Drive Adds a small client-side registry of MCP templates the backend catalog doesn't yet expose, so the marketplace renders them with their brand icons. Connect routes through the existing custom-install endpoint using the official remote URLs. Drops the Google Docs/Sheets/Slides icons that were registered in the previous commit — there's no official remote MCP server for those (only self-hosted community alternatives), and Drive's MCP already covers their files. Generated-By: PostHog Code Task-Id: af4a4d09-f33e-4053-8f4d-5740d632fcc7
Generated-By: PostHog Code Task-Id: 770a6aff-7419-424e-a0b0-893d6a1f9b3b
Replaces the splash with a full home: hero, real PromptInput-style chat that hands off to TaskInput, clickable sample-project cards, and a Work-mode sidebar with placeholder sections (Projects, Automations, Artifacts, MCP, Memory) plus the standard New task entry. Adds new hedgehog assets and a staggered entrance animation. Generated-By: PostHog Code Task-Id: 14cf4155-07c2-4962-ae8e-4065d6322475
Generated-By: PostHog Code Task-Id: 14cf4155-07c2-4962-ae8e-4065d6322475
Adds the first iteration of Work-mode Skills: - New WorkSidebarMenu listing skills, seeded with an example skill - WorkGenerateView with a centered prompt that creates a task and streams the agent authoring the skill via PostHog MCP - WorkSkillDetailView reuses TaskLogsPanel for live streaming, with a static card for seeded examples - workSkillsStore (persisted) plus workView state in navigationStore - os.getHomeDir tRPC helper for fallback repoPath Includes the user's in-progress sound-recorder settings changes. Generated-By: PostHog Code Task-Id: bd0f6387-4ee8-42a4-b17d-80927d214463
# Conflicts: # apps/code/src/renderer/features/work/components/WorkSidebarMenu.tsx # apps/code/src/renderer/features/work/components/WorkView.tsx
…unds Adds the macOS plumbing needed for the custom completion-sound recorder to actually capture audio: - New IMediaAccess platform port + ElectronMediaAccess adapter wrapping systemPreferences.getMediaAccessStatus / askForMediaAccess - os.getMicrophoneAccessStatus / os.requestMicrophoneAccess tRPC procs - useSoundRecorder triggers the macOS prompt up front when status is not-determined and shows a toast with an "Open Settings" deeplink on denial, plus a "Recording capped at 10 seconds" toast on the auto-stop - NSMicrophoneUsageDescription in forge extendInfo (packaged builds) - com.apple.security.device.audio-input entitlement for hardened-runtime signed builds Generated-By: PostHog Code Task-Id: af45b000-f4e8-4c8b-9dd2-ad0b607ea8cf
Prompt To Fix All With AIFix the following 2 code review issues. Work through them one at a time, proposing concise fixes.
---
### Issue 1 of 2
apps/code/src/renderer/features/settings/hooks/useSoundRecorder.ts:120-121
`toast.error` signals an unexpected failure to users, but hitting the 10-second cap is an expected, non-error outcome of leaving a recording running. Using a neutral toast type avoids falsely alarming the user.
```suggestion
recorderRef.current.stop();
toast.info(`Recording capped at ${MAX_RECORDING_MS / 1000} seconds`);
```
### Issue 2 of 2
apps/code/src/renderer/features/settings/hooks/useSoundRecorder.ts:124-133
**macOS-only deeplink shown on non-macOS platforms**
The `isPermissionError` branch can be reached on any platform (e.g. if the user denies Chromium-level microphone access on Linux or Windows). When that happens, the "Open Settings" action fires `x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone`, which is meaningless outside macOS — either silently failing or opening an unrelated URL. The description text ("in System Settings") is also macOS-specific. Consider hiding the action button or swapping the URL and description to a platform-appropriate value on non-macOS.
Reviews (1): Last reviewed commit: "feat(code): prompt for microphone permis..." | Re-trigger Greptile |
| recorderRef.current.stop(); | ||
| toast.error(`Recording capped at ${MAX_RECORDING_MS / 1000} seconds`); |
There was a problem hiding this comment.
toast.error signals an unexpected failure to users, but hitting the 10-second cap is an expected, non-error outcome of leaving a recording running. Using a neutral toast type avoids falsely alarming the user.
| recorderRef.current.stop(); | |
| toast.error(`Recording capped at ${MAX_RECORDING_MS / 1000} seconds`); | |
| recorderRef.current.stop(); | |
| toast.info(`Recording capped at ${MAX_RECORDING_MS / 1000} seconds`); |
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/settings/hooks/useSoundRecorder.ts
Line: 120-121
Comment:
`toast.error` signals an unexpected failure to users, but hitting the 10-second cap is an expected, non-error outcome of leaving a recording running. Using a neutral toast type avoids falsely alarming the user.
```suggestion
recorderRef.current.stop();
toast.info(`Recording capped at ${MAX_RECORDING_MS / 1000} seconds`);
```
How can I resolve this? If you propose a fix, please make it concise.Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
| } catch (error) { | ||
| log.error("Failed to start recording", error); | ||
| cleanup(); | ||
| setIsRecording(false); | ||
| const isPermissionError = | ||
| error instanceof Error && | ||
| (error.name === "NotAllowedError" || | ||
| error.name === "SecurityError" || | ||
| error.message.toLowerCase().includes("permission")); | ||
| if (isPermissionError) { |
There was a problem hiding this comment.
macOS-only deeplink shown on non-macOS platforms
The isPermissionError branch can be reached on any platform (e.g. if the user denies Chromium-level microphone access on Linux or Windows). When that happens, the "Open Settings" action fires x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone, which is meaningless outside macOS — either silently failing or opening an unrelated URL. The description text ("in System Settings") is also macOS-specific. Consider hiding the action button or swapping the URL and description to a platform-appropriate value on non-macOS.
Prompt To Fix With AI
This is a comment left during a code review.
Path: apps/code/src/renderer/features/settings/hooks/useSoundRecorder.ts
Line: 124-133
Comment:
**macOS-only deeplink shown on non-macOS platforms**
The `isPermissionError` branch can be reached on any platform (e.g. if the user denies Chromium-level microphone access on Linux or Windows). When that happens, the "Open Settings" action fires `x-apple.systempreferences:com.apple.preference.security?Privacy_Microphone`, which is meaningless outside macOS — either silently failing or opening an unrelated URL. The description text ("in System Settings") is also macOS-specific. Consider hiding the action button or swapping the URL and description to a platform-appropriate value on non-macOS.
How can I resolve this? If you propose a fix, please make it concise.
Summary
IMediaAccessplatform port +ElectronMediaAccessadapter wrappingsystemPreferences.getMediaAccessStatus/askForMediaAccess, exposed via two newos.*tRPC procedures.useSoundRecordertriggers the macOS prompt up front when status isnot-determined, surfaces a toast with an "Open Settings" deeplink on denial, and shows a "Recording capped at 10 seconds" toast on auto-stop.NSMicrophoneUsageDescriptionto the packaged Info.plist viaextendInfoandcom.apple.security.device.audio-inputto the hardened-runtime entitlements file.Test plan
Created with PostHog Code