From aebf726b5ce0c966c7140f068fd8276197e5fcf9 Mon Sep 17 00:00:00 2001 From: Timothy Jaeryang Baek Date: Fri, 12 Jun 2026 17:50:18 +0100 Subject: [PATCH 1/5] refac --- cptr/app.py | 2 + .../lib/components/Admin/AudioSettings.svelte | 132 +++++++++ .../src/lib/components/Admin/Settings.svelte | 28 +- .../src/lib/components/GroupTabBar.svelte | 24 +- cptr/frontend/src/lib/components/Icon.svelte | 7 + .../src/lib/components/SettingsModal.svelte | 5 + .../src/lib/components/VoiceNoteModal.svelte | 266 ++++++++++++++++++ cptr/frontend/src/lib/stores/audio.ts | 21 ++ cptr/frontend/src/lib/stores/keybindings.ts | 14 +- cptr/frontend/src/routes/+layout.svelte | 11 + cptr/routers/__init__.py | 2 + cptr/routers/audio.py | 73 +++++ 12 files changed, 567 insertions(+), 18 deletions(-) create mode 100644 cptr/frontend/src/lib/components/Admin/AudioSettings.svelte create mode 100644 cptr/frontend/src/lib/components/VoiceNoteModal.svelte create mode 100644 cptr/frontend/src/lib/stores/audio.ts create mode 100644 cptr/routers/audio.py diff --git a/cptr/app.py b/cptr/app.py index 53dbea3..52bf426 100644 --- a/cptr/app.py +++ b/cptr/app.py @@ -7,6 +7,7 @@ from cptr.routers import ( admin_router, + audio_router, auth_router, automations_router, bridge_router, @@ -209,6 +210,7 @@ async def get_config(): # Routers app.include_router(admin_router) +app.include_router(audio_router) app.include_router(auth_router) app.include_router(automations_router) app.include_router(bridge_router) diff --git a/cptr/frontend/src/lib/components/Admin/AudioSettings.svelte b/cptr/frontend/src/lib/components/Admin/AudioSettings.svelte new file mode 100644 index 0000000..d98c05f --- /dev/null +++ b/cptr/frontend/src/lib/components/Admin/AudioSettings.svelte @@ -0,0 +1,132 @@ + + +
+

Audio

+ + {#if loading} +
+ {:else} + +

Voice Notes

+ +
+ +

+ Record voice memos from the "+" menu. +

+ + +

+ {transcribeEnabled ? 'Recordings are transcribed to markdown via STT.' : 'Recordings are saved as audio only.'} +

+
+ + +

Speech-to-Text

+ +
+
+ + +
+
+ + +
+
+ + +
+

+ Compatible with OpenAI's audio/transcriptions API. +

+
+ + +
+ +
+ {/if} +
diff --git a/cptr/frontend/src/lib/components/Admin/Settings.svelte b/cptr/frontend/src/lib/components/Admin/Settings.svelte index bafd500..592f7c5 100644 --- a/cptr/frontend/src/lib/components/Admin/Settings.svelte +++ b/cptr/frontend/src/lib/components/Admin/Settings.svelte @@ -127,12 +127,12 @@

{$t('admin.webAutoHint')}

{:else if provider === 'exa'}
- saveKey('web.exa_api_key', exaKey)} @@ -144,12 +144,12 @@
{:else if provider === 'tavily'}
- saveKey('web.tavily_api_key', tavilyKey)} @@ -161,12 +161,12 @@
{:else if provider === 'brave'}
- saveKey('web.brave_api_key', braveKey)} @@ -182,12 +182,12 @@

{:else if provider === 'perplexity'}
- saveKey('web.perplexity_api_key', perplexityKey)} @@ -200,12 +200,12 @@ {:else if provider === 'chat_completions'}
- saveKey('web.chat_completions_base_url', ccBaseUrl)} @@ -213,12 +213,12 @@ />
- saveKey('web.chat_completions_api_key', ccKey)} @@ -226,12 +226,12 @@ />
- saveKey('web.chat_completions_model', ccModel)} diff --git a/cptr/frontend/src/lib/components/GroupTabBar.svelte b/cptr/frontend/src/lib/components/GroupTabBar.svelte index 3db0391..546a8c4 100644 --- a/cptr/frontend/src/lib/components/GroupTabBar.svelte +++ b/cptr/frontend/src/lib/components/GroupTabBar.svelte @@ -21,12 +21,14 @@ } from '$lib/stores'; import { openChatTab } from '$lib/stores'; import { chatEnabled, streamingChatTabs } from '$lib/stores/chat'; + import { voiceNotesEnabled, showVoiceNote } from '$lib/stores/audio'; import { keybindings, formatChord } from '$lib/stores/keybindings'; import Icon from './Icon.svelte'; import Spinner from './common/Spinner.svelte'; import DropdownMenu from './DropdownMenu.svelte'; import { tooltip } from '$lib/tooltip'; import { t } from '$lib/i18n'; + import VoiceNoteModal from './VoiceNoteModal.svelte'; interface Props { group: EditorGroup; @@ -159,7 +161,19 @@ onclick: () => { openTerminalTab(group.id); } - } + }, + ...($voiceNotesEnabled + ? [ + { + label: 'Voice Note', + icon: 'microphone', + shortcut: formatChord($keybindings.voiceNote), + onclick: () => { + showVoiceNote.set(true); + } + } + ] + : []) ]); const contextMenuItems = $derived.by(() => { @@ -391,6 +405,14 @@ /> {/if} +{#if $showVoiceNote} + showVoiceNote.set(false)} + /> +{/if} +