mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-17 09:58:00 +00:00
Added direct-chat launchers for assistant plugins and a dialog to reconfigure them (#935)
Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
1 parent
f03c2d1c88
commit
a4c35fc2f2
44 files changed
+2615
-219
No files matched your search
@@ -40,6 +40,7 @@
|
||||
Link="@launchLink"
|
||||
OnClick="@(() => this.StartAssistantPluginAsync(assistantPlugin))">
|
||||
<AdditionalActions>
|
||||
<DirectChatLauncherSettingsAction Plugin="@assistantPlugin" />
|
||||
@if (availablePlugin is not null)
|
||||
{
|
||||
<PluginDeleteAction Plugin="@availablePlugin" />
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Agents.AssistantAudit;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.Services;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Pages;
|
||||
@@ -18,7 +18,7 @@ public partial class Assistants : MSGComponentBase
|
||||
private NavigationManager NavigationManager { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private ILogger<Assistants> Logger { get; init; } = null!;
|
||||
private DirectChatService DirectChatService { get; init; } = null!;
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
@@ -100,36 +100,15 @@ public partial class Assistants : MSGComponentBase
|
||||
return;
|
||||
}
|
||||
|
||||
var chatThread = await this.TryCreateDirectChatThreadAsync(assistantPlugin);
|
||||
if (chatThread is null)
|
||||
return;
|
||||
|
||||
MessageBus.INSTANCE.DeferMessage(this, Event.SEND_TO_CHAT, chatThread);
|
||||
this.NavigationManager.NavigateTo(Routes.CHAT);
|
||||
}
|
||||
|
||||
private async Task<ChatThread?> TryCreateDirectChatThreadAsync(PluginAssistants assistantPlugin)
|
||||
{
|
||||
var workspaceId = await WorkspaceBehaviour.ResolveOrCreateWorkspaceIdByNameAsync(assistantPlugin.LaunchWorkspaceName);
|
||||
if (workspaceId == Guid.Empty)
|
||||
var result = await this.DirectChatService.TryCreateAssistantChatAsync(assistantPlugin);
|
||||
if (result.Request is null)
|
||||
{
|
||||
this.Logger.LogWarning("Assistant plugin '{PluginName}' could not resolve or create workspace '{WorkspaceName}'.", assistantPlugin.Name, assistantPlugin.LaunchWorkspaceName);
|
||||
return null;
|
||||
await this.MessageBus.SendError(new(Icons.Material.Filled.ReportProblem, result.ErrorMessage));
|
||||
return;
|
||||
}
|
||||
|
||||
return new ChatThread
|
||||
{
|
||||
IncludeDateTime = true,
|
||||
SelectedProvider = string.Empty,
|
||||
SelectedProfile = string.Empty,
|
||||
SelectedChatTemplate = string.Empty,
|
||||
SystemPrompt = SystemPrompts.DEFAULT,
|
||||
WorkspaceId = workspaceId,
|
||||
ChatId = Guid.NewGuid(),
|
||||
Name = assistantPlugin.AssistantTitle,
|
||||
DataSourceOptions = this.SettingsManager.ConfigurationData.Chat.PreselectedDataSourceOptions.CreateCopy(),
|
||||
Blocks = [],
|
||||
};
|
||||
MessageBus.INSTANCE.DeferMessage(this, Event.SEND_TO_CHAT, result.Request);
|
||||
this.NavigationManager.NavigateTo(Routes.CHAT);
|
||||
}
|
||||
|
||||
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||
|
||||
@@ -132,10 +132,14 @@
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@* A direct chat launcher has nothing to prompt about: its settings are
|
||||
plain selections, so it gets the mechanical dialog instead of the AI
|
||||
revision. *@
|
||||
@if (context is IAvailablePlugin revisionPlugin && CanReviseAssistantPlugin(revisionPlugin))
|
||||
{
|
||||
<MudTooltip Text="@T("Revise assistant plugin with AI")">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.AutoMode" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginRevisionDialogAsync(revisionPlugin))"/>
|
||||
var isLauncher = IsDirectChatLauncher(revisionPlugin);
|
||||
<MudTooltip Text="@(isLauncher ? T("Change what this tile opens") : T("Revise assistant plugin with AI"))">
|
||||
<MudIconButton Icon="@(isLauncher ? Icons.Material.Filled.Tune : Icons.Material.Filled.AutoMode)" Size="Size.Medium" OnClick="@(() => this.OpenAssistantPluginRevisionDialogAsync(revisionPlugin))"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
|
||||
@@ -229,6 +229,15 @@ public partial class Plugins : MSGComponentBase
|
||||
//
|
||||
private static bool CanEditAssistantPlugin(IAvailablePlugin plugin) => plugin is { IsInternal: false, Type: PluginType.ASSISTANT } && !string.IsNullOrWhiteSpace(plugin.LocalPath);
|
||||
|
||||
/// <summary>
|
||||
/// Whether this plugin is a direct chat launcher whose settings can be changed without AI.
|
||||
/// </summary>
|
||||
private static bool IsDirectChatLauncher(IAvailablePlugin plugin)
|
||||
{
|
||||
var assistantPlugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>().FirstOrDefault(x => x.Id == plugin.Id);
|
||||
return assistantPlugin is not null && DirectChatLauncherLuaWriter.CanRewrite(assistantPlugin);
|
||||
}
|
||||
|
||||
private static bool CanReviseAssistantPlugin(IAvailablePlugin plugin)
|
||||
{
|
||||
var assistantPlugin = PluginFactory.RunningPlugins.OfType<PluginAssistants>().FirstOrDefault(x => x.Id == plugin.Id);
|
||||
@@ -298,6 +307,17 @@ public partial class Plugins : MSGComponentBase
|
||||
|
||||
private async Task OpenAssistantPluginRevisionDialogAsync(IAvailablePlugin plugin)
|
||||
{
|
||||
//
|
||||
// Changing a launcher means picking a different workspace, provider, profile, chat template,
|
||||
// or set of data sources. Prompting a model for that would be a detour, so launchers go to
|
||||
// the mechanical dialog instead:
|
||||
//
|
||||
if (IsDirectChatLauncher(plugin))
|
||||
{
|
||||
await this.OpenDirectChatLauncherSettingsDialogAsync(plugin);
|
||||
return;
|
||||
}
|
||||
|
||||
var parameters = new DialogParameters<AssistantPluginRevisionDialog>
|
||||
{
|
||||
{ x => x.PluginId, plugin.Id },
|
||||
@@ -318,6 +338,28 @@ public partial class Plugins : MSGComponentBase
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task OpenDirectChatLauncherSettingsDialogAsync(IAvailablePlugin plugin)
|
||||
{
|
||||
var parameters = new DialogParameters<DirectChatLauncherSettingsDialog>
|
||||
{
|
||||
{ x => x.PluginId, plugin.Id },
|
||||
{ x => x.PluginLocalPath, plugin.LocalPath },
|
||||
};
|
||||
|
||||
var dialogReference = await this.DialogService.ShowAsync<DirectChatLauncherSettingsDialog>(this.T("Tile Settings"), parameters, DialogOptions.BLOCKING_FULLSCREEN);
|
||||
var dialogResult = await dialogReference.Result;
|
||||
if (dialogResult is null || dialogResult.Canceled || dialogResult.Data is not DirectChatLauncherSettingsDialogResult result)
|
||||
return;
|
||||
|
||||
await this.MessageBus.SendSuccess(new(Icons.Material.Filled.Save, string.Format(this.T("The tile '{0}' has been updated."), result.PluginName)));
|
||||
LOG.LogInformation($"The chat launcher '{result.PluginName}' ({result.PluginId}) has been successfully updated.");
|
||||
|
||||
// Saving ran LoadAll, which already sent PLUGINS_RELOADED. We still announce the
|
||||
// configuration change: with automatic audits enabled, the dialog stored an audit result:
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
}
|
||||
|
||||
private async Task SharePluginAsync(IAvailablePlugin plugin)
|
||||
{
|
||||
if (this.isSharingPlugin)
|
||||
|
||||
Reference in new issue
Block a user