mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-20 10:17:59 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8aeeda5dca | ||
|
|
909fbe89bb | ||
|
|
ea0ead58f8 | ||
|
|
3e59f23193 | ||
|
|
05a7e44de4 | ||
|
|
77e7e044e3 | ||
|
|
6b7800b615 | ||
|
|
1ec86ec1a6 | ||
|
|
e08687a5ca | ||
|
|
ab0b855769 | ||
|
|
4cb49d9f27 | ||
|
|
2cea53d2a9 | ||
|
|
155c2d72f8 | ||
|
|
60febfec86 | ||
|
|
76dd08ee11 | ||
|
|
c1b92a05fc | ||
|
|
cac2373269 | ||
|
|
f3aa38e090 | ||
|
|
b3b8bf23dc | ||
|
|
a1c4618796 | ||
|
|
0f06b96943 | ||
|
|
d6bd0dc45b | ||
|
|
426f223a84 | ||
|
|
79892eb829 |
No files matched your search
@@ -0,0 +1,109 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
|
||||
// ReSharper disable MemberCanBePrivate.Global
|
||||
|
||||
namespace AIStudio.Agents;
|
||||
|
||||
public abstract class AgentBase(SettingsManager settingsManager, IJSRuntime jsRuntime, ThreadSafeRandom rng) : IAgent
|
||||
{
|
||||
protected SettingsManager SettingsManager { get; init; } = settingsManager;
|
||||
|
||||
protected IJSRuntime JsRuntime { get; init; } = jsRuntime;
|
||||
|
||||
protected ThreadSafeRandom RNG { get; init; } = rng;
|
||||
|
||||
/// <summary>
|
||||
/// Represents the type or category of this agent.
|
||||
/// </summary>
|
||||
protected abstract Type Type { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name of the agent.
|
||||
/// </summary>
|
||||
public abstract string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The agent's job description. Will be used for the system prompt.
|
||||
/// </summary>
|
||||
protected abstract string JobDescription { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Represents the system prompt provided for the agent.
|
||||
/// </summary>
|
||||
protected abstract string SystemPrompt(string additionalData);
|
||||
|
||||
#region Implementation of IAgent
|
||||
|
||||
public abstract AIStudio.Settings.Provider? ProviderSettings { get; set; }
|
||||
|
||||
public abstract Task<ChatThread> ProcessContext(ChatThread chatThread, IDictionary<string, string> additionalData);
|
||||
|
||||
public abstract Task<ContentBlock> ProcessInput(ContentBlock input, IDictionary<string, string> additionalData);
|
||||
|
||||
public abstract Task<bool> MadeDecision(ContentBlock input);
|
||||
|
||||
public abstract IReadOnlyCollection<ContentBlock> GetContext();
|
||||
|
||||
public abstract IReadOnlyCollection<ContentBlock> GetAnswers();
|
||||
|
||||
#endregion
|
||||
|
||||
protected ChatThread CreateChatThread(string systemPrompt) => new()
|
||||
{
|
||||
WorkspaceId = Guid.Empty,
|
||||
ChatId = Guid.NewGuid(),
|
||||
Name = string.Empty,
|
||||
Seed = this.RNG.Next(),
|
||||
SystemPrompt = systemPrompt,
|
||||
Blocks = [],
|
||||
};
|
||||
|
||||
protected DateTimeOffset AddUserRequest(ChatThread thread, string request)
|
||||
{
|
||||
var time = DateTimeOffset.Now;
|
||||
thread.Blocks.Add(new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.USER,
|
||||
Content = new ContentText
|
||||
{
|
||||
Text = request,
|
||||
},
|
||||
});
|
||||
|
||||
return time;
|
||||
}
|
||||
|
||||
protected async Task AddAIResponseAsync(ChatThread thread, DateTimeOffset time)
|
||||
{
|
||||
if(this.ProviderSettings is null)
|
||||
return;
|
||||
|
||||
var providerSettings = this.ProviderSettings.Value;
|
||||
var aiText = new ContentText
|
||||
{
|
||||
// We have to wait for the remote
|
||||
// for the content stream:
|
||||
InitialRemoteWait = true,
|
||||
};
|
||||
|
||||
var resultingContentBlock = new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.AI,
|
||||
Content = aiText,
|
||||
};
|
||||
|
||||
thread.Blocks.Add(resultingContentBlock);
|
||||
|
||||
// Use the selected provider to get the AI response.
|
||||
// By awaiting this line, we wait for the entire
|
||||
// content to be streamed.
|
||||
await aiText.CreateFromProviderAsync(providerSettings.CreateProvider(), this.JsRuntime, this.SettingsManager, providerSettings.Model, thread);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Agents;
|
||||
|
||||
public sealed class AgentTextContentCleaner(SettingsManager settingsManager, IJSRuntime jsRuntime, ThreadSafeRandom rng) : AgentBase(settingsManager, jsRuntime, rng)
|
||||
{
|
||||
private static readonly ContentBlock EMPTY_BLOCK = new()
|
||||
{
|
||||
Content = null,
|
||||
ContentType = ContentType.NONE,
|
||||
Role = ChatRole.AGENT,
|
||||
Time = DateTimeOffset.UtcNow,
|
||||
};
|
||||
|
||||
private readonly List<ContentBlock> context = new();
|
||||
private readonly List<ContentBlock> answers = new();
|
||||
|
||||
#region Overrides of AgentBase
|
||||
|
||||
public override Settings.Provider? ProviderSettings { get; set; }
|
||||
|
||||
protected override Type Type => Type.SYSTEM;
|
||||
|
||||
public override string Id => "Text Content Cleaner";
|
||||
|
||||
protected override string JobDescription =>
|
||||
"""
|
||||
You receive a Markdown document as input. Your goal is to identify the main content of the document
|
||||
and return it including Markdown formatting. Remove areas that do not belong to the main part of the
|
||||
document. For a blog article, return only the text of the article with its formatting. For a scientific
|
||||
paper, only the contents of the paper. Delete elements of navigation, advertisements, HTML artifacts,
|
||||
cookie banners, etc. If the content contains images, these images remain. The same applies to links.
|
||||
Ensure that links and images are present as valid Markdown:
|
||||
|
||||
- Syntax of links: [link text](URL)
|
||||
- Syntax of images: 
|
||||
|
||||
If you find relative links or images with relative paths, correct them to absolute paths. For this
|
||||
purpose, here is the source URL:
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt(string additionalData) => $"{this.JobDescription} `{additionalData}`.";
|
||||
|
||||
/// <inheritdoc />
|
||||
public override async Task<ChatThread> ProcessContext(ChatThread chatThread, IDictionary<string, string> additionalData)
|
||||
{
|
||||
// We process the last block of the chat thread. Then, we add the result
|
||||
// to the chat thread as the last block:
|
||||
var answer = await this.ProcessInput(chatThread.Blocks[^1], additionalData);
|
||||
chatThread.Blocks.Add(answer);
|
||||
|
||||
this.context.Clear();
|
||||
this.context.AddRange(chatThread.Blocks);
|
||||
|
||||
return chatThread;
|
||||
}
|
||||
|
||||
// <inheritdoc />
|
||||
public override async Task<ContentBlock> ProcessInput(ContentBlock input, IDictionary<string, string> additionalData)
|
||||
{
|
||||
if (input.Content is not ContentText text)
|
||||
return EMPTY_BLOCK;
|
||||
|
||||
if(text.InitialRemoteWait || text.IsStreaming)
|
||||
return EMPTY_BLOCK;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(text.Text))
|
||||
return EMPTY_BLOCK;
|
||||
|
||||
if(!additionalData.TryGetValue("sourceURL", out var sourceURL) || string.IsNullOrWhiteSpace(sourceURL))
|
||||
return EMPTY_BLOCK;
|
||||
|
||||
var thread = this.CreateChatThread(this.SystemPrompt(sourceURL));
|
||||
var time = this.AddUserRequest(thread, text.Text);
|
||||
await this.AddAIResponseAsync(thread, time);
|
||||
|
||||
var answer = thread.Blocks[^1];
|
||||
this.answers.Add(answer);
|
||||
return answer;
|
||||
}
|
||||
|
||||
// <inheritdoc />
|
||||
public override Task<bool> MadeDecision(ContentBlock input) => Task.FromResult(true);
|
||||
|
||||
// <inheritdoc />
|
||||
public override IReadOnlyCollection<ContentBlock> GetContext() => this.context;
|
||||
|
||||
// <inheritdoc />
|
||||
public override IReadOnlyCollection<ContentBlock> GetAnswers() => this.answers;
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
using AIStudio.Chat;
|
||||
|
||||
namespace AIStudio.Agents;
|
||||
|
||||
public interface IAgent
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name of the agent.
|
||||
/// </summary>
|
||||
public string Id { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The provider to use for this agent.
|
||||
/// </summary>
|
||||
public AIStudio.Settings.Provider? ProviderSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Processes a chat thread (i.e., context) and returns the updated thread.
|
||||
/// </summary>
|
||||
/// <param name="chatThread">The chat thread to process. The thread is the context for the agent.</param>
|
||||
/// <param name="additionalData">Additional data to use for processing the chat thread.</param>
|
||||
/// <returns>The updated chat thread. The last content block of the thread is the agent's response.</returns>
|
||||
public Task<ChatThread> ProcessContext(ChatThread chatThread, IDictionary<string, string> additionalData);
|
||||
|
||||
/// <summary>
|
||||
/// Processes the input content block and returns the agent's response.
|
||||
/// </summary>
|
||||
/// <param name="input">The content block to process. It represents the input.</param>
|
||||
/// <param name="additionalData">Additional data to use for processing the input.</param>
|
||||
/// <returns>The content block representing the agent's response.</returns>
|
||||
public Task<ContentBlock> ProcessInput(ContentBlock input, IDictionary<string, string> additionalData);
|
||||
|
||||
/// <summary>
|
||||
/// The agent makes a decision based on the input.
|
||||
/// </summary>
|
||||
/// <param name="input">The content block to process. Should be a question or a request.</param>
|
||||
/// <returns>
|
||||
/// True if a decision has been made based on the input, false otherwise.
|
||||
/// </returns>
|
||||
public Task<bool> MadeDecision(ContentBlock input);
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the context of the agent.
|
||||
/// </summary>
|
||||
/// <returns>The collection of content blocks representing the agent's context. This includes the user's and the other agent's messages.</returns>
|
||||
public IReadOnlyCollection<ContentBlock> GetContext();
|
||||
|
||||
/// <summary>
|
||||
/// Retrieves the answers from the agent's context.
|
||||
/// </summary>
|
||||
/// <returns>
|
||||
/// The collection of content blocks representing the answers provided by this agent.
|
||||
/// </returns>
|
||||
public IReadOnlyCollection<ContentBlock> GetAnswers();
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace AIStudio.Agents;
|
||||
|
||||
public enum Type
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents an unspecified agent type.
|
||||
/// </summary>
|
||||
UNSPECIFIED = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a conversational agent who produces human-like responses and feedback (depending on the context and its job description).
|
||||
/// For example, an expert agent for a specific domain. Answers might be detailed and informative.
|
||||
/// </summary>
|
||||
CONVERSATIONAL,
|
||||
|
||||
/// <summary>
|
||||
/// Represents a worker agent type who performs tasks and provides information or services (depending on the context and its job description).
|
||||
/// For example, a quality assurance agent who assesses the quality of a product or service. Answers might be short and concise.
|
||||
/// </summary>
|
||||
WORKER,
|
||||
|
||||
/// <summary>
|
||||
/// Represents the system agent type who processes the input and provides a specific response (depending on the context and its job description).
|
||||
/// For example, a HTML content agent who processes the arbitrary HTML content and provides a structured Markdown response. Answers might be structured and formatted.
|
||||
/// </summary>
|
||||
SYSTEM,
|
||||
}
|
||||
@@ -11,6 +11,7 @@ public enum ChatRole
|
||||
SYSTEM,
|
||||
USER,
|
||||
AI,
|
||||
AGENT,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -70,7 +70,7 @@ public sealed class ContentText : IContent
|
||||
// Notify the UI that the content has changed,
|
||||
// depending on the energy saving mode:
|
||||
var now = DateTimeOffset.Now;
|
||||
switch (settings.ConfigurationData.IsSavingEnergy)
|
||||
switch (settings.ConfigurationData.App.IsSavingEnergy)
|
||||
{
|
||||
// Energy saving mode is off. We notify the UI
|
||||
// as fast as possible -- no matter the odds:
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<link href="system/MudBlazor.Markdown/MudBlazor.Markdown.min.css" rel="stylesheet" />
|
||||
<link href="app.css" rel="stylesheet" />
|
||||
<HeadOutlet/>
|
||||
<script src="diff.js"></script>
|
||||
</head>
|
||||
|
||||
<body style="overflow: hidden;">
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
@using AIStudio.Chat
|
||||
@using AIStudio.Components.Pages
|
||||
@using AIStudio.Tools
|
||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||
@this.Title
|
||||
</MudText>
|
||||
@@ -15,25 +17,59 @@
|
||||
@this.Body
|
||||
}
|
||||
</MudForm>
|
||||
<Issues IssuesData="@this.inputIssues"/>
|
||||
|
||||
@if (this.inputIssues.Any())
|
||||
@if (this.ShowDedicatedProgress && this.isProcessing)
|
||||
{
|
||||
<MudPaper Class="pr-2 mt-3" Outlined="@true">
|
||||
<MudText Typo="Typo.h6">Issues</MudText>
|
||||
<MudList T="string">
|
||||
@foreach (var issue in this.inputIssues)
|
||||
{
|
||||
<MudListItem Icon="@Icons.Material.Filled.Error" IconColor="Color.Error">
|
||||
@issue
|
||||
</MudListItem>
|
||||
}
|
||||
</MudList>
|
||||
</MudPaper>
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
|
||||
}
|
||||
|
||||
@if (this.resultingContentBlock is not null)
|
||||
<div id="@ASSISTANT_RESULT_DIV_ID" class="mr-2 mt-3">
|
||||
@if (this.ShowResult && this.resultingContentBlock is not null)
|
||||
{
|
||||
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content"/>
|
||||
}
|
||||
</div>
|
||||
|
||||
<div id="@AFTER_RESULT_DIV_ID" class="mt-3">
|
||||
</div>
|
||||
|
||||
@if (this.FooterButtons.Count > 0)
|
||||
{
|
||||
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content" Class="mr-2"/>
|
||||
<MudStack Row="@true" Wrap="Wrap.Wrap" Class="mt-3 mr-2">
|
||||
@foreach (var button in this.FooterButtons)
|
||||
{
|
||||
switch (button)
|
||||
{
|
||||
case ButtonData buttonData when !string.IsNullOrWhiteSpace(buttonData.Tooltip):
|
||||
<MudTooltip Text="@buttonData.Tooltip">
|
||||
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
|
||||
@buttonData.Text
|
||||
</MudButton>
|
||||
</MudTooltip>
|
||||
break;
|
||||
|
||||
case ButtonData buttonData:
|
||||
<MudButton Variant="Variant.Filled" Color="@buttonData.Color" StartIcon="@GetButtonIcon(buttonData.Icon)" OnClick="async () => await buttonData.AsyncAction()">
|
||||
@buttonData.Text
|
||||
</MudButton>
|
||||
break;
|
||||
|
||||
case SendToButton sendToButton:
|
||||
<MudMenu StartIcon="@Icons.Material.Filled.Apps" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="Send to ..." Variant="Variant.Filled" Color="Color.Info">
|
||||
@foreach (var assistant in Enum.GetValues<SendToAssistant>().OrderBy(n => n.Name().Length))
|
||||
{
|
||||
if(assistant is Pages.SendToAssistant.NONE || sendToButton.Self == assistant)
|
||||
continue;
|
||||
|
||||
<MudMenuItem OnClick="() => this.SendToAssistant(assistant, sendToButton)">
|
||||
@assistant.Name()
|
||||
</MudMenuItem>
|
||||
}
|
||||
</MudMenu>
|
||||
break;
|
||||
}
|
||||
}
|
||||
</MudStack>
|
||||
}
|
||||
</ChildContent>
|
||||
</InnerScrolling>
|
||||
@@ -1,9 +1,13 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Components.Pages;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
using Path = AIStudio.Components.Pages.Path;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public abstract partial class AssistantBase : ComponentBase
|
||||
@@ -15,7 +19,19 @@ public abstract partial class AssistantBase : ComponentBase
|
||||
protected IJSRuntime JsRuntime { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected Random RNG { get; set; } = null!;
|
||||
protected ThreadSafeRandom RNG { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected ISnackbar Snackbar { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected Rust Rust { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected NavigationManager NavigationManager { get; init; } = null!;
|
||||
|
||||
internal const string AFTER_RESULT_DIV_ID = "afterAssistantResult";
|
||||
internal const string ASSISTANT_RESULT_DIV_ID = "assistantResult";
|
||||
|
||||
protected abstract string Title { get; }
|
||||
|
||||
@@ -25,6 +41,12 @@ public abstract partial class AssistantBase : ComponentBase
|
||||
|
||||
private protected virtual RenderFragment? Body => null;
|
||||
|
||||
protected virtual bool ShowResult => true;
|
||||
|
||||
protected virtual bool ShowDedicatedProgress => false;
|
||||
|
||||
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
|
||||
|
||||
protected static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
|
||||
protected AIStudio.Settings.Provider providerSettings;
|
||||
@@ -34,6 +56,7 @@ public abstract partial class AssistantBase : ComponentBase
|
||||
private ChatThread? chatThread;
|
||||
private ContentBlock? resultingContentBlock;
|
||||
private string[] inputIssues = [];
|
||||
private bool isProcessing;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
@@ -95,7 +118,7 @@ public abstract partial class AssistantBase : ComponentBase
|
||||
return time;
|
||||
}
|
||||
|
||||
protected async Task AddAIResponseAsync(DateTimeOffset time)
|
||||
protected async Task<string> AddAIResponseAsync(DateTimeOffset time)
|
||||
{
|
||||
var aiText = new ContentText
|
||||
{
|
||||
@@ -113,10 +136,61 @@ public abstract partial class AssistantBase : ComponentBase
|
||||
};
|
||||
|
||||
this.chatThread?.Blocks.Add(this.resultingContentBlock);
|
||||
this.isProcessing = true;
|
||||
this.StateHasChanged();
|
||||
|
||||
// Use the selected provider to get the AI response.
|
||||
// By awaiting this line, we wait for the entire
|
||||
// content to be streamed.
|
||||
await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.JsRuntime, this.SettingsManager, this.providerSettings.Model, this.chatThread);
|
||||
|
||||
this.isProcessing = false;
|
||||
this.StateHasChanged();
|
||||
|
||||
// Return the AI response:
|
||||
return aiText.Text;
|
||||
}
|
||||
|
||||
protected async Task CopyToClipboard(string text)
|
||||
{
|
||||
await this.Rust.CopyText2Clipboard(this.JsRuntime, this.Snackbar, text);
|
||||
}
|
||||
|
||||
private static string? GetButtonIcon(string icon)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(icon))
|
||||
return null;
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
private Task SendToAssistant(SendToAssistant assistant, SendToButton sendToButton)
|
||||
{
|
||||
var contentToSend = sendToButton.UseResultingContentBlockData switch
|
||||
{
|
||||
false => sendToButton.GetData(),
|
||||
true => this.resultingContentBlock?.Content switch
|
||||
{
|
||||
ContentText textBlock => textBlock.Text,
|
||||
_ => string.Empty,
|
||||
},
|
||||
};
|
||||
|
||||
var (eventItem, path) = assistant switch
|
||||
{
|
||||
Pages.SendToAssistant.AGENDA_ASSISTANT => (Event.SEND_TO_AGENDA_ASSISTANT, Path.ASSISTANT_AGENDA),
|
||||
Pages.SendToAssistant.CODING_ASSISTANT => (Event.SEND_TO_CODING_ASSISTANT, Path.ASSISTANT_CODING),
|
||||
Pages.SendToAssistant.REWRITE_ASSISTANT => (Event.SEND_TO_REWRITE_ASSISTANT, Path.ASSISTANT_REWRITE),
|
||||
Pages.SendToAssistant.TRANSLATION_ASSISTANT => (Event.SEND_TO_TRANSLATION_ASSISTANT, Path.ASSISTANT_TRANSLATION),
|
||||
Pages.SendToAssistant.ICON_FINDER_ASSISTANT => (Event.SEND_TO_ICON_FINDER_ASSISTANT, Path.ASSISTANT_ICON_FINDER),
|
||||
Pages.SendToAssistant.GRAMMAR_SPELLING_ASSISTANT => (Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT, Path.ASSISTANT_GRAMMAR_SPELLING),
|
||||
Pages.SendToAssistant.TEXT_SUMMARIZER_ASSISTANT => (Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Path.ASSISTANT_SUMMARIZER),
|
||||
|
||||
_ => (Event.NONE, Path.ASSISTANTS),
|
||||
};
|
||||
|
||||
MessageBus.INSTANCE.DeferMessage(this, eventItem, contentToSend);
|
||||
this.NavigationManager.NavigateTo(path);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,7 @@ using Microsoft.AspNetCore.Components.Rendering;
|
||||
namespace AIStudio.Components;
|
||||
|
||||
//
|
||||
// See https://stackoverflow.com/a/77300384/2258393 for why this class is needed
|
||||
// See https://stackoverflow.com/a/77300384/2258393 for why this class is necessary
|
||||
//
|
||||
|
||||
public abstract class AssistantBaseCore : AssistantBase
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
<MudItem xs="3">
|
||||
<MudCard Outlined="@true" Style="border-width: 2px; border-color: #0d47a1; border-radius: 12px; border-style: solid;">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudStack AlignItems="AlignItems.Center" Row="@true">
|
||||
<MudIcon Icon="@this.Icon" Size="Size.Large" Color="Color.Primary"/>
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.Name
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudStack>
|
||||
<MudText>
|
||||
@this.Description
|
||||
<MudCard Outlined="@true" Style="border-width: 2px; border-color: #0d47a1; border-radius: 12px; border-style: solid; max-width: 20em;">
|
||||
<MudCardHeader>
|
||||
<CardHeaderContent>
|
||||
<MudStack AlignItems="AlignItems.Center" Row="@true">
|
||||
<MudIcon Icon="@this.Icon" Size="Size.Large" Color="Color.Primary"/>
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.Name
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@this.Icon" Color="Color.Default" Href="@this.Link">
|
||||
@this.ButtonText
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
</MudItem>
|
||||
</CardHeaderContent>
|
||||
</MudCardHeader>
|
||||
<MudCardContent>
|
||||
<MudStack>
|
||||
<MudText>
|
||||
@this.Description
|
||||
</MudText>
|
||||
</MudStack>
|
||||
</MudCardContent>
|
||||
<MudCardActions>
|
||||
<MudButton Size="Size.Large" Variant="Variant.Filled" StartIcon="@this.Icon" Color="Color.Default" Href="@this.Link">
|
||||
@this.ButtonText
|
||||
</MudButton>
|
||||
</MudCardActions>
|
||||
</MudCard>
|
||||
@@ -13,6 +13,11 @@ public partial class Changelog
|
||||
|
||||
public static readonly Log[] LOGS =
|
||||
[
|
||||
new (171, "v0.8.9, build 171 (2024-08-18 10:35 UTC)", "v0.8.9.md"),
|
||||
new (170, "v0.8.8, build 170 (2024-08-14 06:30 UTC)", "v0.8.8.md"),
|
||||
new (169, "v0.8.7, build 169 (2024-08-01 19:08 UTC)", "v0.8.7.md"),
|
||||
new (168, "v0.8.6, build 168 (2024-08-01 19:50 UTC)", "v0.8.6.md"),
|
||||
new (167, "v0.8.5, build 167 (2024-07-28 16:44 UTC)", "v0.8.5.md"),
|
||||
new (166, "v0.8.4, build 166 (2024-07-26 06:53 UTC)", "v0.8.4.md"),
|
||||
new (165, "v0.8.3, build 165 (2024-07-25 13:25 UTC)", "v0.8.3.md"),
|
||||
new (164, "v0.8.2, build 164 (2024-07-16 18:03 UTC)", "v0.8.2.md"),
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
@inherits ConfigurationBase
|
||||
|
||||
<MudField Disabled="@this.Disabled()" Label="@this.OptionDescription" Variant="Variant.Outlined" HelperText="@this.OptionHelp" Class="@MARGIN_CLASS">
|
||||
<MudSwitch T="bool" Disabled="@this.Disabled()" Value="@this.State()" ValueChanged="@this.OptionChanged" Color="Color.Primary">
|
||||
@(this.State() ? this.LabelOn : this.LabelOff)
|
||||
</MudSwitch>
|
||||
</MudField>
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration component for any boolean option.
|
||||
@@ -0,0 +1 @@
|
||||
<ConfigurationSelect OptionDescription="Preselected provider" Disabled="@this.Disabled" OptionHelp="Select a provider that is preselected." Data="@this.Data" SelectedValue="@this.SelectedValue" SelectionUpdate="@this.SelectionUpdate"/>
|
||||
@@ -0,0 +1,83 @@
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ConfigurationProviderSelection : ComponentBase, IMessageBusReceiver, IDisposable
|
||||
{
|
||||
[Parameter]
|
||||
public Func<string> SelectedValue { get; set; } = () => string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public Action<string> SelectionUpdate { get; set; } = _ => { };
|
||||
|
||||
[Parameter]
|
||||
public IEnumerable<ConfigurationSelectData<string>> Data { get; set; } = new List<ConfigurationSelectData<string>>();
|
||||
|
||||
/// <summary>
|
||||
/// Is the selection component disabled?
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<bool> Disabled { get; set; } = () => false;
|
||||
|
||||
[Inject]
|
||||
private SettingsManager SettingsManager { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private MessageBus MessageBus { get; init; } = null!;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
// Register this component with the message bus:
|
||||
this.MessageBus.RegisterComponent(this);
|
||||
this.MessageBus.ApplyFilters(this, [], [ Event.CONFIGURATION_CHANGED ]);
|
||||
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IMessageBusReceiver
|
||||
|
||||
public async Task ProcessMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data)
|
||||
{
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.CONFIGURATION_CHANGED:
|
||||
|
||||
if(string.IsNullOrWhiteSpace(this.SelectedValue()))
|
||||
break;
|
||||
|
||||
// Check if the selected value is still valid:
|
||||
if (this.Data.All(x => x.Value != this.SelectedValue()))
|
||||
{
|
||||
this.SelectedValue = () => string.Empty;
|
||||
this.SelectionUpdate(string.Empty);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
}
|
||||
|
||||
this.StateHasChanged();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
|
||||
{
|
||||
return Task.FromResult<TResult?>(default);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.MessageBus.Unregister(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@inherits ConfigurationBase
|
||||
@typeparam T
|
||||
|
||||
<MudSelect T="T" Value="@this.SelectedValue()" Strict="@true" Disabled="@this.Disabled()" Margin="Margin.Dense" Label="@this.OptionDescription" Class="@GetClass" Variant="Variant.Outlined" HelperText="@this.OptionHelp" ValueChanged="@this.OptionChanged">
|
||||
@foreach (var data in this.Data)
|
||||
{
|
||||
<MudSelectItem Value="@data.Value">
|
||||
@data.Name
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
+3
-1
@@ -1,6 +1,8 @@
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
/// <summary>
|
||||
/// Configuration component for selecting a value from a list.
|
||||
@@ -0,0 +1,8 @@
|
||||
@typeparam T
|
||||
@inherits ConfigurationBase
|
||||
|
||||
<MudField Label="@this.OptionDescription" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.Disabled()">
|
||||
<MudSlider T="@T" Size="Size.Medium" Value="@this.Value()" ValueChanged="@this.OptionChanged" Min="@this.Min" Max="@this.Max" Step="@this.Step" Immediate="@true" Disabled="@this.Disabled()">
|
||||
@this.Value() @this.Unit
|
||||
</MudSlider>
|
||||
</MudField>
|
||||
@@ -0,0 +1,76 @@
|
||||
using System.Numerics;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ConfigurationSlider<T> : ConfigurationBase where T : struct, INumber<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The minimum value for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Min { get; set; } = T.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Max { get; set; } = T.One;
|
||||
|
||||
/// <summary>
|
||||
/// The step size for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Step { get; set; } = T.One;
|
||||
|
||||
/// <summary>
|
||||
/// The unit to display next to the slider's value.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Unit { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The value used for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<T> Value { get; set; } = () => T.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// An action which is called when the option is changed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Action<T> ValueUpdate { get; set; } = _ => { };
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await this.EnsureMinMax();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await this.EnsureMinMax();
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task OptionChanged(T updatedValue)
|
||||
{
|
||||
this.ValueUpdate(updatedValue);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.InformAboutChange();
|
||||
}
|
||||
|
||||
private async Task EnsureMinMax()
|
||||
{
|
||||
if (this.Value() < this.Min)
|
||||
await this.OptionChanged(this.Min);
|
||||
|
||||
else if(this.Value() > this.Max)
|
||||
await this.OptionChanged(this.Max);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
@inherits ConfigurationBase
|
||||
|
||||
<MudTextField
|
||||
T="string"
|
||||
Text="@this.Text()"
|
||||
TextChanged="@this.OptionChanged"
|
||||
Label="@this.OptionDescription"
|
||||
Disabled="@this.Disabled()"
|
||||
Class="mb-3"
|
||||
Adornment="Adornment.Start"
|
||||
AdornmentIcon="@this.Icon"
|
||||
AdornmentColor="@this.IconColor"
|
||||
UserAttributes="@SPELLCHECK_ATTRIBUTES"
|
||||
Lines="1"
|
||||
Immediate="@false"
|
||||
DebounceInterval="500"
|
||||
Variant="Variant.Outlined"
|
||||
/>
|
||||
@@ -0,0 +1,37 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ConfigurationText : ConfigurationBase
|
||||
{
|
||||
/// <summary>
|
||||
/// The text used for the textfield.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<string> Text { get; set; } = () => string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// An action which is called when the option is changed.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Action<string> TextUpdate { get; set; } = _ => { };
|
||||
|
||||
/// <summary>
|
||||
/// The icon to display next to the textfield.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Icon { get; set; } = Icons.Material.Filled.Info;
|
||||
|
||||
/// <summary>
|
||||
/// The color of the icon to use.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Color IconColor { get; set; } = Color.Default;
|
||||
|
||||
private async Task OptionChanged(string updatedText)
|
||||
{
|
||||
this.TextUpdate(updatedText);
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.InformAboutChange();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
@typeparam T
|
||||
@inherits EnumSelectionBase
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="@T" Value="@this.Value" ValueChanged="@this.SelectionChanged" AdornmentIcon="@this.Icon" Adornment="Adornment.Start" Label="@this.Label" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateSelection">
|
||||
@foreach (var value in Enum.GetValues<T>())
|
||||
{
|
||||
<MudSelectItem Value="@value">
|
||||
@this.NameFunc(value)
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.AllowOther && this.Value.Equals(this.OtherValue))
|
||||
{
|
||||
<MudTextField T="string" Text="@this.OtherInput" TextChanged="this.OtherInputChanged" Validation="@this.ValidateOther" Label="@this.LabelOther" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Immediate="@true"/>
|
||||
}
|
||||
</MudStack>
|
||||
@@ -0,0 +1,79 @@
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class EnumSelection<T> : EnumSelectionBase where T : struct, Enum
|
||||
{
|
||||
[Parameter]
|
||||
public T Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<T> ValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool AllowOther { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public T OtherValue { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string OtherInput { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> OtherInputChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string LabelOther { get; set; } = "Other";
|
||||
|
||||
[Parameter]
|
||||
public Func<T, string?> ValidateSelection { get; set; } = _ => null;
|
||||
|
||||
[Parameter]
|
||||
public Func<string, string?> ValidateOther { get; set; } = _ => null;
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; } = Icons.Material.Filled.ArrowDropDown;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the custom name function for selecting the display name of an enum value.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The enum type.</typeparam>
|
||||
/// <param name="value">The enum value.</param>
|
||||
/// <returns>The display name of the enum value.</returns>
|
||||
[Parameter]
|
||||
public Func<T, string> NameFunc { get; set; } = value => value.ToString();
|
||||
|
||||
[Parameter]
|
||||
public Func<T, Task> SelectionUpdated { get; set; } = _ => Task.CompletedTask;
|
||||
|
||||
[Inject]
|
||||
private SettingsManager SettingsManager { get; set; } = null!;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Configure the spellchecking for the user input:
|
||||
this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task SelectionChanged(T value)
|
||||
{
|
||||
await this.ValueChanged.InvokeAsync(value);
|
||||
await this.SelectionUpdated(value);
|
||||
}
|
||||
|
||||
private async Task OtherValueChanged(string value)
|
||||
{
|
||||
await this.OtherInputChanged.InvokeAsync(value);
|
||||
await this.SelectionUpdated(this.Value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public abstract class EnumSelectionBase : ComponentBase
|
||||
{
|
||||
protected static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
@if (this.IssuesData.Any())
|
||||
{
|
||||
<MudPaper Class="pa-3 mr-3 mt-3 border-dashed border rounded-lg mud-alert-outlined-error">
|
||||
<MudText Typo="Typo.h6">Issues</MudText>
|
||||
<MudList T="string">
|
||||
@foreach (var issue in this.IssuesData)
|
||||
{
|
||||
<MudListItem Icon="@Icons.Material.Filled.Error" IconColor="Color.Error">
|
||||
@issue
|
||||
</MudListItem>
|
||||
}
|
||||
</MudList>
|
||||
</MudPaper>
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class Issues : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public IEnumerable<string> IssuesData { get; set; } = [];
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
@typeparam T
|
||||
|
||||
<MudField Label="@this.Label" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.Disabled()">
|
||||
<MudSlider T="@T" Size="Size.Medium" Value="@this.Value" ValueChanged="@this.ValueUpdated" Min="@this.Min" Max="@this.Max" Step="@this.Step" Immediate="@true" Disabled="@this.Disabled()">
|
||||
@this.Value @this.Unit
|
||||
</MudSlider>
|
||||
</MudField>
|
||||
@@ -0,0 +1,78 @@
|
||||
using System.Numerics;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class MudTextSlider<T> : ComponentBase where T : struct, INumber<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// The minimum value for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Min { get; set; } = T.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Max { get; set; } = T.One;
|
||||
|
||||
/// <summary>
|
||||
/// The step size for the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public T Step { get; set; } = T.One;
|
||||
|
||||
/// <summary>
|
||||
/// The unit to display next to the slider's value.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Unit { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public T Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<T> ValueChanged { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The label to display above the slider.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public Func<bool> Disabled { get; set; } = () => false;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await this.EnsureMinMax();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
await this.EnsureMinMax();
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task EnsureMinMax()
|
||||
{
|
||||
if (this.Value < this.Min)
|
||||
await this.ValueUpdated(this.Min);
|
||||
|
||||
else if(this.Value > this.Max)
|
||||
await this.ValueUpdated(this.Max);
|
||||
}
|
||||
|
||||
private async Task ValueUpdated(T value)
|
||||
{
|
||||
this.Value = value;
|
||||
await this.ValueChanged.InvokeAsync(this.Value);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
<MudField Label="@this.Label" Variant="Variant.Outlined" Class="mb-3" Disabled="@this.Disabled">
|
||||
<MudSwitch T="bool" Value="@this.Value" ValueChanged="@this.ValueChanged" Color="@this.Color" Validation="@this.Validation" Disabled="@this.Disabled">
|
||||
@(this.Value ? this.LabelOn : this.LabelOff)
|
||||
</MudSwitch>
|
||||
</MudField>
|
||||
@@ -0,0 +1,30 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class MudTextSwitch : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public string Label { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public bool Disabled { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Value { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> ValueChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Color Color { get; set; } = Color.Primary;
|
||||
|
||||
[Parameter]
|
||||
public Func<bool, string?> Validation { get; set; } = _ => null;
|
||||
|
||||
[Parameter]
|
||||
public string LabelOn { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string LabelOff { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
@typeparam T
|
||||
|
||||
@if (this.ShowProgressAnimation)
|
||||
{
|
||||
<div class="pa-1">
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true"/>
|
||||
</div>
|
||||
}
|
||||
<div class="pa-6">
|
||||
<MudSlider T="int" Disabled="@true" Value="@this.StepValue" Min="@this.process.Min" Max="@this.process.Max" TickMarks="@true" Size="Size.Large" Variant="Variant.Filled" TickMarkLabels="@this.process.Labels" Class="mb-12"/>
|
||||
</div>
|
||||
@@ -0,0 +1,16 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ProcessComponent<T> : ComponentBase where T : struct, Enum
|
||||
{
|
||||
[Parameter]
|
||||
public bool ShowProgressAnimation { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public ProcessStepValue StepValue { get; set; }
|
||||
|
||||
private readonly Process<T> process = Process<T>.INSTANCE;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
@using AIStudio.Settings
|
||||
|
||||
<MudSelect T="Provider" Value="@this.ProviderSettings" ValueChanged="@this.SelectionChanged" Validation="@this.ValidateProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
@@ -0,0 +1,26 @@
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ProviderSelection : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public Settings.Provider ProviderSettings { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<Settings.Provider> ProviderSettingsChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<Settings.Provider, string?> ValidateProvider { get; set; } = _ => null;
|
||||
|
||||
[Inject]
|
||||
protected SettingsManager SettingsManager { get; set; } = null!;
|
||||
|
||||
private async Task SelectionChanged(Settings.Provider provider)
|
||||
{
|
||||
this.ProviderSettings = provider;
|
||||
await this.ProviderSettingsChanged.InvokeAsync(provider);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<MudTextSwitch Label="Read content from web?" Disabled="@this.AgentIsRunning" @bind-Value="@this.showWebContentReader" LabelOn="Show web content options" LabelOff="Hide web content options" />
|
||||
@if (this.showWebContentReader)
|
||||
{
|
||||
<MudTextSwitch Label="Cleanup content by using a LLM agent?" @bind-Value="@this.useContentCleanerAgent" Validation="@this.ValidateProvider" Disabled="@this.AgentIsRunning" LabelOn="The content is cleaned using an LLM agent: the main content is extracted, advertisements and other irrelevant things are attempted to be removed; relative links are attempted to be converted into absolute links so that they can be used." LabelOff="No content cleaning" />
|
||||
<MudStack Row="@true" AlignItems="@AlignItems.Baseline" Class="mb-3">
|
||||
<MudTextField T="string" Label="URL from which to load the content" @bind-Value="@this.providedURL" Validation="@this.ValidateURL" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Link" Placeholder="https://..." HelperText="Loads the content from your URL. Does not work when the content is hidden behind a paywall." Variant="Variant.Outlined" Immediate="@true" Disabled="@this.AgentIsRunning"/>
|
||||
<MudButton Disabled="@(!this.IsReady || this.AgentIsRunning)" Variant="Variant.Filled" Size="Size.Large" Color="Color.Primary" StartIcon="@Icons.Material.Filled.Download" OnClick="() => this.LoadFromWeb()">
|
||||
Fetch
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@if (this.AgentIsRunning)
|
||||
{
|
||||
<ProcessComponent T="ReadWebContentSteps" StepValue="@this.processStep" ShowProgressAnimation="@true"/>
|
||||
}
|
||||
}
|
||||
</MudPaper>
|
||||
@@ -0,0 +1,195 @@
|
||||
using AIStudio.Agents;
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class ReadWebContent : ComponentBase
|
||||
{
|
||||
[Inject]
|
||||
private HTMLParser HTMLParser { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private AgentTextContentCleaner AgentTextContentCleaner { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected SettingsManager SettingsManager { get; set; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public string Content { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<string> ContentChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Settings.Provider ProviderSettings { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool AgentIsRunning { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public EventCallback<bool> AgentIsRunningChanged { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool Preselect { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public bool PreselectContentCleanerAgent { get; set; }
|
||||
|
||||
private Process<ReadWebContentSteps> process = Process<ReadWebContentSteps>.INSTANCE;
|
||||
private ProcessStepValue processStep;
|
||||
|
||||
private bool showWebContentReader;
|
||||
private bool useContentCleanerAgent;
|
||||
private string providedURL = string.Empty;
|
||||
private bool urlIsValid;
|
||||
private bool isProviderValid;
|
||||
|
||||
private Settings.Provider providerSettings;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if(this.Preselect)
|
||||
this.showWebContentReader = true;
|
||||
|
||||
if(this.PreselectContentCleanerAgent)
|
||||
this.useContentCleanerAgent = true;
|
||||
|
||||
if (this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider);
|
||||
else
|
||||
this.providerSettings = this.ProviderSettings;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
{
|
||||
if (!this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)
|
||||
this.providerSettings = this.ProviderSettings;
|
||||
|
||||
await base.OnParametersSetAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private async Task LoadFromWeb()
|
||||
{
|
||||
if(!this.IsReady)
|
||||
return;
|
||||
|
||||
var markdown = string.Empty;
|
||||
try
|
||||
{
|
||||
this.processStep = this.process[ReadWebContentSteps.LOADING];
|
||||
this.StateHasChanged();
|
||||
|
||||
var html = await this.HTMLParser.LoadWebContentHTML(new Uri(this.providedURL));
|
||||
|
||||
this.processStep = this.process[ReadWebContentSteps.PARSING];
|
||||
this.StateHasChanged();
|
||||
markdown = this.HTMLParser.ParseToMarkdown(html);
|
||||
|
||||
if (this.useContentCleanerAgent)
|
||||
{
|
||||
this.AgentTextContentCleaner.ProviderSettings = this.providerSettings;
|
||||
var additionalData = new Dictionary<string, string>
|
||||
{
|
||||
{ "sourceURL", this.providedURL },
|
||||
};
|
||||
|
||||
this.processStep = this.process[ReadWebContentSteps.CLEANING];
|
||||
this.AgentIsRunning = true;
|
||||
await this.AgentIsRunningChanged.InvokeAsync(this.AgentIsRunning);
|
||||
this.StateHasChanged();
|
||||
|
||||
var contentBlock = await this.AgentTextContentCleaner.ProcessInput(new ContentBlock
|
||||
{
|
||||
Time = DateTimeOffset.UtcNow,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.USER,
|
||||
Content = new ContentText
|
||||
{
|
||||
Text = markdown,
|
||||
},
|
||||
}, additionalData);
|
||||
|
||||
markdown = contentBlock.Content is ContentText text ? text.Text : markdown;
|
||||
|
||||
this.processStep = this.process[ReadWebContentSteps.DONE];
|
||||
this.AgentIsRunning = false;
|
||||
await this.AgentIsRunningChanged.InvokeAsync(this.AgentIsRunning);
|
||||
this.StateHasChanged();
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
if (this.AgentIsRunning)
|
||||
{
|
||||
this.processStep = this.process[ReadWebContentSteps.START];
|
||||
this.AgentIsRunning = false;
|
||||
await this.AgentIsRunningChanged.InvokeAsync(this.AgentIsRunning);
|
||||
this.StateHasChanged();
|
||||
}
|
||||
}
|
||||
|
||||
this.Content = markdown;
|
||||
await this.ContentChanged.InvokeAsync(this.Content);
|
||||
}
|
||||
|
||||
private bool IsReady
|
||||
{
|
||||
get
|
||||
{
|
||||
if(!this.urlIsValid)
|
||||
return false;
|
||||
|
||||
if(this.useContentCleanerAgent && !this.isProviderValid)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
private string? ValidateProvider(bool shouldUseAgent)
|
||||
{
|
||||
if(shouldUseAgent && this.providerSettings == default)
|
||||
{
|
||||
this.isProviderValid = false;
|
||||
return "Please select a provider to use the cleanup agent.";
|
||||
}
|
||||
|
||||
this.isProviderValid = true;
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateURL(string url)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(url))
|
||||
{
|
||||
this.urlIsValid = false;
|
||||
return "Please provide a URL to load the content from.";
|
||||
}
|
||||
|
||||
var urlParsingResult = Uri.TryCreate(url, UriKind.Absolute, out var uriResult);
|
||||
if(!urlParsingResult)
|
||||
{
|
||||
this.urlIsValid = false;
|
||||
return "Please provide a valid URL.";
|
||||
}
|
||||
|
||||
if(uriResult is not { Scheme: "http" or "https" })
|
||||
{
|
||||
this.urlIsValid = false;
|
||||
return "Please provide a valid HTTP or HTTPS URL.";
|
||||
}
|
||||
|
||||
this.urlIsValid = true;
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public enum ReadWebContentSteps
|
||||
{
|
||||
START,
|
||||
LOADING,
|
||||
PARSING,
|
||||
CLEANING,
|
||||
DONE,
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
@typeparam T
|
||||
|
||||
<MudButtonGroup Color="@this.Color" Variant="Variant.Filled">
|
||||
@if (string.IsNullOrWhiteSpace(this.Icon))
|
||||
{
|
||||
<MudButton OnClick="() => this.OnClick(this.selectedValue)">
|
||||
@this.SelectedValueName()
|
||||
</MudButton>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudButton StartIcon="@this.Icon" OnClick="() => this.OnClick(this.selectedValue)">
|
||||
@this.SelectedValueName()
|
||||
</MudButton>
|
||||
}
|
||||
<MudMenu Icon="@Icons.Material.Filled.ArrowDropDown" Style="align-self: auto;">
|
||||
@foreach(var item in this.Items)
|
||||
{
|
||||
<MudMenuItem OnClick="() => this.SelectItem(item)">
|
||||
@this.NameFunc(item)
|
||||
</MudMenuItem>
|
||||
}
|
||||
</MudMenu>
|
||||
</MudButtonGroup>
|
||||
@@ -0,0 +1,64 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.Blocks;
|
||||
|
||||
public partial class SplitButton<T> : ComponentBase
|
||||
{
|
||||
[Parameter]
|
||||
public Color Color { get; set; } = Color.Default;
|
||||
|
||||
[Parameter]
|
||||
public string Icon { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public IReadOnlyCollection<T> Items { get; set; } = [];
|
||||
|
||||
[Parameter]
|
||||
public Func<T, string> NameFunc { get; set; } = _ => string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public T? PreselectedValue { get; set; }
|
||||
|
||||
[Parameter]
|
||||
public Func<T?, Task> OnClick { get; set; } = _ => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// What happens when the user selects an item by the dropdown?
|
||||
/// Immediate = true means that the OnClick event is triggered immediately
|
||||
/// after the user selects an item. Immediate = false means that the OnClick
|
||||
/// event is triggered only when the user clicks the button.
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public bool Immediate { get; set; }
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if(this.PreselectedValue is not null)
|
||||
this.selectedValue = this.PreselectedValue;
|
||||
else
|
||||
this.selectedValue = this.Items.FirstOrDefault();
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private T? selectedValue;
|
||||
|
||||
private string SelectedValueName()
|
||||
{
|
||||
if(this.selectedValue is null)
|
||||
return "Select...";
|
||||
|
||||
return this.NameFunc(this.selectedValue!);
|
||||
}
|
||||
|
||||
private void SelectItem(T item)
|
||||
{
|
||||
this.selectedValue = item;
|
||||
if(this.Immediate)
|
||||
this.OnClick(this.selectedValue);
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,13 @@ namespace AIStudio.Components.Blocks;
|
||||
public partial class Workspaces : ComponentBase
|
||||
{
|
||||
[Inject]
|
||||
private SettingsManager SettingsManager { get; set; } = null!;
|
||||
private SettingsManager SettingsManager { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
private IDialogService DialogService { get; set; } = null!;
|
||||
private IDialogService DialogService { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
public Random RNG { get; set; } = null!;
|
||||
private ThreadSafeRandom RNG { get; init; } = null!;
|
||||
|
||||
[Parameter]
|
||||
public ChatThread? CurrentChatThread { get; set; }
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<MudText Typo="Typo.body1">@this.Message</MudText>
|
||||
<MudTextField T="string" @bind-Text="@this.UserInput" Variant="Variant.Outlined" AutoGrow="@false" Lines="1" Label="Chat name" AutoFocus="@true"/>
|
||||
<MudTextField T="string" @bind-Text="@this.UserInput" Variant="Variant.Outlined" AutoGrow="@false" Lines="1" Label="Chat name" AutoFocus="@true" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
</DialogContent>
|
||||
<DialogActions>
|
||||
<MudButton OnClick="@this.Cancel" Variant="Variant.Filled">Cancel</MudButton>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using AIStudio.Settings;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components.CommonDialogs;
|
||||
@@ -18,6 +20,22 @@ public partial class SingleInputDialog : ComponentBase
|
||||
|
||||
[Parameter]
|
||||
public Color ConfirmColor { get; set; } = Color.Error;
|
||||
|
||||
[Inject]
|
||||
private SettingsManager SettingsManager { get; set; } = null!;
|
||||
|
||||
private static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Configure the spellchecking for the user input:
|
||||
this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES);
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void Cancel() => this.MudDialog.Cancel();
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<MudDialog>
|
||||
<DialogContent>
|
||||
<MudText Typo="Typo.body1">@this.Message</MudText>
|
||||
<MudList Clickable="@true" @bind-SelectedValue="@this.selectedWorkspace">
|
||||
<MudList T="Guid" @bind-SelectedValue="@this.selectedWorkspace">
|
||||
@foreach (var (workspaceName, workspaceId) in this.workspaces)
|
||||
{
|
||||
<MudListItem Text="@workspaceName" Icon="@Icons.Material.Filled.Description" Value="@workspaceId" />
|
||||
|
||||
@@ -21,7 +21,7 @@ public partial class WorkspaceSelectionDialog : ComponentBase
|
||||
public string ConfirmText { get; set; } = "OK";
|
||||
|
||||
private readonly Dictionary<string, Guid> workspaces = new();
|
||||
private object? selectedWorkspace;
|
||||
private Guid selectedWorkspace;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
@@ -56,5 +56,5 @@ public partial class WorkspaceSelectionDialog : ComponentBase
|
||||
|
||||
private void Cancel() => this.MudDialog.Cancel();
|
||||
|
||||
private void Confirm() => this.MudDialog.Close(DialogResult.Ok(this.selectedWorkspace is Guid workspaceId ? workspaceId : default));
|
||||
private void Confirm() => this.MudDialog.Close(DialogResult.Ok(this.selectedWorkspace));
|
||||
}
|
||||
@@ -8,7 +8,7 @@ namespace AIStudio.Components;
|
||||
/// <summary>
|
||||
/// A base class for configuration options.
|
||||
/// </summary>
|
||||
public partial class ConfigurationBase : ComponentBase
|
||||
public partial class ConfigurationBase : ComponentBase, IMessageBusReceiver, IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// The description of the option, i.e., the name. Should be
|
||||
@@ -23,6 +23,12 @@ public partial class ConfigurationBase : ComponentBase
|
||||
[Parameter]
|
||||
public string OptionHelp { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Is the option disabled?
|
||||
/// </summary>
|
||||
[Parameter]
|
||||
public Func<bool> Disabled { get; set; } = () => false;
|
||||
|
||||
[Inject]
|
||||
protected SettingsManager SettingsManager { get; init; } = null!;
|
||||
|
||||
@@ -30,6 +36,53 @@ public partial class ConfigurationBase : ComponentBase
|
||||
protected MessageBus MessageBus { get; init; } = null!;
|
||||
|
||||
protected const string MARGIN_CLASS = "mb-6";
|
||||
protected static readonly Dictionary<string, object?> SPELLCHECK_ATTRIBUTES = new();
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Configure the spellchecking for the instance name input:
|
||||
this.SettingsManager.InjectSpellchecking(SPELLCHECK_ATTRIBUTES);
|
||||
|
||||
// Register this component with the message bus:
|
||||
this.MessageBus.RegisterComponent(this);
|
||||
this.MessageBus.ApplyFilters(this, [], [ Event.CONFIGURATION_CHANGED ]);
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
protected async Task InformAboutChange() => await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
|
||||
#region Implementation of IMessageBusReceiver
|
||||
|
||||
public Task ProcessMessage<TMsg>(ComponentBase? sendingComponent, Event triggeredEvent, TMsg? data)
|
||||
{
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.CONFIGURATION_CHANGED:
|
||||
this.StateHasChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
|
||||
{
|
||||
return Task.FromResult<TResult?>(default);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.MessageBus.Unregister(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
@inherits ConfigurationBase
|
||||
|
||||
<MudField Label="@this.OptionDescription" Variant="Variant.Outlined" HelperText="@this.OptionHelp" Class="@MARGIN_CLASS">
|
||||
<MudSwitch T="bool" Value="@this.State()" ValueChanged="@(updatedState => this.OptionChanged(updatedState))">
|
||||
@(this.State() ? this.LabelOn : this.LabelOff)
|
||||
</MudSwitch>
|
||||
</MudField>
|
||||
@@ -1,11 +0,0 @@
|
||||
@inherits ConfigurationBase
|
||||
@typeparam T
|
||||
|
||||
<MudSelect T="T" Value="@this.SelectedValue()" Margin="Margin.Dense" Label="@this.OptionDescription" Class="@GetClass" Variant="Variant.Outlined" HelperText="@this.OptionHelp" ValueChanged="selectedValue => this.OptionChanged(selectedValue)">
|
||||
@foreach (var data in this.Data)
|
||||
{
|
||||
<MudSelectItem Value="@data.Value">
|
||||
@data.Name
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@@ -1,7 +0,0 @@
|
||||
@inherits ConfigurationBase
|
||||
|
||||
<MudField Label="@this.OptionDescription" Variant="Variant.Outlined" HelperText="@this.OptionHelp" Class="@MARGIN_CLASS">
|
||||
<MudButton Variant="Variant.Filled" StartIcon="@this.TriggerIcon" OnClick="@this.Click">
|
||||
@this.TriggerText
|
||||
</MudButton>
|
||||
</MudField>
|
||||
@@ -1,24 +0,0 @@
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
|
||||
public partial class ConfigurationTrigger : ConfigurationBase
|
||||
{
|
||||
[Parameter]
|
||||
public string TriggerText { get; set; } = string.Empty;
|
||||
|
||||
[Parameter]
|
||||
public string TriggerIcon { get; set; } = Icons.Material.Filled.AddBox;
|
||||
|
||||
[Parameter]
|
||||
public Action OnClickSync { get; set; } = () => { };
|
||||
|
||||
[Parameter]
|
||||
public Func<Task> OnClickAsync { get; set; } = () => Task.CompletedTask;
|
||||
|
||||
private async Task Click()
|
||||
{
|
||||
this.OnClickSync();
|
||||
await this.OnClickAsync();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Settings.DataModel
|
||||
@inherits LayoutComponentBase
|
||||
|
||||
<MudPaper Height="calc(100vh);" Elevation="0">
|
||||
@@ -6,11 +6,11 @@
|
||||
@if (!this.performingUpdate)
|
||||
{
|
||||
<MudDrawerContainer Class="mud-height-full absolute">
|
||||
<MudDrawer @bind-Open="@this.navBarOpen" MiniWidth="@NAVBAR_COLLAPSED_WIDTH" Width="@NAVBAR_EXPANDED_WIDTH" Elevation="1" Fixed="@true" Variant="@DrawerVariant.Mini" OpenMiniOnHover="@(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.EXPAND_ON_HOVER)" Color="Color.Default">
|
||||
<MudDrawer @bind-Open="@this.navBarOpen" MiniWidth="@NAVBAR_COLLAPSED_WIDTH" Width="@NAVBAR_EXPANDED_WIDTH" Elevation="1" Fixed="@true" Variant="@DrawerVariant.Mini" OpenMiniOnHover="@(this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.EXPAND_ON_HOVER)" Color="Color.Default">
|
||||
<MudNavMenu>
|
||||
@foreach (var navBarItem in NAV_ITEMS)
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.NEVER_EXPAND_USE_TOOLTIPS)
|
||||
if (this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.NEVER_EXPAND_USE_TOOLTIPS)
|
||||
{
|
||||
<MudTooltip Text="@navBarItem.Name" Placement="Placement.Right">
|
||||
<MudNavLink Href="@navBarItem.Path" Match="@(navBarItem.MatchAll ? NavLinkMatch.All : NavLinkMatch.Prefix)" Icon="@navBarItem.Icon" IconColor="@navBarItem.IconColor">@navBarItem.Name</MudNavLink>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using AIStudio.Components.CommonDialogs;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -9,7 +10,7 @@ using DialogOptions = AIStudio.Components.CommonDialogs.DialogOptions;
|
||||
|
||||
namespace AIStudio.Components.Layout;
|
||||
|
||||
public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver
|
||||
public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver, IDisposable
|
||||
{
|
||||
[Inject]
|
||||
private IJSRuntime JsRuntime { get; init; } = null!;
|
||||
@@ -50,12 +51,12 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver
|
||||
|
||||
private static readonly IReadOnlyCollection<NavBarItem> NAV_ITEMS = new List<NavBarItem>
|
||||
{
|
||||
new("Home", Icons.Material.Filled.Home, Color.Default, "/", true),
|
||||
new("Chat", Icons.Material.Filled.Chat, Color.Default, "/chat", false),
|
||||
new("Assistants", Icons.Material.Filled.Apps, Color.Default ,"/assistants", false),
|
||||
new("Supporters", Icons.Material.Filled.Favorite, Color.Error ,"/supporters", false),
|
||||
new("About", Icons.Material.Filled.Info, Color.Default ,"/about", false),
|
||||
new("Settings", Icons.Material.Filled.Settings, Color.Default ,"/settings", false),
|
||||
new("Home", Icons.Material.Filled.Home, Color.Default, Pages.Path.HOME, true),
|
||||
new("Chat", Icons.Material.Filled.Chat, Color.Default, Pages.Path.CHAT, false),
|
||||
new("Assistants", Icons.Material.Filled.Apps, Color.Default, Pages.Path.ASSISTANTS, false),
|
||||
new("Supporters", Icons.Material.Filled.Favorite, Color.Error, Pages.Path.SUPPORTERS, false),
|
||||
new("About", Icons.Material.Filled.Info, Color.Default, Pages.Path.ABOUT, false),
|
||||
new("Settings", Icons.Material.Filled.Settings, Color.Default, Pages.Path.SETTINGS, false),
|
||||
};
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
@@ -88,7 +89,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver
|
||||
TemporaryChatService.Initialize();
|
||||
|
||||
// Should the navigation bar be open by default?
|
||||
if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND)
|
||||
if(this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.ALWAYS_EXPAND)
|
||||
this.navBarOpen = true;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
@@ -120,7 +121,7 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver
|
||||
break;
|
||||
|
||||
case Event.CONFIGURATION_CHANGED:
|
||||
if(this.SettingsManager.ConfigurationData.NavigationBehavior is NavBehavior.ALWAYS_EXPAND)
|
||||
if(this.SettingsManager.ConfigurationData.App.NavigationBehavior is NavBehavior.ALWAYS_EXPAND)
|
||||
this.navBarOpen = true;
|
||||
else
|
||||
this.navBarOpen = false;
|
||||
@@ -211,4 +212,13 @@ public partial class MainLayout : LayoutComponentBase, IMessageBusReceiver
|
||||
await MessageBus.INSTANCE.SendMessage<bool>(this, Event.RESET_CHAT_STATE);
|
||||
}
|
||||
}
|
||||
|
||||
#region Implementation of IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.MessageBus.Unregister(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@page "/about"
|
||||
@attribute [Route(Path.ABOUT)]
|
||||
@using AIStudio.Tools
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-2">About MindWork AI Studio</MudText>
|
||||
@@ -9,7 +9,7 @@
|
||||
<MudText>
|
||||
The following list shows the versions of the MindWork AI Studio, the used compilers, build time, etc.:
|
||||
</MudText>
|
||||
<MudList T="string">
|
||||
<MudList T="string" Class="mb-3">
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Chat" Text="@VersionApp"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Timer" Text="@BuildTime"/>
|
||||
<MudListItem T="string" Icon="@Icons.Material.Outlined.Build" Text="@VersionDotnetSdk"/>
|
||||
@@ -47,6 +47,9 @@
|
||||
<ThirdPartyComponent Name="arboard" Developer="Artur Kovacs, Avi Weinstock, 1Password & Open Source Community" LicenseName="MIT & Apache-2.0" LicenseUrl="https://github.com/1Password/arboard" RepositoryUrl="https://github.com/1Password/arboard" UseCase="To be able to use the responses of the LLM in other apps, we often use the clipboard of the respective operating system. Unfortunately, in .NET there is no solution that works with all operating systems. Therefore, I have opted for this library in Rust. This way, data transfer to other apps works on every system."/>
|
||||
<ThirdPartyComponent Name="tokio" Developer="Alex Crichton & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/tokio-rs/tokio/blob/master/LICENSE" RepositoryUrl="https://github.com/tokio-rs/tokio" UseCase="Code in the Rust language can be specified as synchronous or asynchronous. Unlike .NET and the C# language, Rust cannot execute asynchronous code by itself. Rust requires support in the form of an executor for this. Tokio is one such executor."/>
|
||||
<ThirdPartyComponent Name="flexi_logger" Developer="emabee & Open Source Community" LicenseName="MIT & Apache-2.0" LicenseUrl="https://github.com/emabee/flexi_logger" RepositoryUrl="https://github.com/emabee/flexi_logger" UseCase="This Rust library is used to output the app's messages to the terminal. This is helpful during development and troubleshooting. This feature is initially invisible; when the app is started via the terminal, the messages become visible."/>
|
||||
<ThirdPartyComponent Name="HtmlAgilityPack" Developer="ZZZ Projects & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/zzzprojects/html-agility-pack/blob/master/LICENSE" RepositoryUrl="https://github.com/zzzprojects/html-agility-pack" UseCase="We use the HtmlAgilityPack to extract content from the web. This is necessary, e.g., when you provide a URL as input for an assistant."/>
|
||||
<ThirdPartyComponent Name="ReverseMarkdown" Developer="Babu Annamalai & Open Source Community" LicenseName="MIT" LicenseUrl="https://github.com/mysticmind/reversemarkdown-net/blob/master/LICENSE" RepositoryUrl="https://github.com/mysticmind/reversemarkdown-net" UseCase="This library is used to convert HTML to Markdown. This is necessary, e.g., when you provide a URL as input for an assistant."/>
|
||||
<ThirdPartyComponent Name="wikEd diff" Developer="Cacycle & Open Source Community" LicenseName="None (public domain)" LicenseUrl="https://en.wikipedia.org/wiki/User:Cacycle/diff#License" RepositoryUrl="https://en.wikipedia.org/wiki/User:Cacycle/diff" UseCase="This library is used to display the differences between two texts. This is necessary, e.g., for the grammar and spelling assistant."/>
|
||||
</MudGrid>
|
||||
</ExpansionPanel>
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Verified" HeaderText="License: FSL-1.1-MIT">
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
@attribute [Route(Path.ASSISTANT_AGENDA)]
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputName" Validation="@this.ValidateName" Label="Meeting Name" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Tag" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Name the meeting, seminar, etc." Placeholder="Weekly jour fixe" Class="mb-3"/>
|
||||
<MudTextField T="string" @bind-Text="@this.inputTopic" Validation="@this.ValidateTopic" Label="Topic" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.EventNote" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe the topic of the meeting, seminar, etc. Is it about quantum computing, software engineering, or is it a general business meeting?" Placeholder="Project meeting" Class="mb-3"/>
|
||||
<MudTextField T="string" @bind-Text="@this.inputContent" Validation="@this.ValidateContent" Label="Content list" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Bullet list the content of the meeting, seminar, etc. roughly. Use dashes (-) to separate the items." Placeholder="@PLACEHOLDER_CONTENT" Class="mb-3" Immediate="@false" DebounceInterval="1_000" OnDebounceIntervalElapsed="@this.OnContentChanged" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt"/>
|
||||
<MudSelect T="string" Label="(Optional) What topics should be the focus?" MultiSelection="@true" @bind-SelectedValues="@this.selectedFoci" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
|
||||
@foreach (var contentLine in this.contentLines)
|
||||
{
|
||||
@if(!this.justBriefly.Contains(contentLine))
|
||||
{
|
||||
<MudSelectItem T="string" Value="@contentLine">@contentLine</MudSelectItem>
|
||||
}
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudSelect T="string" Label="(Optional) What topics should only be briefly addressed?" MultiSelection="@true" @bind-SelectedValues="@this.justBriefly" Variant="Variant.Outlined" Class="mb-3" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.ListAlt">
|
||||
@foreach (var contentLine in this.contentLines)
|
||||
{
|
||||
@if(!this.selectedFoci.Contains(contentLine))
|
||||
{
|
||||
<MudSelectItem T="string" Value="@contentLine">@contentLine</MudSelectItem>
|
||||
}
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputObjective" Validation="@this.ValidateObjective" Label="Objective" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Flag" Variant="Variant.Outlined" Lines="3" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Describe the objective(s) of the meeting, seminar, etc. What should be achieved?" Placeholder="Discuss the current project status and plan the next steps." Class="mb-3"/>
|
||||
<MudTextField T="string" @bind-Text="@this.inputModerator" Validation="@this.ValidateModerator" Label="Moderator" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Person3" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Who will moderate the meeting, seminar, etc.?" Placeholder="Jane Doe" Class="mb-3" />
|
||||
<MudTextField T="string" @bind-Text="@this.inputDuration" Validation="@this.ValidateDuration" Label="Duration" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="How long will the meeting, seminar, etc. last? E.g., '2 hours', or '2 days (first day 8 hours, then 4 hours)', etc." Placeholder="2 hours" Class="mb-3"/>
|
||||
<MudTextField T="string" @bind-Text="@this.inputStartTime" Validation="@this.ValidateStartTime" Label="Start time" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Schedule" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="When will the meeting, seminar, etc. start? E.g., '9:00 AM', or '9:00 AM (CET)', etc. When the meeting is a multi-day event, specify the start time for each day." Placeholder="9:00 AM" Class="mb-3"/>
|
||||
<MudTextField T="string" @bind-Text="@this.inputWhoIsPresenting" Label="(Optional) Who is presenting?" Variant="Variant.Outlined" Lines="6" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="(Optional) List the persons who will present at the meeting, seminar, etc. Use dashes (-) to separate the items." Placeholder="@PLACEHOLDER_WHO_IS_PRESENTING" Class="mb-3"/>
|
||||
<MudTextSwitch Label="Do the participants need to get to know each other first?" @bind-Value="@this.introduceParticipants" LabelOn="Yes, introduce participants" LabelOff="No, participants know each other" />
|
||||
<EnumSelection T="NumberParticipants" @bind-Value="@this.numberParticipants" NameFunc="@(participants => participants.Name())" Icon="@Icons.Material.Filled.Group" Label="Number of participants" ValidateSelection="@this.ValidateNumberParticipants"/>
|
||||
<MudTextSwitch Label="Should the participants be involved passively or actively?" @bind-Value="@this.activeParticipation" LabelOn="Active participation, like world café, discussions, etc." LabelOff="Passive participation, like presentations, lectures, etc." />
|
||||
<MudTextSwitch Label="Is this a virtual event, e.g., a call or webinar?" @bind-Value="@this.isMeetingVirtual" LabelOn="Yes, this is a virtual event" LabelOff="No, this is a physical event" />
|
||||
@if (!this.isMeetingVirtual)
|
||||
{
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<MudTextField T="string" @bind-Text="@this.inputLocation" Validation="@this.ValidateLocation" Label="Location" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.MyLocation" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" HelperText="Where will the meeting, seminar, etc. take place?" Placeholder="Hamburg, Germany" Class="mb-3"/>
|
||||
<MudTextSwitch Label="Should there be a joint dinner?" @bind-Value="@this.goingToDinner" LabelOn="Yes, there should be a joint dinner" LabelOff="No, there should be no joint dinner" />
|
||||
<MudTextSwitch Label="Should there be a social activity?" @bind-Value="@this.doingSocialActivity" LabelOn="Yes, there should be a social activity" LabelOff="No, there should be no social activity" />
|
||||
<MudTextSwitch Label="Do participants need to arrive and depart?" @bind-Value="@this.needToArriveAndDepart" LabelOn="Yes, participants need to arrive and depart" LabelOff="No, participants do not need to arrive and depart" />
|
||||
<MudStack Row="@true" Wrap="Wrap.Wrap">
|
||||
<MudTextSlider T="int" Label="Approx. duration of the lunch break" @bind-Value="@this.durationLunchBreak" Min="30" Max="120" Step="5" Unit="minutes"/>
|
||||
<MudTextSlider T="int" Label="Approx. duration of the coffee or tea breaks" @bind-Value="@this.durationBreaks" Min="10" Max="60" Step="5" Unit="minutes"/>
|
||||
</MudStack>
|
||||
</MudPaper>
|
||||
}
|
||||
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidateTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.CreateAgenda()">
|
||||
Create agenda
|
||||
</MudButton>
|
||||
@@ -0,0 +1,464 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Agenda;
|
||||
|
||||
public partial class AssistantAgenda : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Agenda Planner";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
This agenda planner helps you create a structured agenda for your meeting or seminar. Just provide some basic
|
||||
information about the event, and the assistant will generate an agenda for you. You can also specify the
|
||||
duration, the start time, the location, the target language, and other details.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
$"""
|
||||
You are a friendly assistant who supports the planning and consultation of events. You receive
|
||||
metadata about an event and create an agenda from it. Additionally, you provide advice on what
|
||||
the organizer and moderator should consider. When creating the agenda, you take into account that
|
||||
time for questions and discussions needs to be scheduled. For large events, you take into account
|
||||
the logistical challenges that come with an increasing number of participants.
|
||||
|
||||
If the user is planning interactions with participants, you know various methods. For example:
|
||||
|
||||
- **Townhall Meeting**: An open assembly where participants can ask questions and provide feedback directly to leaders or speakers. Good moderation is necessary to queue contributions and hand the floor to the respective person. Additionally, one person should take notes visible to all. Ideally, this should not be the moderator.
|
||||
|
||||
- **Speed Dating**: Short, structured interaction rounds where participants get the chance to quickly introduce themselves and make initial connections. A long row of tables is needed so that two people can sit opposite each other. A moderator with a stopwatch must ensure that participants rotate and change seats every 3 to 5 minutes.
|
||||
|
||||
- **World Café**: Participants discuss in small groups at tables and rotate after set intervals to exchange thoughts and develop ideas further. Each table needs a host. Notes should be taken on a flipchart or digitally at each table. At the end, the table hosts could present their insights to all participants in a plenary session.
|
||||
|
||||
- **Fishbowl**: A group discusses in an inner circle while a larger group listens from the outside. Occasionally, listeners can move into the inner circle to actively participate.
|
||||
|
||||
- **BarCamp (Unconference)**: Participants contribute to part of the agenda themselves and can act as both presenters and listeners. Anyone can propose and lead a session. However, there should be initial moderation to guide this meta-process.
|
||||
|
||||
- **Open Space Technology**: A method for large groups where participants bring up their own topics and then work intensively in small groups. At the end, the groups can present their findings to all participants in a plenary session.
|
||||
|
||||
- **Panel Discussion**: A group of experts discusses a specific topic in front of an audience, followed by a question-and-answer session.
|
||||
|
||||
- **Breakout Sessions**: Larger groups are divided into smaller, topic-related groups to discuss specific issues more deeply and interactively.
|
||||
|
||||
- **Interactive Polling**: Real-time surveys during the meeting or seminar using digital technology to collect immediate feedback from participants. With an increasing number of participants, technical requirements also become more complex: not every Wi-Fi router can handle several hundred or thousand devices. Additionally, the moderator or speaker must have a stable network connection to display the results. It would be problematic if the speaker depends on the same Wi-Fi as the participants: if the Wi-Fi crashes due to the high number of participants, the speaker cannot show the results. Therefore, a LAN for the speaker or the use of a mobile hotspot would be a better choice.
|
||||
|
||||
- **Peer Learning Groups**: Small groups of participants work together to learn from each other and collaboratively develop solutions for specific challenges.
|
||||
|
||||
- **Role Play/Simulation**: Participants take on roles to simulate certain scenarios, gaining practical experience and promoting dynamic discussions.
|
||||
|
||||
- **Round Table Discussions**: Small group discussions on specific topics, often without formal moderation, to encourage open and equal dialogue.
|
||||
|
||||
- **Mind Mapping**: A method for visualizing ideas and concepts, which can foster creative exchange within groups.
|
||||
|
||||
- **Case Study Analysis**: Groups analyze real or hypothetical case studies and present their solutions or insights.
|
||||
|
||||
- **Silent Meeting/Writing**: Participants write down their thoughts and questions, which are then collected and discussed to balance out loud or dominant voices.
|
||||
|
||||
- **Debate**: Participants argue for or against a specific topic, often with a moderator who ensures that the discussion remains constructive.
|
||||
|
||||
- **Workshops**: Interactive sessions where participants work together on specific tasks or challenges.
|
||||
|
||||
- **Brainstorming**: A method for generating ideas in a group setting, often with a focus on quantity and creativity.
|
||||
|
||||
- **Design Thinking**: A structured approach to innovation solutions. Design thinking is structured in six phases: understand, observe, point of view, ideate, prototype, and test. Depending on the number of participants, there are two moderates needed. One moderator leads the process, the other supports the participants in their work. Design thinking may takes up to two days.
|
||||
|
||||
You output the agenda in the following Markdown format:
|
||||
|
||||
# [Agenda Title]
|
||||
- 09:00 - 09:05 (5 minutes): Welcome
|
||||
- 09:05 - 09:15 (10 minutes): Introduction
|
||||
- ...
|
||||
{this.SystemPromptSocialActivity()}
|
||||
{this.SystemPromptDinner()}
|
||||
|
||||
# Organizational notes
|
||||
[Your advice for the organizer goes here, like room setup, technical requirements, etc.]
|
||||
|
||||
# Moderation notes
|
||||
[Your advice for the moderator goes here]
|
||||
|
||||
Output the agenda in the following language: {this.PromptLanguage()}.
|
||||
""";
|
||||
|
||||
private const string PLACEHOLDER_CONTENT = """
|
||||
- Project status
|
||||
- We need to discuss how to proceed
|
||||
- Problem solving in work package 3 possible?
|
||||
- Concerns of the members
|
||||
""";
|
||||
|
||||
private const string PLACEHOLDER_WHO_IS_PRESENTING = """
|
||||
- John Doe: Project status
|
||||
- Mary Jane: Work package 3
|
||||
""";
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.AGENDA_ASSISTANT,
|
||||
},
|
||||
];
|
||||
|
||||
private string inputTopic = string.Empty;
|
||||
private string inputName = string.Empty;
|
||||
private string inputContent = string.Empty;
|
||||
private string inputDuration = string.Empty;
|
||||
private string inputStartTime = string.Empty;
|
||||
private IEnumerable<string> selectedFoci = new HashSet<string>();
|
||||
private IEnumerable<string> justBriefly = new HashSet<string>();
|
||||
private string inputObjective = string.Empty;
|
||||
private string inputModerator = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private bool introduceParticipants;
|
||||
private bool isMeetingVirtual = true;
|
||||
private string inputLocation = string.Empty;
|
||||
private bool goingToDinner;
|
||||
private bool doingSocialActivity;
|
||||
private bool needToArriveAndDepart;
|
||||
private int durationLunchBreak;
|
||||
private int durationBreaks;
|
||||
private bool activeParticipation;
|
||||
private NumberParticipants numberParticipants;
|
||||
private string inputWhoIsPresenting = string.Empty;
|
||||
|
||||
private readonly List<string> contentLines = [];
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)
|
||||
{
|
||||
this.inputTopic = this.SettingsManager.ConfigurationData.Agenda.PreselectTopic;
|
||||
this.inputName = this.SettingsManager.ConfigurationData.Agenda.PreselectName;
|
||||
this.inputDuration = this.SettingsManager.ConfigurationData.Agenda.PreselectDuration;
|
||||
this.inputStartTime = this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime;
|
||||
this.inputObjective = this.SettingsManager.ConfigurationData.Agenda.PreselectObjective;
|
||||
this.inputModerator = this.SettingsManager.ConfigurationData.Agenda.PreselectModerator;
|
||||
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage;
|
||||
this.customTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage;
|
||||
this.introduceParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants;
|
||||
this.isMeetingVirtual = this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual;
|
||||
this.inputLocation = this.SettingsManager.ConfigurationData.Agenda.PreselectLocation;
|
||||
this.goingToDinner = this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner;
|
||||
this.doingSocialActivity = this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity;
|
||||
this.needToArriveAndDepart = this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart;
|
||||
this.durationLunchBreak = this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime;
|
||||
this.durationBreaks = this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime;
|
||||
this.activeParticipation = this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation;
|
||||
this.numberParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_AGENDA_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputContent = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private void OnContentChanged(string content)
|
||||
{
|
||||
var previousSelectedFoci = new HashSet<string>();
|
||||
var previousJustBriefly = new HashSet<string>();
|
||||
|
||||
this.contentLines.Clear();
|
||||
foreach (var line in content.AsSpan().EnumerateLines())
|
||||
{
|
||||
var trimmedLine = line.Trim();
|
||||
if (trimmedLine.StartsWith("-"))
|
||||
trimmedLine = trimmedLine[1..].Trim();
|
||||
|
||||
if (trimmedLine.Length == 0)
|
||||
continue;
|
||||
|
||||
var finalLine = trimmedLine.ToString();
|
||||
if(this.selectedFoci.Any(x => x.StartsWith(finalLine, StringComparison.InvariantCultureIgnoreCase)))
|
||||
previousSelectedFoci.Add(finalLine);
|
||||
|
||||
if(this.justBriefly.Any(x => x.StartsWith(finalLine, StringComparison.InvariantCultureIgnoreCase)))
|
||||
previousJustBriefly.Add(finalLine);
|
||||
|
||||
this.contentLines.Add(finalLine);
|
||||
}
|
||||
|
||||
this.selectedFoci = previousSelectedFoci;
|
||||
this.justBriefly = previousJustBriefly;
|
||||
}
|
||||
|
||||
private string? ValidateLocation(string location)
|
||||
{
|
||||
if(!this.isMeetingVirtual && string.IsNullOrWhiteSpace(location))
|
||||
return "Please provide a location for the meeting or the seminar.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateNumberParticipants(NumberParticipants selectedSize)
|
||||
{
|
||||
if(selectedSize is NumberParticipants.NOT_SPECIFIED)
|
||||
return "Please select the number of participants.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateTargetLanguage(CommonLanguages language)
|
||||
{
|
||||
if(language is CommonLanguages.AS_IS)
|
||||
return "Please select a target language for the agenda.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateDuration(string duration)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(duration))
|
||||
return "Please provide a duration for the meeting or the seminar, e.g. '2 hours', or '2 days (8 hours and 4 hours)', etc.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateStartTime(string startTime)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(startTime))
|
||||
return "Please provide a start time for the meeting or the seminar. When the meeting is a multi-day event, specify the start time for each day, e.g. '9:00 AM, 10:00 AM', etc.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateCustomLanguage(string language)
|
||||
{
|
||||
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
|
||||
return "Please provide a custom language.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateTopic(string topic)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(topic))
|
||||
return "Please provide a topic for the agenda. What is the meeting or the seminar about?";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateName(string name)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(name))
|
||||
return "Please provide a name for the meeting or the seminar.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateContent(string content)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(content))
|
||||
return "Please provide some content for the agenda. What are the main points of the meeting or the seminar?";
|
||||
|
||||
var lines = content.Split('\n');
|
||||
foreach (var line in lines)
|
||||
if(!line.TrimStart().StartsWith('-'))
|
||||
return "Please start each line of your content list with a dash (-) to create a bullet point list.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateObjective(string objective)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(objective))
|
||||
return "Please provide an objective for the meeting or the seminar. What do you want to achieve?";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateModerator(string moderator)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(moderator))
|
||||
return "Please provide a moderator for the meeting or the seminar. Who will lead the discussion?";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private async Task CreateAgenda()
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
Create an agenda for the meeting or seminar wit the title '{this.inputName}' using the following details:
|
||||
|
||||
- The overall topic is '{this.inputTopic}'.
|
||||
- The objective of the meeting is '{this.inputObjective}'.
|
||||
- The moderator is '{this.inputModerator}'.
|
||||
- The planned duration is '{this.inputDuration}'.
|
||||
- The planned start time is '{this.inputStartTime}'.
|
||||
{this.PromptGettingToKnowEachOther()}
|
||||
- The number of participants is '{this.numberParticipants.Name()}'.
|
||||
{this.PromptActiveParticipation()}
|
||||
{this.PromptVirtualMeeting()}
|
||||
{this.PromptPhysicalMeeting()}
|
||||
|
||||
Here is draft what was planned for the meeting:
|
||||
{this.inputContent}
|
||||
|
||||
Please do not follow this draft strictly. It is just a suggestion.
|
||||
{this.PromptFoci()}
|
||||
{this.PromptBriefly()}
|
||||
{this.PromptWhoIsPresenting()}
|
||||
""");
|
||||
|
||||
await this.AddAIResponseAsync(time);
|
||||
}
|
||||
|
||||
private string PromptLanguage()
|
||||
{
|
||||
if(this.selectedTargetLanguage is CommonLanguages.OTHER)
|
||||
return this.customTargetLanguage;
|
||||
|
||||
return this.selectedTargetLanguage.Name();
|
||||
}
|
||||
|
||||
private string PromptPhysicalMeeting()
|
||||
{
|
||||
if(this.isMeetingVirtual)
|
||||
return string.Empty;
|
||||
|
||||
return $"""
|
||||
- The meeting takes place at the following location: '{this.inputLocation}'.
|
||||
{this.PromptJoiningDinner()}
|
||||
{this.PromptSocialActivity()}
|
||||
{this.PromptArriveAndDepart()}
|
||||
- In case a lunch break is necessary, the break should about {this.durationLunchBreak} minutes long.
|
||||
- In case any breaks are necessary, the breaks should be about {this.durationBreaks} minutes long.
|
||||
""";
|
||||
}
|
||||
|
||||
private string PromptArriveAndDepart()
|
||||
{
|
||||
if (this.needToArriveAndDepart)
|
||||
return "- The participants should have time to arrive and depart.";
|
||||
|
||||
return "- The participants do not need to arrive and depart.";
|
||||
}
|
||||
|
||||
private string PromptSocialActivity()
|
||||
{
|
||||
if (this.doingSocialActivity)
|
||||
return "- The participants will engage in a social activity after the meeting or seminar. This can be a team-building exercise, a sightseeing tour, or a visit to a local attraction. Please make a recommendation for an activity at '{this.inputLocation}'.";
|
||||
|
||||
return "- The participants will not engage in a social activity after the meeting or seminar.";
|
||||
}
|
||||
|
||||
private string SystemPromptSocialActivity()
|
||||
{
|
||||
if(this.doingSocialActivity)
|
||||
return """
|
||||
- 16:00 Departure to the social event [Consider the time needed to get to the location].
|
||||
- 17:00 [Insert your advice for the social activity here].
|
||||
""";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string SystemPromptDinner()
|
||||
{
|
||||
if(this.goingToDinner)
|
||||
return """
|
||||
- 19:00 Departure to the restaurant [Consider the time needed to get to the restaurant].
|
||||
- 20:00 [Insert your advice for the dinner here.].
|
||||
""";
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string PromptJoiningDinner()
|
||||
{
|
||||
if (this.goingToDinner)
|
||||
return $"- The participants will join for a dinner after the meeting or seminar. Please make a recommendation for a restaurant at '{this.inputLocation}'.";
|
||||
|
||||
return "- The participants will not join for a dinner after the meeting or seminar.";
|
||||
}
|
||||
|
||||
private string PromptVirtualMeeting()
|
||||
{
|
||||
if (this.isMeetingVirtual)
|
||||
return "- The meeting or seminar will be held virtually, e.g, a call or webinar. The participants will join online.";
|
||||
|
||||
return "- The meeting or seminar will be held in person.";
|
||||
}
|
||||
|
||||
private string PromptActiveParticipation()
|
||||
{
|
||||
if (this.activeParticipation)
|
||||
return "- The participants should actively participate in the meeting or seminar. This can be done through discussions, questions, and contributions to the content.";
|
||||
|
||||
return "- The participants do not need to actively participate.";
|
||||
}
|
||||
|
||||
private string PromptGettingToKnowEachOther()
|
||||
{
|
||||
if (this.introduceParticipants)
|
||||
return "- The participants should introduce themselves to get to know each other. This can be done in a round or in pairs. The moderator should ensure that everyone has the opportunity to speak.";
|
||||
|
||||
return "- The participants do not need to introduce themselves.";
|
||||
}
|
||||
|
||||
private string PromptFoci()
|
||||
{
|
||||
if (this.selectedFoci.Any())
|
||||
{
|
||||
return $"""
|
||||
|
||||
Out of this content, the following points should be focused on:
|
||||
{this.ConvertItemsToMarkdown(this.selectedFoci)}
|
||||
""";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string PromptBriefly()
|
||||
{
|
||||
if (this.justBriefly.Any())
|
||||
{
|
||||
return $"""
|
||||
|
||||
The following points should be just briefly mentioned:
|
||||
{this.ConvertItemsToMarkdown(this.justBriefly)}
|
||||
""";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string PromptWhoIsPresenting()
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(this.inputWhoIsPresenting))
|
||||
{
|
||||
return $"""
|
||||
|
||||
The following persons will present the content:
|
||||
{this.inputWhoIsPresenting}
|
||||
""";
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
|
||||
private string ConvertItemsToMarkdown(IEnumerable<string> items)
|
||||
{
|
||||
var markdown = new StringBuilder();
|
||||
foreach (var item in items)
|
||||
markdown.AppendLine($"- {item}");
|
||||
|
||||
return markdown.ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
namespace AIStudio.Components.Pages.Agenda;
|
||||
|
||||
public enum NumberParticipants
|
||||
{
|
||||
NOT_SPECIFIED,
|
||||
|
||||
PEER_TO_PEER, // 2 participants
|
||||
|
||||
SMALL_GROUP, // 3 - 5 participants
|
||||
LARGE_GROUP, // 6 - 12 participants
|
||||
MULTIPLE_SMALL_GROUPS, // 13 - 20 participants
|
||||
MULTIPLE_LARGE_GROUPS, // 21 - 30 participants
|
||||
|
||||
SYMPOSIUM, // 31 - 100 participants
|
||||
CONFERENCE, // 101 - 200 participants
|
||||
CONGRESS, // 201 - 1000 participants
|
||||
LARGE_EVENT, // 1000+ participants
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace AIStudio.Components.Pages.Agenda;
|
||||
|
||||
public static class NumberParticipantsExtensions
|
||||
{
|
||||
public static string Name(this NumberParticipants numberParticipants) => numberParticipants switch
|
||||
{
|
||||
NumberParticipants.NOT_SPECIFIED => "Please select how many participants are expected",
|
||||
|
||||
NumberParticipants.PEER_TO_PEER => "2 (peer to peer)",
|
||||
|
||||
NumberParticipants.SMALL_GROUP => "3 - 5 (small group)",
|
||||
NumberParticipants.LARGE_GROUP => "6 - 12 (large group)",
|
||||
NumberParticipants.MULTIPLE_SMALL_GROUPS => "13 - 20 (multiple small groups)",
|
||||
NumberParticipants.MULTIPLE_LARGE_GROUPS => "21 - 30 (multiple large groups)",
|
||||
|
||||
NumberParticipants.SYMPOSIUM => "31 - 100 (symposium)",
|
||||
NumberParticipants.CONFERENCE => "101 - 200 (conference)",
|
||||
NumberParticipants.CONGRESS => "201 - 1,000 (congress)",
|
||||
|
||||
NumberParticipants.LARGE_EVENT => "1,000+ (large event)",
|
||||
|
||||
_ => "Unknown"
|
||||
};
|
||||
}
|
||||
@@ -1,12 +1,34 @@
|
||||
@page "/assistants"
|
||||
@attribute [Route(Path.ASSISTANTS)]
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
|
||||
Assistants
|
||||
</MudText>
|
||||
|
||||
<MudGrid>
|
||||
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="/assistant/icons"/>
|
||||
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="/assistant/summarizer"/>
|
||||
<AssistantBlock Name="Translator" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="/assistant/translator"/>
|
||||
<AssistantBlock Name="Coding" Description="Get coding and debugging support from a LLM." Icon="@Icons.Material.Filled.Code" Link="/assistant/coding"/>
|
||||
</MudGrid>
|
||||
<InnerScrolling HeaderHeight="6em">
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-2 mr-3">
|
||||
General
|
||||
</MudText>
|
||||
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
||||
<AssistantBlock Name="Text Summarizer" Description="Using a LLM to summarize a given text." Icon="@Icons.Material.Filled.TextSnippet" Link="@Path.ASSISTANT_SUMMARIZER"/>
|
||||
<AssistantBlock Name="Translation" Description="Translate text into another language." Icon="@Icons.Material.Filled.Translate" Link="@Path.ASSISTANT_TRANSLATION"/>
|
||||
<AssistantBlock Name="Grammar & Spelling" Description="Check grammar and spelling of a given text." Icon="@Icons.Material.Filled.Edit" Link="@Path.ASSISTANT_GRAMMAR_SPELLING"/>
|
||||
<AssistantBlock Name="Rewrite & Improve" Description="Rewrite and improve a given text for a chosen style." Icon="@Icons.Material.Filled.Edit" Link="@Path.ASSISTANT_REWRITE"/>
|
||||
</MudStack>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6">
|
||||
Business
|
||||
</MudText>
|
||||
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
||||
<AssistantBlock Name="Agenda Planner" Description="Generate an agenda for a given meeting, seminar, etc." Icon="@Icons.Material.Filled.CalendarToday" Link="@Path.ASSISTANT_AGENDA"/>
|
||||
<AssistantBlock Name="Icon Finder" Description="Using a LLM to find an icon for a given context." Icon="@Icons.Material.Filled.FindInPage" Link="@Path.ASSISTANT_ICON_FINDER"/>
|
||||
</MudStack>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-2 mr-3 mt-6">
|
||||
Software Engineering
|
||||
</MudText>
|
||||
<MudStack Row="@true" Wrap="@Wrap.Wrap" Class="mb-3">
|
||||
<AssistantBlock Name="Coding" Description="Get coding and debugging support from a LLM." Icon="@Icons.Material.Filled.Code" Link="@Path.ASSISTANT_CODING"/>
|
||||
</MudStack>
|
||||
|
||||
</InnerScrolling>
|
||||
@@ -1,6 +1,6 @@
|
||||
@page "/chat"
|
||||
@attribute [Route(Path.CHAT)]
|
||||
@using AIStudio.Chat
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Settings.DataModel
|
||||
|
||||
@inherits MSGComponentBase
|
||||
|
||||
@@ -15,13 +15,7 @@
|
||||
}
|
||||
</MudText>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.providerSettings" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-2 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings"/>
|
||||
<InnerScrolling HeaderHeight="12.3em">
|
||||
<ChildContent>
|
||||
@if (this.chatThread is not null)
|
||||
@@ -38,14 +32,14 @@
|
||||
</MudPaper>
|
||||
<MudPaper Class="mt-1" Outlined="@true">
|
||||
<MudToolBar WrapContent="true">
|
||||
@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
{
|
||||
<MudTooltip Text="Your workspaces" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.SnippetFolder" OnClick="() => this.ToggleWorkspaces()"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY)
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY)
|
||||
{
|
||||
<MudTooltip Text="Save chat" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="() => this.SaveThread()" Disabled="@(!this.CanThreadBeSaved)"/>
|
||||
@@ -63,16 +57,16 @@
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
{
|
||||
<MudTooltip Text="Delete this chat & start a new one" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.Refresh" OnClick="() => this.StartNewChat(useSameWorkspace: true, deletePreviousChat: true)" Disabled="@(!this.CanThreadBeSaved)"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
|
||||
@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is not WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
{
|
||||
<MudTooltip Text="Move chat to (another) workspace" Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudTooltip Text="Move the chat to a workspace, or to another if it is already in one." Placement="@TOOLBAR_TOOLTIP_PLACEMENT">
|
||||
<MudIconButton Icon="@Icons.Material.Filled.MoveToInbox" Disabled="@(!this.CanThreadBeSaved)" OnClick="() => this.MoveChatToWorkspace()"/>
|
||||
</MudTooltip>
|
||||
}
|
||||
@@ -81,7 +75,7 @@
|
||||
</FooterContent>
|
||||
</InnerScrolling>
|
||||
|
||||
@if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
@if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior != WorkspaceStorageBehavior.DISABLE_WORKSPACES)
|
||||
{
|
||||
<MudDrawer @bind-Open="@this.workspacesVisible" Width="40em" Height="100%" Anchor="Anchor.Start" Variant="DrawerVariant.Temporary" Elevation="1">
|
||||
<MudDrawerHeader>
|
||||
|
||||
@@ -3,6 +3,7 @@ using AIStudio.Components.Blocks;
|
||||
using AIStudio.Components.CommonDialogs;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -24,7 +25,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
public IJSRuntime JsRuntime { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
public Random RNG { get; set; } = null!;
|
||||
private ThreadSafeRandom RNG { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
public IDialogService DialogService { get; set; } = null!;
|
||||
@@ -55,6 +56,11 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
// Configure the spellchecking for the user input:
|
||||
this.SettingsManager.InjectSpellchecking(USER_INPUT_ATTRIBUTES);
|
||||
|
||||
if (this.SettingsManager.ConfigurationData.Chat.PreselectOptions)
|
||||
{
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Chat.PreselectedProvider);
|
||||
}
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
@@ -114,7 +120,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
});
|
||||
|
||||
// Save the chat:
|
||||
if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
{
|
||||
await this.SaveThread();
|
||||
this.hasUnsavedChanges = false;
|
||||
@@ -154,7 +160,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
await aiText.CreateFromProviderAsync(this.providerSettings.CreateProvider(), this.JsRuntime, this.SettingsManager, this.providerSettings.Model, this.chatThread);
|
||||
|
||||
// Save the chat:
|
||||
if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
{
|
||||
await this.SaveThread();
|
||||
this.hasUnsavedChanges = false;
|
||||
@@ -177,7 +183,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
var isModifier = keyEvent.AltKey || keyEvent.CtrlKey || keyEvent.MetaKey || keyEvent.ShiftKey;
|
||||
|
||||
// Depending on the user's settings, might react to shortcuts:
|
||||
switch (this.SettingsManager.ConfigurationData.ShortcutSendBehavior)
|
||||
switch (this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior)
|
||||
{
|
||||
case SendBehavior.ENTER_IS_SENDING:
|
||||
if (!isModifier && isEnter)
|
||||
@@ -226,7 +232,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
private async Task StartNewChat(bool useSameWorkspace = false, bool deletePreviousChat = false)
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
|
||||
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
|
||||
{
|
||||
var dialogParameters = new DialogParameters
|
||||
{
|
||||
@@ -244,11 +250,11 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
string chatPath;
|
||||
if (this.chatThread.WorkspaceId == Guid.Empty)
|
||||
{
|
||||
chatPath = Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString());
|
||||
chatPath = System.IO.Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
chatPath = Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString());
|
||||
chatPath = System.IO.Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString());
|
||||
}
|
||||
|
||||
await this.workspaces.DeleteChat(chatPath, askForConfirmation: false, unloadChat: true);
|
||||
@@ -288,7 +294,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
if(this.workspaces is null)
|
||||
return;
|
||||
|
||||
if (this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
|
||||
if (this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_MANUALLY && this.hasUnsavedChanges)
|
||||
{
|
||||
var confirmationDialogParameters = new DialogParameters
|
||||
{
|
||||
@@ -321,12 +327,12 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
if (this.chatThread!.WorkspaceId == Guid.Empty)
|
||||
{
|
||||
// Case: The chat is stored in the temporary storage:
|
||||
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
||||
await this.workspaces.DeleteChat(System.IO.Path.Join(SettingsManager.DataDirectory, "tempChats", this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: The chat is stored in a workspace.
|
||||
await this.workspaces.DeleteChat(Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
||||
await this.workspaces.DeleteChat(System.IO.Path.Join(SettingsManager.DataDirectory, "workspaces", this.chatThread.WorkspaceId.ToString(), this.chatThread.ChatId.ToString()), askForConfirmation: false, unloadChat: false);
|
||||
}
|
||||
|
||||
this.chatThread!.WorkspaceId = workspaceId;
|
||||
@@ -379,7 +385,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.HAS_CHAT_UNSAVED_CHANGES:
|
||||
if(this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
return Task.FromResult((TResult?) (object) false);
|
||||
|
||||
return Task.FromResult((TResult?)(object)this.hasUnsavedChanges);
|
||||
@@ -394,7 +400,7 @@ public partial class Chat : MSGComponentBase, IAsyncDisposable
|
||||
|
||||
public async ValueTask DisposeAsync()
|
||||
{
|
||||
if(this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
if(this.SettingsManager.ConfigurationData.Workspace.StorageBehavior is WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY)
|
||||
{
|
||||
await this.SaveThread();
|
||||
this.hasUnsavedChanges = false;
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/assistant/coding"
|
||||
@using AIStudio.Settings
|
||||
@attribute [Route(Path.ASSISTANT_CODING)]
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudExpansionPanels Class="mb-3">
|
||||
@@ -16,9 +15,7 @@
|
||||
</MudButton>
|
||||
|
||||
<MudStack Row="@false" Class="mb-3">
|
||||
<MudSwitch T="bool" @bind-Value="@this.provideCompilerMessages">
|
||||
@(this.provideCompilerMessages ? "Provide compiler messages" : "Provide no compiler messages")
|
||||
</MudSwitch>
|
||||
<MudTextSwitch Label="Do you want to provide compiler messages?" @bind-Value="@this.provideCompilerMessages" LabelOn="Yes, provide compiler messages" LabelOff="No, there are no compiler messages" />
|
||||
@if (this.provideCompilerMessages)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.compilerMessages" Validation="@this.ValidatingCompilerMessages" AdornmentIcon="@Icons.Material.Filled.Error" Adornment="Adornment.Start" Label="Compiler messages" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
@@ -26,13 +23,7 @@
|
||||
</MudStack>
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.questions" Validation="@this.ValidateQuestions" AdornmentIcon="@Icons.Material.Filled.QuestionMark" Adornment="Adornment.Start" Label="Your question(s)" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.providerSettings" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" OnClick="() => this.GetSupport()" Class="mb-3">
|
||||
Get support
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Coding;
|
||||
|
||||
public partial class AssistantCoding : AssistantBaseCore
|
||||
@@ -24,11 +26,38 @@ public partial class AssistantCoding : AssistantBaseCore
|
||||
When the user asks in a different language than English, you answer in the same language!
|
||||
""";
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.CODING_ASSISTANT,
|
||||
},
|
||||
];
|
||||
|
||||
private readonly List<CodingContext> codingContexts = new();
|
||||
private bool provideCompilerMessages;
|
||||
private string compilerMessages = string.Empty;
|
||||
private string questions = string.Empty;
|
||||
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.Coding.PreselectOptions)
|
||||
{
|
||||
this.provideCompilerMessages = this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Coding.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_CODING_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.questions = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string? ValidatingCompilerMessages(string checkCompilerMessages)
|
||||
{
|
||||
if(!this.provideCompilerMessages)
|
||||
@@ -53,6 +82,8 @@ public partial class AssistantCoding : AssistantBaseCore
|
||||
this.codingContexts.Add(new()
|
||||
{
|
||||
Id = $"Context {this.codingContexts.Count + 1}",
|
||||
Language = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage : default,
|
||||
OtherLanguage = this.SettingsManager.ConfigurationData.Coding.PreselectOptions ? this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage : string.Empty,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
@using AIStudio.Tools
|
||||
@attribute [Route(Path.ASSISTANT_GRAMMAR_SPELLING)]
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to check" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.ProofreadText()">
|
||||
Proofread
|
||||
</MudButton>
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.GrammarSpelling;
|
||||
|
||||
public partial class AssistantGrammarSpelling : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Grammar & Spelling Checker";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
Check the grammar and spelling of a text.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
$"""
|
||||
You are an expert in languages and their rules. For example, you know how US and UK English or German in
|
||||
Germany and German in Austria differ. You receive text as input. You check the spelling and grammar of
|
||||
this text according to the rules of {this.SystemPromptLanguage()}. You never add information. You
|
||||
never ask the user for additional information. You do not attempt to improve the wording of the text.
|
||||
Your response includes only the corrected text. Do not explain your changes. If no changes are needed,
|
||||
you return the text unchanged.
|
||||
""";
|
||||
|
||||
protected override bool ShowResult => false;
|
||||
|
||||
protected override bool ShowDedicatedProgress => true;
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.correctedText)),
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.GRAMMAR_SPELLING_ASSISTANT,
|
||||
UseResultingContentBlockData = false,
|
||||
GetData = () => string.IsNullOrWhiteSpace(this.correctedText) ? this.inputText : this.correctedText
|
||||
},
|
||||
];
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)
|
||||
{
|
||||
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage;
|
||||
this.customTargetLanguage = this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputText = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string inputText = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private string correctedText = string.Empty;
|
||||
|
||||
private string? ValidateText(string text)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(text))
|
||||
return "Please provide a text as input. You might copy the desired text from a document or a website.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateCustomLanguage(string language)
|
||||
{
|
||||
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
|
||||
return "Please provide a custom language.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string SystemPromptLanguage()
|
||||
{
|
||||
var lang = this.selectedTargetLanguage switch
|
||||
{
|
||||
CommonLanguages.AS_IS => "the source language",
|
||||
CommonLanguages.OTHER => this.customTargetLanguage,
|
||||
|
||||
_ => $"{this.selectedTargetLanguage.Name()}",
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(lang))
|
||||
return "the source language";
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
private async Task ProofreadText()
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(this.inputText);
|
||||
|
||||
this.correctedText = await this.AddAIResponseAsync(time);
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@page "/"
|
||||
@attribute [Route(Path.HOME)]
|
||||
@using AIStudio.Tools
|
||||
|
||||
<MudImage Src="svg/banner.svg" />
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
@page "/assistant/icons"
|
||||
@using AIStudio.Settings
|
||||
@attribute [Route(Path.ASSISTANT_ICON_FINDER)]
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputContext" Validation="@this.ValidatingContext" AdornmentIcon="@Icons.Material.Filled.Description" Adornment="Adornment.Start" Label="Your context" Variant="Variant.Outlined" Lines="3" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
@@ -16,13 +15,7 @@
|
||||
<MudButton Href="@this.selectedIconSource.URL()" Target="_blank" Variant="Variant.Filled" Size="Size.Medium">Open website</MudButton>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.providerSettings" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.FindIcon()">
|
||||
Find icon
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.IconFinder;
|
||||
|
||||
public partial class AssistantIconFinder : AssistantBaseCore
|
||||
@@ -25,7 +27,34 @@ public partial class AssistantIconFinder : AssistantBaseCore
|
||||
related to the keyword "buildings" might be the best match. Provide your keywords in a Markdown list without
|
||||
quotation marks.
|
||||
""";
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.ICON_FINDER_ASSISTANT,
|
||||
},
|
||||
];
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)
|
||||
{
|
||||
this.selectedIconSource = this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_ICON_FINDER_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputContext = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string? ValidatingContext(string context)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(context))
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace AIStudio.Components.Pages;
|
||||
|
||||
public static class Path
|
||||
{
|
||||
public const string HOME = "/";
|
||||
public const string CHAT = "/chat";
|
||||
public const string ABOUT = "/about";
|
||||
public const string ASSISTANTS = "/assistants";
|
||||
public const string SETTINGS = "/settings";
|
||||
public const string SUPPORTERS = "/supporters";
|
||||
|
||||
public const string ASSISTANT_TRANSLATION = "/assistant/translation";
|
||||
public const string ASSISTANT_REWRITE = "/assistant/rewrite-improve";
|
||||
public const string ASSISTANT_ICON_FINDER = "/assistant/icons";
|
||||
public const string ASSISTANT_GRAMMAR_SPELLING = "/assistant/grammar-spelling";
|
||||
public const string ASSISTANT_SUMMARIZER = "/assistant/summarizer";
|
||||
public const string ASSISTANT_CODING = "/assistant/coding";
|
||||
public const string ASSISTANT_AGENDA = "/assistant/agenda";
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
@using AIStudio.Tools
|
||||
@attribute [Route(Path.ASSISTANT_REWRITE)]
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidateText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input to improve" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelectingOptional())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom language" />
|
||||
<EnumSelection T="WritingStyles" NameFunc="@(style => style.Name())" @bind-Value="@this.selectedWritingStyle" Icon="@Icons.Material.Filled.Edit" Label="Writing style" AllowOther="@false" />
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.RewriteText()">
|
||||
Improve
|
||||
</MudButton>
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.RewriteImprove;
|
||||
|
||||
public partial class AssistantRewriteImprove : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Rewrite & Improve Text";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
Rewrite and improve your text. Please note, that the capabilities of the different LLM providers will vary.
|
||||
""";
|
||||
|
||||
protected override string SystemPrompt =>
|
||||
$"""
|
||||
You are an expert in language and style. You receive a text as input. First, you review the text. If no
|
||||
changes are needed, you return the text without modifications. If a change is necessary, you improve the
|
||||
text. You can also correct spelling and grammar issues. You never add additional information. You never
|
||||
ask the user for additional information. Your response only contains the improved text. You do not explain
|
||||
your changes. If no changes are needed, you return the text unchanged.
|
||||
The style of the text: {this.selectedWritingStyle.Prompt()}. You follow the rules according
|
||||
to {this.SystemPromptLanguage()} in all your changes.
|
||||
""";
|
||||
|
||||
protected override bool ShowResult => false;
|
||||
|
||||
protected override bool ShowDedicatedProgress => true;
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new ButtonData("Copy result", Icons.Material.Filled.ContentCopy, Color.Default, string.Empty, () => this.CopyToClipboard(this.rewrittenText)),
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.REWRITE_ASSISTANT,
|
||||
UseResultingContentBlockData = false,
|
||||
GetData = () => string.IsNullOrWhiteSpace(this.rewrittenText) ? this.inputText : this.rewrittenText,
|
||||
},
|
||||
];
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)
|
||||
{
|
||||
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage;
|
||||
this.customTargetLanguage = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider);
|
||||
this.selectedWritingStyle = this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle;
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_REWRITE_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputText = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string inputText = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private string rewrittenText = string.Empty;
|
||||
private WritingStyles selectedWritingStyle;
|
||||
|
||||
private string? ValidateText(string text)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(text))
|
||||
return "Please provide a text as input. You might copy the desired text from a document or a website.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string? ValidateCustomLanguage(string language)
|
||||
{
|
||||
if(this.selectedTargetLanguage == CommonLanguages.OTHER && string.IsNullOrWhiteSpace(language))
|
||||
return "Please provide a custom language.";
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private string SystemPromptLanguage()
|
||||
{
|
||||
var lang = this.selectedTargetLanguage switch
|
||||
{
|
||||
CommonLanguages.AS_IS => "the source language",
|
||||
CommonLanguages.OTHER => this.customTargetLanguage,
|
||||
|
||||
_ => $"{this.selectedTargetLanguage.Name()}",
|
||||
};
|
||||
|
||||
if (string.IsNullOrWhiteSpace(lang))
|
||||
return "the source language";
|
||||
|
||||
return lang;
|
||||
}
|
||||
|
||||
private async Task RewriteText()
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(this.inputText);
|
||||
|
||||
this.rewrittenText = await this.AddAIResponseAsync(time);
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
namespace AIStudio.Components.Pages.RewriteImprove;
|
||||
|
||||
public enum WritingStyles
|
||||
{
|
||||
NOT_SPECIFIED = 0,
|
||||
|
||||
EVERYDAY,
|
||||
BUSINESS,
|
||||
SCIENTIFIC,
|
||||
JOURNALISTIC,
|
||||
LITERARY,
|
||||
TECHNICAL,
|
||||
MARKETING,
|
||||
ACADEMIC,
|
||||
LEGAL,
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
namespace AIStudio.Components.Pages.RewriteImprove;
|
||||
|
||||
public static class WritingStylesExtensions
|
||||
{
|
||||
public static string Name(this WritingStyles style)
|
||||
{
|
||||
return style switch
|
||||
{
|
||||
WritingStyles.EVERYDAY => "Everyday (personal texts, social media)",
|
||||
WritingStyles.BUSINESS => "Business (business emails, reports, presentations)",
|
||||
WritingStyles.SCIENTIFIC => "Scientific (scientific papers, research reports)",
|
||||
WritingStyles.JOURNALISTIC => "Journalistic (magazines, newspapers, news)",
|
||||
WritingStyles.LITERARY => "Literary (fiction, poetry)",
|
||||
WritingStyles.TECHNICAL => "Technical (manuals, documentation)",
|
||||
WritingStyles.MARKETING => "Marketing (advertisements, sales texts)",
|
||||
WritingStyles.ACADEMIC => "Academic (essays, seminar papers)",
|
||||
WritingStyles.LEGAL => "Legal (legal texts, contracts)",
|
||||
|
||||
_ => "Not specified",
|
||||
};
|
||||
}
|
||||
|
||||
public static string Prompt(this WritingStyles style)
|
||||
{
|
||||
return style switch
|
||||
{
|
||||
WritingStyles.EVERYDAY => "Use a everyday style like for personal texts, social media, and informal communication.",
|
||||
WritingStyles.BUSINESS => "Use a business style like for business emails, reports, and presentations. Most important is clarity and professionalism.",
|
||||
WritingStyles.SCIENTIFIC => "Use a scientific style like for scientific papers, research reports, and academic writing. Most important is precision and objectivity.",
|
||||
WritingStyles.JOURNALISTIC => "Use a journalistic style like for magazines, newspapers, and news. Most important is readability and engaging content.",
|
||||
WritingStyles.LITERARY => "Use a literary style like for fiction, poetry, and creative writing. Most important is creativity and emotional impact.",
|
||||
WritingStyles.TECHNICAL => "Use a technical style like for manuals, documentation, and technical writing. Most important is clarity and precision.",
|
||||
WritingStyles.MARKETING => "Use a marketing style like for advertisements, sales texts, and promotional content. Most important is persuasiveness and engagement.",
|
||||
WritingStyles.ACADEMIC => "Use a academic style like for essays, seminar papers, and academic writing. Most important is clarity and objectivity.",
|
||||
WritingStyles.LEGAL => "Use a legal style like for legal texts, contracts, and official documents. Most important is precision and legal correctness. Use formal legal language.",
|
||||
|
||||
_ => "Keep the style of the text as it is.",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace AIStudio.Components.Pages;
|
||||
|
||||
public enum SendToAssistant
|
||||
{
|
||||
NONE = 0,
|
||||
|
||||
GRAMMAR_SPELLING_ASSISTANT,
|
||||
ICON_FINDER_ASSISTANT,
|
||||
REWRITE_ASSISTANT,
|
||||
TRANSLATION_ASSISTANT,
|
||||
AGENDA_ASSISTANT,
|
||||
CODING_ASSISTANT,
|
||||
TEXT_SUMMARIZER_ASSISTANT,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
namespace AIStudio.Components.Pages;
|
||||
|
||||
public static class SendToAssistantExtensions
|
||||
{
|
||||
public static string Name(this SendToAssistant assistant)
|
||||
{
|
||||
return assistant switch
|
||||
{
|
||||
SendToAssistant.GRAMMAR_SPELLING_ASSISTANT => "Grammar & Spelling Assistant",
|
||||
SendToAssistant.TEXT_SUMMARIZER_ASSISTANT => "Text Summarizer Assistant",
|
||||
SendToAssistant.ICON_FINDER_ASSISTANT => "Icon Finder Assistant",
|
||||
SendToAssistant.TRANSLATION_ASSISTANT => "Translation Assistant",
|
||||
SendToAssistant.REWRITE_ASSISTANT => "Rewrite Assistant",
|
||||
SendToAssistant.AGENDA_ASSISTANT => "Agenda Assistant",
|
||||
SendToAssistant.CODING_ASSISTANT => "Coding Assistant",
|
||||
|
||||
_ => "Send to ...",
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -1,78 +1,213 @@
|
||||
@page "/settings"
|
||||
@attribute [Route(Path.SETTINGS)]
|
||||
@using AIStudio.Components.Pages.Coding
|
||||
@using AIStudio.Components.Pages.TextSummarizer
|
||||
@using AIStudio.Provider
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Tools
|
||||
@using Host = AIStudio.Provider.SelfHosted.Host
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-12">Settings</MudText>
|
||||
|
||||
<InnerScrolling HeaderHeight="6em">
|
||||
<MudPaper Class="pa-3 mb-8 border-solid border rounded-lg">
|
||||
<MudText Typo="Typo.h4" Class="mb-3">Configured Providers</MudText>
|
||||
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Class="border-dashed border rounded-lg">
|
||||
<ColGroup>
|
||||
<col style="width: 3em;"/>
|
||||
<col style="width: 12em;"/>
|
||||
<col style="width: 12em;"/>
|
||||
<col/>
|
||||
<col style="width: 34em;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>#</MudTh>
|
||||
<MudTh>Instance Name</MudTh>
|
||||
<MudTh>Provider</MudTh>
|
||||
<MudTh>Model</MudTh>
|
||||
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.Num</MudTd>
|
||||
<MudTd>@context.InstanceName</MudTd>
|
||||
<MudTd>@context.UsedProvider</MudTd>
|
||||
<MudTd>
|
||||
@if (context.UsedProvider is not Providers.SELF_HOSTED)
|
||||
{
|
||||
@this.GetProviderModelName(context)
|
||||
}
|
||||
else if (context.UsedProvider is Providers.SELF_HOSTED && context.Host is not Host.LLAMACPP)
|
||||
{
|
||||
@this.GetProviderModelName(context)
|
||||
}
|
||||
else
|
||||
{
|
||||
@("as selected by provider")
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd Style="text-align: left;">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@this.GetProviderDashboardURL(context.UsedProvider)" Target="_blank" Disabled="@(!this.HasDashboard(context.UsedProvider))">
|
||||
Open Dashboard
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditProvider(context)">
|
||||
Edit
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteProvider(context)">
|
||||
Delete
|
||||
</MudButton>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
<InnerScrolling HeaderHeight="10em">
|
||||
<MudExpansionPanels Class="mb-3" MultiExpansion="@false">
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Layers" HeaderText="Configure Providers">
|
||||
<MudText Typo="Typo.h4" Class="mb-3">Configured Providers</MudText>
|
||||
<MudTable Items="@this.SettingsManager.ConfigurationData.Providers" Class="border-dashed border rounded-lg">
|
||||
<ColGroup>
|
||||
<col style="width: 3em;"/>
|
||||
<col style="width: 12em;"/>
|
||||
<col style="width: 12em;"/>
|
||||
<col/>
|
||||
<col style="width: 34em;"/>
|
||||
</ColGroup>
|
||||
<HeaderContent>
|
||||
<MudTh>#</MudTh>
|
||||
<MudTh>Instance Name</MudTh>
|
||||
<MudTh>Provider</MudTh>
|
||||
<MudTh>Model</MudTh>
|
||||
<MudTh Style="text-align: left;">Actions</MudTh>
|
||||
</HeaderContent>
|
||||
<RowTemplate>
|
||||
<MudTd>@context.Num</MudTd>
|
||||
<MudTd>@context.InstanceName</MudTd>
|
||||
<MudTd>@context.UsedProvider</MudTd>
|
||||
<MudTd>
|
||||
@if (context.UsedProvider is not Providers.SELF_HOSTED)
|
||||
{
|
||||
@this.GetProviderModelName(context)
|
||||
}
|
||||
else if (context.UsedProvider is Providers.SELF_HOSTED && context.Host is not Host.LLAMACPP)
|
||||
{
|
||||
@this.GetProviderModelName(context)
|
||||
}
|
||||
else
|
||||
{
|
||||
@("as selected by provider")
|
||||
}
|
||||
</MudTd>
|
||||
<MudTd Style="text-align: left;">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.OpenInBrowser" Class="ma-2" Href="@this.GetProviderDashboardURL(context.UsedProvider)" Target="_blank" Disabled="@(!this.HasDashboard(context.UsedProvider))">
|
||||
Open Dashboard
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" Class="ma-2" OnClick="() => this.EditProvider(context)">
|
||||
Edit
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" Class="ma-2" OnClick="() => this.DeleteProvider(context)">
|
||||
Delete
|
||||
</MudButton>
|
||||
</MudTd>
|
||||
</RowTemplate>
|
||||
</MudTable>
|
||||
|
||||
@if(this.SettingsManager.ConfigurationData.Providers.Count == 0)
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mt-3">No providers configured yet.</MudText>
|
||||
}
|
||||
@if(this.SettingsManager.ConfigurationData.Providers.Count == 0)
|
||||
{
|
||||
<MudText Typo="Typo.h6" Class="mt-3">No providers configured yet.</MudText>
|
||||
}
|
||||
|
||||
<MudButton
|
||||
Variant="Variant.Filled" Color="@Color.Primary"
|
||||
StartIcon="@Icons.Material.Filled.AddRoad"
|
||||
Class="mt-3 mb-6" OnClick="@this.AddProvider">
|
||||
Add Provider
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddProvider">
|
||||
Add Provider
|
||||
</MudButton>
|
||||
</ExpansionPanel>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mb-3">Options</MudText>
|
||||
<ConfigurationOption OptionDescription="Save energy?" LabelOn="Energy saving is enabled" LabelOff="Energy saving is disabled" State="@(() => this.SettingsManager.ConfigurationData.IsSavingEnergy)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.IsSavingEnergy = updatedState)" OptionHelp="When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."/>
|
||||
<ConfigurationOption OptionDescription="Enable spellchecking?" LabelOn="Spellchecking is enabled" LabelOff="Spellchecking is disabled" State="@(() => this.SettingsManager.ConfigurationData.EnableSpellchecking)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.EnableSpellchecking = updatedState)" OptionHelp="When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections." />
|
||||
<ConfigurationSelect OptionDescription="Shortcut to send input" SelectedValue="@(() => this.SettingsManager.ConfigurationData.ShortcutSendBehavior)" Data="@ConfigurationSelectDataFactory.GetSendBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.ShortcutSendBehavior = selectedValue)" OptionHelp="Do you want to use any shortcut to send your input?"/>
|
||||
<ConfigurationSelect OptionDescription="Check for updates" SelectedValue="@(() => this.SettingsManager.ConfigurationData.UpdateBehavior)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.UpdateBehavior = selectedValue)" OptionHelp="How often should we check for app updates?"/>
|
||||
<ConfigurationSelect OptionDescription="Workspace behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.WorkspaceStorageBehavior = selectedValue)" OptionHelp="Should we store your chats?"/>
|
||||
<ConfigurationSelect OptionDescription="Workspace maintenance" SelectedValue="@(() => this.SettingsManager.ConfigurationData.WorkspaceStorageTemporaryMaintenancePolicy)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageTemporaryMaintenancePolicyData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.WorkspaceStorageTemporaryMaintenancePolicy = selectedValue)" OptionHelp="If and when should we delete your temporary chats?"/>
|
||||
<ConfigurationSelect OptionDescription="Navigation bar behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.NavigationBehavior = selectedValue)" OptionHelp="Select the desired behavior for the navigation bar."/>
|
||||
</MudPaper>
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Apps" HeaderText="App Options">
|
||||
<ConfigurationOption OptionDescription="Save energy?" LabelOn="Energy saving is enabled" LabelOff="Energy saving is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.IsSavingEnergy)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.IsSavingEnergy = updatedState)" OptionHelp="When enabled, streamed content from the AI is updated once every third second. When disabled, streamed content will be updated as soon as it is available."/>
|
||||
<ConfigurationOption OptionDescription="Enable spellchecking?" LabelOn="Spellchecking is enabled" LabelOff="Spellchecking is disabled" State="@(() => this.SettingsManager.ConfigurationData.App.EnableSpellchecking)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.App.EnableSpellchecking = updatedState)" OptionHelp="When enabled, spellchecking will be active in all input fields. Depending on your operating system, errors may not be visually highlighted, but right-clicking may still offer possible corrections." />
|
||||
<ConfigurationSelect OptionDescription="Check for updates" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.UpdateBehavior)" Data="@ConfigurationSelectDataFactory.GetUpdateBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.UpdateBehavior = selectedValue)" OptionHelp="How often should we check for app updates?"/>
|
||||
<ConfigurationSelect OptionDescription="Navigation bar behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.App.NavigationBehavior)" Data="@ConfigurationSelectDataFactory.GetNavBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.App.NavigationBehavior = selectedValue)" OptionHelp="Select the desired behavior for the navigation bar."/>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Chat" HeaderText="Chat Options">
|
||||
<ConfigurationSelect OptionDescription="Shortcut to send input" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior)" Data="@ConfigurationSelectDataFactory.GetSendBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.ShortcutSendBehavior = selectedValue)" OptionHelp="Do you want to use any shortcut to send your input?"/>
|
||||
<ConfigurationOption OptionDescription="Preselect chat options?" LabelOn="Chat options are preselected" LabelOff="No chat options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Chat.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect chat options. This is might be useful when you prefer a specific provider."/>
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Chat.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Chat.PreselectedProvider = selectedValue)"/>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Work" HeaderText="Workspace Options">
|
||||
<ConfigurationSelect OptionDescription="Workspace behavior" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageBehaviorData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageBehavior = selectedValue)" OptionHelp="Should we store your chats?"/>
|
||||
<ConfigurationSelect OptionDescription="Workspace maintenance" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy)" Data="@ConfigurationSelectDataFactory.GetWorkspaceStorageTemporaryMaintenancePolicyData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Workspace.StorageTemporaryMaintenancePolicy = selectedValue)" OptionHelp="If and when should we delete your temporary chats?"/>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.FindInPage" HeaderText="Assistant: Icon Finder Options">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect icon options?" LabelOn="Icon options are preselected" LabelOff="No icon options are preselected" State="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the icon options. This is might be useful when you prefer a specific icon source or LLM model."/>
|
||||
<ConfigurationSelect OptionDescription="Preselect the icon source" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource)" Data="@ConfigurationSelectDataFactory.GetIconSourcesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedSource = selectedValue)" OptionHelp="Which icon source should be preselected?"/>
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.IconFinder.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.IconFinder.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Translate" HeaderText="Assistant: Translator Options">
|
||||
<ConfigurationSlider T="int" OptionDescription="How fast should the live translation react?" Min="500" Max="3_000" Step="100" Unit="milliseconds" Value="@(() => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds = updatedValue)"/>
|
||||
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect translator options?" LabelOn="Translator options are preselected" LabelOff="No translator options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the translator options. This is might be useful when you prefer a specific target language or LLM model."/>
|
||||
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
||||
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions || this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before translating it."/>
|
||||
<ConfigurationOption OptionDescription="Preselect live translation?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" LabelOn="Live translation is preselected" LabelOff="Live translation is not preselected" State="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation = updatedState)" />
|
||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Translation.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Translation.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Code" HeaderText="Assistant: Coding Options">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect coding options?" LabelOn="Coding options are preselected" LabelOff="No coding options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the coding options. This is might be useful when you prefer a specific programming language or LLM model."/>
|
||||
<ConfigurationOption OptionDescription="Preselect compiler messages?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" LabelOn="Compiler messages are preselected" LabelOff="Compiler messages are not preselected" State="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Coding.PreselectCompilerMessages = updatedState)" />
|
||||
<ConfigurationSelect OptionDescription="Preselect a programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonCodingLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage = selectedValue)" OptionHelp="Which programming language should be preselected for added contexts?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.Coding.PreselectedProgrammingLanguage is CommonCodingLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another programming language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" Icon="@Icons.Material.Filled.Code" Text="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Coding.PreselectedOtherProgrammingLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Coding.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Coding.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextSnippet" HeaderText="Assistant: Text Summarizer Options">
|
||||
<ConfigurationOption OptionDescription="Hide the web content reader?" LabelOn="Web content reader is hidden" LabelOff="Web content reader is shown" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader = updatedState)" OptionHelp="When activated, the web content reader is hidden and cannot be used. As a result, the user interface becomes a bit easier to use."/>
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect summarizer options?" LabelOn="Summarizer options are preselected" LabelOff="No summarizer options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the text summarizer options. This is might be useful when you prefer a specific language, complexity, or LLM."/>
|
||||
<ConfigurationOption OptionDescription="Preselect the web content reader?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Web content reader is preselected" LabelOff="Web content reader is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader = updatedState)" OptionHelp="When enabled, the web content reader is preselected. This is might be useful when you prefer to load content from the web very often."/>
|
||||
<ConfigurationOption OptionDescription="Preselect the content cleaner agent?" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions || this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)" LabelOn="Content cleaner agent is preselected" LabelOff="Content cleaner agent is not preselected" State="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent = updatedState)" OptionHelp="When enabled, the content cleaner agent is preselected. This is might be useful when you prefer to clean up the content before summarize it."/>
|
||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationSelect OptionDescription="Preselect the summarizer complexity" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity)" Data="@ConfigurationSelectDataFactory.GetComplexityData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity = selectedValue)" OptionHelp="Which summarizer complexity should be preselected?"/>
|
||||
@if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect your expertise" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" Icon="@Icons.Material.Filled.Person" Text="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField = updatedText)"/>
|
||||
}
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.CalendarToday" HeaderText="Assistant: Agenda Options">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect agenda options?" LabelOn="Agenda options are preselected" LabelOff="No agenda options are preselected" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect most agenda options. This is might be useful when you need to create similar agendas often."/>
|
||||
<ConfigurationText OptionDescription="Preselect a name?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Tag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectName)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectName = updatedText)" />
|
||||
<ConfigurationText OptionDescription="Preselect a topic?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.EventNote" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectTopic = updatedText)" />
|
||||
<ConfigurationText OptionDescription="Preselect an objective?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Flag" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectObjective = updatedText)" />
|
||||
<ConfigurationText OptionDescription="Preselect a moderator?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Person3" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectModerator = updatedText)" />
|
||||
<ConfigurationText OptionDescription="Preselect a duration?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectDuration = updatedText)" />
|
||||
<ConfigurationText OptionDescription="Preselect a start time?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Schedule" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime = updatedText)" />
|
||||
<ConfigurationOption OptionDescription="Preselect whether the participants should get to know each other" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should get to know each other" LabelOff="Participants do not need to get to know each other" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants = updatedState)" />
|
||||
<ConfigurationSelect OptionDescription="Preselect the number of participants" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants)" Data="@ConfigurationSelectDataFactory.GetNumberParticipantsData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants = selectedValue)" OptionHelp="How many participants should be preselected?"/>
|
||||
<ConfigurationOption OptionDescription="Preselect whether the participants should actively involved" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants should be actively involved" LabelOff="Participants do not need to be actively involved" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation = updatedState)" />
|
||||
<ConfigurationOption OptionDescription="Preselect whether the meeting is virtual" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Meeting is virtual" LabelOff="Meeting is in person" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual = updatedState)" />
|
||||
<ConfigurationText OptionDescription="Preselect a location?" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.MyLocation" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectLocation = updatedText)" />
|
||||
<ConfigurationOption OptionDescription="Preselect whether there is a joint dinner" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a joint dinner" LabelOff="There is no joint dinner" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner = updatedState)" />
|
||||
<ConfigurationOption OptionDescription="Preselect whether there is a social event" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="There is a social event" LabelOff="There is no social event" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity = updatedState)" />
|
||||
<ConfigurationOption OptionDescription="Preselect whether participants needs to arrive and depart" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" LabelOn="Participants need to arrive and depart" LabelOff="Participants do not need to arrive and depart" State="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart = updatedState)" />
|
||||
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. lunch time" Min="30" Max="120" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime = updatedValue)" />
|
||||
<ConfigurationSlider T="int" OptionDescription="Preselect the approx. break time" Min="10" Max="60" Step="5" Unit="minutes" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Value="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime)" ValueUpdate="@(updatedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime = updatedValue)" />
|
||||
|
||||
<ConfigurationSelect OptionDescription="Preselect the agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which agenda language should be preselected?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another agenda language" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Grammar & Spelling Checker">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect grammar & spell checker options?" LabelOn="Grammar & spell checker options are preselected" LabelOff="No grammar & spell checker options are preselected" State="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the grammar & spell checker options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedOtherLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.GrammarSpelling.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.Edit" HeaderText="Assistant: Rewrite & Improve Text">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<ConfigurationOption OptionDescription="Preselect rewrite & improve text options?" LabelOn="Rewrite & improve text options are preselected" LabelOff="No rewrite & improve text options are preselected" State="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions = updatedState)" OptionHelp="When enabled, you can preselect the rewrite & improve text options. This is might be useful when you prefer a specific language or LLM model."/>
|
||||
<ConfigurationSelect OptionDescription="Preselect the target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage)" Data="@ConfigurationSelectDataFactory.GetCommonLanguagesTranslationData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage = selectedValue)" OptionHelp="Which target language should be preselected?"/>
|
||||
@if (this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<ConfigurationText OptionDescription="Preselect another target language" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" Icon="@Icons.Material.Filled.Translate" Text="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage)" TextUpdate="@(updatedText => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedOtherLanguage = updatedText)"/>
|
||||
}
|
||||
<ConfigurationSelect OptionDescription="Preselect a writing style" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle)" Data="@ConfigurationSelectDataFactory.GetWritingStylesData()" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedWritingStyle = selectedValue)" OptionHelp="Which writing style should be preselected?"/>
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.RewriteImprove.PreselectOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.RewriteImprove.PreselectedProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
|
||||
<ExpansionPanel HeaderIcon="@Icons.Material.Filled.TextFields" HeaderText="Agent: Text Content Cleaner Options">
|
||||
<MudPaper Class="pa-3 mb-8 border-dashed border rounded-lg">
|
||||
<MudText Typo="Typo.body1" Class="mb-3">
|
||||
Use Case: this agent is used to clean up text content. It extracts the main content, removes advertisements and other irrelevant things,
|
||||
and attempts to convert relative links into absolute links so that they can be used.
|
||||
</MudText>
|
||||
<ConfigurationOption OptionDescription="Preselect text content cleaner options?" LabelOn="Options are preselected" LabelOff="No options are preselected" State="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" StateUpdate="@(updatedState => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions = updatedState)" OptionHelp="When enabled, you can preselect some agent options. This is might be useful when you prefer a LLM."/>
|
||||
<ConfigurationProviderSelection Data="@this.availableProviders" Disabled="@(() => !this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectAgentOptions)" SelectedValue="@(() => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider)" SelectionUpdate="@(selectedValue => this.SettingsManager.ConfigurationData.TextContentCleaner.PreselectedAgentProvider = selectedValue)"/>
|
||||
</MudPaper>
|
||||
</ExpansionPanel>
|
||||
</MudExpansionPanels>
|
||||
</InnerScrolling>
|
||||
@@ -11,7 +11,7 @@ using DialogOptions = AIStudio.Components.CommonDialogs.DialogOptions;
|
||||
|
||||
namespace AIStudio.Components.Pages;
|
||||
|
||||
public partial class Settings : ComponentBase
|
||||
public partial class Settings : ComponentBase, IMessageBusReceiver, IDisposable
|
||||
{
|
||||
[Inject]
|
||||
public SettingsManager SettingsManager { get; init; } = null!;
|
||||
@@ -24,6 +24,22 @@ public partial class Settings : ComponentBase
|
||||
|
||||
[Inject]
|
||||
protected MessageBus MessageBus { get; init; } = null!;
|
||||
|
||||
private readonly List<ConfigurationSelectData<string>> availableProviders = new();
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
// Register this component with the message bus:
|
||||
this.MessageBus.RegisterComponent(this);
|
||||
this.MessageBus.ApplyFilters(this, [], [ Event.CONFIGURATION_CHANGED ]);
|
||||
|
||||
this.UpdateProviders();
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Provider related
|
||||
|
||||
@@ -43,6 +59,8 @@ public partial class Settings : ComponentBase
|
||||
addedProvider = addedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
||||
|
||||
this.SettingsManager.ConfigurationData.Providers.Add(addedProvider);
|
||||
this.UpdateProviders();
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
@@ -75,6 +93,8 @@ public partial class Settings : ComponentBase
|
||||
editedProvider = editedProvider with { Num = this.SettingsManager.ConfigurationData.NextProviderNum++ };
|
||||
|
||||
this.SettingsManager.ConfigurationData.Providers[this.SettingsManager.ConfigurationData.Providers.IndexOf(provider)] = editedProvider;
|
||||
this.UpdateProviders();
|
||||
|
||||
await this.SettingsManager.StoreSettings();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
@@ -99,6 +119,7 @@ public partial class Settings : ComponentBase
|
||||
await this.SettingsManager.StoreSettings();
|
||||
}
|
||||
|
||||
this.UpdateProviders();
|
||||
await this.MessageBus.SendMessage<bool>(this, Event.CONFIGURATION_CHANGED);
|
||||
}
|
||||
|
||||
@@ -128,6 +149,43 @@ public partial class Settings : ComponentBase
|
||||
var modelName = provider.Model.ToString();
|
||||
return modelName.Length > MAX_LENGTH ? "[...] " + modelName[^Math.Min(MAX_LENGTH, modelName.Length)..] : modelName;
|
||||
}
|
||||
|
||||
private void UpdateProviders()
|
||||
{
|
||||
this.availableProviders.Clear();
|
||||
foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
this.availableProviders.Add(new (provider.InstanceName, provider.Id));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IMessageBusReceiver
|
||||
|
||||
public Task ProcessMessage<TMsg>(ComponentBase? sendingComponent, Event triggeredEvent, TMsg? data)
|
||||
{
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.CONFIGURATION_CHANGED:
|
||||
this.StateHasChanged();
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task<TResult?> ProcessMessageWithResult<TPayload, TResult>(ComponentBase? sendingComponent, Event triggeredEvent, TPayload? data)
|
||||
{
|
||||
return Task.FromResult<TResult?>(default);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Implementation of IDisposable
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
this.MessageBus.Unregister(this);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
@page "/Supporters"
|
||||
@attribute [Route(Path.SUPPORTERS)]
|
||||
|
||||
<MudText Typo="Typo.h3" Class="mb-2">Supporters</MudText>
|
||||
|
||||
|
||||
+10
-36
@@ -1,43 +1,17 @@
|
||||
@page "/assistant/summarizer"
|
||||
@using AIStudio.Settings
|
||||
@attribute [Route(Path.ASSISTANT_SUMMARIZER)]
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
@if (!this.SettingsManager.ConfigurationData.TextSummarizer.HideWebContentReader)
|
||||
{
|
||||
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" Preselect="@(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions && this.SettingsManager.ConfigurationData.TextSummarizer.PreselectWebContentReader)" PreselectContentCleanerAgent="@(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions && this.SettingsManager.ConfigurationData.TextSummarizer.PreselectContentCleanerAgent)"/>
|
||||
}
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="CommonLanguages" @bind-Value="@this.selectedTargetLanguage" AdornmentIcon="@Icons.Material.Filled.Translate" Adornment="Adornment.Start" Label="Target language" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetLanguage in Enum.GetValues<CommonLanguages>())
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">@targetLanguage.Name()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.customTargetLanguage" Validation="@this.ValidateCustomLanguage" Label="Custom target language" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
</MudStack>
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.Name())" @bind-Value="@this.selectedTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" @bind-OtherInput="@this.customTargetLanguage" OtherValue="CommonLanguages.OTHER" LabelOther="Custom target language" ValidateOther="@this.ValidateCustomLanguage" />
|
||||
<EnumSelection T="Complexity" NameFunc="@(complexity => complexity.Name())" @bind-Value="@this.selectedComplexity" Icon="@Icons.Material.Filled.Layers" Label="Target complexity" AllowOther="@true" @bind-OtherInput="@this.expertInField" OtherValue="Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS" LabelOther="Your expertise" ValidateOther="@this.ValidateExpertInField" />
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="Complexity" @bind-Value="@this.selectedComplexity" AdornmentIcon="@Icons.Material.Filled.Layers" Adornment="Adornment.Start" Label="Target complexity" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetComplexity in Enum.GetValues<Complexity>())
|
||||
{
|
||||
<MudSelectItem Value="@targetComplexity">@targetComplexity.Name()</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedComplexity is Complexity.SCIENTIFIC_LANGUAGE_OTHER_EXPERTS)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.expertInField" Validation="@this.ValidateExpertInField" Label="Your expertise" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.providerSettings" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.SummarizeText()">
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.SummarizeText()" Disabled="@this.isAgentRunning">
|
||||
Summarize
|
||||
</MudButton>
|
||||
+32
-1
@@ -23,12 +23,43 @@ public partial class AssistantTextSummarizer : AssistantBaseCore
|
||||
a summary with the requested complexity. In any case, do not add any information.
|
||||
""";
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.TEXT_SUMMARIZER_ASSISTANT,
|
||||
},
|
||||
];
|
||||
|
||||
private string inputText = string.Empty;
|
||||
private bool isAgentRunning;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private Complexity selectedComplexity;
|
||||
private string expertInField = string.Empty;
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if(this.SettingsManager.ConfigurationData.TextSummarizer.PreselectOptions)
|
||||
{
|
||||
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedTargetLanguage;
|
||||
this.customTargetLanguage = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedOtherLanguage;
|
||||
this.selectedComplexity = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedComplexity;
|
||||
this.expertInField = this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedExpertInField;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.TextSummarizer.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputText = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string? ValidatingText(string text)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(text))
|
||||
@@ -62,7 +93,7 @@ public partial class AssistantTextSummarizer : AssistantBaseCore
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
{this.selectedTargetLanguage.Prompt(this.customTargetLanguage)}
|
||||
{this.selectedTargetLanguage.PromptSummarizing(this.customTargetLanguage)}
|
||||
{this.selectedComplexity.Prompt(this.expertInField)}
|
||||
|
||||
Please summarize the following text:
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.TextSummarizer;
|
||||
|
||||
public static class CommonLanguagePrompts
|
||||
{
|
||||
public static string Prompt(this CommonLanguages language, string customLanguage) => language switch
|
||||
{
|
||||
CommonLanguages.AS_IS => "Do not change the language of the text.",
|
||||
CommonLanguages.OTHER => $"Output you summary in {customLanguage}.",
|
||||
|
||||
_ => $"Output your summary in {language.Name()} ({language}).",
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
@attribute [Route(Path.ASSISTANT_TRANSLATION)]
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
@if (!this.SettingsManager.ConfigurationData.Translation.HideWebContentReader)
|
||||
{
|
||||
<ReadWebContent @bind-Content="@this.inputText" ProviderSettings="@this.providerSettings" @bind-AgentIsRunning="@this.isAgentRunning" Preselect="@(this.SettingsManager.ConfigurationData.Translation.PreselectOptions && this.SettingsManager.ConfigurationData.Translation.PreselectWebContentReader)" PreselectContentCleanerAgent="@(this.SettingsManager.ConfigurationData.Translation.PreselectOptions && this.SettingsManager.ConfigurationData.Translation.PreselectContentCleanerAgent)"/>
|
||||
}
|
||||
|
||||
<MudTextSwitch Label="Live translation" @bind-Value="@this.liveTranslation" LabelOn="Live translation" LabelOff="No live translation"/>
|
||||
@if (this.liveTranslation)
|
||||
{
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" Immediate="@true" DebounceInterval="@this.SettingsManager.ConfigurationData.Translation.DebounceIntervalMilliseconds" OnDebounceIntervalElapsed="() => this.TranslateText(force: false)" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTextField T="string" Disabled="@this.isAgentRunning" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="Target language" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="Custom target language" />
|
||||
<ProviderSelection @bind-ProviderSettings="@this.providerSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
|
||||
<MudButton Disabled="@this.isAgentRunning" Variant="Variant.Filled" Class="mb-3" OnClick="() => this.TranslateText(force: true)">
|
||||
Translate
|
||||
</MudButton>
|
||||
+37
-6
@@ -1,10 +1,10 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Translator;
|
||||
namespace AIStudio.Components.Pages.Translation;
|
||||
|
||||
public partial class AssistantTranslator : AssistantBaseCore
|
||||
public partial class AssistantTranslation : AssistantBaseCore
|
||||
{
|
||||
protected override string Title => "Translator";
|
||||
protected override string Title => "Translation";
|
||||
|
||||
protected override string Description =>
|
||||
"""
|
||||
@@ -19,12 +19,42 @@ public partial class AssistantTranslator : AssistantBaseCore
|
||||
language requires, e.g., shorter sentences, you should split the text into shorter sentences.
|
||||
""";
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new SendToButton
|
||||
{
|
||||
Self = SendToAssistant.TRANSLATION_ASSISTANT,
|
||||
},
|
||||
];
|
||||
|
||||
private bool liveTranslation;
|
||||
private bool isAgentRunning;
|
||||
private string inputText = string.Empty;
|
||||
private string inputTextLastTranslation = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
if (this.SettingsManager.ConfigurationData.Translation.PreselectOptions)
|
||||
{
|
||||
this.liveTranslation = this.SettingsManager.ConfigurationData.Translation.PreselectLiveTranslation;
|
||||
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectedTargetLanguage;
|
||||
this.customTargetLanguage = this.SettingsManager.ConfigurationData.Translation.PreselectOtherLanguage;
|
||||
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Translation.PreselectedProvider);
|
||||
}
|
||||
|
||||
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_TRANSLATION_ASSISTANT).FirstOrDefault();
|
||||
if (deferredContent is not null)
|
||||
this.inputText = deferredContent;
|
||||
|
||||
await base.OnInitializedAsync();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string? ValidatingText(string text)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(text))
|
||||
@@ -48,9 +78,10 @@ public partial class AssistantTranslator : AssistantBaseCore
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
private async Task TranslateText(bool force)
|
||||
{
|
||||
await this.form!.Validate();
|
||||
if (!this.inputIsValid)
|
||||
return;
|
||||
|
||||
@@ -61,7 +92,7 @@ public partial class AssistantTranslator : AssistantBaseCore
|
||||
this.CreateChatThread();
|
||||
var time = this.AddUserRequest(
|
||||
$"""
|
||||
{this.selectedTargetLanguage.Prompt(this.customTargetLanguage)}
|
||||
{this.selectedTargetLanguage.PromptTranslation(this.customTargetLanguage)}
|
||||
|
||||
The given text is:
|
||||
|
||||
@@ -1,50 +0,0 @@
|
||||
@page "/assistant/translator"
|
||||
@using AIStudio.Settings
|
||||
@using AIStudio.Tools
|
||||
@inherits AssistantBaseCore
|
||||
|
||||
<MudField Label="Live translation" Variant="Variant.Outlined" Class="mb-3">
|
||||
<MudSwitch T="bool" @bind-Value="@this.liveTranslation">
|
||||
@(this.liveTranslation ? "Live translation" : "No live translation")
|
||||
</MudSwitch>
|
||||
</MudField>
|
||||
|
||||
@if (this.liveTranslation)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" Immediate="@true" DebounceInterval="1_000" OnDebounceIntervalElapsed="() => this.TranslateText(force: false)" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.inputText" Validation="@this.ValidatingText" AdornmentIcon="@Icons.Material.Filled.DocumentScanner" Adornment="Adornment.Start" Label="Your input" Variant="Variant.Outlined" Lines="6" AutoGrow="@true" MaxLines="12" Class="mb-3" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect T="CommonLanguages" @bind-Value="@this.selectedTargetLanguage" Validation="@this.ValidatingTargetLanguage" AdornmentIcon="@Icons.Material.Filled.Translate" Adornment="Adornment.Start" Label="Target language" Variant="Variant.Outlined" Margin="Margin.Dense">
|
||||
@foreach (var targetLanguage in Enum.GetValues<CommonLanguages>())
|
||||
{
|
||||
if (targetLanguage is CommonLanguages.AS_IS)
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">Please select the target language</MudSelectItem>
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudSelectItem Value="@targetLanguage">@targetLanguage.Name()</MudSelectItem>
|
||||
}
|
||||
}
|
||||
</MudSelect>
|
||||
@if (this.selectedTargetLanguage is CommonLanguages.OTHER)
|
||||
{
|
||||
<MudTextField T="string" @bind-Text="@this.customTargetLanguage" Validation="@this.ValidateCustomLanguage" Label="Custom target language" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudSelect T="Provider" @bind-Value="@this.providerSettings" Validation="@this.ValidatingProvider" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Apps" Margin="Margin.Dense" Label="Provider" Class="mb-3 rounded-lg" Variant="Variant.Outlined">
|
||||
@foreach (var provider in this.SettingsManager.ConfigurationData.Providers)
|
||||
{
|
||||
<MudSelectItem Value="@provider"/>
|
||||
}
|
||||
</MudSelect>
|
||||
|
||||
<MudButton Variant="Variant.Filled" Class="mb-3" OnClick="() => this.TranslateText(force: true)">
|
||||
Translate
|
||||
</MudButton>
|
||||
@@ -1,13 +0,0 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components.Pages.Translator;
|
||||
|
||||
public static class CommonLanguageExtension
|
||||
{
|
||||
public static string Prompt(this CommonLanguages language, string customLanguage) => language switch
|
||||
{
|
||||
CommonLanguages.OTHER => $"Translate the text in {customLanguage}.",
|
||||
|
||||
_ => $"Translate the given text in {language.Name()} ({language}).",
|
||||
};
|
||||
}
|
||||
@@ -45,9 +45,11 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.7" />
|
||||
<PackageReference Include="MudBlazor" Version="7.4.0" />
|
||||
<PackageReference Include="HtmlAgilityPack" Version="1.11.62" />
|
||||
<PackageReference Include="Microsoft.Extensions.FileProviders.Embedded" Version="8.0.8" />
|
||||
<PackageReference Include="MudBlazor" Version="7.6.0" />
|
||||
<PackageReference Include="MudBlazor.Markdown" Version="1.0.2" />
|
||||
<PackageReference Include="ReverseMarkdown" Version="4.6.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<!-- Read the meta data file -->
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio;
|
||||
using AIStudio.Agents;
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools;
|
||||
@@ -29,7 +30,9 @@ builder.Services.AddSingleton(MessageBus.INSTANCE);
|
||||
builder.Services.AddSingleton<Rust>();
|
||||
builder.Services.AddMudMarkdownClipboardService<MarkdownClipboardService>();
|
||||
builder.Services.AddSingleton<SettingsManager>();
|
||||
builder.Services.AddSingleton<Random>();
|
||||
builder.Services.AddSingleton<ThreadSafeRandom>();
|
||||
builder.Services.AddTransient<HTMLParser>();
|
||||
builder.Services.AddTransient<AgentTextContentCleaner>();
|
||||
builder.Services.AddHostedService<UpdateService>();
|
||||
builder.Services.AddHostedService<TemporaryChatService>();
|
||||
builder.Services.AddRazorComponents()
|
||||
|
||||
@@ -41,6 +41,7 @@ public sealed class ProviderAnthropic() : BaseProvider("https://api.anthropic.co
|
||||
{
|
||||
ChatRole.USER => "user",
|
||||
ChatRole.AI => "assistant",
|
||||
ChatRole.AGENT => "assistant",
|
||||
|
||||
_ => "user",
|
||||
},
|
||||
|
||||
@@ -52,6 +52,7 @@ public class ProviderFireworks() : BaseProvider("https://api.fireworks.ai/infere
|
||||
{
|
||||
ChatRole.USER => "user",
|
||||
ChatRole.AI => "assistant",
|
||||
ChatRole.AGENT => "assistant",
|
||||
ChatRole.SYSTEM => "system",
|
||||
|
||||
_ => "user",
|
||||
|
||||
@@ -51,6 +51,7 @@ public sealed class ProviderMistral() : BaseProvider("https://api.mistral.ai/v1/
|
||||
{
|
||||
ChatRole.USER => "user",
|
||||
ChatRole.AI => "assistant",
|
||||
ChatRole.AGENT => "assistant",
|
||||
ChatRole.SYSTEM => "system",
|
||||
|
||||
_ => "user",
|
||||
|
||||
@@ -55,6 +55,7 @@ public sealed class ProviderOpenAI() : BaseProvider("https://api.openai.com/v1/"
|
||||
{
|
||||
ChatRole.USER => "user",
|
||||
ChatRole.AI => "assistant",
|
||||
ChatRole.AGENT => "assistant",
|
||||
ChatRole.SYSTEM => "system",
|
||||
|
||||
_ => "user",
|
||||
|
||||
@@ -44,6 +44,7 @@ public sealed class ProviderSelfHosted(Settings.Provider provider) : BaseProvide
|
||||
{
|
||||
ChatRole.USER => "user",
|
||||
ChatRole.AI => "assistant",
|
||||
ChatRole.AGENT => "assistant",
|
||||
ChatRole.SYSTEM => "system",
|
||||
|
||||
_ => "user",
|
||||
|
||||
+53
-2
@@ -1,6 +1,12 @@
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Components.Pages.Agenda;
|
||||
using AIStudio.Components.Pages.Coding;
|
||||
using AIStudio.Components.Pages.IconFinder;
|
||||
using AIStudio.Components.Pages.RewriteImprove;
|
||||
using AIStudio.Components.Pages.TextSummarizer;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Components;
|
||||
namespace AIStudio.Settings;
|
||||
|
||||
/// <summary>
|
||||
/// A data structure to map a name to a value.
|
||||
@@ -55,4 +61,49 @@ public static class ConfigurationSelectDataFactory
|
||||
yield return new("Navigation never expands, no tooltips", NavBehavior.NEVER_EXPAND_NO_TOOLTIPS);
|
||||
yield return new("Always expand navigation", NavBehavior.ALWAYS_EXPAND);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<IconSources>> GetIconSourcesData()
|
||||
{
|
||||
foreach (var source in Enum.GetValues<IconSources>())
|
||||
yield return new(source.Name(), source);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<CommonLanguages>> GetCommonLanguagesData()
|
||||
{
|
||||
foreach (var language in Enum.GetValues<CommonLanguages>())
|
||||
yield return new(language.Name(), language);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<CommonLanguages>> GetCommonLanguagesTranslationData()
|
||||
{
|
||||
foreach (var language in Enum.GetValues<CommonLanguages>())
|
||||
if(language is CommonLanguages.AS_IS)
|
||||
yield return new("Not yet specified", language);
|
||||
else
|
||||
yield return new(language.Name(), language);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<CommonCodingLanguages>> GetCommonCodingLanguagesData()
|
||||
{
|
||||
foreach (var language in Enum.GetValues<CommonCodingLanguages>())
|
||||
yield return new(language.Name(), language);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<Complexity>> GetComplexityData()
|
||||
{
|
||||
foreach (var complexity in Enum.GetValues<Complexity>())
|
||||
yield return new(complexity.Name(), complexity);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<NumberParticipants>> GetNumberParticipantsData()
|
||||
{
|
||||
foreach (var number in Enum.GetValues<NumberParticipants>())
|
||||
yield return new(number.Name(), number);
|
||||
}
|
||||
|
||||
public static IEnumerable<ConfigurationSelectData<WritingStyles>> GetWritingStylesData()
|
||||
{
|
||||
foreach (var style in Enum.GetValues<WritingStyles>())
|
||||
yield return new(style.Name(), style);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
namespace AIStudio.Settings;
|
||||
|
||||
/// <summary>
|
||||
/// The data model for the settings file.
|
||||
/// </summary>
|
||||
public sealed class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The version of the settings file. Allows us to upgrade the settings
|
||||
/// when a new version is available.
|
||||
/// </summary>
|
||||
public Version Version { get; init; } = Version.V3;
|
||||
|
||||
/// <summary>
|
||||
/// List of configured providers.
|
||||
/// </summary>
|
||||
public List<Provider> Providers { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The next provider number to use.
|
||||
/// </summary>
|
||||
public uint NextProviderNum { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// Should we save energy? When true, we will update content streamed
|
||||
/// from the server, i.e., AI, less frequently.
|
||||
/// </summary>
|
||||
public bool IsSavingEnergy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Shortcuts to send the input to the AI.
|
||||
/// </summary>
|
||||
public SendBehavior ShortcutSendBehavior { get; set; } = SendBehavior.MODIFER_ENTER_IS_SENDING;
|
||||
|
||||
/// <summary>
|
||||
/// Should we enable spellchecking for all input fields?
|
||||
/// </summary>
|
||||
public bool EnableSpellchecking { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If and when we should look for updates.
|
||||
/// </summary>
|
||||
public UpdateBehavior UpdateBehavior { get; set; } = UpdateBehavior.ONCE_STARTUP;
|
||||
|
||||
/// <summary>
|
||||
/// The chat storage behavior.
|
||||
/// </summary>
|
||||
public WorkspaceStorageBehavior WorkspaceStorageBehavior { get; set; } = WorkspaceStorageBehavior.STORE_CHATS_AUTOMATICALLY;
|
||||
|
||||
/// <summary>
|
||||
/// The chat storage maintenance behavior.
|
||||
/// </summary>
|
||||
public WorkspaceStorageTemporaryMaintenancePolicy WorkspaceStorageTemporaryMaintenancePolicy { get; set; } = WorkspaceStorageTemporaryMaintenancePolicy.DELETE_OLDER_THAN_90_DAYS;
|
||||
|
||||
/// <summary>
|
||||
/// The navigation behavior.
|
||||
/// </summary>
|
||||
public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER;
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
/// <summary>
|
||||
/// The data model for the settings file.
|
||||
/// </summary>
|
||||
public sealed class Data
|
||||
{
|
||||
/// <summary>
|
||||
/// The version of the settings file. Allows us to upgrade the settings
|
||||
/// when a new version is available.
|
||||
/// </summary>
|
||||
public Version Version { get; init; } = Version.V4;
|
||||
|
||||
/// <summary>
|
||||
/// List of configured providers.
|
||||
/// </summary>
|
||||
public List<Provider> Providers { get; init; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// The next provider number to use.
|
||||
/// </summary>
|
||||
public uint NextProviderNum { get; set; } = 1;
|
||||
|
||||
public DataApp App { get; init; } = new();
|
||||
|
||||
public DataChat Chat { get; init; } = new();
|
||||
|
||||
public DataWorkspace Workspace { get; init; } = new();
|
||||
|
||||
public DataIconFinder IconFinder { get; init; } = new();
|
||||
|
||||
public DataTranslation Translation { get; init; } = new();
|
||||
|
||||
public DataCoding Coding { get; init; } = new();
|
||||
|
||||
public DataTextSummarizer TextSummarizer { get; init; } = new();
|
||||
|
||||
public DataTextContentCleaner TextContentCleaner { get; init; } = new();
|
||||
|
||||
public DataAgenda Agenda { get; init; } = new();
|
||||
|
||||
public DataGrammarSpelling GrammarSpelling { get; init; } = new();
|
||||
|
||||
public DataRewriteImprove RewriteImprove { get; init; } = new();
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
using AIStudio.Components.Pages.Agenda;
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataAgenda
|
||||
{
|
||||
/// <summary>
|
||||
/// Preselect any agenda options?
|
||||
/// </summary>
|
||||
public bool PreselectOptions { get; set; }
|
||||
|
||||
public string PreselectName { get; set; } = string.Empty;
|
||||
|
||||
public string PreselectTopic { get; set; } = string.Empty;
|
||||
|
||||
public string PreselectObjective { get; set; } = string.Empty;
|
||||
|
||||
public string PreselectModerator { get; set; } = string.Empty;
|
||||
|
||||
public string PreselectDuration { get; set; } = string.Empty;
|
||||
|
||||
public string PreselectStartTime { get; set; } = string.Empty;
|
||||
|
||||
public bool PreselectIntroduceParticipants { get; set; }
|
||||
|
||||
public NumberParticipants PreselectNumberParticipants { get; set; } = NumberParticipants.NOT_SPECIFIED;
|
||||
|
||||
public bool PreselectActiveParticipation { get; set; }
|
||||
|
||||
public bool PreselectIsMeetingVirtual { get; set; } = true;
|
||||
|
||||
public string PreselectLocation { get; set; } = string.Empty;
|
||||
|
||||
public bool PreselectJointDinner { get; set; }
|
||||
|
||||
public bool PreselectSocialActivity { get; set; }
|
||||
|
||||
public bool PreselectArriveAndDepart { get; set; }
|
||||
|
||||
public int PreselectLunchTime { get; set; }
|
||||
|
||||
public int PreselectBreakTime { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect the target language?
|
||||
/// </summary>
|
||||
public CommonLanguages PreselectedTargetLanguage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect any other language?
|
||||
/// </summary>
|
||||
public string PreselectedOtherLanguage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Preselect a agenda provider?
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Should we save energy? When true, we will update content streamed
|
||||
/// from the server, i.e., AI, less frequently.
|
||||
/// </summary>
|
||||
public bool IsSavingEnergy { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we enable spellchecking for all input fields?
|
||||
/// </summary>
|
||||
public bool EnableSpellchecking { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If and when we should look for updates.
|
||||
/// </summary>
|
||||
public UpdateBehavior UpdateBehavior { get; set; } = UpdateBehavior.ONCE_STARTUP;
|
||||
|
||||
/// <summary>
|
||||
/// The navigation behavior.
|
||||
/// </summary>
|
||||
public NavBehavior NavigationBehavior { get; set; } = NavBehavior.EXPAND_ON_HOVER;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataChat
|
||||
{
|
||||
/// <summary>
|
||||
/// Shortcuts to send the input to the AI.
|
||||
/// </summary>
|
||||
public SendBehavior ShortcutSendBehavior { get; set; } = SendBehavior.MODIFER_ENTER_IS_SENDING;
|
||||
|
||||
/// <summary>
|
||||
/// Preselect any chat options?
|
||||
/// </summary>
|
||||
public bool PreselectOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Should we preselect a provider for the chat?
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
using AIStudio.Components.Pages.Coding;
|
||||
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataCoding
|
||||
{
|
||||
/// <summary>
|
||||
/// Preselect any coding options?
|
||||
/// </summary>
|
||||
public bool PreselectOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect the compiler messages?
|
||||
/// </summary>
|
||||
public bool PreselectCompilerMessages { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect the coding language for new contexts?
|
||||
/// </summary>
|
||||
public CommonCodingLanguages PreselectedProgrammingLanguage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Do you want to preselect any other language?
|
||||
/// </summary>
|
||||
public string PreselectedOtherProgrammingLanguage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Which coding provider should be preselected?
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
using AIStudio.Tools;
|
||||
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataGrammarSpelling
|
||||
{
|
||||
/// <summary>
|
||||
/// Preselect any rewrite options?
|
||||
/// </summary>
|
||||
public bool PreselectOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect the target language?
|
||||
/// </summary>
|
||||
public CommonLanguages PreselectedTargetLanguage { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Preselect any other language?
|
||||
/// </summary>
|
||||
public string PreselectedOtherLanguage { get; set; } = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// Preselect a provider?
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using AIStudio.Components.Pages.IconFinder;
|
||||
|
||||
namespace AIStudio.Settings.DataModel;
|
||||
|
||||
public sealed class DataIconFinder
|
||||
{
|
||||
/// <summary>
|
||||
/// Do we want to preselect any icon options?
|
||||
/// </summary>
|
||||
public bool PreselectOptions { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The preselected icon source.
|
||||
/// </summary>
|
||||
public IconSources PreselectedSource { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The preselected icon provider.
|
||||
/// </summary>
|
||||
public string PreselectedProvider { get; set; } = string.Empty;
|
||||
}
|
||||
Loaded 100 of 144 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user