diff --git a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
index ec6ce952..b458beba 100644
--- a/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
+++ b/app/MindWork AI Studio/Assistants/I18N/allTexts.lua
@@ -2389,6 +2389,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T3571008422"] = "Assistan
-- The result is ready.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T661906146"] = "The result is ready."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1318944584"] = "The assistant cannot be deleted while background work is still running."
+
+-- Delete assistant plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1692493145"] = "Delete assistant plugin"
+
+-- Delete Assistant Plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3637071001"] = "Delete Assistant Plugin"
+
+-- The '{0}' assistant plugin has been successfully removed.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3815023384"] = "The '{0}' assistant plugin has been successfully removed."
+
+-- The assistant plugin '{0}' could not be deleted: {1}
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3985264168"] = "The assistant plugin '{0}' could not be deleted: {1}"
+
+-- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T4033722845"] = "Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."
+
-- Show or hide the detailed security information.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T1045105126"] = "Show or hide the detailed security information."
@@ -7282,9 +7300,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1506922856"] = "Assistant Audit"
-- Internal Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Internal Plugins"
--- Delete assistant plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1692493145"] = "Delete assistant plugin"
-
-- Disabled Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
@@ -7318,24 +7333,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3143506997"] = "The assistant plugin
-- Close
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3448155331"] = "Close"
--- Delete Assistant Plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3637071001"] = "Delete Assistant Plugin"
-
-- Revise assistant plugin with AI
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3801095542"] = "Revise assistant plugin with AI"
--- The '{0}' assistant plugin has been successfully removed.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3815023384"] = "The '{0}' assistant plugin has been successfully removed."
-
-- Actions
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
--- The assistant plugin '{0}' could not be deleted: {1}
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3985264168"] = "The assistant plugin '{0}' could not be deleted: {1}"
-
--- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4033722845"] = "Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."
-
-- The automatic security audit for the assistant plugin '{0}' failed. Please run it manually.
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4066679817"] = "The automatic security audit for the assistant plugin '{0}' failed. Please run it manually."
@@ -8857,6 +8860,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1211
-- Only assistant plugins can be edited.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1288328479"] = "Only assistant plugins can be edited."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1318944584"] = "The assistant cannot be deleted while background work is still running."
+
-- No Lua plugin code was generated.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1839013358"] = "No Lua plugin code was generated."
@@ -8887,6 +8893,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T2955
-- The generated assistant plugin uses the ID of an internal AI Studio plugin.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3162363526"] = "The generated assistant plugin uses the ID of an internal AI Studio plugin."
+-- Config Server managed assistant plugins cannot be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3751820312"] = "Config Server managed assistant plugins cannot be deleted."
+
+-- Only assistants generated by the Assistant Builder can be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3940247198"] = "Only assistants generated by the Assistant Builder can be deleted."
+
-- The edited plugin is not an assistant plugin. Issue: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3984111892"] = "The edited plugin is not an assistant plugin. Issue: {0}"
diff --git a/app/MindWork AI Studio/Components/AssistantBlock.razor b/app/MindWork AI Studio/Components/AssistantBlock.razor
index efb7eee4..c3d33a98 100644
--- a/app/MindWork AI Studio/Components/AssistantBlock.razor
+++ b/app/MindWork AI Studio/Components/AssistantBlock.razor
@@ -50,6 +50,7 @@
{
}
+ @this.AdditionalActions
@if (this.SecurityBadge is not null)
{
diff --git a/app/MindWork AI Studio/Components/AssistantBlock.razor.cs b/app/MindWork AI Studio/Components/AssistantBlock.razor.cs
index 48672332..adf8b13a 100644
--- a/app/MindWork AI Studio/Components/AssistantBlock.razor.cs
+++ b/app/MindWork AI Studio/Components/AssistantBlock.razor.cs
@@ -43,6 +43,9 @@ public partial class AssistantBlock : MSGComponentBase where TSetting
[Parameter]
public RenderFragment? SecurityBadge { get; set; }
+ [Parameter]
+ public RenderFragment? AdditionalActions { get; set; }
+
[Parameter]
public Tools.Components Component { get; set; } = Tools.Components.NONE;
diff --git a/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor b/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor
new file mode 100644
index 00000000..777b94d5
--- /dev/null
+++ b/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor
@@ -0,0 +1,13 @@
+@inherits MSGComponentBase
+
+@if (this.CanDelete)
+{
+
+
+
+}
\ No newline at end of file
diff --git a/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor.cs b/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor.cs
new file mode 100644
index 00000000..cd474c2c
--- /dev/null
+++ b/app/MindWork AI Studio/Components/AssistantPluginDeleteAction.razor.cs
@@ -0,0 +1,90 @@
+using AIStudio.Dialogs;
+using AIStudio.Tools.Media;
+using AIStudio.Tools.PluginSystem;
+using AIStudio.Tools.Services;
+using Microsoft.AspNetCore.Components;
+using DialogOptions = AIStudio.Dialogs.DialogOptions;
+
+namespace AIStudio.Components;
+
+public partial class AssistantPluginDeleteAction : MSGComponentBase
+{
+ [Parameter, EditorRequired]
+ public IAvailablePlugin Plugin { get; set; } = null!;
+
+ [Inject]
+ private IDialogService DialogService { get; init; } = null!;
+
+ [Inject]
+ private AssistantPluginInstallService AssistantPluginInstallService { get; init; } = null!;
+
+ [Inject]
+ private MediaTranscriptionService MediaTranscriptionService { get; init; } = null!;
+
+ [Inject]
+ private ILogger Logger { get; init; } = null!;
+
+ private bool CanDelete => AssistantPluginInstallService.CanDeleteInstalledAssistant(this.Plugin);
+
+ private bool IsBlockedByActiveWork => this.AssistantPluginInstallService.HasActiveAssistantWork(this.Plugin.Id);
+
+ private string Tooltip => this.IsBlockedByActiveWork
+ ? this.T("The assistant cannot be deleted while background work is still running.")
+ : this.T("Delete assistant plugin");
+
+ protected override async Task OnInitializedAsync()
+ {
+ this.ApplyFilters([], [ Event.ASSISTANT_SESSION_CHANGED, Event.ASSISTANT_SESSION_FINISHED ]);
+ this.MediaTranscriptionService.StateChanged += this.OnMediaTranscriptionStateChanged;
+ await base.OnInitializedAsync();
+ }
+
+ private async Task DeleteAssistantPluginAsync()
+ {
+ if (!this.CanDelete || this.IsBlockedByActiveWork)
+ return;
+
+ var dialogParameters = new DialogParameters
+ {
+ {
+ x => x.Message,
+ string.Format(this.T("Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."), this.Plugin.Name)
+ },
+ };
+
+ var dialogReference = await this.DialogService.ShowAsync(this.T("Delete Assistant Plugin"), dialogParameters, DialogOptions.FULLSCREEN);
+ var dialogResult = await dialogReference.Result;
+ if (dialogResult is null || dialogResult.Canceled)
+ return;
+
+ var result = await this.AssistantPluginInstallService.DeleteInstalledAssistantAsync(this.Plugin, CancellationToken.None);
+ if (!result.Success)
+ {
+ this.Logger.LogError("Failed to delete assistant plugin '{PluginName}' ({PluginId}) from '{PluginDirectory}' with issue '{Issue}'.", result.PluginName, result.PluginId, result.PluginDirectory, result.Issue);
+ await this.MessageBus.SendError(new(Icons.Material.Filled.DeleteForever, string.Format(this.T("The assistant plugin '{0}' could not be deleted: {1}"), this.Plugin.Name, result.Issue)));
+ return;
+ }
+
+ await this.MessageBus.SendSuccess(new(Icons.Material.Filled.Check, string.Format(this.T("The '{0}' assistant plugin has been successfully removed."), result.PluginName)));
+ }
+
+ private void OnMediaTranscriptionStateChanged(MediaImportOwner owner)
+ {
+ if (owner.Kind is MediaImportOwnerKind.ASSISTANT && owner.Id.EndsWith($":{this.Plugin.Id}", StringComparison.Ordinal))
+ _ = this.InvokeAsync(this.StateHasChanged);
+ }
+
+ protected override Task ProcessIncomingMessage(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
+ {
+ if (triggeredEvent is Event.ASSISTANT_SESSION_CHANGED or Event.ASSISTANT_SESSION_FINISHED)
+ this.StateHasChanged();
+
+ return base.ProcessIncomingMessage(sendingComponent, triggeredEvent, data);
+ }
+
+ protected override void DisposeResources()
+ {
+ this.MediaTranscriptionService.StateChanged -= this.OnMediaTranscriptionStateChanged;
+ base.DisposeResources();
+ }
+}
diff --git a/app/MindWork AI Studio/Pages/Assistants.razor b/app/MindWork AI Studio/Pages/Assistants.razor
index 6b66071e..ee5d5c16 100644
--- a/app/MindWork AI Studio/Pages/Assistants.razor
+++ b/app/MindWork AI Studio/Pages/Assistants.razor
@@ -1,6 +1,7 @@
@attribute [Route(Routes.ASSISTANTS)]
@using AIStudio.Dialogs.Settings
@using AIStudio.Settings.DataModel
+@using AIStudio.Tools.PluginSystem
@using AIStudio.Tools.PluginSystem.Assistants
@inherits MSGComponentBase
@@ -45,6 +46,7 @@
{
var securityState = PluginAssistantSecurityResolver.Resolve(this.SettingsManager, assistantPlugin);
var launchLink = assistantPlugin.StartsChatDirectly ? string.Empty : $"{Routes.ASSISTANT_DYNAMIC}?assistantId={assistantPlugin.Id}";
+ var availablePlugin = PluginFactory.AvailablePlugins.OfType().FirstOrDefault(plugin => plugin.Id == assistantPlugin.Id);
+
+ @if (availablePlugin is not null)
+ {
+
+ }
+
diff --git a/app/MindWork AI Studio/Pages/Plugins.razor b/app/MindWork AI Studio/Pages/Plugins.razor
index 73a58e3c..eab51b12 100644
--- a/app/MindWork AI Studio/Pages/Plugins.razor
+++ b/app/MindWork AI Studio/Pages/Plugins.razor
@@ -115,11 +115,9 @@
}
- @if (context is IAvailablePlugin availablePlugin && CanDeleteAssistantPlugin(availablePlugin))
+ @if (context is IAvailablePlugin availablePlugin)
{
-
-
-
+
}
diff --git a/app/MindWork AI Studio/Pages/Plugins.razor.cs b/app/MindWork AI Studio/Pages/Plugins.razor.cs
index be7c2105..23bcb7da 100644
--- a/app/MindWork AI Studio/Pages/Plugins.razor.cs
+++ b/app/MindWork AI Studio/Pages/Plugins.razor.cs
@@ -28,9 +28,6 @@ public partial class Plugins : MSGComponentBase
[Inject]
private AssistantPluginAuditService AssistantPluginAuditService { get; init; } = null!;
- [Inject]
- private AssistantPluginInstallService AssistantPluginInstallService { get; init; } = null!;
-
private static readonly ILogger LOG = Program.LOGGER_FACTORY.CreateLogger(nameof(Plugins));
#region Overrides of ComponentBase
@@ -190,8 +187,6 @@ public partial class Plugins : MSGComponentBase
private static bool CanEditAssistantPlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath);
- private static bool CanDeleteAssistantPlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath);
-
private static bool CanReviseAssistantPlugin(IAvailablePlugin plugin)
{
var assistantPlugin = PluginFactory.RunningPlugins.OfType().FirstOrDefault(x => x.Id == plugin.Id);
@@ -239,33 +234,6 @@ public partial class Plugins : MSGComponentBase
await this.InvokeAsync(this.StateHasChanged);
}
- private async Task DeleteAssistantPluginAsync(IAvailablePlugin plugin)
- {
- var dialogParameters = new DialogParameters
- {
- {
- x => x.Message,
- string.Format(this.T("Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."), plugin.Name)
- },
- };
-
- var dialogReference = await this.DialogService.ShowAsync(this.T("Delete Assistant Plugin"), dialogParameters, DialogOptions.FULLSCREEN);
- var dialogResult = await dialogReference.Result;
- if (dialogResult is null || dialogResult.Canceled)
- return;
-
- var result = await this.AssistantPluginInstallService.DeleteInstalledAssistantAsync(plugin, CancellationToken.None);
- if (!result.Success)
- {
- LOG.LogError($"Failed to delete assistant plugin '{result.PluginName}' ({result.PluginId}) from '{result.PluginDirectory}' with issue '{result.Issue}'.");
- await this.MessageBus.SendError(new(Icons.Material.Filled.DeleteForever, string.Format(this.T("The assistant plugin '{0}' could not be deleted: {1}"), plugin.Name, result.Issue)));
- return;
- }
-
- await this.MessageBus.SendSuccess(new(Icons.Material.Filled.Check, string.Format(this.T("The '{0}' assistant plugin has been successfully removed."), result.PluginName)));
- await this.InvokeAsync(this.StateHasChanged);
- }
-
private static bool IsSendingMail(string sourceUrl) => sourceUrl.TrimStart().StartsWith("mailto:", StringComparison.OrdinalIgnoreCase);
private PluginAssistants? TryGetAssistantPlugin(Guid pluginId) => PluginFactory.RunningPlugins.OfType().FirstOrDefault(x => x.Id == pluginId);
diff --git a/app/MindWork AI Studio/Plugins/assistants/README.md b/app/MindWork AI Studio/Plugins/assistants/README.md
index f0b723f9..301a311d 100644
--- a/app/MindWork AI Studio/Plugins/assistants/README.md
+++ b/app/MindWork AI Studio/Plugins/assistants/README.md
@@ -82,6 +82,7 @@ Each assistant plugin lives in its own directory under the assistants plugin roo
## Structure
- `ASSISTANT` is the root table. It must contain `Title`, `Description`, `SystemPrompt`, `SubmitText`, `AllowProfiles`, and the nested `UI` definition.
- `DEPLOYED_USING_CONFIG_SERVER` identifies who manages the assistant plugin. Set it to `false` for locally managed plugins. A missing field is also treated as local for compatibility with existing plugins. Enterprise-distributed plugins must set it to `true` and cannot be revised with AI in AI Studio.
+- `AI_STUDIO_ASSISTANT_BUILDER = {Generated = true, SchemaVersion = 1}` is reserved for plugins generated by the AI Studio Assistant Builder. It enables Builder-specific actions such as safe deletion and must not be added to manually authored or enterprise-distributed assistants. Newly generated Builder assistants always set `DEPLOYED_USING_CONFIG_SERVER = false` explicitly.
- `ASSISTANT` may optionally define direct-launch metadata for assistant tiles:
- `LaunchBehavior = "OPEN_WORKSPACE_CHAT_BY_NAME"`
- `WorkspaceName = ""`
diff --git a/app/MindWork AI Studio/Plugins/assistants/plugin.lua b/app/MindWork AI Studio/Plugins/assistants/plugin.lua
index 50b72045..58b314ac 100644
--- a/app/MindWork AI Studio/Plugins/assistants/plugin.lua
+++ b/app/MindWork AI Studio/Plugins/assistants/plugin.lua
@@ -49,6 +49,11 @@ DEPRECATION_MESSAGE = ""
-- Enterprise-managed assistants cannot be revised with AI. Keep false for locally managed plugins:
DEPLOYED_USING_CONFIG_SERVER = false
+-- Reserved for assistants created by the AI Studio Assistant Builder. Generated assistants use this
+-- metadata so AI Studio can identify them and offer Builder-specific actions such as safe deletion.
+-- Manually authored or enterprise-distributed assistants must not set this metadata:
+-- AI_STUDIO_ASSISTANT_BUILDER = {Generated = true, SchemaVersion = 1}
+
ASSISTANT = {
["Title"] = "",
["Description"] = "",
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 2c6c1bab..cf755036 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
@@ -2391,6 +2391,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T3571008422"] = "Assisten
-- The result is ready.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T661906146"] = "Das Ergebnis ist fertig."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1318944584"] = "Der Assistent kann nicht gelöscht werden, solange noch Hintergrundaufgaben ausgeführt werden."
+
+-- Delete assistant plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1692493145"] = "Assistenten-Plugin löschen"
+
+-- Delete Assistant Plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3637071001"] = "Assistenten-Plugin löschen"
+
+-- The '{0}' assistant plugin has been successfully removed.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3815023384"] = "Das Assistenten-Plugin „{0}“ wurde erfolgreich entfernt."
+
+-- The assistant plugin '{0}' could not be deleted: {1}
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3985264168"] = "Das Assistenten-Plugin „{0}“ konnte nicht gelöscht werden: {1}"
+
+-- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T4033722845"] = "Möchtest du das Assistenten-Plug-in „{0}“ wirklich löschen? Dadurch werden die lokalen Plug-in-Dateien dauerhaft gelöscht."
+
-- Show or hide the detailed security information.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T1045105126"] = "Detaillierte Sicherheitsinformationen anzeigen oder ausblenden."
@@ -7284,9 +7302,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1506922856"] = "Assistentenprüfung"
-- Internal Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Interne Plugins"
--- Delete assistant plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1692493145"] = "Assistenten-Plugin löschen"
-
-- Disabled Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Deaktivierte Plugins"
@@ -7320,24 +7335,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3143506997"] = "Das Assistent-Plugin
-- Close
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3448155331"] = "Schließen"
--- Delete Assistant Plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3637071001"] = "Assistant-Plug-in löschen"
-
-- Revise assistant plugin with AI
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3801095542"] = "Assistenten-Plugin mit KI überarbeiten"
--- The '{0}' assistant plugin has been successfully removed.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3815023384"] = "Das Assistenten-Plugin „{0}“ wurde erfolgreich entfernt."
-
-- Actions
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Aktionen"
--- The assistant plugin '{0}' could not be deleted: {1}
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3985264168"] = "Das Assistenten-Plugin „{0}“ konnte nicht gelöscht werden: {1}"
-
--- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4033722845"] = "Möchten Sie das Assistenten-Plugin „{0}“ wirklich löschen? Dadurch werden die lokalen Plugin-Dateien dauerhaft gelöscht."
-
-- The automatic security audit for the assistant plugin '{0}' failed. Please run it manually.
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4066679817"] = "Die automatische Sicherheitsprüfung für das Assistenten-Plugin „{0}“ ist fehlgeschlagen. Bitte führen Sie sie manuell aus."
@@ -8748,42 +8751,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T378481461"] = "Source Code
-- Document
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T4165204724"] = "Dokument"
--- The configured transcription provider could not be created.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1235984176"] = "Der konfigurierte Transkriptionsanbieter konnte nicht erstellt werden."
-
--- The selected media file no longer exists.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T129859547"] = "Die ausgewählte Mediendatei ist nicht mehr vorhanden."
-
--- The selected media file does not contain an audio track.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T134825479"] = "Die ausgewählte Mediendatei enthält keine Audiospur."
-
--- The media file could not be transcribed.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1543974632"] = "Die Mediendatei konnte nicht transkribiert werden."
-
--- The selected file cannot be processed as media.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1707342767"] = "Die ausgewählte Datei kann nicht als Medium verarbeitet werden."
-
--- The audio track contains no audible signal, so there is nothing to transcribe.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1988190152"] = "Die Audiospur enthält kein hörbares Signal. Daher gibt es nichts zu transkribieren."
-
--- The media file is damaged or its format could not be identified.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2004316549"] = "Die Mediendatei ist beschädigt oder ihr Format konnte nicht erkannt werden."
-
--- This media format or audio codec is not supported.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2142564510"] = "Dieses Medienformat oder dieser Audiocodec wird nicht unterstützt."
-
--- No usable transcription provider is configured.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2282521655"] = "Es ist kein nutzbarer Transkriptionsanbieter konfiguriert."
-
--- The media file could not be prepared for transcription.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2749117459"] = "Die Mediendatei konnte nicht für die Transkription vorbereitet werden."
-
--- The transcription provider could not transcribe the media file.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T3091669215"] = "Der Transkriptionsanbieter konnte die Mediendatei nicht transkribieren."
-
--- The media pipeline ended without an output file.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T632852430"] = "Die Medienpipeline wurde beendet, ohne eine Ausgabedatei zu erzeugen."
-
-- The Assistant Builder context could not be loaded.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T108292972"] = "Der Kontext des Assistenten-Builders konnte nicht geladen werden."
@@ -8895,6 +8862,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1211
-- Only assistant plugins can be edited.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1288328479"] = "Nur Assistant-Plugins können bearbeitet werden."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1318944584"] = "Der Assistent kann nicht gelöscht werden, solange noch Hintergrundaktivitäten ausgeführt werden."
+
-- No Lua plugin code was generated.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1839013358"] = "Es wurde kein Lua-Plugin-Code generiert."
@@ -8925,6 +8895,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T2955
-- The generated assistant plugin uses the ID of an internal AI Studio plugin.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3162363526"] = "Das generierte Assistent-Plugin verwendet die ID eines internen AI-Studio-Plugins."
+-- Config Server managed assistant plugins cannot be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3751820312"] = "Von einem Config-Server verwaltete Assistenten-Plugins können nicht gelöscht werden."
+
+-- Only assistants generated by the Assistant Builder can be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3940247198"] = "Nur mit dem Assistant Builder erstellte Assistenten können gelöscht werden."
+
-- The edited plugin is not an assistant plugin. Issue: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3984111892"] = "Das bearbeitete Plugin ist kein Assistenten-Plugin. Problem: {0}"
@@ -8946,6 +8922,42 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T8163
-- The generated assistant plugin is invalid. Issue: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T939708112"] = "Das generierte Assistenten-Plugin ist ungültig. Problem: {0}"
+-- The configured transcription provider could not be created.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1235984176"] = "Der konfigurierte Transkriptionsanbieter konnte nicht erstellt werden."
+
+-- The selected media file no longer exists.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T129859547"] = "Die ausgewählte Mediendatei ist nicht mehr vorhanden."
+
+-- The selected media file does not contain an audio track.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T134825479"] = "Die ausgewählte Mediendatei enthält keine Audiospur."
+
+-- The media file could not be transcribed.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1543974632"] = "Die Mediendatei konnte nicht transkribiert werden."
+
+-- The selected file cannot be processed as media.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1707342767"] = "Die ausgewählte Datei kann nicht als Medium verarbeitet werden."
+
+-- The audio track contains no audible signal, so there is nothing to transcribe.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1988190152"] = "Die Audiospur enthält kein hörbares Signal. Daher gibt es nichts zu transkribieren."
+
+-- The media file is damaged or its format could not be identified.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2004316549"] = "Die Mediendatei ist beschädigt oder ihr Format konnte nicht erkannt werden."
+
+-- This media format or audio codec is not supported.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2142564510"] = "Dieses Medienformat oder dieser Audiocodec wird nicht unterstützt."
+
+-- No usable transcription provider is configured.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2282521655"] = "Es ist kein nutzbarer Transkriptionsanbieter konfiguriert."
+
+-- The media file could not be prepared for transcription.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2749117459"] = "Die Mediendatei konnte nicht für die Transkription vorbereitet werden."
+
+-- The transcription provider could not transcribe the media file.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T3091669215"] = "Der Transkriptionsanbieter konnte die Mediendatei nicht transkribieren."
+
+-- The media pipeline ended without an output file.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T632852430"] = "Die Medienpipeline wurde beendet, ohne eine Ausgabedatei zu erzeugen."
+
-- Pandoc Installation
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::PANDOCAVAILABILITYSERVICE::T185447014"] = "Pandoc-Installation"
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 d3a58f2b..c716b6fb 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
@@ -2391,6 +2391,24 @@ UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T3571008422"] = "Assistan
-- The result is ready.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T661906146"] = "The result is ready."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1318944584"] = "The assistant cannot be deleted while background work is still running."
+
+-- Delete assistant plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T1692493145"] = "Delete assistant plugin"
+
+-- Delete Assistant Plugin
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3637071001"] = "Delete Assistant Plugin"
+
+-- The '{0}' assistant plugin has been successfully removed.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3815023384"] = "The '{0}' assistant plugin has been successfully removed."
+
+-- The assistant plugin '{0}' could not be deleted: {1}
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T3985264168"] = "The assistant plugin '{0}' could not be deleted: {1}"
+
+-- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
+UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINDELETEACTION::T4033722845"] = "Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."
+
-- Show or hide the detailed security information.
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T1045105126"] = "Show or hide the detailed security information."
@@ -7284,9 +7302,6 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1506922856"] = "Assistant Audit"
-- Internal Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T158493184"] = "Internal Plugins"
--- Delete assistant plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1692493145"] = "Delete assistant plugin"
-
-- Disabled Plugins
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T1724138133"] = "Disabled Plugins"
@@ -7320,24 +7335,12 @@ UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3143506997"] = "The assistant plugin
-- Close
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3448155331"] = "Close"
--- Delete Assistant Plugin
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3637071001"] = "Delete Assistant Plugin"
-
-- Revise assistant plugin with AI
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3801095542"] = "Revise assistant plugin with AI"
--- The '{0}' assistant plugin has been successfully removed.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3815023384"] = "The '{0}' assistant plugin has been successfully removed."
-
-- Actions
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3865031940"] = "Actions"
--- The assistant plugin '{0}' could not be deleted: {1}
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T3985264168"] = "The assistant plugin '{0}' could not be deleted: {1}"
-
--- Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files.
-UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4033722845"] = "Do you really want to delete the assistant plugin '{0}'? This will permanently delete the local plugin files."
-
-- The automatic security audit for the assistant plugin '{0}' failed. Please run it manually.
UI_TEXT_CONTENT["AISTUDIO::PAGES::PLUGINS::T4066679817"] = "The automatic security audit for the assistant plugin '{0}' failed. Please run it manually."
@@ -8748,42 +8751,6 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T378481461"] = "Source like p
-- Document
UI_TEXT_CONTENT["AISTUDIO::TOOLS::RUST::FILETYPES::T4165204724"] = "Document"
--- The configured transcription provider could not be created.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1235984176"] = "The configured transcription provider could not be created."
-
--- The selected media file no longer exists.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T129859547"] = "The selected media file no longer exists."
-
--- The selected media file does not contain an audio track.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T134825479"] = "The selected media file does not contain an audio track."
-
--- The media file could not be transcribed.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1543974632"] = "The media file could not be transcribed."
-
--- The selected file cannot be processed as media.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1707342767"] = "The selected file cannot be processed as media."
-
--- The audio track contains no audible signal, so there is nothing to transcribe.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1988190152"] = "The audio track contains no audible signal, so there is nothing to transcribe."
-
--- The media file is damaged or its format could not be identified.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2004316549"] = "The media file is damaged or its format could not be identified."
-
--- This media format or audio codec is not supported.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2142564510"] = "This media format or audio codec is not supported."
-
--- No usable transcription provider is configured.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2282521655"] = "No usable transcription provider is configured."
-
--- The media file could not be prepared for transcription.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2749117459"] = "The media file could not be prepared for transcription."
-
--- The transcription provider could not transcribe the media file.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T3091669215"] = "The transcription provider could not transcribe the media file."
-
--- The media pipeline ended without an output file.
-UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T632852430"] = "The media pipeline ended without an output file."
-
-- The Assistant Builder context could not be loaded.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGINGENERATIONSERVICE::T108292972"] = "The Assistant Builder context could not be loaded."
@@ -8895,6 +8862,9 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1211
-- Only assistant plugins can be edited.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1288328479"] = "Only assistant plugins can be edited."
+-- The assistant cannot be deleted while background work is still running.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1318944584"] = "The assistant cannot be deleted while background work is still running."
+
-- No Lua plugin code was generated.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T1839013358"] = "No Lua plugin code was generated."
@@ -8925,6 +8895,12 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T2955
-- The generated assistant plugin uses the ID of an internal AI Studio plugin.
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3162363526"] = "The generated assistant plugin uses the ID of an internal AI Studio plugin."
+-- Config Server managed assistant plugins cannot be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3751820312"] = "Config Server managed assistant plugins cannot be deleted."
+
+-- Only assistants generated by the Assistant Builder can be deleted.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3940247198"] = "Only assistants generated by the Assistant Builder can be deleted."
+
-- The edited plugin is not an assistant plugin. Issue: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T3984111892"] = "The edited plugin is not an assistant plugin. Issue: {0}"
@@ -8946,6 +8922,42 @@ UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T8163
-- The generated assistant plugin is invalid. Issue: {0}
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::ASSISTANTPLUGININSTALLSERVICE::T939708112"] = "The generated assistant plugin is invalid. Issue: {0}"
+-- The configured transcription provider could not be created.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1235984176"] = "The configured transcription provider could not be created."
+
+-- The selected media file no longer exists.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T129859547"] = "The selected media file no longer exists."
+
+-- The selected media file does not contain an audio track.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T134825479"] = "The selected media file does not contain an audio track."
+
+-- The media file could not be transcribed.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1543974632"] = "The media file could not be transcribed."
+
+-- The selected file cannot be processed as media.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1707342767"] = "The selected file cannot be processed as media."
+
+-- The audio track contains no audible signal, so there is nothing to transcribe.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T1988190152"] = "The audio track contains no audible signal, so there is nothing to transcribe."
+
+-- The media file is damaged or its format could not be identified.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2004316549"] = "The media file is damaged or its format could not be identified."
+
+-- This media format or audio codec is not supported.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2142564510"] = "This media format or audio codec is not supported."
+
+-- No usable transcription provider is configured.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2282521655"] = "No usable transcription provider is configured."
+
+-- The media file could not be prepared for transcription.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T2749117459"] = "The media file could not be prepared for transcription."
+
+-- The transcription provider could not transcribe the media file.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T3091669215"] = "The transcription provider could not transcribe the media file."
+
+-- The media pipeline ended without an output file.
+UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::MEDIATRANSCRIPTIONSERVICE::T632852430"] = "The media pipeline ended without an output file."
+
-- Pandoc Installation
UI_TEXT_CONTENT["AISTUDIO::TOOLS::SERVICES::PANDOCAVAILABILITYSERVICE::T185447014"] = "Pandoc Installation"
diff --git a/app/MindWork AI Studio/Tools/PluginSystem/Assistants/PluginAssistants.cs b/app/MindWork AI Studio/Tools/PluginSystem/Assistants/PluginAssistants.cs
index b16910ac..9c610c85 100644
--- a/app/MindWork AI Studio/Tools/PluginSystem/Assistants/PluginAssistants.cs
+++ b/app/MindWork AI Studio/Tools/PluginSystem/Assistants/PluginAssistants.cs
@@ -37,6 +37,7 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
public bool HasEmbeddedProfileSelection { get; private set; }
public bool HasCustomPromptBuilder => this.buildPromptFunction is not null;
public bool IsAssistantBuilderGenerated { get; private set; }
+ public bool HasDeploymentManagementMetadata { get; private set; }
public bool IsManagedByConfigServer { get; private set; }
public AssistantPluginLaunchBehavior LaunchBehavior { get; private set; }
public string LaunchWorkspaceName { get; private set; } = string.Empty;
@@ -66,6 +67,7 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
message = string.Empty;
this.HasEmbeddedProfileSelection = false;
this.IsAssistantBuilderGenerated = false;
+ this.HasDeploymentManagementMetadata = false;
this.IsManagedByConfigServer = false;
this.buildPromptFunction = null;
this.LaunchBehavior = AssistantPluginLaunchBehavior.NONE;
@@ -169,7 +171,10 @@ public sealed class PluginAssistants(bool isInternal, LuaState state, PluginType
private void TryReadDeploymentMetadata()
{
if (this.State.Environment["DEPLOYED_USING_CONFIG_SERVER"].TryRead(out var deployedUsingConfigServer))
+ {
+ this.HasDeploymentManagementMetadata = true;
this.IsManagedByConfigServer = deployedUsingConfigServer;
+ }
}
private bool TryReadLaunchConfiguration(LuaTable assistantTable, out string message)
diff --git a/app/MindWork AI Studio/Tools/Services/AssistantPluginGenerationService.cs b/app/MindWork AI Studio/Tools/Services/AssistantPluginGenerationService.cs
index b0342356..f5df3303 100644
--- a/app/MindWork AI Studio/Tools/Services/AssistantPluginGenerationService.cs
+++ b/app/MindWork AI Studio/Tools/Services/AssistantPluginGenerationService.cs
@@ -115,7 +115,7 @@ public sealed class AssistantPluginGenerationService(ILogger logger;
private readonly SettingsManager settingsManager;
+ private readonly AssistantSessionService assistantSessionService;
+ private readonly MediaTranscriptionService mediaTranscriptionService;
private readonly SemaphoreSlim installSemaphore = new(1, 1);
private static AssistantPluginInstallResult Error(string issue) => new(false, Guid.Empty, string.Empty, string.Empty, false, issue);
@@ -34,13 +38,39 @@ public sealed class AssistantPluginInstallService
private static AssistantPluginUpdateResult UpdateError(IPluginMetadata plugin, string pluginDirectory, string issue) => new(false, plugin.Id, plugin.Name, pluginDirectory, issue);
- public AssistantPluginInstallService(ILogger logger, SettingsManager settingsManager)
+ public AssistantPluginInstallService(
+ ILogger logger,
+ SettingsManager settingsManager,
+ AssistantSessionService assistantSessionService,
+ MediaTranscriptionService mediaTranscriptionService)
{
this.logger = logger;
this.settingsManager = settingsManager;
+ this.assistantSessionService = assistantSessionService;
+ this.mediaTranscriptionService = mediaTranscriptionService;
this.logger.LogInformation("The assistant plugin install service has been initialized.");
}
+ ///
+ /// Checks whether a local plugin is an Assistant Builder generated assistant that users may delete.
+ ///
+ public static bool CanDeleteInstalledAssistant(IAvailablePlugin plugin) => string.IsNullOrWhiteSpace(GetAssistantDeletionEligibilityIssue(plugin));
+
+ ///
+ /// Checks whether an assistant still owns running or canceling background work.
+ ///
+ public bool HasActiveAssistantWork(Guid pluginId)
+ {
+ var instanceId = pluginId.ToString();
+ if (this.assistantSessionService.GetSnapshots().Any(snapshot => snapshot.IsActive && string.Equals(snapshot.Key.InstanceId, instanceId, StringComparison.Ordinal)))
+ return true;
+
+ var ownerIdSuffix = $":{instanceId}";
+ return this.mediaTranscriptionService.GetSnapshots().Any(snapshot =>
+ snapshot is { IsBusy: true, Owner.Kind: MediaImportOwnerKind.ASSISTANT } &&
+ snapshot.Owner.Id.EndsWith(ownerIdSuffix, StringComparison.Ordinal));
+ }
+
///
/// Checks whether generated Lua assistant plugin code can be loaded and installed.
/// The plugin is written to a temporary staging directory and validated through the
@@ -232,32 +262,28 @@ public sealed class AssistantPluginInstallService
///
public async Task DeleteInstalledAssistantAsync(IAvailablePlugin plugin, CancellationToken token)
{
- if (plugin.Type is not PluginType.ASSISTANT)
- return DeleteError(plugin, plugin.LocalPath, TB("Only assistant plugins can be deleted."));
+ var eligibilityIssue = GetAssistantDeletionEligibilityIssue(plugin);
+ if (!string.IsNullOrEmpty(eligibilityIssue))
+ return DeleteError(plugin, plugin.LocalPath, eligibilityIssue);
- if (plugin.IsInternal)
- return DeleteError(plugin, plugin.LocalPath, TB("Internal assistant plugins cannot be deleted."));
-
- if (string.IsNullOrWhiteSpace(plugin.LocalPath))
- return DeleteError(plugin, string.Empty, TB("The assistant plugin has no local directory."));
-
- if (!TryGetAssistantPluginsRoot(out var assistantPluginsRoot, out var rootIssue))
- return DeleteError(plugin, plugin.LocalPath, rootIssue);
-
- var pluginDirectory = plugin.LocalPath;
- if (!IsPathInsideDirectory(assistantPluginsRoot, pluginDirectory) || IsSameDirectory(assistantPluginsRoot, pluginDirectory))
- return DeleteError(plugin, pluginDirectory, TB("The assistant plugin directory is outside the local assistant plugin directory."));
-
- if (!Directory.Exists(pluginDirectory))
- return DeleteError(plugin, pluginDirectory, TB("The assistant plugin directory does not exist."));
+ if (this.HasActiveAssistantWork(plugin.Id))
+ return DeleteError(plugin, plugin.LocalPath, TB("The assistant cannot be deleted while background work is still running."));
await this.installSemaphore.WaitAsync(token);
+ var pluginDirectory = plugin.LocalPath;
var backupDirectory = string.Empty;
var wasEnabled = false;
var removedAudits = new List();
try
{
+ eligibilityIssue = GetAssistantDeletionEligibilityIssue(plugin);
+ if (!string.IsNullOrEmpty(eligibilityIssue))
+ return DeleteError(plugin, pluginDirectory, eligibilityIssue);
+
+ if (this.HasActiveAssistantWork(plugin.Id))
+ return DeleteError(plugin, pluginDirectory, TB("The assistant cannot be deleted while background work is still running."));
+
backupDirectory = CreateDeleteBackupDirectory(plugin);
Directory.CreateDirectory(Path.GetDirectoryName(backupDirectory)!);
Directory.Move(pluginDirectory, backupDirectory);
@@ -486,6 +512,41 @@ public sealed class AssistantPluginInstallService
return true;
}
+ private static string GetAssistantDeletionEligibilityIssue(IAvailablePlugin plugin)
+ {
+ if (plugin.Type is not PluginType.ASSISTANT)
+ return TB("Only assistant plugins can be deleted.");
+
+ if (plugin.IsInternal)
+ return TB("Internal assistant plugins cannot be deleted.");
+
+ if (plugin.IsManagedByConfigServer)
+ return TB("Config Server managed assistant plugins cannot be deleted.");
+
+ if (string.IsNullOrWhiteSpace(plugin.LocalPath))
+ return TB("The assistant plugin has no local directory.");
+
+ var assistantPlugin = PluginFactory.RunningPlugins
+ .OfType()
+ .FirstOrDefault(candidate => candidate.Id == plugin.Id && IsSameDirectory(candidate.PluginPath, plugin.LocalPath));
+
+ if (assistantPlugin is null || assistantPlugin.IsInternal || !assistantPlugin.IsAssistantBuilderGenerated)
+ return TB("Only assistants generated by the Assistant Builder can be deleted.");
+
+ if (assistantPlugin.IsManagedByConfigServer)
+ return TB("Config Server managed assistant plugins cannot be deleted.");
+
+ if (!TryGetAssistantPluginsRoot(out var assistantPluginsRoot, out var rootIssue))
+ return rootIssue;
+
+ if (!IsPathInsideDirectory(assistantPluginsRoot, plugin.LocalPath) || IsSameDirectory(assistantPluginsRoot, plugin.LocalPath))
+ return TB("The assistant plugin directory is outside the local assistant plugin directory.");
+
+ return Directory.Exists(plugin.LocalPath)
+ ? string.Empty
+ : TB("The assistant plugin directory does not exist.");
+ }
+
private void TryDeleteStagingDirectory(string stagingDirectory)
{
TryDeleteDirectory(stagingDirectory, "assistant plugin staging", this.logger);
@@ -645,4 +706,4 @@ public sealed class AssistantPluginInstallService
{
public static AssistantPluginValidationResult Failure(string issue) => new(false, string.Empty, null, issue);
}
-}
+}
\ No newline at end of file