mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-12 23:13:48 +00:00
Assistant Builder improvements (#851)
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Sync Flatpak repo (push) Blocked by required conditions
Build and Release / Collect Flatpak artifacts (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
b1459523d9
commit
88aab302a2
37 files changed
+4098
-482
No files matched your search
@@ -51,11 +51,17 @@
|
||||
<MudIconButton Variant="Variant.Text" Icon="@Icons.Material.Filled.Settings" Color="Color.Default" OnClick="@this.OpenSettingsDialog"/>
|
||||
}
|
||||
</MudButtonGroup>
|
||||
@if (this.SecurityBadge is not null)
|
||||
@if (this.SecurityBadge is not null || this.AdditionalActions is not null)
|
||||
{
|
||||
<MudElement>
|
||||
@this.SecurityBadge
|
||||
</MudElement>
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Spacing="1">
|
||||
@if (this.SecurityBadge is not null)
|
||||
{
|
||||
<MudElement>
|
||||
@this.SecurityBadge
|
||||
</MudElement>
|
||||
}
|
||||
@this.AdditionalActions
|
||||
</MudStack>
|
||||
}
|
||||
</MudStack>
|
||||
</MudCardActions>
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
<div class="code-editor @this.Class" style="@this.CodeEditorThemeStyle">
|
||||
<div @ref="this.lineNumbersElement" class="code-editor-line-numbers" aria-hidden="true"></div>
|
||||
<div @ref="this.editorElement" class="code-editor-input"></div>
|
||||
</div>
|
||||
@@ -0,0 +1,104 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public partial class CodeEditor : ComponentBase, IAsyncDisposable
|
||||
{
|
||||
private static readonly CodeEditorTheme DARK_CODE_EDITOR_THEME = new("#191a1c", "#bdbdbd", "#404040", "#85c46c", "#c9a26d", "#ed94c0", "#6c95eb", "#39cc9b", "#66c3cc");
|
||||
private static readonly CodeEditorTheme LIGHT_CODE_EDITOR_THEME = new("#fefcf6", "#383838", "#d8d8d8", "#248700", "#8c6c41", "#ab2f6b", "#0f54d6", "#00855f", "#0093a1");
|
||||
|
||||
[Inject]
|
||||
private IJSRuntime JsRuntime { get; set; } = null!;
|
||||
|
||||
[Inject]
|
||||
private global::AIStudio.Settings.SettingsManager SettingsManager { get; init; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public string Value { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public CodeEditorLanguage Language { get; set; } = CodeEditorLanguage.PLAIN_TEXT;
|
||||
|
||||
[Parameter]
|
||||
public string Class { get; set; } = string.Empty;
|
||||
|
||||
private readonly string editorId = $"code-editor-{Guid.NewGuid():N}";
|
||||
private const string CODE_EDITOR_MODULE = "./system/CodeEditor/code-editor.js?v=20260713-1";
|
||||
private ElementReference editorElement;
|
||||
private ElementReference lineNumbersElement;
|
||||
private IJSObjectReference? module;
|
||||
private string CodeEditorThemeStyle => this.GetCodeEditorThemeStyle();
|
||||
|
||||
protected override async Task OnAfterRenderAsync(bool firstRender)
|
||||
{
|
||||
if (!firstRender)
|
||||
return;
|
||||
|
||||
this.module = await this.JsRuntime.InvokeAsync<IJSObjectReference>("import", CODE_EDITOR_MODULE);
|
||||
await this.module.InvokeVoidAsync("init", this.editorId, this.editorElement, this.lineNumbersElement, this.Value, this.Language.ToString());
|
||||
}
|
||||
|
||||
public async ValueTask<string> GetCodeAsync()
|
||||
{
|
||||
if (this.module is null)
|
||||
return this.Value;
|
||||
|
||||
return await this.module.InvokeAsync<string>("getCode", this.editorId);
|
||||
}
|
||||
|
||||
public async ValueTask SetCodeAsync(string code)
|
||||
{
|
||||
this.Value = code;
|
||||
if (this.module is null)
|
||||
return;
|
||||
|
||||
await this.module.InvokeVoidAsync("setCode", this.editorId, code);
|
||||
}
|
||||
|
||||
private string GetCodeEditorThemeStyle()
|
||||
{
|
||||
var codeEditorTheme = this.SettingsManager.IsDarkMode ? DARK_CODE_EDITOR_THEME : LIGHT_CODE_EDITOR_THEME;
|
||||
|
||||
return
|
||||
$"--mw-code-editor-background: {codeEditorTheme.Background}; " +
|
||||
$"--mw-code-editor-foreground: {codeEditorTheme.Foreground}; " +
|
||||
$"--mw-code-editor-border: {codeEditorTheme.Border}; " +
|
||||
$"--mw-code-editor-comment: {codeEditorTheme.Comment}; " +
|
||||
$"--mw-code-editor-string: {codeEditorTheme.String}; " +
|
||||
$"--mw-code-editor-number: {codeEditorTheme.Number}; " +
|
||||
$"--mw-code-editor-keyword: {codeEditorTheme.Keyword}; " +
|
||||
$"--mw-code-editor-literal: {codeEditorTheme.Keyword}; " +
|
||||
$"--mw-code-editor-built-in: {codeEditorTheme.Function}; " +
|
||||
$"--mw-code-editor-constant: {codeEditorTheme.Constant}; " +
|
||||
$"--mw-code-editor-function: {codeEditorTheme.Function}; " +
|
||||
$"--mw-code-editor-property: {codeEditorTheme.Function}; " +
|
||||
$"--mw-code-editor-variable: {codeEditorTheme.Foreground};";
|
||||
}
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if (this.module is null)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await this.module.InvokeVoidAsync("destroy", this.editorId);
|
||||
await this.module.DisposeAsync();
|
||||
}
|
||||
catch (JSDisconnectedException)
|
||||
{
|
||||
// The circuit can already be gone while Blazor disposes the component.
|
||||
}
|
||||
}
|
||||
|
||||
private sealed record CodeEditorTheme(
|
||||
string Background,
|
||||
string Foreground,
|
||||
string Border,
|
||||
string Comment,
|
||||
string String,
|
||||
string Number,
|
||||
string Keyword,
|
||||
string Function,
|
||||
string Constant);
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace AIStudio.Components;
|
||||
|
||||
/// <summary>
|
||||
/// Selects the syntax highlighter used by <see cref="CodeEditor"/>.
|
||||
/// The enum value is passed to the JavaScript module as a string, so a new
|
||||
/// language must also be handled in <c>wwwroot/system/CodeEditor/code-editor.js</c>.
|
||||
/// </summary>
|
||||
public enum CodeEditorLanguage
|
||||
{
|
||||
PLAIN_TEXT,
|
||||
LUA,
|
||||
}
|
||||
Reference in new issue
Block a user