Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
253 changes: 0 additions & 253 deletions apps/desktop/src/components/settings/ai/stt/shared.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,6 @@ type Provider = {

export type ProviderId = (typeof PROVIDERS)[number]["id"];

type ProviderModels = {
hyprnote: (typeof PROVIDERS)[0]["models"];
deepgram: (typeof PROVIDERS)[1]["models"];
custom: (typeof PROVIDERS)[2]["models"];
groq: (typeof PROVIDERS)[3]["models"];
fireworks: (typeof PROVIDERS)[4]["models"];
};

type LanguageSupportMap = {
[K in ProviderId]: Partial<Record<ProviderModels[K][number], string[]>>;
};

export const displayModelId = (model: string) => {
if (model === "cloud") {
return "Cloud";
Expand Down Expand Up @@ -142,247 +130,6 @@ export const sttProviderRequiresPro = (providerId: ProviderId) =>
PROVIDERS.find((provider) => provider.id === providerId)?.requiresPro ??
false;

export const LANGUAGE_SUPPORT: LanguageSupportMap = {
hyprnote: {
QuantizedTinyEn: ["en"],
QuantizedSmallEn: ["en"],
"am-parakeet-v2": ["en"],
"am-parakeet-v3": [
"en",
"de",
"es",
"fr",
"nl",
"it",
"da",
"et",
"fi",
"el",
"hu",
"lv",
"lt",
"mt",
"pl",
"pt",
"ro",
"sk",
"sl",
"sv",
"ru",
"uk",
"bg",
"hr",
"cs",
],
"am-whisper-large-v3": [
"af",
"am",
"ar",
"as",
"az",
"ba",
"be",
"bg",
"bn",
"bo",
"br",
"bs",
"ca",
"cs",
"cy",
"da",
"de",
"el",
"en",
"es",
"et",
"eu",
"fa",
"fi",
"fo",
"fr",
"gl",
"gu",
"ha",
"he",
"hi",
"hr",
"ht",
"hu",
"hy",
"id",
"is",
"it",
"ja",
"jv",
"ka",
"kk",
"km",
"kn",
"ko",
"la",
"lb",
"lo",
"lt",
"lv",
"mg",
"mi",
"mk",
"ml",
"mn",
"mr",
"ms",
"mt",
"my",
"ne",
"nl",
"nn",
"no",
"oc",
"pa",
"pl",
"ps",
"pt",
"ro",
"ru",
"sa",
"sd",
"si",
"sk",
"sl",
"sn",
"so",
"sq",
"sr",
"su",
"sv",
"sw",
"ta",
"te",
"tg",
"th",
"tk",
"tl",
"tr",
"tt",
"uk",
"ur",
"uz",
"vi",
"yi",
"yo",
"zh",
],
},
deepgram: {
// https://developers.deepgram.com/docs/models-languages-overview#nova-3
"nova-3-general": [
"en",
"en-US",
"en-AU",
"en-GB",
"en-IN",
"en-NZ",
"de",
"nl",
"sv",
"sv-SE",
"da",
"da-DK",
"es",
"es-419",
"fr",
"fr-CA",
"pt",
"pt-BR",
"pt-PT",
"it",
"tr",
"no",
"id",
],
"nova-3-medical": [
"en",
"en-US",
"en-AU",
"en-CA",
"en-GB",
"en-IE",
"en-IN",
"en-NZ",
],
// https://developers.deepgram.com/docs/models-languages-overview#nova-2
"nova-2-general": [
"bg",
"ca",
"zh",
"zh-CN",
"zh-Hans",
"zh-TW",
"zh-Hant",
"zh-HK",
"cs",
"da",
"da-DK",
"nl",
"en",
"en-US",
"en-AU",
"en-GB",
"en-NZ",
"en-IN",
"et",
"fi",
"nl-BE",
"fr",
"fr-CA",
"de",
"de-CH",
"el",
"hi",
"hu",
"id",
"it",
"ja",
"ko",
"ko-KR",
"lv",
"lt",
"ms",
"no",
"pl",
"pt",
"pt-BR",
"pt-PT",
"ro",
"ru",
"sk",
"es",
"es-419",
"sv",
"sv-SE",
"th",
"th-TH",
"tr",
"uk",
"vi",
],
"nova-2-meeting": ["en", "en-US"],
"nova-2-phonecall": ["en", "en-US"],
"nova-2-finance": ["en", "en-US"],
"nova-2-conversationalai": ["en", "en-US"],
"nova-2-voicemail": ["en", "en-US"],
"nova-2-video": ["en", "en-US"],
"nova-2-medical": ["en", "en-US"],
"nova-2-drivethru": ["en", "en-US"],
"nova-2-automotive": ["en", "en-US"],
"nova-2-atc": ["en", "en-US"],
},
custom: {},
groq: {},
fireworks: {},
};

export const sttModelQueries = {
isDownloaded: (model: SupportedSttModel) =>
queryOptions({
Expand Down
10 changes: 10 additions & 0 deletions apps/desktop/src/components/settings/general/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import * as main from "../../../store/tinybase/main";
import { AppSettingsView } from "./app-settings";
import { MainLanguageView } from "./main-language";
import { Permissions } from "./permissions";
import { SpokenLanguagesView } from "./spoken-languages";

export function SettingsGeneral() {
const value = useConfigValues([
Expand Down Expand Up @@ -134,6 +135,15 @@ export function SettingsGeneral() {
/>
)}
</form.Field>
<form.Field name="spoken_languages">
{(field) => (
<SpokenLanguagesView
value={field.state.value}
onChange={(val) => field.handleChange(val)}
supportedLanguages={SUPPORTED_LANGUAGES}
/>
)}
</form.Field>
</div>
</div>

Expand Down
40 changes: 23 additions & 17 deletions apps/desktop/src/components/settings/general/spoken-languages.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@ interface SpokenLanguagesViewProps {
supportedLanguages: ISO_639_1_CODE[];
}

function getLanguageName(code: string): string {
const lang = LANGUAGES_ISO_639_1[code as ISO_639_1_CODE];
return lang?.name ?? code;
}

export function SpokenLanguagesView({
value,
onChange,
Expand All @@ -28,14 +33,12 @@ export function SpokenLanguagesView({
return [];
}
const query = languageSearchQuery.toLowerCase();
return supportedLanguages
.filter((langCode) => {
const langName = LANGUAGES_ISO_639_1[langCode].name;
return (
!value.includes(langName) && langName.toLowerCase().includes(query)
);
})
.map((langCode) => LANGUAGES_ISO_639_1[langCode].name);
return supportedLanguages.filter((langCode) => {
const langName = LANGUAGES_ISO_639_1[langCode].name;
return (
!value.includes(langCode) && langName.toLowerCase().includes(query)
);
});
}, [languageSearchQuery, value, supportedLanguages]);

const handleLanguageKeyDown = (e: React.KeyboardEvent<HTMLInputElement>) => {
Expand Down Expand Up @@ -63,7 +66,8 @@ export function SpokenLanguagesView({
languageSelectedIndex >= 0 &&
languageSelectedIndex < filteredLanguages.length
) {
onChange([...value, filteredLanguages[languageSelectedIndex]]);
const selectedCode = filteredLanguages[languageSelectedIndex];
onChange([...value, selectedCode]);
setLanguageSearchQuery("");
setLanguageSelectedIndex(-1);
}
Expand All @@ -90,21 +94,21 @@ export function SpokenLanguagesView({
document.getElementById("language-search-input")?.focus()
}
>
{value.map((lang) => (
{value.map((code) => (
<Badge
key={lang}
key={code}
variant="secondary"
className="flex items-center gap-1 px-2 py-0.5 text-xs bg-muted"
>
{lang}
{getLanguageName(code)}
<Button
type="button"
variant="ghost"
size="sm"
className="h-3 w-3 p-0 hover:bg-transparent ml-0.5"
onClick={(e) => {
e.stopPropagation();
onChange(value.filter((l) => l !== lang));
onChange(value.filter((c) => c !== code));
}}
>
<X className="h-2.5 w-2.5" />
Expand Down Expand Up @@ -147,15 +151,15 @@ export function SpokenLanguagesView({
className="absolute top-full left-0 right-0 mt-1 flex flex-col w-full rounded border border-neutral-200 overflow-hidden bg-white shadow-md z-10 max-h-60 overflow-y-auto"
>
{filteredLanguages.length > 0 ? (
filteredLanguages.map((langName, index) => (
filteredLanguages.map((langCode, index) => (
<button
key={langName}
key={langCode}
id={`language-option-${index}`}
type="button"
role="option"
aria-selected={languageSelectedIndex === index}
onClick={() => {
onChange([...value, langName]);
onChange([...value, langCode]);
setLanguageSearchQuery("");
setLanguageSelectedIndex(-1);
}}
Expand All @@ -168,7 +172,9 @@ export function SpokenLanguagesView({
: "hover:bg-neutral-100",
])}
>
<span className="font-medium truncate">{langName}</span>
<span className="font-medium truncate">
{getLanguageName(langCode)}
</span>
</button>
))
) : (
Expand Down
Loading