diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua index 75137ecd..72cb83c2 100644 --- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua +++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua @@ -3127,6 +3127,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2372624045"] = "Start rec -- Transcription in progress... UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2851219233"] = "Transcription in progress..." +-- Unfortunately, there was an error communicating with the AI system. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T3236134591"] = "Unfortunately, there was an error communicating with the AI system." + -- The configured transcription provider was not found. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T331613105"] = "The configured transcription provider was not found." diff --git a/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs b/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs index 686656dd..93ec3f00 100644 --- a/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs +++ b/app/MindWork AI Studio/Components/VoiceRecorder.razor.cs @@ -361,7 +361,15 @@ public partial class VoiceRecorder : MSGComponentBase // Call the transcription API: this.Logger.LogInformation("Starting transcription with provider '{ProviderName}' and model '{ModelName}'.", transcriptionProviderSettings.UsedLLMProvider, transcriptionProviderSettings.Model.ToString()); - var transcribedText = await provider.TranscribeAudioAsync(transcriptionProviderSettings.Model, this.finalRecordingPath, this.SettingsManager); + var transcriptionResult = await provider.TranscribeAudioAsync(transcriptionProviderSettings.Model, this.finalRecordingPath, this.SettingsManager); + if (!transcriptionResult.Success) + { + this.Logger.LogWarning("The transcription request failed."); + await this.MessageBus.SendError(new(Icons.Material.Filled.VoiceChat, this.T("Unfortunately, there was an error communicating with the AI system."))); + return; + } + + var transcribedText = transcriptionResult.Text; if (string.IsNullOrWhiteSpace(transcribedText)) { diff --git a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua index d79e6f5c..04abccb5 100644 --- a/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/de-de-43065dbc-78d0-45b7-92be-f14c2926e2dc/plugin.lua @@ -3129,6 +3129,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2372624045"] = "Beginnen -- Transcription in progress... UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2851219233"] = "Transkription läuft …" +-- Unfortunately, there was an error communicating with the AI system. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T3236134591"] = "Leider ist bei der Kommunikation mit dem KI-System ein Fehler aufgetreten." + -- The configured transcription provider was not found. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T331613105"] = "Der konfigurierte Anbieter für die Transkription wurde nicht gefunden." @@ -4797,9 +4800,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T38241 -- Actions UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T3865031940"] = "Aktionen" --- Export -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T3898821075"] = "Exportieren" - -- Delete Chat Template UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4025180906"] = "Chat-Vorlage löschen" @@ -7746,9 +7746,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T13982828 -- File has no extension UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T1555980031"] = "Datei hat keine Erweiterung" --- This file format is not supported. -UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T2634293666"] = "Dieses Dateiformat wird nicht unterstützt. Bitte konvertieren Sie die .doc-Datei in .docx (z. B. mit Microsoft Word)." - -- Audio files are not supported yet UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T2919730669"] = "Audio-Dateien werden noch nicht unterstützt." @@ -7761,6 +7758,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T29806295 -- Images are not supported at this place UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T305247150"] = "Bilder werden an dieser Stelle nicht unterstützt." +-- This file format is not supported. Please convert the .doc file to .docx (e.g. with Microsoft Word). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T3740637731"] = "Dieses Dateiformat wird nicht unterstützt. Bitte konvertieren Sie die .doc-Datei in eine .docx-Datei (z. B. mit Microsoft Word)." + -- Unsupported file type UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T4041351522"] = "Nicht unterstützter Dateityp" diff --git a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua index 2cfa7dca..e356ad7a 100644 --- a/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua +++ b/app/MindWork AI Studio/Plugins/languages/en-us-97dfb1ba-50c4-4440-8dfa-6575daf543c8/plugin.lua @@ -3129,6 +3129,9 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2372624045"] = "Start rec -- Transcription in progress... UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T2851219233"] = "Transcription in progress..." +-- Unfortunately, there was an error communicating with the AI system. +UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T3236134591"] = "Unfortunately, there was an error communicating with the AI system." + -- The configured transcription provider was not found. UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::VOICERECORDER::T331613105"] = "The configured transcription provider was not found." @@ -4797,9 +4800,6 @@ UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T38241 -- Actions UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T3865031940"] = "Actions" --- Export -UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T3898821075"] = "Export" - -- Delete Chat Template UI_TEXT_CONTENT["AISTUDIO::DIALOGS::SETTINGS::SETTINGSDIALOGCHATTEMPLATE::T4025180906"] = "Delete Chat Template" @@ -7758,8 +7758,8 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T29806295 -- Images are not supported at this place UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T305247150"] = "Images are not supported at this place" --- This file format is not supported. -UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T1506058512"] = "This file format is not supported. Please convert the .doc file to .docx (e.g. with Microsoft Word)." +-- This file format is not supported. Please convert the .doc file to .docx (e.g. with Microsoft Word). +UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T3740637731"] = "This file format is not supported. Please convert the .doc file to .docx (e.g. with Microsoft Word)." -- Unsupported file type UI_TEXT_CONTENT["AISTUDIO::TOOLS::VALIDATION::FILEEXTENSIONVALIDATION::T4041351522"] = "Unsupported file type" diff --git a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs index 888a52a6..7be6cdc5 100644 --- a/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs +++ b/app/MindWork AI Studio/Provider/AlibabaCloud/ProviderAlibabaCloud.cs @@ -60,9 +60,9 @@ public sealed class ProviderAlibabaCloud() : BaseProvider(LLMProviders.ALIBABA_C #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs index 4a57a3a2..c881eb13 100644 --- a/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs +++ b/app/MindWork AI Studio/Provider/Anthropic/ProviderAnthropic.cs @@ -116,9 +116,9 @@ public sealed class ProviderAnthropic() : BaseProvider(LLMProviders.ANTHROPIC, " #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/BaseProvider.cs b/app/MindWork AI Studio/Provider/BaseProvider.cs index d3bcd005..81d92c3e 100644 --- a/app/MindWork AI Studio/Provider/BaseProvider.cs +++ b/app/MindWork AI Studio/Provider/BaseProvider.cs @@ -100,7 +100,7 @@ public abstract class BaseProvider : IProvider, ISecretId public abstract IAsyncEnumerable StreamImageCompletion(Model imageModel, string promptPositive, string promptNegative = FilterOperator.String.Empty, ImageURL referenceImageURL = default, CancellationToken token = default); /// - public abstract Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default); + public abstract Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default); /// public abstract Task>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List texts); @@ -804,7 +804,7 @@ public abstract class BaseProvider : IProvider, ISecretId yield return content; } - protected async Task PerformStandardTranscriptionRequest(RequestedSecret requestedSecret, Model transcriptionModel, string audioFilePath, Host host = Host.NONE, CancellationToken token = default) + protected async Task PerformStandardTranscriptionRequest(RequestedSecret requestedSecret, Model transcriptionModel, string audioFilePath, Host host = Host.NONE, CancellationToken token = default) { try { @@ -846,7 +846,7 @@ public abstract class BaseProvider : IProvider, ISecretId if(!requestedSecret.Success) { this.logger.LogError("No valid API key available for transcription request."); - return string.Empty; + return TranscriptionResult.Failure(); } request.Headers.Add("Authorization", await requestedSecret.Secret.Decrypt(ENCRYPTION)); @@ -856,7 +856,7 @@ public abstract class BaseProvider : IProvider, ISecretId if(!requestedSecret.Success) { this.logger.LogError("No valid API key available for transcription request."); - return string.Empty; + return TranscriptionResult.Failure(); } request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", await requestedSecret.Secret.Decrypt(ENCRYPTION)); @@ -864,22 +864,22 @@ public abstract class BaseProvider : IProvider, ISecretId } using var response = await this.HttpClient.SendAsync(request, token); - var responseBody = response.Content.ReadAsStringAsync(token).Result; + var responseBody = await response.Content.ReadAsStringAsync(token); if (!response.IsSuccessStatusCode) { this.logger.LogError("Transcription request failed with status code {ResponseStatusCode} and body: '{ResponseBody}'.", response.StatusCode, responseBody); - return string.Empty; + return TranscriptionResult.Failure(); } var transcriptionResponse = JsonSerializer.Deserialize(responseBody, JSON_SERIALIZER_OPTIONS); if(transcriptionResponse is null) { this.logger.LogError("Was not able to deserialize the transcription response."); - return string.Empty; + return TranscriptionResult.Failure(); } - return transcriptionResponse.Text; + return TranscriptionResult.FromText(transcriptionResponse.Text); } catch (Exception e) { @@ -887,7 +887,7 @@ public abstract class BaseProvider : IProvider, ISecretId await this.SendTimeoutError("transcribing audio"); this.logger.LogError("Failed to perform transcription request: '{Message}'.", e.Message); - return string.Empty; + return TranscriptionResult.Failure(); } } diff --git a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs index 05910bab..a24e6b3d 100644 --- a/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs +++ b/app/MindWork AI Studio/Provider/DeepSeek/ProviderDeepSeek.cs @@ -60,9 +60,9 @@ public sealed class ProviderDeepSeek() : BaseProvider(LLMProviders.DEEP_SEEK, "h #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs index 160bc9fb..2849f6c8 100644 --- a/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs +++ b/app/MindWork AI Studio/Provider/Fireworks/ProviderFireworks.cs @@ -61,7 +61,7 @@ public class ProviderFireworks() : BaseProvider(LLMProviders.FIREWORKS, "https:/ #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.TRANSCRIPTION_PROVIDER); return await this.PerformStandardTranscriptionRequest(requestedSecret, transcriptionModel, audioFilePath, token: token); diff --git a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs index a68eacb2..07787c87 100644 --- a/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs +++ b/app/MindWork AI Studio/Provider/GWDG/ProviderGWDG.cs @@ -60,7 +60,7 @@ public sealed class ProviderGWDG() : BaseProvider(LLMProviders.GWDG, "https://ch #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.TRANSCRIPTION_PROVIDER); return await this.PerformStandardTranscriptionRequest(requestedSecret, transcriptionModel, audioFilePath, token: token); diff --git a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs index 9aa2658e..97ef11d5 100644 --- a/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs +++ b/app/MindWork AI Studio/Provider/Google/ProviderGoogle.cs @@ -63,9 +63,9 @@ public class ProviderGoogle() : BaseProvider(LLMProviders.GOOGLE, "https://gener #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs index 52b9416a..ae59bf7d 100644 --- a/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs +++ b/app/MindWork AI Studio/Provider/Groq/ProviderGroq.cs @@ -64,9 +64,9 @@ public class ProviderGroq() : BaseProvider(LLMProviders.GROQ, "https://api.groq. #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs index 13273018..df7fbe14 100644 --- a/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs +++ b/app/MindWork AI Studio/Provider/Helmholtz/ProviderHelmholtz.cs @@ -62,9 +62,9 @@ public sealed class ProviderHelmholtz() : BaseProvider(LLMProviders.HELMHOLTZ, " #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs index 74d969a5..b3728521 100644 --- a/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs +++ b/app/MindWork AI Studio/Provider/HuggingFace/ProviderHuggingFace.cs @@ -65,9 +65,9 @@ public sealed class ProviderHuggingFace : BaseProvider #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/IProvider.cs b/app/MindWork AI Studio/Provider/IProvider.cs index 76fcaa27..3656b5e3 100644 --- a/app/MindWork AI Studio/Provider/IProvider.cs +++ b/app/MindWork AI Studio/Provider/IProvider.cs @@ -64,7 +64,7 @@ public interface IProvider /// The settings manager instance to use. /// The cancellation token. /// >The transcription result. - public Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default); + public Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default); /// /// Embed a text file. diff --git a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs index 65964e83..04ac9898 100644 --- a/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs +++ b/app/MindWork AI Studio/Provider/Mistral/ProviderMistral.cs @@ -67,7 +67,7 @@ public sealed class ProviderMistral() : BaseProvider(LLMProviders.MISTRAL, "http #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override async Task TranscribeAudioAsync(Provider.Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override async Task TranscribeAudioAsync(Provider.Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.TRANSCRIPTION_PROVIDER); return await this.PerformStandardTranscriptionRequest(requestedSecret, transcriptionModel, audioFilePath, token: token); diff --git a/app/MindWork AI Studio/Provider/NoProvider.cs b/app/MindWork AI Studio/Provider/NoProvider.cs index c8a334ed..1106292a 100644 --- a/app/MindWork AI Studio/Provider/NoProvider.cs +++ b/app/MindWork AI Studio/Provider/NoProvider.cs @@ -41,7 +41,7 @@ public class NoProvider : IProvider yield break; } - public Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) => Task.FromResult(string.Empty); + public Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) => Task.FromResult(TranscriptionResult.Failure()); public Task>> EmbedTextAsync(Model embeddingModel, SettingsManager settingsManager, CancellationToken token = default, params List texts) => Task.FromResult>>([]); diff --git a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs index 28cf2327..aa9fb49b 100644 --- a/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs +++ b/app/MindWork AI Studio/Provider/OpenAI/ProviderOpenAI.cs @@ -222,7 +222,7 @@ public sealed class ProviderOpenAI() : BaseProvider(LLMProviders.OPEN_AI, "https #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override async Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.TRANSCRIPTION_PROVIDER); return await this.PerformStandardTranscriptionRequest(requestedSecret, transcriptionModel, audioFilePath, token: token); diff --git a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs index 9b5bdd69..d84431e3 100644 --- a/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs +++ b/app/MindWork AI Studio/Provider/OpenRouter/ProviderOpenRouter.cs @@ -71,9 +71,9 @@ public sealed class ProviderOpenRouter() : BaseProvider(LLMProviders.OPEN_ROUTER #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs index c019d77c..8d714985 100644 --- a/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs +++ b/app/MindWork AI Studio/Provider/Perplexity/ProviderPerplexity.cs @@ -68,9 +68,9 @@ public sealed class ProviderPerplexity() : BaseProvider(LLMProviders.PERPLEXITY, #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs index 598cb2f3..a79a1341 100644 --- a/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs +++ b/app/MindWork AI Studio/Provider/SelfHosted/ProviderSelfHosted.cs @@ -73,7 +73,7 @@ public sealed class ProviderSelfHosted(Host host, string hostname) : BaseProvide #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override async Task TranscribeAudioAsync(Provider.Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override async Task TranscribeAudioAsync(Provider.Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { var requestedSecret = await RUST_SERVICE.GetAPIKey(this, SecretStoreType.TRANSCRIPTION_PROVIDER, isTrying: true); return await this.PerformStandardTranscriptionRequest(requestedSecret, transcriptionModel, audioFilePath, host, token); diff --git a/app/MindWork AI Studio/Provider/TranscriptionResult.cs b/app/MindWork AI Studio/Provider/TranscriptionResult.cs new file mode 100644 index 00000000..4ee6256a --- /dev/null +++ b/app/MindWork AI Studio/Provider/TranscriptionResult.cs @@ -0,0 +1,8 @@ +namespace AIStudio.Provider; + +public sealed record TranscriptionResult(bool Success, string Text) +{ + public static TranscriptionResult FromText(string text) => new(true, text); + + public static TranscriptionResult Failure() => new(false, string.Empty); +} \ No newline at end of file diff --git a/app/MindWork AI Studio/Provider/X/ProviderX.cs b/app/MindWork AI Studio/Provider/X/ProviderX.cs index 5d63850d..ecfa87b0 100644 --- a/app/MindWork AI Studio/Provider/X/ProviderX.cs +++ b/app/MindWork AI Studio/Provider/X/ProviderX.cs @@ -61,9 +61,9 @@ public sealed class ProviderX() : BaseProvider(LLMProviders.X, "https://api.x.ai #pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously /// - public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) + public override Task TranscribeAudioAsync(Model transcriptionModel, string audioFilePath, SettingsManager settingsManager, CancellationToken token = default) { - return Task.FromResult(string.Empty); + return Task.FromResult(TranscriptionResult.Failure()); } /// diff --git a/app/MindWork AI Studio/wwwroot/changelog/v26.5.5.md b/app/MindWork AI Studio/wwwroot/changelog/v26.5.5.md index 4bf9d0f2..b5a65956 100644 --- a/app/MindWork AI Studio/wwwroot/changelog/v26.5.5.md +++ b/app/MindWork AI Studio/wwwroot/changelog/v26.5.5.md @@ -12,6 +12,7 @@ - Fixed an issue where the spellchecking setting was not applied to all text fields in the slide builder assistant. - Fixed an issue where legacy `.doc` files could be selected even though AI Studio could not process them. These files are now rejected with a clear error message. Thanks to Bernhard for reporting this issue. - Fixed an issue where attached documents were detached when editing a previous prompt. They now remain attached. +- Fixed an issue where failed transcription requests could be shown as empty transcription results instead of a clear error message. - Fixed missing translations for file type names in file selection dialogs. - Upgraded the native secret storage integration to `keyring-core`, keeping API keys in the secure credential store provided by the operating system. - Upgraded Rust to v1.95.0.