mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-08-11 17:32:11 +00:00
Add assistant plugin deletion with eligibility checks
This commit is contained in:
parent
cba505a632
commit
521b495fa9
@ -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}"
|
||||
|
||||
|
||||
@ -50,6 +50,7 @@
|
||||
{
|
||||
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" Color="Color.Default" OnClick="@this.OpenSettingsDialog"/>
|
||||
}
|
||||
@this.AdditionalActions
|
||||
</MudButtonGroup>
|
||||
@if (this.SecurityBadge is not null)
|
||||
{
|
||||
|
||||
@ -43,6 +43,9 @@ public partial class AssistantBlock<TSettings> : 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;
|
||||
|
||||
|
||||
@ -0,0 +1,13 @@
|
||||
@inherits MSGComponentBase
|
||||
|
||||
@if (this.CanDelete)
|
||||
{
|
||||
<MudTooltip Text="@this.Tooltip">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.DeleteOutline"
|
||||
Color="Color.Error"
|
||||
Variant="Variant.Text"
|
||||
Size="Size.Medium"
|
||||
Disabled="@this.IsBlockedByActiveWork"
|
||||
OnClick="@this.DeleteAssistantPluginAsync" />
|
||||
</MudTooltip>
|
||||
}
|
||||
@ -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<AssistantPluginDeleteAction> 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<ConfirmDialog>
|
||||
{
|
||||
{
|
||||
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<ConfirmDialog>(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<T>(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();
|
||||
}
|
||||
}
|
||||
@ -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<IAvailablePlugin>().FirstOrDefault(plugin => plugin.Id == assistantPlugin.Id);
|
||||
<AssistantBlock TSettings="NoSettingsPanel"
|
||||
Name="@T(assistantPlugin.AssistantTitle)"
|
||||
Description="@T(assistantPlugin.Description)"
|
||||
@ -53,6 +55,12 @@
|
||||
AssistantSessionInstanceId="@assistantPlugin.Id.ToString()"
|
||||
Link="@launchLink"
|
||||
OnClick="@(() => this.StartAssistantPluginAsync(assistantPlugin))">
|
||||
<AdditionalActions>
|
||||
@if (availablePlugin is not null)
|
||||
{
|
||||
<AssistantPluginDeleteAction Plugin="@availablePlugin" />
|
||||
}
|
||||
</AdditionalActions>
|
||||
<SecurityBadge>
|
||||
<AssistantPluginSecurityCard Plugin="@assistantPlugin" Compact="@true" />
|
||||
</SecurityBadge>
|
||||
|
||||
@ -115,11 +115,9 @@
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@if (context is IAvailablePlugin availablePlugin && CanDeleteAssistantPlugin(availablePlugin))
|
||||
@if (context is IAvailablePlugin availablePlugin)
|
||||
{
|
||||
<MudTooltip Text="@T("Delete assistant plugin")">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.DeleteOutline" Size="Size.Medium" OnClick="@(() => this.DeleteAssistantPluginAsync(availablePlugin))"/>
|
||||
</MudTooltip>
|
||||
<AssistantPluginDeleteAction Plugin="@availablePlugin" />
|
||||
}
|
||||
</MudButtonGroup>
|
||||
</MudStack>
|
||||
|
||||
@ -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<PluginAssistants>().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<ConfirmDialog>
|
||||
{
|
||||
{
|
||||
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<ConfirmDialog>(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<PluginAssistants>().FirstOrDefault(x => x.Id == pluginId);
|
||||
|
||||
@ -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 = "<target workspace name>"`
|
||||
|
||||
@ -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"] = "<Title of your assistant>",
|
||||
["Description"] = "<Description presented to the users, explaining your assistant>",
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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"
|
||||
|
||||
|
||||
@ -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<bool>(out var deployedUsingConfigServer))
|
||||
{
|
||||
this.HasDeploymentManagementMetadata = true;
|
||||
this.IsManagedByConfigServer = deployedUsingConfigServer;
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryReadLaunchConfiguration(LuaTable assistantTable, out string message)
|
||||
|
||||
@ -115,7 +115,7 @@ public sealed class AssistantPluginGenerationService(ILogger<AssistantPluginGene
|
||||
if (!generatedAssistant.IsAssistantBuilderGenerated)
|
||||
return InitialFailure(TB("The generated assistant plugin must include the Assistant Builder metadata."));
|
||||
|
||||
if (generatedAssistant.IsManagedByConfigServer)
|
||||
if (!generatedAssistant.HasDeploymentManagementMetadata || generatedAssistant.IsManagedByConfigServer)
|
||||
return InitialFailure(TB("The generated assistant plugin must be marked as locally managed."));
|
||||
|
||||
return new(true, fullLua, parsedResponse.Plugin?.Name ?? string.Empty, string.Empty);
|
||||
@ -168,7 +168,8 @@ public sealed class AssistantPluginGenerationService(ILogger<AssistantPluginGene
|
||||
if (plugin.IsAssistantBuilderGenerated && !revisedAssistant.IsAssistantBuilderGenerated)
|
||||
return RevisionFailure(TB("The revised assistant plugin must keep the Assistant Builder metadata."));
|
||||
|
||||
if (revisedAssistant.IsManagedByConfigServer)
|
||||
if (revisedAssistant.IsManagedByConfigServer ||
|
||||
plugin.IsAssistantBuilderGenerated && !revisedAssistant.HasDeploymentManagementMetadata)
|
||||
return RevisionFailure(TB("The revised assistant plugin must remain locally managed."));
|
||||
|
||||
return new(true, revisedLua, parsedResponse.Plugin?.Name ?? plugin.Name, string.Empty);
|
||||
@ -364,7 +365,7 @@ public sealed class AssistantPluginGenerationService(ILogger<AssistantPluginGene
|
||||
{
|
||||
var companionLua = FormatCompanionLuaFiles(plugin);
|
||||
var builderMetadataRule = plugin.IsAssistantBuilderGenerated
|
||||
? "- Keep AI_STUDIO_ASSISTANT_BUILDER = {Generated = true, SchemaVersion = 1}."
|
||||
? "- Keep AI_STUDIO_ASSISTANT_BUILDER = {Generated = true, SchemaVersion = 1} and set DEPLOYED_USING_CONFIG_SERVER = false explicitly."
|
||||
: string.Empty;
|
||||
return $$"""
|
||||
Revise an existing locally managed AI Studio Lua assistant plugin.
|
||||
|
||||
@ -1,5 +1,7 @@
|
||||
using System.Text;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.Media;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
|
||||
@ -24,6 +26,8 @@ public sealed class AssistantPluginInstallService
|
||||
|
||||
private readonly ILogger<AssistantPluginInstallService> 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<AssistantPluginInstallService> logger, SettingsManager settingsManager)
|
||||
public AssistantPluginInstallService(
|
||||
ILogger<AssistantPluginInstallService> 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.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether a local plugin is an Assistant Builder generated assistant that users may delete.
|
||||
/// </summary>
|
||||
public static bool CanDeleteInstalledAssistant(IAvailablePlugin plugin) => string.IsNullOrWhiteSpace(GetAssistantDeletionEligibilityIssue(plugin));
|
||||
|
||||
/// <summary>
|
||||
/// Checks whether an assistant still owns running or canceling background work.
|
||||
/// </summary>
|
||||
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));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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
|
||||
/// </returns>
|
||||
public async Task<AssistantPluginDeleteResult> 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<PluginAssistantAudit>();
|
||||
|
||||
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<PluginAssistants>()
|
||||
.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);
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user