mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-10-18 05:58:00 +00:00
Allow assistants to run in the background (#828)
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
Build and Release / Determine run mode (push) Waiting to run
Build and Release / Read metadata (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-apple-darwin, osx-arm64, macos-latest, aarch64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-pc-windows-msvc.exe, win-arm64, windows-latest, aarch64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-aarch64-unknown-linux-gnu, linux-arm64, ubuntu-22.04-arm, aarch64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-apple-darwin, osx-x64, macos-latest, x86_64-apple-darwin, dmg,app,updater, dmg) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-pc-windows-msvc.exe, win-x64, windows-latest, x86_64-pc-windows-msvc, nsis,updater, nsis) (push) Blocked by required conditions
Build and Release / Build app (${{ matrix.dotnet_runtime }}) (-x86_64-unknown-linux-gnu, linux-x64, ubuntu-22.04, x86_64-unknown-linux-gnu, appimage,updater, appimage) (push) Blocked by required conditions
Build and Release / Prepare & create release (push) Blocked by required conditions
Build and Release / Publish release (push) Blocked by required conditions
This commit is contained in:
1 parent
fc53278c60
commit
508c7f9701
52 files changed
+2464
-168
No files matched your search
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.Agenda;
|
||||
|
||||
@@ -185,6 +186,85 @@ public partial class AssistantAgenda : AssistantBaseCore<SettingsDialogAgenda>
|
||||
private string inputWhoIsPresenting = string.Empty;
|
||||
|
||||
private readonly List<string> contentLines = [];
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TOPIC_STATE_KEY = new(nameof(inputTopic));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_NAME_STATE_KEY = new(nameof(inputName));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_CONTENT_STATE_KEY = new(nameof(inputContent));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_DURATION_STATE_KEY = new(nameof(inputDuration));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_START_TIME_STATE_KEY = new(nameof(inputStartTime));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> SELECTED_FOCI_STATE_KEY = new(nameof(selectedFoci));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> JUST_BRIEFLY_STATE_KEY = new(nameof(justBriefly));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_OBJECTIVE_STATE_KEY = new(nameof(inputObjective));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_MODERATOR_STATE_KEY = new(nameof(inputModerator));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<bool> INTRODUCE_PARTICIPANTS_STATE_KEY = new(nameof(introduceParticipants));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_MEETING_VIRTUAL_STATE_KEY = new(nameof(isMeetingVirtual));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_LOCATION_STATE_KEY = new(nameof(inputLocation));
|
||||
private static readonly AssistantSessionStateKey<bool> GOING_TO_DINNER_STATE_KEY = new(nameof(goingToDinner));
|
||||
private static readonly AssistantSessionStateKey<bool> DOING_SOCIAL_ACTIVITY_STATE_KEY = new(nameof(doingSocialActivity));
|
||||
private static readonly AssistantSessionStateKey<bool> NEED_TO_ARRIVE_AND_DEPART_STATE_KEY = new(nameof(needToArriveAndDepart));
|
||||
private static readonly AssistantSessionStateKey<int> DURATION_LUNCH_BREAK_STATE_KEY = new(nameof(durationLunchBreak));
|
||||
private static readonly AssistantSessionStateKey<int> DURATION_BREAKS_STATE_KEY = new(nameof(durationBreaks));
|
||||
private static readonly AssistantSessionStateKey<bool> ACTIVE_PARTICIPATION_STATE_KEY = new(nameof(activeParticipation));
|
||||
private static readonly AssistantSessionStateKey<NumberParticipants> NUMBER_PARTICIPANTS_STATE_KEY = new(nameof(numberParticipants));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_WHO_IS_PRESENTING_STATE_KEY = new(nameof(inputWhoIsPresenting));
|
||||
private static readonly AssistantSessionStateKey<List<string>> CONTENT_LINES_STATE_KEY = new(nameof(contentLines));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TOPIC_STATE_KEY, this.inputTopic);
|
||||
state.Set(INPUT_NAME_STATE_KEY, this.inputName);
|
||||
state.Set(INPUT_CONTENT_STATE_KEY, this.inputContent);
|
||||
state.Set(INPUT_DURATION_STATE_KEY, this.inputDuration);
|
||||
state.Set(INPUT_START_TIME_STATE_KEY, this.inputStartTime);
|
||||
state.SetHashSet(SELECTED_FOCI_STATE_KEY, this.selectedFoci);
|
||||
state.SetHashSet(JUST_BRIEFLY_STATE_KEY, this.justBriefly);
|
||||
state.Set(INPUT_OBJECTIVE_STATE_KEY, this.inputObjective);
|
||||
state.Set(INPUT_MODERATOR_STATE_KEY, this.inputModerator);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(INTRODUCE_PARTICIPANTS_STATE_KEY, this.introduceParticipants);
|
||||
state.Set(IS_MEETING_VIRTUAL_STATE_KEY, this.isMeetingVirtual);
|
||||
state.Set(INPUT_LOCATION_STATE_KEY, this.inputLocation);
|
||||
state.Set(GOING_TO_DINNER_STATE_KEY, this.goingToDinner);
|
||||
state.Set(DOING_SOCIAL_ACTIVITY_STATE_KEY, this.doingSocialActivity);
|
||||
state.Set(NEED_TO_ARRIVE_AND_DEPART_STATE_KEY, this.needToArriveAndDepart);
|
||||
state.Set(DURATION_LUNCH_BREAK_STATE_KEY, this.durationLunchBreak);
|
||||
state.Set(DURATION_BREAKS_STATE_KEY, this.durationBreaks);
|
||||
state.Set(ACTIVE_PARTICIPATION_STATE_KEY, this.activeParticipation);
|
||||
state.Set(NUMBER_PARTICIPANTS_STATE_KEY, this.numberParticipants);
|
||||
state.Set(INPUT_WHO_IS_PRESENTING_STATE_KEY, this.inputWhoIsPresenting);
|
||||
state.SetList(CONTENT_LINES_STATE_KEY, this.contentLines);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TOPIC_STATE_KEY, value => this.inputTopic = value);
|
||||
state.Restore(INPUT_NAME_STATE_KEY, value => this.inputName = value);
|
||||
state.Restore(INPUT_CONTENT_STATE_KEY, value => this.inputContent = value);
|
||||
state.Restore(INPUT_DURATION_STATE_KEY, value => this.inputDuration = value);
|
||||
state.Restore(INPUT_START_TIME_STATE_KEY, value => this.inputStartTime = value);
|
||||
state.Restore(SELECTED_FOCI_STATE_KEY, value => this.selectedFoci = value);
|
||||
state.Restore(JUST_BRIEFLY_STATE_KEY, value => this.justBriefly = value);
|
||||
state.Restore(INPUT_OBJECTIVE_STATE_KEY, value => this.inputObjective = value);
|
||||
state.Restore(INPUT_MODERATOR_STATE_KEY, value => this.inputModerator = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(INTRODUCE_PARTICIPANTS_STATE_KEY, value => this.introduceParticipants = value);
|
||||
state.Restore(IS_MEETING_VIRTUAL_STATE_KEY, value => this.isMeetingVirtual = value);
|
||||
state.Restore(INPUT_LOCATION_STATE_KEY, value => this.inputLocation = value);
|
||||
state.Restore(GOING_TO_DINNER_STATE_KEY, value => this.goingToDinner = value);
|
||||
state.Restore(DOING_SOCIAL_ACTIVITY_STATE_KEY, value => this.doingSocialActivity = value);
|
||||
state.Restore(NEED_TO_ARRIVE_AND_DEPART_STATE_KEY, value => this.needToArriveAndDepart = value);
|
||||
state.Restore(DURATION_LUNCH_BREAK_STATE_KEY, value => this.durationLunchBreak = value);
|
||||
state.Restore(DURATION_BREAKS_STATE_KEY, value => this.durationBreaks = value);
|
||||
state.Restore(ACTIVE_PARTICIPATION_STATE_KEY, value => this.activeParticipation = value);
|
||||
state.Restore(NUMBER_PARTICIPANTS_STATE_KEY, value => this.numberParticipants = value);
|
||||
state.Restore(INPUT_WHO_IS_PRESENTING_STATE_KEY, value => this.inputWhoIsPresenting = value);
|
||||
state.RestoreList(CONTENT_LINES_STATE_KEY, this.contentLines);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
|
||||
<InnerScrolling>
|
||||
<ChildContent>
|
||||
<MudForm @ref="@(this.Form)" @bind-IsValid="@(this.InputIsValid)" @bind-Errors="@(this.inputIssues)" FieldChanged="@this.TriggerFormChange" Class="pr-2">
|
||||
<MudForm @ref="@(this.Form)" @bind-IsValid="@(this.InputIsValid)" @bind-Errors="@(this.InputIssues)" FieldChanged="@this.TriggerFormChange" Class="pr-2">
|
||||
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-2">
|
||||
@this.Description
|
||||
</MudText>
|
||||
@@ -38,10 +38,10 @@
|
||||
</CascadingValue>
|
||||
|
||||
<MudStack Row="true" AlignItems="AlignItems.Center" StretchItems="StretchItems.Start" Class="mb-3">
|
||||
<MudButton Disabled="@(this.SubmitDisabled || this.isProcessing)" Variant="Variant.Filled" OnClick="@(async () => await this.Start())" Style="@this.SubmitButtonStyle">
|
||||
<MudButton Disabled="@(this.SubmitDisabled || this.IsProcessing)" Variant="Variant.Filled" OnClick="@(async () => await this.Start())" Style="@this.SubmitButtonStyle">
|
||||
@this.SubmitText
|
||||
</MudButton>
|
||||
@if (this.isProcessing && this.CancellationTokenSource is not null)
|
||||
@if (this.IsProcessing)
|
||||
{
|
||||
<MudTooltip Text="@TB("Stop generation")">
|
||||
<MudIconButton Variant="Variant.Filled" Icon="@Icons.Material.Filled.Stop" Color="Color.Error" OnClick="@(async () => await this.CancelStreaming())"/>
|
||||
@@ -50,9 +50,9 @@
|
||||
</MudStack>
|
||||
}
|
||||
</MudForm>
|
||||
<Issues IssuesData="@(this.inputIssues)"/>
|
||||
<Issues IssuesData="@(this.InputIssues)"/>
|
||||
|
||||
@if (this.ShowDedicatedProgress && this.isProcessing)
|
||||
@if (this.ShowDedicatedProgress && this.IsProcessing)
|
||||
{
|
||||
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
|
||||
}
|
||||
@@ -63,9 +63,9 @@
|
||||
<div id="@BEFORE_RESULT_DIV_ID" class="mt-3">
|
||||
</div>
|
||||
|
||||
@if (this.ShowResult && !this.ShowEntireChatThread && this.resultingContentBlock is not null && this.resultingContentBlock.Content is not null)
|
||||
@if (this.ShowResult && !this.ShowEntireChatThread && this.ResultingContentBlock is not null && this.ResultingContentBlock.Content is not null)
|
||||
{
|
||||
<ContentBlockComponent Role="@(this.resultingContentBlock.Role)" Type="@(this.resultingContentBlock.ContentType)" Time="@(this.resultingContentBlock.Time)" Content="@this.resultingContentBlock.Content"/>
|
||||
<ContentBlockComponent Role="@(this.ResultingContentBlock.Role)" Type="@(this.ResultingContentBlock.ContentType)" Time="@(this.ResultingContentBlock.Time)" Content="@this.ResultingContentBlock.Content"/>
|
||||
}
|
||||
|
||||
@if(this.ShowResult && this.ShowEntireChatThread && this.ChatThread is not null)
|
||||
|
||||
@@ -2,6 +2,8 @@ using AIStudio.Chat;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AIJobs;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.Services;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
@@ -36,6 +38,15 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
[Inject]
|
||||
private MudTheme ColorTheme { get; init; } = null!;
|
||||
|
||||
[Inject]
|
||||
protected AssistantSessionService AssistantSessionService { get; init; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the job service used to run assistant-created chats independently from the assistant UI.
|
||||
/// </summary>
|
||||
[Inject]
|
||||
protected AIJobService AIJobService { get; init; } = null!;
|
||||
|
||||
protected abstract string Title { get; }
|
||||
|
||||
@@ -45,7 +56,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
protected abstract Tools.Components Component { get; }
|
||||
|
||||
protected virtual Func<string> Result2Copy => () => this.resultingContentBlock is null ? string.Empty : this.resultingContentBlock.Content switch
|
||||
protected virtual Func<string> Result2Copy => () => this.ResultingContentBlock is null ? string.Empty : this.ResultingContentBlock.Content switch
|
||||
{
|
||||
ContentText textBlock => textBlock.Text,
|
||||
_ => string.Empty,
|
||||
@@ -111,20 +122,29 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
protected virtual bool HasSettingsPanel => typeof(TSettings) != typeof(NoSettingsPanel);
|
||||
|
||||
protected AIStudio.Settings.Provider ProviderSettings = Settings.Provider.NONE;
|
||||
protected MudForm? Form;
|
||||
protected bool InputIsValid;
|
||||
protected Profile CurrentProfile = Profile.NO_PROFILE;
|
||||
protected ChatTemplate CurrentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE;
|
||||
protected ChatThread? ChatThread;
|
||||
protected IContent? LastUserPrompt;
|
||||
protected CancellationTokenSource? CancellationTokenSource;
|
||||
|
||||
private readonly Timer formChangeTimer = new(TimeSpan.FromSeconds(1.6));
|
||||
|
||||
protected MudForm? Form;
|
||||
protected CancellationTokenSource? CancellationTokenSource;
|
||||
private bool isDisposed;
|
||||
private AssistantSessionKey assistantSessionKey;
|
||||
private Guid? assistantSessionId;
|
||||
private AssistantSessionSnapshot? pendingRenderedAssistantSessionSnapshot;
|
||||
|
||||
private ContentBlock? resultingContentBlock;
|
||||
private string[] inputIssues = [];
|
||||
private bool isProcessing;
|
||||
/// <summary>
|
||||
/// Gets whether the Blazor component instance has already been disposed.
|
||||
/// </summary>
|
||||
protected bool IsAssistantComponentDisposed => this.isDisposed;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether this component has attached an assistant session snapshot.
|
||||
/// </summary>
|
||||
protected bool HasAssistantSession => this.assistantSessionId is not null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the assistant-specific identifier used to distinguish session slots.
|
||||
/// </summary>
|
||||
protected virtual string AssistantSessionInstanceId => this.GetType().FullName ?? this.Component.ToString();
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
@@ -150,6 +170,8 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
this.ProviderSettings = this.SettingsManager.GetPreselectedProvider(this.Component);
|
||||
this.CurrentProfile = this.SettingsManager.GetPreselectedProfile(this.Component);
|
||||
this.CurrentChatTemplate = this.SettingsManager.GetPreselectedChatTemplate(this.Component);
|
||||
this.assistantSessionKey = new(this.Component, this.AssistantSessionInstanceId);
|
||||
await this.AttachAssistantSessionIfAvailable();
|
||||
}
|
||||
|
||||
protected override async Task OnParametersSetAsync()
|
||||
@@ -166,6 +188,12 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
// We don't want to show validation errors when the user opens the dialog.
|
||||
if(firstRender)
|
||||
this.Form?.ResetValidation();
|
||||
|
||||
if (this.pendingRenderedAssistantSessionSnapshot is { } snapshot)
|
||||
{
|
||||
this.pendingRenderedAssistantSessionSnapshot = null;
|
||||
await this.OnAssistantSessionRenderedAsync(snapshot);
|
||||
}
|
||||
|
||||
await base.OnAfterRenderAsync(firstRender);
|
||||
}
|
||||
@@ -191,12 +219,67 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
private async Task Start()
|
||||
{
|
||||
using (this.CancellationTokenSource = new())
|
||||
var activeSession = this.AssistantSessionService.TryGetSnapshot(this.assistantSessionKey);
|
||||
if (activeSession?.IsActive ?? false)
|
||||
{
|
||||
await this.AttachAssistantSession(activeSession, restoreClientOnlyContent: true);
|
||||
return;
|
||||
}
|
||||
|
||||
this.CancellationTokenSource = new();
|
||||
this.IsProcessing = true;
|
||||
var startedSession = await this.AssistantSessionService.TryBeginAsync(this.assistantSessionKey, this.Title, this.CancellationTokenSource, this.ChatThread, this.CaptureAssistantSessionState(), this);
|
||||
if (startedSession.IsActive is not true || startedSession.Key != this.assistantSessionKey)
|
||||
{
|
||||
this.CancellationTokenSource.Dispose();
|
||||
this.CancellationTokenSource = null;
|
||||
return;
|
||||
}
|
||||
|
||||
this.assistantSessionId = startedSession.SessionId;
|
||||
await this.RefreshAssistantUIAsync();
|
||||
|
||||
var sessionStatus = AssistantSessionStatus.COMPLETED;
|
||||
var errorMessage = string.Empty;
|
||||
try
|
||||
{
|
||||
await this.SubmitAction();
|
||||
|
||||
if (this.CancellationTokenSource?.IsCancellationRequested ?? false)
|
||||
sessionStatus = AssistantSessionStatus.CANCELED;
|
||||
}
|
||||
catch (OperationCanceledException)
|
||||
{
|
||||
sessionStatus = AssistantSessionStatus.CANCELED;
|
||||
}
|
||||
catch (ProviderRequestException e)
|
||||
{
|
||||
sessionStatus = AssistantSessionStatus.FAILED;
|
||||
errorMessage = e.UserMessage;
|
||||
this.Logger.LogError(e, "The provider request failed for assistant '{AssistantTitle}'. Status={StatusCode}, Reason='{ReasonPhrase}', Body='{ResponseBody}'", this.Title, e.StatusCode, e.ReasonPhrase, e.ResponseBody);
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, e.UserMessage));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
sessionStatus = AssistantSessionStatus.FAILED;
|
||||
errorMessage = e.Message;
|
||||
this.Logger.LogError(e, "The assistant session '{AssistantTitle}' failed.", this.Title);
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.Stream, string.Format(this.TB("The assistant failed. The message is: '{0}'"), e.Message)));
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.IsProcessing = false;
|
||||
var sessionCancellationTokenSource = this.CancellationTokenSource;
|
||||
this.CancellationTokenSource = null;
|
||||
if (this.assistantSessionId is { } sessionId)
|
||||
{
|
||||
await this.AssistantSessionService.CompleteAsync(this.assistantSessionKey, sessionId, sessionStatus, errorMessage, this.ChatThread, this.CaptureAssistantSessionState(), this);
|
||||
if (!this.isDisposed)
|
||||
_ = this.AssistantSessionService.TryTakeInactiveSnapshot(this.assistantSessionKey);
|
||||
}
|
||||
sessionCancellationTokenSource?.Dispose();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
}
|
||||
|
||||
this.CancellationTokenSource = null;
|
||||
}
|
||||
|
||||
private void TriggerFormChange(FormFieldChangedEventArgs _)
|
||||
@@ -221,10 +304,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
/// <param name="issue">The issue to add.</param>
|
||||
protected void AddInputIssue(string issue)
|
||||
{
|
||||
Array.Resize(ref this.inputIssues, this.inputIssues.Length + 1);
|
||||
this.inputIssues[^1] = issue;
|
||||
Array.Resize(ref this.InputIssues, this.InputIssues.Length + 1);
|
||||
this.InputIssues[^1] = issue;
|
||||
this.InputIsValid = false;
|
||||
this.StateHasChanged();
|
||||
_ = this.RefreshAssistantUIAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -232,9 +315,9 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
/// </summary>
|
||||
protected void ClearInputIssues()
|
||||
{
|
||||
this.inputIssues = [];
|
||||
this.InputIssues = [];
|
||||
this.InputIsValid = true;
|
||||
this.StateHasChanged();
|
||||
_ = this.RefreshAssistantUIAsync();
|
||||
}
|
||||
|
||||
protected void CreateChatThread()
|
||||
@@ -310,7 +393,19 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
InitialRemoteWait = true,
|
||||
};
|
||||
|
||||
this.resultingContentBlock = new ContentBlock
|
||||
aiText.StreamingEvent = async () =>
|
||||
{
|
||||
await this.CheckpointAssistantSession();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
};
|
||||
|
||||
aiText.StreamingDone = async () =>
|
||||
{
|
||||
await this.CheckpointAssistantSession();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
};
|
||||
|
||||
this.ResultingContentBlock = new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
@@ -321,12 +416,13 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
if (this.ChatThread is not null)
|
||||
{
|
||||
this.ChatThread.Blocks.Add(this.resultingContentBlock);
|
||||
this.ChatThread.Blocks.Add(this.ResultingContentBlock);
|
||||
this.ChatThread.SelectedProvider = this.ProviderSettings.Id;
|
||||
}
|
||||
|
||||
this.isProcessing = true;
|
||||
this.StateHasChanged();
|
||||
this.IsProcessing = true;
|
||||
await this.CheckpointAssistantSession();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
|
||||
try
|
||||
{
|
||||
@@ -343,18 +439,19 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
this.Logger.LogError(e, "The provider request failed for assistant '{AssistantTitle}'. Status={StatusCode}, Reason='{ReasonPhrase}', Body='{ResponseBody}'", this.Title, e.StatusCode, e.ReasonPhrase, e.ResponseBody);
|
||||
await MessageBus.INSTANCE.SendError(new(Icons.Material.Filled.CloudOff, e.UserMessage));
|
||||
|
||||
if (this.resultingContentBlock is not null && string.IsNullOrWhiteSpace(aiText.Text))
|
||||
if (this.ResultingContentBlock is not null && string.IsNullOrWhiteSpace(aiText.Text))
|
||||
{
|
||||
this.ChatThread?.Blocks.Remove(this.resultingContentBlock);
|
||||
this.resultingContentBlock = null;
|
||||
this.ChatThread?.Blocks.Remove(this.ResultingContentBlock);
|
||||
this.ResultingContentBlock = null;
|
||||
}
|
||||
|
||||
return string.Empty;
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.isProcessing = false;
|
||||
this.StateHasChanged();
|
||||
this.IsProcessing = this.assistantSessionId is not null && (this.AssistantSessionService.TryGetSnapshot(this.assistantSessionKey)?.IsActive ?? false);
|
||||
await this.CheckpointAssistantSession();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
|
||||
if(manageCancellationLocally)
|
||||
{
|
||||
@@ -363,12 +460,54 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Starts the current assistant chat thread as a regular background-capable chat generation job.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Use this when an assistant creates a chat and hands it over to the chat page instead of
|
||||
/// rendering the answer inside the assistant UI.
|
||||
/// </remarks>
|
||||
/// <param name="time">The timestamp to use for the AI response block.</param>
|
||||
/// <param name="hideContentFromUser">Whether the AI response block should be hidden from the user.</param>
|
||||
/// <param name="isForeground">Whether the chat job should start as the current foreground job.</param>
|
||||
/// <returns>A task that completes after the chat job was registered.</returns>
|
||||
protected async Task StartChatGenerationJobAsync(DateTimeOffset time, bool hideContentFromUser = false, bool isForeground = true)
|
||||
{
|
||||
if (this.ChatThread is null)
|
||||
return;
|
||||
|
||||
var aiText = new ContentText
|
||||
{
|
||||
InitialRemoteWait = true,
|
||||
};
|
||||
|
||||
this.ResultingContentBlock = new ContentBlock
|
||||
{
|
||||
Time = time,
|
||||
ContentType = ContentType.TEXT,
|
||||
Role = ChatRole.AI,
|
||||
Content = aiText,
|
||||
HideFromUser = hideContentFromUser,
|
||||
};
|
||||
|
||||
this.ChatThread.Blocks.Add(this.ResultingContentBlock);
|
||||
this.ChatThread.SelectedProvider = this.ProviderSettings.Id;
|
||||
|
||||
await this.CheckpointAssistantSession();
|
||||
await this.AIJobService.TryStartChatGenerationAsync(new ChatGenerationRequest
|
||||
{
|
||||
ChatThread = this.ChatThread,
|
||||
AIText = aiText,
|
||||
LastUserPrompt = this.LastUserPrompt,
|
||||
ProviderSettings = this.ProviderSettings,
|
||||
IsForeground = isForeground,
|
||||
});
|
||||
}
|
||||
|
||||
private async Task CancelStreaming()
|
||||
{
|
||||
if (this.CancellationTokenSource is not null)
|
||||
if(!this.CancellationTokenSource.IsCancellationRequested)
|
||||
await this.CancellationTokenSource.CancelAsync();
|
||||
await this.AssistantSessionService.CancelAsync(this.assistantSessionKey, this);
|
||||
}
|
||||
|
||||
protected async Task CopyToClipboard()
|
||||
@@ -434,15 +573,15 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
await this.DialogService.ShowAsync<TSettings>(null, dialogParameters, DialogOptions.FULLSCREEN);
|
||||
}
|
||||
|
||||
protected Task SendToAssistant(Tools.Components destination, SendToButton sendToButton)
|
||||
protected async Task SendToAssistant(Tools.Components destination, SendToButton sendToButton)
|
||||
{
|
||||
if (!this.CanSendToAssistant(destination))
|
||||
return Task.CompletedTask;
|
||||
return;
|
||||
|
||||
var contentToSend = sendToButton == default ? string.Empty : sendToButton.UseResultingContentBlockData switch
|
||||
{
|
||||
false => sendToButton.GetText(),
|
||||
true => this.resultingContentBlock?.Content switch
|
||||
true => this.ResultingContentBlock?.Content switch
|
||||
{
|
||||
ContentText textBlock => textBlock.Text,
|
||||
_ => string.Empty,
|
||||
@@ -450,6 +589,16 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
};
|
||||
|
||||
var sendToData = destination.GetData();
|
||||
if (destination is not Tools.Components.CHAT && this.AssistantSessionService.GetSnapshots().Any(snapshot => snapshot.IsActive && snapshot.Key.Component == destination))
|
||||
{
|
||||
await this.MessageBus.SendWarning(new(Icons.Material.Filled.Apps, this.TB("This assistant is already running. AI Studio opens the running session instead.")));
|
||||
this.NavigationManager.NavigateTo(sendToData.Route);
|
||||
return;
|
||||
}
|
||||
|
||||
if (destination is not Tools.Components.CHAT)
|
||||
await this.AssistantSessionService.ClearInactiveSessionsForComponentAsync(destination);
|
||||
|
||||
switch (destination)
|
||||
{
|
||||
case Tools.Components.CHAT:
|
||||
@@ -469,7 +618,6 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
}
|
||||
|
||||
this.NavigationManager.NavigateTo(sendToData.Route);
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
private bool CanSendToAssistant(Tools.Components component)
|
||||
@@ -482,7 +630,12 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
private async Task InnerResetForm()
|
||||
{
|
||||
this.resultingContentBlock = null;
|
||||
if (this.AssistantSessionService.TryGetSnapshot(this.assistantSessionKey)?.IsActive ?? false)
|
||||
return;
|
||||
|
||||
await this.AssistantSessionService.ClearAsync(this.assistantSessionKey);
|
||||
this.assistantSessionId = null;
|
||||
this.ResultingContentBlock = null;
|
||||
this.ProviderSettings = Settings.Provider.NONE;
|
||||
|
||||
await this.JsRuntime.ClearDiv(RESULT_DIV_ID);
|
||||
@@ -492,10 +645,10 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
this.ResetProviderAndProfileSelection();
|
||||
|
||||
this.InputIsValid = false;
|
||||
this.inputIssues = [];
|
||||
this.InputIssues = [];
|
||||
|
||||
this.Form?.ResetValidation();
|
||||
this.StateHasChanged();
|
||||
await this.RefreshAssistantUIAsync();
|
||||
this.Form?.ResetValidation();
|
||||
}
|
||||
|
||||
@@ -515,6 +668,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
|
||||
protected override void DisposeResources()
|
||||
{
|
||||
this.isDisposed = true;
|
||||
try
|
||||
{
|
||||
this.formChangeTimer.Stop();
|
||||
@@ -529,4 +683,177 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
#region Assistant sessions
|
||||
|
||||
/// <summary>
|
||||
/// Stores the current assistant UI and chat state in the active assistant session.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes after the checkpoint was stored and published.</returns>
|
||||
private Task CheckpointAssistantSession()
|
||||
{
|
||||
if (this.assistantSessionId is null)
|
||||
return Task.CompletedTask;
|
||||
|
||||
return this.AssistantSessionService.CheckpointAsync(this.assistantSessionKey, this.assistantSessionId.Value, this.Title, this.ChatThread, this.CaptureAssistantSessionState(), this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Allows derived assistants to restore client-only UI after a session was attached.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The assistant session snapshot that was attached.</param>
|
||||
/// <returns>A task that completes after derived UI restore work has finished.</returns>
|
||||
protected virtual Task OnAssistantSessionAttachedAsync(AssistantSessionSnapshot snapshot) => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Allows derived assistants to restore DOM-dependent client-only UI after an attached session was rendered.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The assistant session snapshot that was rendered.</param>
|
||||
/// <returns>A task that completes after derived UI restore work has finished.</returns>
|
||||
protected virtual Task OnAssistantSessionRenderedAsync(AssistantSessionSnapshot snapshot) => Task.CompletedTask;
|
||||
|
||||
/// <summary>
|
||||
/// Handles assistant session change events for the current assistant instance.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The message payload type.</typeparam>
|
||||
/// <param name="sendingComponent">The component that sent the message, if any.</param>
|
||||
/// <param name="triggeredEvent">The event that was triggered.</param>
|
||||
/// <param name="data">The message payload.</param>
|
||||
/// <returns>A task that completes after the message was processed.</returns>
|
||||
protected override async Task ProcessIncomingMessage<T>(ComponentBase? sendingComponent, Event triggeredEvent, T? data) where T : default
|
||||
{
|
||||
if (ReferenceEquals(sendingComponent, this))
|
||||
return;
|
||||
|
||||
switch (triggeredEvent)
|
||||
{
|
||||
case Event.ASSISTANT_SESSION_CHANGED:
|
||||
case Event.ASSISTANT_SESSION_FINISHED:
|
||||
if (data is AssistantSessionSnapshot snapshot && snapshot.Key == this.assistantSessionKey)
|
||||
{
|
||||
await this.AttachAssistantSession(snapshot, restoreClientOnlyContent: triggeredEvent is Event.ASSISTANT_SESSION_FINISHED);
|
||||
if (triggeredEvent is Event.ASSISTANT_SESSION_FINISHED)
|
||||
_ = this.AssistantSessionService.TryTakeInactiveSnapshot(this.assistantSessionKey);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attaches the component to an existing assistant session if one is available.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes after the session was attached.</returns>
|
||||
private async Task AttachAssistantSessionIfAvailable()
|
||||
{
|
||||
var snapshot = this.AssistantSessionService.TryGetSnapshot(this.assistantSessionKey);
|
||||
if (snapshot?.IsActive ?? false)
|
||||
{
|
||||
await this.AttachAssistantSession(snapshot, restoreClientOnlyContent: true);
|
||||
return;
|
||||
}
|
||||
|
||||
snapshot = this.AssistantSessionService.TryTakeInactiveSnapshot(this.assistantSessionKey);
|
||||
if (snapshot is null)
|
||||
return;
|
||||
|
||||
await this.AttachAssistantSession(snapshot, restoreClientOnlyContent: true);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Applies an assistant session snapshot to this component instance.
|
||||
/// </summary>
|
||||
/// <param name="snapshot">The snapshot to attach.</param>
|
||||
/// <param name="restoreClientOnlyContent">Whether derived assistants should restore client-only UI state.</param>
|
||||
/// <returns>A task that completes after the component was refreshed.</returns>
|
||||
private async Task AttachAssistantSession(AssistantSessionSnapshot snapshot, bool restoreClientOnlyContent)
|
||||
{
|
||||
this.assistantSessionId = snapshot.SessionId;
|
||||
this.ImportAssistantSessionState(snapshot.State);
|
||||
this.ChatThread = snapshot.ChatThread ?? this.ChatThread;
|
||||
this.IsProcessing = snapshot.IsActive;
|
||||
|
||||
if (!snapshot.IsActive)
|
||||
this.CancellationTokenSource = null;
|
||||
|
||||
if (restoreClientOnlyContent)
|
||||
await this.OnAssistantSessionAttachedAsync(snapshot);
|
||||
|
||||
if (restoreClientOnlyContent)
|
||||
this.pendingRenderedAssistantSessionSnapshot = snapshot;
|
||||
|
||||
await this.RefreshAssistantUIAsync();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes the component when it is still mounted.
|
||||
/// </summary>
|
||||
/// <returns>A task that completes after the renderer was notified.</returns>
|
||||
private async Task RefreshAssistantUIAsync()
|
||||
{
|
||||
if (this.isDisposed)
|
||||
return;
|
||||
|
||||
try
|
||||
{
|
||||
await this.InvokeAsync(this.StateHasChanged);
|
||||
}
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
// The component may already have left the renderer while a background session is finishing.
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures the base assistant state and assistant-specific typed state values for session restore.
|
||||
/// </summary>
|
||||
/// <returns>A dictionary containing the current assistant state.</returns>
|
||||
private Dictionary<string, IAssistantSessionSnapshotField> CaptureAssistantSessionState()
|
||||
{
|
||||
var state = new AssistantSessionStateWriter();
|
||||
state.Set(PROVIDER_SETTINGS_STATE_KEY, this.ProviderSettings);
|
||||
state.Set(INPUT_IS_VALID_STATE_KEY, this.InputIsValid);
|
||||
state.Set(CURRENT_PROFILE_STATE_KEY, this.CurrentProfile);
|
||||
state.Set(CURRENT_CHAT_TEMPLATE_STATE_KEY, this.CurrentChatTemplate);
|
||||
state.Set(CHAT_THREAD_STATE_KEY, this.ChatThread);
|
||||
state.Set(LAST_USER_PROMPT_STATE_KEY, this.LastUserPrompt);
|
||||
state.Set(RESULTING_CONTENT_BLOCK_STATE_KEY, this.ResultingContentBlock);
|
||||
state.Set(INPUT_ISSUES_STATE_KEY, this.InputIssues);
|
||||
state.Set(IS_PROCESSING_STATE_KEY, this.IsProcessing);
|
||||
this.CaptureCustomAssistantSessionState(state);
|
||||
|
||||
return state.ToDictionary();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Captures assistant-specific state values.
|
||||
/// </summary>
|
||||
/// <param name="state">The typed state writer to update.</param>
|
||||
protected virtual void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state) { }
|
||||
|
||||
/// <summary>
|
||||
/// Restores the base assistant state and assistant-specific typed state values from a session snapshot.
|
||||
/// </summary>
|
||||
/// <param name="state">The captured assistant state to import.</param>
|
||||
private void ImportAssistantSessionState(IReadOnlyDictionary<string, IAssistantSessionSnapshotField> state)
|
||||
{
|
||||
var reader = new AssistantSessionStateReader(state, this.Title);
|
||||
reader.Restore(PROVIDER_SETTINGS_STATE_KEY, value => this.ProviderSettings = value);
|
||||
reader.Restore(INPUT_IS_VALID_STATE_KEY, value => this.InputIsValid = value);
|
||||
reader.Restore(CURRENT_PROFILE_STATE_KEY, value => this.CurrentProfile = value);
|
||||
reader.Restore(CURRENT_CHAT_TEMPLATE_STATE_KEY, value => this.CurrentChatTemplate = value);
|
||||
reader.Restore(CHAT_THREAD_STATE_KEY, value => this.ChatThread = value);
|
||||
reader.Restore(LAST_USER_PROMPT_STATE_KEY, value => this.LastUserPrompt = value);
|
||||
reader.Restore(RESULTING_CONTENT_BLOCK_STATE_KEY, value => this.ResultingContentBlock = value);
|
||||
reader.Restore(INPUT_ISSUES_STATE_KEY, value => this.InputIssues = value);
|
||||
reader.Restore(IS_PROCESSING_STATE_KEY, value => this.IsProcessing = value);
|
||||
this.RestoreCustomAssistantSessionState(reader);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Restores assistant-specific state values.
|
||||
/// </summary>
|
||||
/// <param name="state">The typed state reader to read from.</param>
|
||||
protected virtual void RestoreCustomAssistantSessionState(AssistantSessionStateReader state) { }
|
||||
|
||||
#endregion
|
||||
}
|
||||
@@ -1,4 +1,7 @@
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Components;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants;
|
||||
|
||||
@@ -9,4 +12,25 @@ public abstract class AssistantLowerBase : MSGComponentBase
|
||||
internal const string RESULT_DIV_ID = "assistantResult";
|
||||
internal const string BEFORE_RESULT_DIV_ID = "beforeAssistantResult";
|
||||
internal const string AFTER_RESULT_DIV_ID = "afterAssistantResult";
|
||||
|
||||
protected static readonly AssistantSessionStateKey<AIStudio.Settings.Provider> PROVIDER_SETTINGS_STATE_KEY = new(nameof(ProviderSettings));
|
||||
protected static readonly AssistantSessionStateKey<bool> INPUT_IS_VALID_STATE_KEY = new(nameof(InputIsValid));
|
||||
protected static readonly AssistantSessionStateKey<Profile> CURRENT_PROFILE_STATE_KEY = new(nameof(CurrentProfile));
|
||||
protected static readonly AssistantSessionStateKey<ChatTemplate> CURRENT_CHAT_TEMPLATE_STATE_KEY = new(nameof(CurrentChatTemplate));
|
||||
protected static readonly AssistantSessionStateKey<ChatThread?> CHAT_THREAD_STATE_KEY = new(nameof(ChatThread));
|
||||
protected static readonly AssistantSessionStateKey<IContent?> LAST_USER_PROMPT_STATE_KEY = new(nameof(LastUserPrompt));
|
||||
protected static readonly AssistantSessionStateKey<ContentBlock?> RESULTING_CONTENT_BLOCK_STATE_KEY = new(nameof(ResultingContentBlock));
|
||||
protected static readonly AssistantSessionStateKey<string[]> INPUT_ISSUES_STATE_KEY = new(nameof(InputIssues));
|
||||
protected static readonly AssistantSessionStateKey<bool> IS_PROCESSING_STATE_KEY = new(nameof(IsProcessing));
|
||||
|
||||
protected AIStudio.Settings.Provider ProviderSettings = Settings.Provider.NONE;
|
||||
protected bool InputIsValid;
|
||||
protected Profile CurrentProfile = Profile.NO_PROFILE;
|
||||
protected ChatTemplate CurrentChatTemplate = ChatTemplate.NO_CHAT_TEMPLATE;
|
||||
protected ChatThread? ChatThread;
|
||||
protected IContent? LastUserPrompt;
|
||||
|
||||
protected ContentBlock? ResultingContentBlock;
|
||||
protected string[] InputIssues = [];
|
||||
protected bool IsProcessing;
|
||||
}
|
||||
@@ -3,6 +3,7 @@ using System.Text;
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.BiasDay;
|
||||
|
||||
@@ -66,6 +67,25 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
|
||||
private Bias biasOfTheDay = BiasCatalog.NONE;
|
||||
private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<Bias> BIAS_OF_THE_DAY_STATE_KEY = new(nameof(biasOfTheDay));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(BIAS_OF_THE_DAY_STATE_KEY, this.biasOfTheDay);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(BIAS_OF_THE_DAY_STATE_KEY, value => this.biasOfTheDay = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
}
|
||||
|
||||
private string? ValidateTargetLanguage(CommonLanguages language)
|
||||
{
|
||||
@@ -149,8 +169,7 @@ public partial class BiasOfTheDayAssistant : AssistantBaseCore<SettingsDialogAss
|
||||
Please tell me about the bias of the day.
|
||||
""", true);
|
||||
|
||||
// Start the AI response without waiting for it to finish:
|
||||
_ = this.AddAIResponseAsync(time);
|
||||
await this.StartChatGenerationJobAsync(time);
|
||||
await this.SendToAssistant(Tools.Components.CHAT, default);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.Coding;
|
||||
|
||||
@@ -59,6 +60,28 @@ public partial class AssistantCoding : AssistantBaseCore<SettingsDialogCoding>
|
||||
private bool provideCompilerMessages;
|
||||
private string compilerMessages = string.Empty;
|
||||
private string questions = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<List<CodingContext>> CODING_CONTEXTS_STATE_KEY = new(nameof(codingContexts));
|
||||
private static readonly AssistantSessionStateKey<bool> PROVIDE_COMPILER_MESSAGES_STATE_KEY = new(nameof(provideCompilerMessages));
|
||||
private static readonly AssistantSessionStateKey<string> COMPILER_MESSAGES_STATE_KEY = new(nameof(compilerMessages));
|
||||
private static readonly AssistantSessionStateKey<string> QUESTIONS_STATE_KEY = new(nameof(questions));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.SetList(CODING_CONTEXTS_STATE_KEY, this.codingContexts);
|
||||
state.Set(PROVIDE_COMPILER_MESSAGES_STATE_KEY, this.provideCompilerMessages);
|
||||
state.Set(COMPILER_MESSAGES_STATE_KEY, this.compilerMessages);
|
||||
state.Set(QUESTIONS_STATE_KEY, this.questions);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.RestoreList(CODING_CONTEXTS_STATE_KEY, this.codingContexts);
|
||||
state.Restore(PROVIDE_COMPILER_MESSAGES_STATE_KEY, value => this.provideCompilerMessages = value);
|
||||
state.Restore(COMPILER_MESSAGES_STATE_KEY, value => this.compilerMessages = value);
|
||||
state.Restore(QUESTIONS_STATE_KEY, value => this.questions = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
+51
-1
@@ -7,6 +7,7 @@ using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Provider;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@@ -279,6 +280,55 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
private ProfilePreselection policyPreselectedProfile = ProfilePreselection.NoProfile;
|
||||
private HashSet<FileAttachment> loadedDocumentPaths = [];
|
||||
private readonly List<ConfigurationSelectData<string>> availableLLMProviders = new();
|
||||
private static readonly AssistantSessionStateKey<DataDocumentAnalysisPolicy?> SELECTED_POLICY_STATE_KEY = new(nameof(selectedPolicy));
|
||||
private static readonly AssistantSessionStateKey<bool> POLICY_IS_PROTECTED_STATE_KEY = new(nameof(policyIsProtected));
|
||||
private static readonly AssistantSessionStateKey<bool> POLICY_HIDE_POLICY_DEFINITION_STATE_KEY = new(nameof(policyHidePolicyDefinition));
|
||||
private static readonly AssistantSessionStateKey<bool> POLICY_DEFINITION_EXPANDED_STATE_KEY = new(nameof(policyDefinitionExpanded));
|
||||
private static readonly AssistantSessionStateKey<string> POLICY_NAME_STATE_KEY = new(nameof(policyName));
|
||||
private static readonly AssistantSessionStateKey<string> POLICY_DESCRIPTION_STATE_KEY = new(nameof(policyDescription));
|
||||
private static readonly AssistantSessionStateKey<string> POLICY_ANALYSIS_RULES_STATE_KEY = new(nameof(policyAnalysisRules));
|
||||
private static readonly AssistantSessionStateKey<string> POLICY_OUTPUT_RULES_STATE_KEY = new(nameof(policyOutputRules));
|
||||
private static readonly AssistantSessionStateKey<ConfidenceLevel> POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY = new(nameof(policyMinimumProviderConfidence));
|
||||
private static readonly AssistantSessionStateKey<string> POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY = new(nameof(policyPreselectedProviderId));
|
||||
private static readonly AssistantSessionStateKey<ProfilePreselection> POLICY_PRESELECTED_PROFILE_STATE_KEY = new(nameof(policyPreselectedProfile));
|
||||
private static readonly AssistantSessionStateKey<HashSet<FileAttachment>> LOADED_DOCUMENT_PATHS_STATE_KEY = new(nameof(loadedDocumentPaths));
|
||||
private static readonly AssistantSessionStateKey<List<ConfigurationSelectData<string>>> AVAILABLE_LLM_PROVIDERS_STATE_KEY = new(nameof(availableLLMProviders));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SELECTED_POLICY_STATE_KEY, this.selectedPolicy);
|
||||
state.Set(POLICY_IS_PROTECTED_STATE_KEY, this.policyIsProtected);
|
||||
state.Set(POLICY_HIDE_POLICY_DEFINITION_STATE_KEY, this.policyHidePolicyDefinition);
|
||||
state.Set(POLICY_DEFINITION_EXPANDED_STATE_KEY, this.policyDefinitionExpanded);
|
||||
state.Set(POLICY_NAME_STATE_KEY, this.policyName);
|
||||
state.Set(POLICY_DESCRIPTION_STATE_KEY, this.policyDescription);
|
||||
state.Set(POLICY_ANALYSIS_RULES_STATE_KEY, this.policyAnalysisRules);
|
||||
state.Set(POLICY_OUTPUT_RULES_STATE_KEY, this.policyOutputRules);
|
||||
state.Set(POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY, this.policyMinimumProviderConfidence);
|
||||
state.Set(POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY, this.policyPreselectedProviderId);
|
||||
state.Set(POLICY_PRESELECTED_PROFILE_STATE_KEY, this.policyPreselectedProfile);
|
||||
state.SetHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
|
||||
state.SetList(AVAILABLE_LLM_PROVIDERS_STATE_KEY, this.availableLLMProviders);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SELECTED_POLICY_STATE_KEY, value => this.selectedPolicy = value);
|
||||
state.Restore(POLICY_IS_PROTECTED_STATE_KEY, value => this.policyIsProtected = value);
|
||||
state.Restore(POLICY_HIDE_POLICY_DEFINITION_STATE_KEY, value => this.policyHidePolicyDefinition = value);
|
||||
state.Restore(POLICY_DEFINITION_EXPANDED_STATE_KEY, value => this.policyDefinitionExpanded = value);
|
||||
state.Restore(POLICY_NAME_STATE_KEY, value => this.policyName = value);
|
||||
state.Restore(POLICY_DESCRIPTION_STATE_KEY, value => this.policyDescription = value);
|
||||
state.Restore(POLICY_ANALYSIS_RULES_STATE_KEY, value => this.policyAnalysisRules = value);
|
||||
state.Restore(POLICY_OUTPUT_RULES_STATE_KEY, value => this.policyOutputRules = value);
|
||||
state.Restore(POLICY_MINIMUM_PROVIDER_CONFIDENCE_STATE_KEY, value => this.policyMinimumProviderConfidence = value);
|
||||
state.Restore(POLICY_PRESELECTED_PROVIDER_ID_STATE_KEY, value => this.policyPreselectedProviderId = value);
|
||||
state.Restore(POLICY_PRESELECTED_PROFILE_STATE_KEY, value => this.policyPreselectedProfile = value);
|
||||
state.RestoreHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
|
||||
state.RestoreList(AVAILABLE_LLM_PROVIDERS_STATE_KEY, this.availableLLMProviders);
|
||||
}
|
||||
|
||||
private bool IsNoPolicySelectedOrProtected => this.selectedPolicy is null || this.selectedPolicy.IsProtected;
|
||||
|
||||
@@ -515,7 +565,7 @@ public partial class DocumentAnalysisAssistant : AssistantBaseCore<NoSettingsPan
|
||||
break;
|
||||
}
|
||||
|
||||
return Task.CompletedTask;
|
||||
return base.ProcessIncomingMessage(sendingComponent, triggeredEvent, data);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
using AIStudio.Tools.PluginSystem.Assistants;
|
||||
using AIStudio.Tools.PluginSystem.Assistants.DataModel;
|
||||
@@ -27,6 +28,11 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
// Reuse chat-level provider filtering/preselection instead of NONE.
|
||||
protected override Tools.Components Component => Tools.Components.CHAT;
|
||||
|
||||
/// <summary>
|
||||
/// Gets the plugin ID as the assistant session instance ID.
|
||||
/// </summary>
|
||||
protected override string AssistantSessionInstanceId => this.assistantPlugin is null ? base.AssistantSessionInstanceId : this.assistantPlugin.Id.ToString();
|
||||
|
||||
private string title = string.Empty;
|
||||
private string description = string.Empty;
|
||||
private string systemPrompt = string.Empty;
|
||||
@@ -44,6 +50,61 @@ public partial class AssistantDynamic : AssistantBaseCore<NoSettingsPanel>
|
||||
private string securityMessage = string.Empty;
|
||||
private bool isSecurityBlocked;
|
||||
private const string ASSISTANT_QUERY_KEY = "assistantId";
|
||||
private static readonly AssistantSessionStateKey<string> TITLE_STATE_KEY = new(nameof(title));
|
||||
private static readonly AssistantSessionStateKey<string> DESCRIPTION_STATE_KEY = new(nameof(description));
|
||||
private static readonly AssistantSessionStateKey<string> SYSTEM_PROMPT_STATE_KEY = new(nameof(systemPrompt));
|
||||
private static readonly AssistantSessionStateKey<bool> ALLOW_PROFILES_STATE_KEY = new(nameof(allowProfiles));
|
||||
private static readonly AssistantSessionStateKey<string> SUBMIT_TEXT_STATE_KEY = new(nameof(submitText));
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY = new(nameof(showFooterProfileSelection));
|
||||
private static readonly AssistantSessionStateKey<PluginAssistants?> ASSISTANT_PLUGIN_STATE_KEY = new(nameof(assistantPlugin));
|
||||
private static readonly AssistantSessionStateKey<AssistantState> ASSISTANT_STATE_STATE_KEY = new(nameof(assistantState));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> IMAGE_CACHE_STATE_KEY = new(nameof(imageCache));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> EXECUTING_BUTTON_ACTIONS_STATE_KEY = new(nameof(executingButtonActions));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> EXECUTING_SWITCH_ACTIONS_STATE_KEY = new(nameof(executingSwitchActions));
|
||||
private static readonly AssistantSessionStateKey<string> PLUGIN_PATH_STATE_KEY = new(nameof(pluginPath));
|
||||
private static readonly AssistantSessionStateKey<PluginAssistantAudit?> AUDIT_STATE_KEY = new(nameof(audit));
|
||||
private static readonly AssistantSessionStateKey<string> SECURITY_MESSAGE_STATE_KEY = new(nameof(securityMessage));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_SECURITY_BLOCKED_STATE_KEY = new(nameof(isSecurityBlocked));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(TITLE_STATE_KEY, this.title);
|
||||
state.Set(DESCRIPTION_STATE_KEY, this.description);
|
||||
state.Set(SYSTEM_PROMPT_STATE_KEY, this.systemPrompt);
|
||||
state.Set(ALLOW_PROFILES_STATE_KEY, this.allowProfiles);
|
||||
state.Set(SUBMIT_TEXT_STATE_KEY, this.submitText);
|
||||
state.Set(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, this.showFooterProfileSelection);
|
||||
state.Set(ASSISTANT_PLUGIN_STATE_KEY, this.assistantPlugin);
|
||||
state.Set(ASSISTANT_STATE_STATE_KEY, this.assistantState.Clone());
|
||||
state.SetDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
state.SetHashSet(EXECUTING_BUTTON_ACTIONS_STATE_KEY, this.executingButtonActions);
|
||||
state.SetHashSet(EXECUTING_SWITCH_ACTIONS_STATE_KEY, this.executingSwitchActions);
|
||||
state.Set(PLUGIN_PATH_STATE_KEY, this.pluginPath);
|
||||
state.Set(AUDIT_STATE_KEY, this.audit);
|
||||
state.Set(SECURITY_MESSAGE_STATE_KEY, this.securityMessage);
|
||||
state.Set(IS_SECURITY_BLOCKED_STATE_KEY, this.isSecurityBlocked);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(TITLE_STATE_KEY, value => this.title = value);
|
||||
state.Restore(DESCRIPTION_STATE_KEY, value => this.description = value);
|
||||
state.Restore(SYSTEM_PROMPT_STATE_KEY, value => this.systemPrompt = value);
|
||||
state.Restore(ALLOW_PROFILES_STATE_KEY, value => this.allowProfiles = value);
|
||||
state.Restore(SUBMIT_TEXT_STATE_KEY, value => this.submitText = value);
|
||||
state.Restore(SHOW_FOOTER_PROFILE_SELECTION_STATE_KEY, value => this.showFooterProfileSelection = value);
|
||||
state.Restore(ASSISTANT_PLUGIN_STATE_KEY, value => this.assistantPlugin = value);
|
||||
state.Restore(ASSISTANT_STATE_STATE_KEY, value => this.assistantState.CopyFrom(value));
|
||||
state.RestoreDictionary(IMAGE_CACHE_STATE_KEY, this.imageCache);
|
||||
state.RestoreHashSet(EXECUTING_BUTTON_ACTIONS_STATE_KEY, this.executingButtonActions);
|
||||
state.RestoreHashSet(EXECUTING_SWITCH_ACTIONS_STATE_KEY, this.executingSwitchActions);
|
||||
state.Restore(PLUGIN_PATH_STATE_KEY, value => this.pluginPath = value);
|
||||
state.Restore(AUDIT_STATE_KEY, value => this.audit = value);
|
||||
state.Restore(SECURITY_MESSAGE_STATE_KEY, value => this.securityMessage = value);
|
||||
state.Restore(IS_SECURITY_BLOCKED_STATE_KEY, value => this.isSecurityBlocked = value);
|
||||
}
|
||||
|
||||
#region Implementation of AssistantBase
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.EMail;
|
||||
|
||||
@@ -78,6 +79,46 @@ public partial class AssistantEMail : AssistantBaseCore<SettingsDialogWritingEMa
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private bool provideHistory;
|
||||
private string inputHistory = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<WritingStyles> SELECTED_WRITING_STYLE_STATE_KEY = new(nameof(selectedWritingStyle));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_GREETING_STATE_KEY = new(nameof(inputGreeting));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_BULLET_POINTS_STATE_KEY = new(nameof(inputBulletPoints));
|
||||
private static readonly AssistantSessionStateKey<List<string>> BULLET_POINTS_LINES_STATE_KEY = new(nameof(bulletPointsLines));
|
||||
private static readonly AssistantSessionStateKey<HashSet<string>> SELECTED_FOCI_STATE_KEY = new(nameof(selectedFoci));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_NAME_STATE_KEY = new(nameof(inputName));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<bool> PROVIDE_HISTORY_STATE_KEY = new(nameof(provideHistory));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_HISTORY_STATE_KEY = new(nameof(inputHistory));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SELECTED_WRITING_STYLE_STATE_KEY, this.selectedWritingStyle);
|
||||
state.Set(INPUT_GREETING_STATE_KEY, this.inputGreeting);
|
||||
state.Set(INPUT_BULLET_POINTS_STATE_KEY, this.inputBulletPoints);
|
||||
state.SetList(BULLET_POINTS_LINES_STATE_KEY, this.bulletPointsLines);
|
||||
state.SetHashSet(SELECTED_FOCI_STATE_KEY, this.selectedFoci);
|
||||
state.Set(INPUT_NAME_STATE_KEY, this.inputName);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(PROVIDE_HISTORY_STATE_KEY, this.provideHistory);
|
||||
state.Set(INPUT_HISTORY_STATE_KEY, this.inputHistory);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SELECTED_WRITING_STYLE_STATE_KEY, value => this.selectedWritingStyle = value);
|
||||
state.Restore(INPUT_GREETING_STATE_KEY, value => this.inputGreeting = value);
|
||||
state.Restore(INPUT_BULLET_POINTS_STATE_KEY, value => this.inputBulletPoints = value);
|
||||
state.RestoreList(BULLET_POINTS_LINES_STATE_KEY, this.bulletPointsLines);
|
||||
state.Restore(SELECTED_FOCI_STATE_KEY, value => this.selectedFoci = value);
|
||||
state.Restore(INPUT_NAME_STATE_KEY, value => this.inputName = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(PROVIDE_HISTORY_STATE_KEY, value => this.provideHistory = value);
|
||||
state.Restore(INPUT_HISTORY_STATE_KEY, value => this.inputHistory = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
}
|
||||
else
|
||||
{
|
||||
<MudList Disabled="@this.AreServerPresetsBlocked" T="DataERIServer" Class="mb-1" SelectedValue="@this.selectedERIServer" SelectedValueChanged="@this.SelectedERIServerChanged">
|
||||
<MudList Disabled="@this.AreServerPresetControlsDisabled" T="DataERIServer" Class="mb-1" SelectedValue="@this.selectedERIServer" SelectedValueChanged="@this.SelectedERIServerChanged">
|
||||
@foreach (var server in this.SettingsManager.ConfigurationData.ERI.ERIServers)
|
||||
{
|
||||
<MudListItem T="DataERIServer" Icon="@Icons.Material.Filled.Settings" Value="@server">
|
||||
@@ -52,10 +52,10 @@ else
|
||||
}
|
||||
|
||||
<MudStack Row="@true" Class="mt-1">
|
||||
<MudButton Disabled="@this.AreServerPresetsBlocked" OnClick="@this.AddERIServer" Variant="Variant.Filled" Color="Color.Primary">
|
||||
<MudButton Disabled="@this.AreServerPresetControlsDisabled" OnClick="@this.AddERIServer" Variant="Variant.Filled" Color="Color.Primary">
|
||||
@T("Add ERI server preset")
|
||||
</MudButton>
|
||||
<MudButton OnClick="@this.RemoveERIServer" Disabled="@(this.AreServerPresetsBlocked || this.IsNoneERIServerSelected)" Variant="Variant.Filled" Color="Color.Error">
|
||||
<MudButton OnClick="@this.RemoveERIServer" Disabled="@(this.AreServerPresetControlsDisabled || this.IsNoneERIServerSelected)" Variant="Variant.Filled" Color="Color.Error">
|
||||
@T("Delete this server preset")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@@ -82,18 +82,18 @@ else
|
||||
</MudJustifiedText>
|
||||
}
|
||||
|
||||
<MudTextSwitch Label="@T("Should we automatically save any input made?")" Disabled="@this.AreServerPresetsBlocked" @bind-Value="@this.autoSave" LabelOn="@T("Yes, please save my inputs")" LabelOff="@T("No, I will enter everything again or configure it manually in the settings")" />
|
||||
<MudTextSwitch Label="@T("Should we automatically save any input made?")" Disabled="@this.AreServerPresetControlsDisabled" @bind-Value="@this.autoSave" LabelOn="@T("Yes, please save my inputs")" LabelOff="@T("No, I will enter everything again or configure it manually in the settings")" />
|
||||
|
||||
<hr style="width: 100%; border-width: 0.25ch;" class="mt-6"/>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mt-6 mb-1">
|
||||
@T("Common ERI server settings")
|
||||
</MudText>
|
||||
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverName" Validation="@this.ValidateServerName" Immediate="@true" Label="@T("ERI server name")" HelperText="@T("Please give your ERI server a name that provides information about the data source and/or its intended purpose. The name will be displayed to users in AI Studio.")" Counter="60" MaxLength="60" Variant="Variant.Outlined" Margin="Margin.Normal" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" OnKeyUp="() => this.ServerNameWasChanged()"/>
|
||||
<MudTextField T="string" Disabled="@this.IsNoneERIServerSelected" @bind-Text="@this.serverDescription" Validation="@this.ValidateServerDescription" Immediate="@true" Label="@T("ERI server description")" HelperText="@T("Please provide a brief description of your ERI server. Describe or explain what your ERI server does and what data it uses for this purpose. This description will be shown to users in AI Studio.")" Counter="512" MaxLength="512" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
<MudTextField T="string" Disabled="@this.IsERIInputDisabled" @bind-Text="@this.serverName" Validation="@this.ValidateServerName" Immediate="@true" Label="@T("ERI server name")" HelperText="@T("Please give your ERI server a name that provides information about the data source and/or its intended purpose. The name will be displayed to users in AI Studio.")" Counter="60" MaxLength="60" Variant="Variant.Outlined" Margin="Margin.Normal" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3" OnKeyUp="() => this.ServerNameWasChanged()"/>
|
||||
<MudTextField T="string" Disabled="@this.IsERIInputDisabled" @bind-Text="@this.serverDescription" Validation="@this.ValidateServerDescription" Immediate="@true" Label="@T("ERI server description")" HelperText="@T("Please provide a brief description of your ERI server. Describe or explain what your ERI server does and what data it uses for this purpose. This description will be shown to users in AI Studio.")" Counter="512" MaxLength="512" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
|
||||
<MudStack Row="@true" Class="mb-3">
|
||||
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ProgrammingLanguages" @bind-Value="@this.selectedProgrammingLanguage" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="@T("Programming language")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateProgrammingLanguage">
|
||||
<MudSelect Disabled="@this.IsERIInputDisabled" T="ProgrammingLanguages" @bind-Value="@this.selectedProgrammingLanguage" AdornmentIcon="@Icons.Material.Filled.Code" Adornment="Adornment.Start" Label="@T("Programming language")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateProgrammingLanguage">
|
||||
@foreach (var language in Enum.GetValues<ProgrammingLanguages>())
|
||||
{
|
||||
<MudSelectItem Value="@language">
|
||||
@@ -103,12 +103,12 @@ else
|
||||
</MudSelect>
|
||||
@if (this.selectedProgrammingLanguage is ProgrammingLanguages.OTHER)
|
||||
{
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherProgrammingLanguage" Validation="@this.ValidateOtherLanguage" Label="@T("Other language")" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.otherProgrammingLanguage" Validation="@this.ValidateOtherLanguage" Label="@T("Other language")" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
<MudStack Row="@true" AlignItems="AlignItems.Center" Class="mb-3">
|
||||
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="ERIVersion" @bind-Value="@this.selectedERIVersion" Label="@T("ERI specification version")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateERIVersion">
|
||||
<MudSelect Disabled="@this.IsERIInputDisabled" T="ERIVersion" @bind-Value="@this.selectedERIVersion" Label="@T("ERI specification version")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateERIVersion">
|
||||
@foreach (var version in Enum.GetValues<ERIVersion>())
|
||||
{
|
||||
<MudSelectItem Value="@version">
|
||||
@@ -116,7 +116,7 @@ else
|
||||
</MudSelectItem>
|
||||
}
|
||||
</MudSelect>
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Small" Disabled="@(!this.selectedERIVersion.WasSpecificationSelected() || this.IsNoneERIServerSelected)" Href="@this.selectedERIVersion.SpecificationURL()" Target="_blank">
|
||||
<MudButton Variant="Variant.Outlined" Size="Size.Small" Disabled="@this.IsSpecificationDownloadDisabled" Href="@this.selectedERIVersion.SpecificationURL()" Target="_blank">
|
||||
<MudIcon Icon="@Icons.Material.Filled.Link" Class="mr-2"/> @T("Download specification")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@@ -126,7 +126,7 @@ else
|
||||
</MudText>
|
||||
|
||||
<MudStack Row="@false" Spacing="1" Class="mb-3">
|
||||
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="DataSources" @bind-Value="@this.selectedDataSource" AdornmentIcon="@Icons.Material.Filled.Dataset" Adornment="Adornment.Start" Label="@T("Data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateDataSource" SelectedValuesChanged="@this.DataSourceWasChanged">
|
||||
<MudSelect Disabled="@this.IsERIInputDisabled" T="DataSources" @bind-Value="@this.selectedDataSource" AdornmentIcon="@Icons.Material.Filled.Dataset" Adornment="Adornment.Start" Label="@T("Data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateDataSource" SelectedValuesChanged="@this.DataSourceWasChanged">
|
||||
@foreach (var dataSource in Enum.GetValues<DataSources>())
|
||||
{
|
||||
<MudSelectItem Value="@dataSource">
|
||||
@@ -136,21 +136,21 @@ else
|
||||
</MudSelect>
|
||||
@if (this.selectedDataSource is DataSources.CUSTOM)
|
||||
{
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.otherDataSource" Validation="@this.ValidateOtherDataSource" Label="@T("Describe your data source")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.otherDataSource" Validation="@this.ValidateOtherDataSource" Label="@T("Describe your data source")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
}
|
||||
</MudStack>
|
||||
|
||||
@if(this.selectedDataSource > DataSources.FILE_SYSTEM)
|
||||
{
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceProductName" Label="@T("Data source: product name")" Validation="@this.ValidateDataSourceProductName" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.dataSourceProductName" Label="@T("Data source: product name")" Validation="@this.ValidateDataSourceProductName" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
}
|
||||
|
||||
@if (this.NeedHostnamePort())
|
||||
{
|
||||
<div class="mb-3">
|
||||
<MudStack Row="@true">
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.dataSourceHostname" Label="@T("Data source: hostname")" Validation="@this.ValidateHostname" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudNumericField Disabled="@this.IsNoneERIServerSelected" Label="@T("Data source: port")" Immediate="@true" Min="1" Max="65535" Validation="@this.ValidatePort" @bind-Value="@this.dataSourcePort" Variant="Variant.Outlined" Margin="Margin.Dense" OnKeyUp="() => this.DataSourcePortWasTyped()"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.dataSourceHostname" Label="@T("Data source: hostname")" Validation="@this.ValidateHostname" Variant="Variant.Outlined" Margin="Margin.Dense" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudNumericField Disabled="@this.IsERIInputDisabled" Label="@T("Data source: port")" Immediate="@true" Min="1" Max="65535" Validation="@this.ValidatePort" @bind-Value="@this.dataSourcePort" Variant="Variant.Outlined" Margin="Margin.Dense" OnKeyUp="() => this.DataSourcePortWasTyped()"/>
|
||||
</MudStack>
|
||||
@if (this.dataSourcePort < 1024)
|
||||
{
|
||||
@@ -168,7 +168,7 @@ else
|
||||
<MudStack Row="@false" Spacing="1" Class="mb-1">
|
||||
<MudSelectExtended
|
||||
T="Auth"
|
||||
Disabled="@this.IsNoneERIServerSelected"
|
||||
Disabled="@this.IsERIInputDisabled"
|
||||
ShrinkLabel="@true"
|
||||
MultiSelection="@true"
|
||||
MultiSelectionTextFunc="@this.GetMultiSelectionAuthText"
|
||||
@@ -185,12 +185,12 @@ else
|
||||
</MudSelectItemExtended>
|
||||
}
|
||||
</MudSelectExtended>
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.authDescription" Label="@this.AuthDescriptionTitle()" Validation="@this.ValidateAuthDescription" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.authDescription" Label="@this.AuthDescriptionTitle()" Validation="@this.ValidateAuthDescription" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="6" UserAttributes="@USER_INPUT_ATTRIBUTES"/>
|
||||
</MudStack>
|
||||
|
||||
@if (this.selectedAuthenticationMethods.Contains(Auth.KERBEROS))
|
||||
{
|
||||
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="OperatingSystem" @bind-Value="@this.selectedOperatingSystem" Label="@T("Operating system on which your ERI will run")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateOperatingSystem" Class="mb-1">
|
||||
<MudSelect Disabled="@this.IsERIInputDisabled" T="OperatingSystem" @bind-Value="@this.selectedOperatingSystem" Label="@T("Operating system on which your ERI will run")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateOperatingSystem" Class="mb-1">
|
||||
@foreach (var os in Enum.GetValues<OperatingSystem>())
|
||||
{
|
||||
<MudSelectItem Value="@os">
|
||||
@@ -204,7 +204,7 @@ else
|
||||
@T("Data protection settings")
|
||||
</MudText>
|
||||
|
||||
<MudSelect Disabled="@this.IsNoneERIServerSelected" T="AllowedLLMProviders" @bind-Value="@this.allowedLLMProviders" Label="@T("Allowed LLM providers for this data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateAllowedLLMProviders" Class="mb-1">
|
||||
<MudSelect Disabled="@this.IsERIInputDisabled" T="AllowedLLMProviders" @bind-Value="@this.allowedLLMProviders" Label="@T("Allowed LLM providers for this data source")" Variant="Variant.Outlined" Margin="Margin.Dense" Validation="@this.ValidateAllowedLLMProviders" Class="mb-1">
|
||||
@foreach (var option in Enum.GetValues<AllowedLLMProviders>())
|
||||
{
|
||||
<MudSelectItem Value="@option">
|
||||
@@ -227,7 +227,7 @@ else
|
||||
|
||||
@if (!this.IsNoneERIServerSelected)
|
||||
{
|
||||
<MudTable Items="@this.embeddings" Hover="@true" Class="border-dashed border rounded-lg">
|
||||
<MudTable Items="@this.EmbeddingRows" Hover="@true" Class="border-dashed border rounded-lg">
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col style="width: 34em;"/>
|
||||
@@ -243,10 +243,10 @@ else
|
||||
<MudTd>@context.EmbeddingType</MudTd>
|
||||
<MudTd>
|
||||
<MudStack Row="true" Class="mb-2 mt-2" Wrap="Wrap.Wrap">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditEmbedding(context)">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditEmbedding(context)" Disabled="@this.IsProcessing">
|
||||
@T("Edit")
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteEmbedding(context)">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteEmbedding(context)" Disabled="@this.IsProcessing">
|
||||
@T("Delete")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@@ -262,7 +262,7 @@ else
|
||||
}
|
||||
}
|
||||
|
||||
<MudButton Disabled="@this.IsNoneERIServerSelected" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbedding">
|
||||
<MudButton Disabled="@this.IsERIInputDisabled" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddEmbedding">
|
||||
@T("Add Embedding Method")
|
||||
</MudButton>
|
||||
|
||||
@@ -276,7 +276,7 @@ else
|
||||
|
||||
@if (!this.IsNoneERIServerSelected)
|
||||
{
|
||||
<MudTable Items="@this.retrievalProcesses" Hover="@true" Class="border-dashed border rounded-lg">
|
||||
<MudTable Items="@this.RetrievalProcessRows" Hover="@true" Class="border-dashed border rounded-lg">
|
||||
<ColGroup>
|
||||
<col/>
|
||||
<col style="width: 34em;"/>
|
||||
@@ -289,10 +289,10 @@ else
|
||||
<MudTd>@context.Name</MudTd>
|
||||
<MudTd>
|
||||
<MudStack Row="true" Class="mb-2 mt-2" Wrap="Wrap.Wrap">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditRetrievalProcess(context)">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Info" StartIcon="@Icons.Material.Filled.Edit" OnClick="() => this.EditRetrievalProcess(context)" Disabled="@this.IsProcessing">
|
||||
@T("Edit")
|
||||
</MudButton>
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteRetrievalProcess(context)">
|
||||
<MudButton Variant="Variant.Filled" Color="Color.Error" StartIcon="@Icons.Material.Filled.Delete" OnClick="() => this.DeleteRetrievalProcess(context)" Disabled="@this.IsProcessing">
|
||||
@T("Delete")
|
||||
</MudButton>
|
||||
</MudStack>
|
||||
@@ -308,7 +308,7 @@ else
|
||||
}
|
||||
}
|
||||
|
||||
<MudButton Disabled="@this.IsNoneERIServerSelected" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddRetrievalProcess">
|
||||
<MudButton Disabled="@this.IsERIInputDisabled" Variant="Variant.Filled" Color="@Color.Primary" StartIcon="@Icons.Material.Filled.AddRoad" Class="mt-3 mb-6" OnClick="@this.AddRetrievalProcess">
|
||||
@T("Add Retrieval Process")
|
||||
</MudButton>
|
||||
|
||||
@@ -316,7 +316,7 @@ else
|
||||
@T("You can integrate additional libraries. Perhaps you want to evaluate the prompts in advance using a machine learning method or analyze them with a text mining approach? Or maybe you want to preprocess images in the prompts? For such advanced scenarios, you can specify which libraries you want to use here. It's best to describe which library you want to integrate for which purpose. This way, the LLM that writes the ERI server for you can try to use these libraries effectively. This should result in less rework being necessary. If you don't know the necessary libraries, you can instead attempt to describe the intended use. The LLM can then attempt to choose suitable libraries. However, hallucinations can occur, and fictional libraries might be selected.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<MudTextField Disabled="@this.IsNoneERIServerSelected" T="string" @bind-Text="@this.additionalLibraries" Label="@T("(Optional) Additional libraries")" HelperText="@T("Do you want to include additional libraries? Then name them and briefly describe what you want to achieve with them.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="12" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
<MudTextField Disabled="@this.IsERIInputDisabled" T="string" @bind-Text="@this.additionalLibraries" Label="@T("(Optional) Additional libraries")" HelperText="@T("Do you want to include additional libraries? Then name them and briefly describe what you want to achieve with them.")" Variant="Variant.Outlined" Margin="Margin.Normal" Lines="3" AutoGrow="@true" MaxLines="12" UserAttributes="@USER_INPUT_ATTRIBUTES" Class="mb-3"/>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mt-9 mb-1">
|
||||
@T("Provider selection for generation")
|
||||
@@ -330,7 +330,7 @@ else
|
||||
<b>@T("Important:")</b> @T("The LLM may need to generate many files. This reaches the request limit of most providers. Typically, only a certain number of requests can be made per minute, and only a maximum number of tokens can be generated per minute. AI Studio automatically considers this.") <b>@T("However, generating all the files takes a certain amount of time.")</b> @T("Local or self-hosted models may work without these limitations and can generate responses faster. AI Studio dynamically adapts its behavior and always tries to achieve the fastest possible data processing.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider"/>
|
||||
<ProviderSelection @bind-ProviderSettings="@this.ProviderSettings" ValidateProvider="@this.ValidatingProvider" Disabled="@this.IsProcessing"/>
|
||||
|
||||
<MudText Typo="Typo.h4" Class="mt-9 mb-1">
|
||||
@T("Write code to file system")
|
||||
@@ -344,5 +344,5 @@ else
|
||||
@T("When you rebuild / re-generate the ERI server code, AI Studio proceeds as follows: All files generated last time will be deleted. All other files you have created remain. Then, the AI generates the new files.") <b>@T("But beware:")</b> @T("It may happen that the AI generates a file this time that you manually created last time. In this case, your manually created file will then be overwritten. Therefore, you should always create a Git repository and commit or revert all changes before using this assistant. With a diff visualization, you can immediately see where the AI has made changes. It is best to use an IDE suitable for your selected language for this purpose.")
|
||||
</MudJustifiedText>
|
||||
|
||||
<MudTextSwitch Label="@T("Should we write the generated code to the file system?")" Disabled="@this.IsNoneERIServerSelected" @bind-Value="@this.writeToFilesystem" LabelOn="@T("Yes, please write or update all generated code to the file system")" LabelOff="@T("No, just show me the code")" />
|
||||
<SelectDirectory Label="@T("Base directory where to write the code")" @bind-Directory="@this.baseDirectory" Disabled="@(this.IsNoneERIServerSelected || !this.writeToFilesystem)" DirectoryDialogTitle="@T("Select the target directory for the ERI server")" Validation="@this.ValidateDirectory" />
|
||||
<MudTextSwitch Label="@T("Should we write the generated code to the file system?")" Disabled="@this.IsERIInputDisabled" @bind-Value="@this.writeToFilesystem" LabelOn="@T("Yes, please write or update all generated code to the file system")" LabelOff="@T("No, just show me the code")" />
|
||||
<SelectDirectory Label="@T("Base directory where to write the code")" @bind-Directory="@this.baseDirectory" Disabled="@this.IsBaseDirectorySelectionDisabled" DirectoryDialogTitle="@T("Select the target directory for the ERI server")" Validation="@this.ValidateDirectory" />
|
||||
@@ -5,6 +5,7 @@ using AIStudio.Chat;
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Settings.DataModel;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
@@ -291,7 +292,17 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
}
|
||||
}
|
||||
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons => [];
|
||||
protected override IReadOnlyList<IButtonData> FooterButtons =>
|
||||
[
|
||||
new ButtonData
|
||||
{
|
||||
Text = T("Open in chat"),
|
||||
Icon = Icons.Material.Filled.Chat,
|
||||
Color = Color.Default,
|
||||
AsyncAction = this.OpenInChat,
|
||||
DisabledActionParam = () => !this.CanOpenInChat,
|
||||
},
|
||||
];
|
||||
|
||||
protected override bool ShowEntireChatThread => true;
|
||||
|
||||
@@ -307,6 +318,22 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
{
|
||||
SystemPrompt = this.SystemPrompt,
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Indicates whether the generated ERI conversation can be opened in the chat view.
|
||||
/// </summary>
|
||||
private bool CanOpenInChat => !this.IsProcessing && this.ChatThread is { Blocks.Count: > 0 };
|
||||
|
||||
/// <summary>
|
||||
/// Opens the generated ERI conversation in the chat view when a finished conversation is available.
|
||||
/// </summary>
|
||||
private async Task OpenInChat()
|
||||
{
|
||||
if (!this.CanOpenInChat)
|
||||
return;
|
||||
|
||||
await this.SendToAssistant(Tools.Components.CHAT, default);
|
||||
}
|
||||
|
||||
protected override void ResetForm()
|
||||
{
|
||||
@@ -449,17 +476,110 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
private bool writeToFilesystem;
|
||||
private string baseDirectory = string.Empty;
|
||||
private List<string> previouslyGeneratedFiles = new();
|
||||
private static readonly AssistantSessionStateKey<DataERIServer?> SELECTED_ERI_SERVER_STATE_KEY = new(nameof(selectedERIServer));
|
||||
private static readonly AssistantSessionStateKey<bool> AUTO_SAVE_STATE_KEY = new(nameof(autoSave));
|
||||
private static readonly AssistantSessionStateKey<string> SERVER_NAME_STATE_KEY = new(nameof(serverName));
|
||||
private static readonly AssistantSessionStateKey<string> SERVER_DESCRIPTION_STATE_KEY = new(nameof(serverDescription));
|
||||
private static readonly AssistantSessionStateKey<ERIVersion> SELECTED_ERI_VERSION_STATE_KEY = new(nameof(selectedERIVersion));
|
||||
private static readonly AssistantSessionStateKey<string?> ERI_SPECIFICATION_STATE_KEY = new(nameof(eriSpecification));
|
||||
private static readonly AssistantSessionStateKey<ProgrammingLanguages> SELECTED_PROGRAMMING_LANGUAGE_STATE_KEY = new(nameof(selectedProgrammingLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> OTHER_PROGRAMMING_LANGUAGE_STATE_KEY = new(nameof(otherProgrammingLanguage));
|
||||
private static readonly AssistantSessionStateKey<DataSources> SELECTED_DATA_SOURCE_STATE_KEY = new(nameof(selectedDataSource));
|
||||
private static readonly AssistantSessionStateKey<string> OTHER_DATA_SOURCE_STATE_KEY = new(nameof(otherDataSource));
|
||||
private static readonly AssistantSessionStateKey<string> DATA_SOURCE_PRODUCT_NAME_STATE_KEY = new(nameof(dataSourceProductName));
|
||||
private static readonly AssistantSessionStateKey<string> DATA_SOURCE_HOSTNAME_STATE_KEY = new(nameof(dataSourceHostname));
|
||||
private static readonly AssistantSessionStateKey<int?> DATA_SOURCE_PORT_STATE_KEY = new(nameof(dataSourcePort));
|
||||
private static readonly AssistantSessionStateKey<bool> USER_TYPED_PORT_STATE_KEY = new(nameof(userTypedPort));
|
||||
private static readonly AssistantSessionStateKey<HashSet<Auth>> SELECTED_AUTHENTICATION_METHODS_STATE_KEY = new(nameof(selectedAuthenticationMethods));
|
||||
private static readonly AssistantSessionStateKey<string> AUTH_DESCRIPTION_STATE_KEY = new(nameof(authDescription));
|
||||
private static readonly AssistantSessionStateKey<OperatingSystem> SELECTED_OPERATING_SYSTEM_STATE_KEY = new(nameof(selectedOperatingSystem));
|
||||
private static readonly AssistantSessionStateKey<AllowedLLMProviders> ALLOWED_LLM_PROVIDERS_STATE_KEY = new(nameof(allowedLLMProviders));
|
||||
private static readonly AssistantSessionStateKey<List<EmbeddingInfo>> EMBEDDINGS_STATE_KEY = new(nameof(embeddings));
|
||||
private static readonly AssistantSessionStateKey<List<RetrievalInfo>> RETRIEVAL_PROCESSES_STATE_KEY = new(nameof(retrievalProcesses));
|
||||
private static readonly AssistantSessionStateKey<string> ADDITIONAL_LIBRARIES_STATE_KEY = new(nameof(additionalLibraries));
|
||||
private static readonly AssistantSessionStateKey<bool> WRITE_TO_FILESYSTEM_STATE_KEY = new(nameof(writeToFilesystem));
|
||||
private static readonly AssistantSessionStateKey<string> BASE_DIRECTORY_STATE_KEY = new(nameof(baseDirectory));
|
||||
private static readonly AssistantSessionStateKey<List<string>> PREVIOUSLY_GENERATED_FILES_STATE_KEY = new(nameof(previouslyGeneratedFiles));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SELECTED_ERI_SERVER_STATE_KEY, this.selectedERIServer);
|
||||
state.Set(AUTO_SAVE_STATE_KEY, this.autoSave);
|
||||
state.Set(SERVER_NAME_STATE_KEY, this.serverName);
|
||||
state.Set(SERVER_DESCRIPTION_STATE_KEY, this.serverDescription);
|
||||
state.Set(SELECTED_ERI_VERSION_STATE_KEY, this.selectedERIVersion);
|
||||
state.Set(ERI_SPECIFICATION_STATE_KEY, this.eriSpecification);
|
||||
state.Set(SELECTED_PROGRAMMING_LANGUAGE_STATE_KEY, this.selectedProgrammingLanguage);
|
||||
state.Set(OTHER_PROGRAMMING_LANGUAGE_STATE_KEY, this.otherProgrammingLanguage);
|
||||
state.Set(SELECTED_DATA_SOURCE_STATE_KEY, this.selectedDataSource);
|
||||
state.Set(OTHER_DATA_SOURCE_STATE_KEY, this.otherDataSource);
|
||||
state.Set(DATA_SOURCE_PRODUCT_NAME_STATE_KEY, this.dataSourceProductName);
|
||||
state.Set(DATA_SOURCE_HOSTNAME_STATE_KEY, this.dataSourceHostname);
|
||||
state.Set(DATA_SOURCE_PORT_STATE_KEY, this.dataSourcePort);
|
||||
state.Set(USER_TYPED_PORT_STATE_KEY, this.userTypedPort);
|
||||
state.SetHashSet(SELECTED_AUTHENTICATION_METHODS_STATE_KEY, this.selectedAuthenticationMethods);
|
||||
state.Set(AUTH_DESCRIPTION_STATE_KEY, this.authDescription);
|
||||
state.Set(SELECTED_OPERATING_SYSTEM_STATE_KEY, this.selectedOperatingSystem);
|
||||
state.Set(ALLOWED_LLM_PROVIDERS_STATE_KEY, this.allowedLLMProviders);
|
||||
state.SetList(EMBEDDINGS_STATE_KEY, this.embeddings);
|
||||
state.SetList(RETRIEVAL_PROCESSES_STATE_KEY, this.retrievalProcesses);
|
||||
state.Set(ADDITIONAL_LIBRARIES_STATE_KEY, this.additionalLibraries);
|
||||
state.Set(WRITE_TO_FILESYSTEM_STATE_KEY, this.writeToFilesystem);
|
||||
state.Set(BASE_DIRECTORY_STATE_KEY, this.baseDirectory);
|
||||
state.SetList(PREVIOUSLY_GENERATED_FILES_STATE_KEY, this.previouslyGeneratedFiles);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SELECTED_ERI_SERVER_STATE_KEY, value => this.selectedERIServer = value);
|
||||
state.Restore(AUTO_SAVE_STATE_KEY, value => this.autoSave = value);
|
||||
state.Restore(SERVER_NAME_STATE_KEY, value => this.serverName = value);
|
||||
state.Restore(SERVER_DESCRIPTION_STATE_KEY, value => this.serverDescription = value);
|
||||
state.Restore(SELECTED_ERI_VERSION_STATE_KEY, value => this.selectedERIVersion = value);
|
||||
state.Restore(ERI_SPECIFICATION_STATE_KEY, value => this.eriSpecification = value);
|
||||
state.Restore(SELECTED_PROGRAMMING_LANGUAGE_STATE_KEY, value => this.selectedProgrammingLanguage = value);
|
||||
state.Restore(OTHER_PROGRAMMING_LANGUAGE_STATE_KEY, value => this.otherProgrammingLanguage = value);
|
||||
state.Restore(SELECTED_DATA_SOURCE_STATE_KEY, value => this.selectedDataSource = value);
|
||||
state.Restore(OTHER_DATA_SOURCE_STATE_KEY, value => this.otherDataSource = value);
|
||||
state.Restore(DATA_SOURCE_PRODUCT_NAME_STATE_KEY, value => this.dataSourceProductName = value);
|
||||
state.Restore(DATA_SOURCE_HOSTNAME_STATE_KEY, value => this.dataSourceHostname = value);
|
||||
state.Restore(DATA_SOURCE_PORT_STATE_KEY, value => this.dataSourcePort = value);
|
||||
state.Restore(USER_TYPED_PORT_STATE_KEY, value => this.userTypedPort = value);
|
||||
state.Restore(SELECTED_AUTHENTICATION_METHODS_STATE_KEY, value => this.selectedAuthenticationMethods = value);
|
||||
state.Restore(AUTH_DESCRIPTION_STATE_KEY, value => this.authDescription = value);
|
||||
state.Restore(SELECTED_OPERATING_SYSTEM_STATE_KEY, value => this.selectedOperatingSystem = value);
|
||||
state.Restore(ALLOWED_LLM_PROVIDERS_STATE_KEY, value => this.allowedLLMProviders = value);
|
||||
state.RestoreList(EMBEDDINGS_STATE_KEY, this.embeddings);
|
||||
state.RestoreList(RETRIEVAL_PROCESSES_STATE_KEY, this.retrievalProcesses);
|
||||
state.Restore(ADDITIONAL_LIBRARIES_STATE_KEY, value => this.additionalLibraries = value);
|
||||
state.Restore(WRITE_TO_FILESYSTEM_STATE_KEY, value => this.writeToFilesystem = value);
|
||||
state.Restore(BASE_DIRECTORY_STATE_KEY, value => this.baseDirectory = value);
|
||||
state.RestoreList(PREVIOUSLY_GENERATED_FILES_STATE_KEY, this.previouslyGeneratedFiles);
|
||||
}
|
||||
|
||||
private bool AreServerPresetsBlocked => !this.SettingsManager.ConfigurationData.ERI.PreselectOptions;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether ERI server preset controls should be disabled.
|
||||
/// </summary>
|
||||
private bool AreServerPresetControlsDisabled => this.AreServerPresetsBlocked || this.IsProcessing;
|
||||
|
||||
private void SelectedERIServerChanged(DataERIServer? server)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
this.selectedERIServer = server;
|
||||
this.ResetForm();
|
||||
}
|
||||
|
||||
private async Task AddERIServer()
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
this.SettingsManager.ConfigurationData.ERI.ERIServers.Add(new ()
|
||||
{
|
||||
ServerName = string.Format(T("ERI Server {0}"), DateTimeOffset.UtcNow),
|
||||
@@ -470,6 +590,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task RemoveERIServer()
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
if(this.selectedERIServer is null)
|
||||
return;
|
||||
|
||||
@@ -493,6 +616,31 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private bool IsNoneERIServerSelected => this.selectedERIServer is null;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether ERI configuration input controls should be disabled.
|
||||
/// </summary>
|
||||
private bool IsERIInputDisabled => this.IsNoneERIServerSelected || this.IsProcessing;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the selected ERI specification cannot be downloaded.
|
||||
/// </summary>
|
||||
private bool IsSpecificationDownloadDisabled => !this.selectedERIVersion.WasSpecificationSelected() || this.IsERIInputDisabled;
|
||||
|
||||
/// <summary>
|
||||
/// Gets whether the generated-code target directory selection should be disabled.
|
||||
/// </summary>
|
||||
private bool IsBaseDirectorySelectionDisabled => this.IsERIInputDisabled || !this.writeToFilesystem;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stable row snapshot for the embedding-method table.
|
||||
/// </summary>
|
||||
private EmbeddingInfo[] EmbeddingRows => this.embeddings.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stable row snapshot for the retrieval-process table.
|
||||
/// </summary>
|
||||
private RetrievalInfo[] RetrievalProcessRows => this.retrievalProcesses.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets called when the server name was changed by typing.
|
||||
/// </summary>
|
||||
@@ -780,6 +928,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task AddEmbedding()
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<EmbeddingMethodDialog>
|
||||
{
|
||||
{ x => x.IsEditing, false },
|
||||
@@ -798,6 +949,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task EditEmbedding(EmbeddingInfo embeddingInfo)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<EmbeddingMethodDialog>
|
||||
{
|
||||
{ x => x.DataEmbeddingName, embeddingInfo.EmbeddingName },
|
||||
@@ -823,6 +977,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task DeleteEmbedding(EmbeddingInfo embeddingInfo)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var message = this.retrievalProcesses.Any(n => n.Embeddings?.Contains(embeddingInfo) is true)
|
||||
? string.Format(T("The embedding '{0}' is used in one or more retrieval processes. Are you sure you want to delete it?"), embeddingInfo.EmbeddingName)
|
||||
: string.Format(T("Are you sure you want to delete the embedding '{0}'?"), embeddingInfo.EmbeddingName);
|
||||
@@ -845,6 +1002,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task AddRetrievalProcess()
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<RetrievalProcessDialog>
|
||||
{
|
||||
{ x => x.IsEditing, false },
|
||||
@@ -864,6 +1024,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task EditRetrievalProcess(RetrievalInfo retrievalInfo)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<RetrievalProcessDialog>
|
||||
{
|
||||
{ x => x.DataName, retrievalInfo.Name },
|
||||
@@ -890,6 +1053,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
|
||||
private async Task DeleteRetrievalProcess(RetrievalInfo retrievalInfo)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
var dialogParameters = new DialogParameters<ConfirmDialog>
|
||||
{
|
||||
{ x => x.Message, string.Format(T("Are you sure you want to delete the retrieval process '{0}'?"), retrievalInfo.Name) },
|
||||
@@ -949,6 +1115,10 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
this.AddInputIssue(T("Please describe at least one retrieval process."));
|
||||
return;
|
||||
}
|
||||
|
||||
var writeToFilesystemSnapshot = this.writeToFilesystem;
|
||||
var baseDirectorySnapshot = this.baseDirectory;
|
||||
var previouslyGeneratedFilesSnapshot = this.previouslyGeneratedFiles.ToArray();
|
||||
|
||||
this.eriSpecification = await this.selectedERIVersion.ReadSpecification(this.HttpClient);
|
||||
if (string.IsNullOrWhiteSpace(this.eriSpecification))
|
||||
@@ -990,9 +1160,9 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
var fileListAnswer = await this.AddAIResponseAsync(time, true);
|
||||
|
||||
// Is this an update of the ERI server? If so, we need to delete the previously generated files:
|
||||
if (this.writeToFilesystem && this.previouslyGeneratedFiles.Count > 0 && !string.IsNullOrWhiteSpace(fileListAnswer))
|
||||
if (writeToFilesystemSnapshot && previouslyGeneratedFilesSnapshot.Length > 0 && !string.IsNullOrWhiteSpace(fileListAnswer))
|
||||
{
|
||||
foreach (var file in this.previouslyGeneratedFiles)
|
||||
foreach (var file in previouslyGeneratedFilesSnapshot)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -1014,7 +1184,8 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
}
|
||||
|
||||
var generatedFiles = new List<string>();
|
||||
foreach (var file in this.ExtractFiles(fileListAnswer))
|
||||
var filesToGenerate = this.ExtractFiles(fileListAnswer).ToArray();
|
||||
foreach (var file in filesToGenerate)
|
||||
{
|
||||
this.Logger.LogInformation($"The LLM want to create the file: '{file}'");
|
||||
|
||||
@@ -1034,15 +1205,15 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
```
|
||||
""", true);
|
||||
var generatedCodeMarkdown = await this.AddAIResponseAsync(time);
|
||||
if (this.writeToFilesystem)
|
||||
if (writeToFilesystemSnapshot)
|
||||
{
|
||||
var desiredFilePath = Path.Join(this.baseDirectory, file);
|
||||
var desiredFilePath = Path.Join(baseDirectorySnapshot, file);
|
||||
|
||||
// Security check: ensure that the desired file path is inside the base directory.
|
||||
// We cannot trust the beginning of the file path because it would be possible
|
||||
// to escape by using `..` in the file path.
|
||||
if (!desiredFilePath.StartsWith(this.baseDirectory, StringComparison.InvariantCultureIgnoreCase) || desiredFilePath.Contains(".."))
|
||||
this.Logger.LogWarning($"The file path '{desiredFilePath}' is may not inside the base directory '{this.baseDirectory}'.");
|
||||
if (!desiredFilePath.StartsWith(baseDirectorySnapshot, StringComparison.InvariantCultureIgnoreCase) || desiredFilePath.Contains(".."))
|
||||
this.Logger.LogWarning($"The file path '{desiredFilePath}' is may not inside the base directory '{baseDirectorySnapshot}'.");
|
||||
|
||||
else
|
||||
{
|
||||
@@ -1077,7 +1248,7 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
}
|
||||
}
|
||||
|
||||
if(this.writeToFilesystem)
|
||||
if(writeToFilesystemSnapshot)
|
||||
{
|
||||
this.previouslyGeneratedFiles = generatedFiles;
|
||||
this.selectedERIServer!.PreviouslyGeneratedFiles = generatedFiles;
|
||||
@@ -1096,6 +1267,5 @@ public partial class AssistantERI : AssistantBaseCore<SettingsDialogERIServer>
|
||||
like Docker.
|
||||
""", true);
|
||||
await this.AddAIResponseAsync(time);
|
||||
await this.SendToAssistant(Tools.Components.CHAT, default);
|
||||
}
|
||||
}
|
||||
+31
-1
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.GrammarSpelling;
|
||||
|
||||
@@ -84,6 +85,28 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore<SettingsDialog
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private string correctedText = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CORRECTED_TEXT_STATE_KEY = new(nameof(correctedText));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(CORRECTED_TEXT_STATE_KEY, this.correctedText);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(CORRECTED_TEXT_STATE_KEY, value => this.correctedText = value);
|
||||
}
|
||||
|
||||
private string? ValidateText(string text)
|
||||
{
|
||||
@@ -127,6 +150,13 @@ public partial class AssistantGrammarSpelling : AssistantBaseCore<SettingsDialog
|
||||
var time = this.AddUserRequest(this.inputText);
|
||||
|
||||
this.correctedText = await this.AddAIResponseAsync(time);
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
|
||||
if (!this.IsAssistantComponentDisposed)
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
|
||||
}
|
||||
|
||||
protected override async Task OnAssistantSessionRenderedAsync(AssistantSessionSnapshot snapshot)
|
||||
{
|
||||
if (!snapshot.IsActive && !string.IsNullOrWhiteSpace(this.inputText) && !string.IsNullOrWhiteSpace(this.correctedText))
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.correctedText);
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,8 @@
|
||||
@using AIStudio.Settings
|
||||
@inherits AssistantBaseCore<AIStudio.Dialogs.Settings.SettingsDialogI18N>
|
||||
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" SelectionUpdated="_ => this.OnChangedLanguage()" />
|
||||
<ConfigurationSelect OptionDescription="@T("Language plugin used for comparision")" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="@T("Select the language plugin used for comparision.")"/>
|
||||
<EnumSelection T="CommonLanguages" NameFunc="@(language => language.NameSelecting())" @bind-Value="@this.selectedTargetLanguage" ValidateSelection="@this.ValidatingTargetLanguage" Icon="@Icons.Material.Filled.Translate" Label="@T("Target language")" AllowOther="@true" OtherValue="CommonLanguages.OTHER" @bind-OtherInput="@this.customTargetLanguage" ValidateOther="@this.ValidateCustomLanguage" LabelOther="@T("Custom target language")" SelectionUpdated="_ => this.OnChangedLanguage()" Disabled="@this.IsProcessing" />
|
||||
<ConfigurationSelect OptionDescription="@T("Language plugin used for comparision")" SelectedValue="@(() => this.selectedLanguagePluginId)" Data="@ConfigurationSelectDataFactory.GetLanguagesData()" SelectionUpdate="@(async void (id) => await this.OnLanguagePluginChanged(id))" OptionHelp="@T("Select the language plugin used for comparision.")" Disabled="@(() => this.IsProcessing)"/>
|
||||
@if (this.isLoading)
|
||||
{
|
||||
<MudText Typo="Typo.body1" Class="mb-6">
|
||||
@@ -20,7 +20,7 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.AddedContentText
|
||||
</MudText>
|
||||
<MudTable Items="@this.addedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<MudTable Items="@this.AddedContentRows" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
|
||||
</ToolBarContent>
|
||||
@@ -50,7 +50,7 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.RemovedContentText
|
||||
</MudText>
|
||||
<MudTable Items="@this.removedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<MudTable Items="@this.RemovedContentRows" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
|
||||
</ToolBarContent>
|
||||
@@ -94,7 +94,7 @@ else if (!this.isLoading && string.IsNullOrWhiteSpace(this.loadingIssue))
|
||||
<MudText Typo="Typo.h6">
|
||||
@this.LocalizedContentText
|
||||
</MudText>
|
||||
<MudTable Items="@this.localizedContent" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<MudTable Items="@this.LocalizedContentRows" Hover="@true" Filter="@this.FilterFunc" Class="border-dashed border rounded-lg mb-6">
|
||||
<ToolBarContent>
|
||||
<MudTextField @bind-Value="@this.searchString" Immediate="true" Placeholder="@T("Search")" Adornment="Adornment.Start" AdornmentIcon="@Icons.Material.Filled.Search" IconSize="Size.Medium" Class="mt-0"/>
|
||||
</ToolBarContent>
|
||||
|
||||
@@ -2,6 +2,7 @@ using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using AIStudio.Tools.PluginSystem;
|
||||
|
||||
using Microsoft.Extensions.FileProviders;
|
||||
@@ -117,32 +118,87 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
|
||||
private Dictionary<string, string> removedContent = [];
|
||||
private Dictionary<string, string> localizedContent = [];
|
||||
private StringBuilder finalLuaCode = new();
|
||||
private string? activeSystemPromptLanguage;
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_LOADING_STATE_KEY = new(nameof(isLoading));
|
||||
private static readonly AssistantSessionStateKey<string> LOADING_ISSUE_STATE_KEY = new(nameof(loadingIssue));
|
||||
private static readonly AssistantSessionStateKey<bool> LOCALIZATION_POSSIBLE_STATE_KEY = new(nameof(localizationPossible));
|
||||
private static readonly AssistantSessionStateKey<string> SEARCH_STRING_STATE_KEY = new(nameof(searchString));
|
||||
private static readonly AssistantSessionStateKey<Guid> SELECTED_LANGUAGE_PLUGIN_ID_STATE_KEY = new(nameof(selectedLanguagePluginId));
|
||||
private static readonly AssistantSessionStateKey<ILanguagePlugin?> SELECTED_LANGUAGE_PLUGIN_STATE_KEY = new(nameof(selectedLanguagePlugin));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> ADDED_CONTENT_STATE_KEY = new(nameof(addedContent));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> REMOVED_CONTENT_STATE_KEY = new(nameof(removedContent));
|
||||
private static readonly AssistantSessionStateKey<Dictionary<string, string>> LOCALIZED_CONTENT_STATE_KEY = new(nameof(localizedContent));
|
||||
private static readonly AssistantSessionStateKey<string> FINAL_LUA_CODE_STATE_KEY = new(nameof(finalLuaCode));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(IS_LOADING_STATE_KEY, this.isLoading);
|
||||
state.Set(LOADING_ISSUE_STATE_KEY, this.loadingIssue);
|
||||
state.Set(LOCALIZATION_POSSIBLE_STATE_KEY, this.localizationPossible);
|
||||
state.Set(SEARCH_STRING_STATE_KEY, this.searchString);
|
||||
state.Set(SELECTED_LANGUAGE_PLUGIN_ID_STATE_KEY, this.selectedLanguagePluginId);
|
||||
state.Set(SELECTED_LANGUAGE_PLUGIN_STATE_KEY, this.selectedLanguagePlugin);
|
||||
state.SetDictionary(ADDED_CONTENT_STATE_KEY, this.addedContent);
|
||||
state.SetDictionary(REMOVED_CONTENT_STATE_KEY, this.removedContent);
|
||||
state.SetDictionary(LOCALIZED_CONTENT_STATE_KEY, this.localizedContent);
|
||||
state.SetStringBuilder(FINAL_LUA_CODE_STATE_KEY, this.finalLuaCode);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(IS_LOADING_STATE_KEY, value => this.isLoading = value);
|
||||
state.Restore(LOADING_ISSUE_STATE_KEY, value => this.loadingIssue = value);
|
||||
state.Restore(LOCALIZATION_POSSIBLE_STATE_KEY, value => this.localizationPossible = value);
|
||||
state.Restore(SEARCH_STRING_STATE_KEY, value => this.searchString = value);
|
||||
state.Restore(SELECTED_LANGUAGE_PLUGIN_ID_STATE_KEY, value => this.selectedLanguagePluginId = value);
|
||||
state.Restore(SELECTED_LANGUAGE_PLUGIN_STATE_KEY, value => this.selectedLanguagePlugin = value);
|
||||
state.RestoreDictionary(ADDED_CONTENT_STATE_KEY, this.addedContent);
|
||||
state.RestoreDictionary(REMOVED_CONTENT_STATE_KEY, this.removedContent);
|
||||
state.RestoreDictionary(LOCALIZED_CONTENT_STATE_KEY, this.localizedContent);
|
||||
state.RestoreStringBuilder(FINAL_LUA_CODE_STATE_KEY, this.finalLuaCode);
|
||||
}
|
||||
|
||||
#region Overrides of AssistantBase<SettingsDialogI18N>
|
||||
|
||||
protected override async Task OnInitializedAsync()
|
||||
{
|
||||
await base.OnInitializedAsync();
|
||||
if (this.HasAssistantSession)
|
||||
return;
|
||||
|
||||
await this.OnLanguagePluginChanged(this.selectedLanguagePluginId);
|
||||
await this.LoadData();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private string SystemPromptLanguage() => this.selectedTargetLanguage switch
|
||||
private string SystemPromptLanguage() => this.activeSystemPromptLanguage ?? (this.selectedTargetLanguage switch
|
||||
{
|
||||
CommonLanguages.OTHER => this.customTargetLanguage,
|
||||
_ => $"{this.selectedTargetLanguage.Name()}",
|
||||
};
|
||||
});
|
||||
|
||||
private async Task OnLanguagePluginChanged(Guid pluginId)
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
this.selectedLanguagePluginId = pluginId;
|
||||
await this.OnChangedLanguage();
|
||||
}
|
||||
|
||||
private async Task OnChangedLanguage()
|
||||
{
|
||||
if (this.IsProcessing)
|
||||
return;
|
||||
|
||||
this.finalLuaCode.Clear();
|
||||
this.localizedContent.Clear();
|
||||
this.localizationPossible = false;
|
||||
@@ -261,6 +317,21 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
|
||||
|
||||
private int NumTotalItems => (this.selectedLanguagePlugin?.Content.Count ?? 0) + this.addedContent.Count - this.removedContent.Count;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stable row snapshot for the added-content table.
|
||||
/// </summary>
|
||||
private KeyValuePair<string, string>[] AddedContentRows => this.addedContent.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stable row snapshot for the removed-content table.
|
||||
/// </summary>
|
||||
private KeyValuePair<string, string>[] RemovedContentRows => this.removedContent.ToArray();
|
||||
|
||||
/// <summary>
|
||||
/// Gets a stable row snapshot for the localized-content table.
|
||||
/// </summary>
|
||||
private KeyValuePair<string, string>[] LocalizedContentRows => this.localizedContent.ToArray();
|
||||
|
||||
private string AddedContentText => string.Format(T("Added Content ({0} entries)"), this.addedContent.Count);
|
||||
|
||||
private string RemovedContentText => string.Format(T("Removed Content ({0} entries)"), this.removedContent.Count);
|
||||
@@ -279,68 +350,87 @@ public partial class AssistantI18N : AssistantBaseCore<SettingsDialogI18N>
|
||||
if (this.selectedLanguagePlugin.IETFTag != this.selectedTargetLanguage.ToIETFTag())
|
||||
return;
|
||||
|
||||
this.localizedContent.Clear();
|
||||
if (this.selectedTargetLanguage is not CommonLanguages.EN_US)
|
||||
{
|
||||
// Phase 1: Translate added content
|
||||
await this.Phase1TranslateAddedContent();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: no translation needed
|
||||
this.localizedContent = this.addedContent.ToDictionary();
|
||||
}
|
||||
var addedContentSnapshot = this.addedContent.ToArray();
|
||||
var removedContentSnapshot = this.removedContent.ToArray();
|
||||
var removedContentKeys = removedContentSnapshot.Select(keyValuePair => keyValuePair.Key).ToHashSet(StringComparer.Ordinal);
|
||||
var selectedLanguageContentSnapshot = this.selectedLanguagePlugin.Content.ToArray();
|
||||
var baseLanguageContentSnapshot = PluginFactory.BaseLanguage.Content.ToArray();
|
||||
|
||||
if(this.CancellationTokenSource!.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
//
|
||||
// Now, we have localized the added content. Next, we must merge
|
||||
// the localized content with the existing content. However, we
|
||||
// must skip the removed content. We use the localizedContent
|
||||
// dictionary for the final result:
|
||||
//
|
||||
foreach (var keyValuePair in this.selectedLanguagePlugin.Content)
|
||||
this.localizedContent.Clear();
|
||||
this.activeSystemPromptLanguage = this.SystemPromptLanguage();
|
||||
try
|
||||
{
|
||||
if (this.CancellationTokenSource!.IsCancellationRequested)
|
||||
break;
|
||||
if (this.selectedTargetLanguage is not CommonLanguages.EN_US)
|
||||
{
|
||||
// Phase 1: Translate added content
|
||||
await this.Phase1TranslateAddedContent(addedContentSnapshot);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Case: no translation needed
|
||||
this.localizedContent = addedContentSnapshot.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value, StringComparer.Ordinal);
|
||||
}
|
||||
|
||||
if(this.CancellationTokenSource!.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
if (this.localizedContent.ContainsKey(keyValuePair.Key))
|
||||
continue;
|
||||
//
|
||||
// Now, we have localized the added content. Next, we must merge
|
||||
// the localized content with the existing content. However, we
|
||||
// must skip the removed content. We use the localizedContent
|
||||
// dictionary for the final result:
|
||||
//
|
||||
foreach (var keyValuePair in selectedLanguageContentSnapshot)
|
||||
{
|
||||
if (this.CancellationTokenSource!.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
if (this.localizedContent.ContainsKey(keyValuePair.Key))
|
||||
continue;
|
||||
|
||||
if (removedContentKeys.Contains(keyValuePair.Key))
|
||||
continue;
|
||||
|
||||
this.localizedContent.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
|
||||
if(this.CancellationTokenSource!.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
if (this.removedContent.ContainsKey(keyValuePair.Key))
|
||||
continue;
|
||||
//
|
||||
// Phase 2: Create the Lua code. We want to use the base language
|
||||
// for the comments, though:
|
||||
//
|
||||
var commentContent = addedContentSnapshot.ToDictionary(keyValuePair => keyValuePair.Key, keyValuePair => keyValuePair.Value, StringComparer.Ordinal);
|
||||
foreach (var keyValuePair in baseLanguageContentSnapshot)
|
||||
{
|
||||
if (this.CancellationTokenSource!.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
if (removedContentKeys.Contains(keyValuePair.Key))
|
||||
continue;
|
||||
|
||||
commentContent.TryAdd(keyValuePair.Key, keyValuePair.Value);
|
||||
}
|
||||
|
||||
this.localizedContent.Add(keyValuePair.Key, keyValuePair.Value);
|
||||
this.Phase2CreateLuaCode(commentContent);
|
||||
}
|
||||
|
||||
if(this.CancellationTokenSource!.IsCancellationRequested)
|
||||
return;
|
||||
|
||||
//
|
||||
// Phase 2: Create the Lua code. We want to use the base language
|
||||
// for the comments, though:
|
||||
//
|
||||
var commentContent = new Dictionary<string, string>(this.addedContent);
|
||||
foreach (var keyValuePair in PluginFactory.BaseLanguage.Content)
|
||||
finally
|
||||
{
|
||||
if (this.CancellationTokenSource!.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
if (this.removedContent.ContainsKey(keyValuePair.Key))
|
||||
continue;
|
||||
|
||||
commentContent.TryAdd(keyValuePair.Key, keyValuePair.Value);
|
||||
this.activeSystemPromptLanguage = null;
|
||||
}
|
||||
|
||||
this.Phase2CreateLuaCode(commentContent);
|
||||
}
|
||||
|
||||
private async Task Phase1TranslateAddedContent()
|
||||
/// <summary>
|
||||
/// Translates the added text content from a stable snapshot.
|
||||
/// </summary>
|
||||
/// <param name="addedContentSnapshot">The added text entries captured when the job started.</param>
|
||||
/// <returns>A task that completes when all added text entries were translated or cancellation was requested.</returns>
|
||||
private async Task Phase1TranslateAddedContent(KeyValuePair<string, string>[] addedContentSnapshot)
|
||||
{
|
||||
var stopwatch = new Stopwatch();
|
||||
var minimumTime = TimeSpan.FromMilliseconds(500);
|
||||
foreach (var keyValuePair in this.addedContent)
|
||||
foreach (var keyValuePair in addedContentSnapshot)
|
||||
{
|
||||
if(this.CancellationTokenSource!.IsCancellationRequested)
|
||||
break;
|
||||
|
||||
@@ -310,6 +310,12 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ASSISTANTBASE::T180921696"] = "Reset"
|
||||
-- Please select a provider.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ASSISTANTBASE::T1809312323"] = "Please select a provider."
|
||||
|
||||
-- The assistant failed. The message is: '{0}'
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ASSISTANTBASE::T1833836281"] = "The assistant failed. The message is: '{0}'"
|
||||
|
||||
-- This assistant is already running. AI Studio opens the running session instead.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ASSISTANTBASE::T2575715765"] = "This assistant is already running. AI Studio opens the running session instead."
|
||||
|
||||
-- Assistant - {0}
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ASSISTANTBASE::T3043922"] = "Assistant - {0}"
|
||||
|
||||
@@ -748,6 +754,9 @@ UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1565111217"] = "Relat
|
||||
-- Please select an ERI specification version for the ERI server.
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1612890554"] = "Please select an ERI specification version for the ERI server."
|
||||
|
||||
-- Open in chat
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T1664804142"] = "Open in chat"
|
||||
|
||||
-- Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user).
|
||||
UI_TEXT_CONTENT["AISTUDIO::ASSISTANTS::ERI::ASSISTANTERI::T168780641"] = "Ports below 1024 are reserved for system services. Your ERI server need to run with elevated permissions (root user)."
|
||||
|
||||
@@ -1981,6 +1990,18 @@ UI_TEXT_CONTENT["AISTUDIO::CHAT::IIMAGESOURCEEXTENSIONS::T349928509"] = "The ima
|
||||
-- Open Settings
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T1172211894"] = "Open Settings"
|
||||
|
||||
-- Assistant is still running.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T2719896610"] = "Assistant is still running."
|
||||
|
||||
-- Assistant was canceled. Open it to review the result.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T3390934621"] = "Assistant was canceled. Open it to review the result."
|
||||
|
||||
-- Assistant failed. Open it to review the result.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T3571008422"] = "Assistant failed. Open it to review the result."
|
||||
|
||||
-- The result is ready.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTBLOCK::T661906146"] = "The result is ready."
|
||||
|
||||
-- Show or hide the detailed security information.
|
||||
UI_TEXT_CONTENT["AISTUDIO::COMPONENTS::ASSISTANTPLUGINSECURITYCARD::T1045105126"] = "Show or hide the detailed security information."
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.IconFinder;
|
||||
|
||||
@@ -56,6 +57,22 @@ public partial class AssistantIconFinder : AssistantBaseCore<SettingsDialogIconF
|
||||
|
||||
private string inputContext = string.Empty;
|
||||
private IconSources selectedIconSource;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_CONTEXT_STATE_KEY = new(nameof(inputContext));
|
||||
private static readonly AssistantSessionStateKey<IconSources> SELECTED_ICON_SOURCE_STATE_KEY = new(nameof(selectedIconSource));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_CONTEXT_STATE_KEY, this.inputContext);
|
||||
state.Set(SELECTED_ICON_SOURCE_STATE_KEY, this.selectedIconSource);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_CONTEXT_STATE_KEY, value => this.inputContext = value);
|
||||
state.Restore(SELECTED_ICON_SOURCE_STATE_KEY, value => this.selectedIconSource = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.JobPosting;
|
||||
|
||||
@@ -128,6 +129,49 @@ public partial class AssistantJobPostings : AssistantBaseCore<SettingsDialogJobP
|
||||
private string inputCountryLegalFramework = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_MANDATORY_INFORMATION_STATE_KEY = new(nameof(inputMandatoryInformation));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_JOB_DESCRIPTION_STATE_KEY = new(nameof(inputJobDescription));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_QUALIFICATIONS_STATE_KEY = new(nameof(inputQualifications));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_RESPONSIBILITIES_STATE_KEY = new(nameof(inputResponsibilities));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_COMPANY_NAME_STATE_KEY = new(nameof(inputCompanyName));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_ENTRY_DATE_STATE_KEY = new(nameof(inputEntryDate));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_VALID_UNTIL_STATE_KEY = new(nameof(inputValidUntil));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_WORK_LOCATION_STATE_KEY = new(nameof(inputWorkLocation));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_COUNTRY_LEGAL_FRAMEWORK_STATE_KEY = new(nameof(inputCountryLegalFramework));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_MANDATORY_INFORMATION_STATE_KEY, this.inputMandatoryInformation);
|
||||
state.Set(INPUT_JOB_DESCRIPTION_STATE_KEY, this.inputJobDescription);
|
||||
state.Set(INPUT_QUALIFICATIONS_STATE_KEY, this.inputQualifications);
|
||||
state.Set(INPUT_RESPONSIBILITIES_STATE_KEY, this.inputResponsibilities);
|
||||
state.Set(INPUT_COMPANY_NAME_STATE_KEY, this.inputCompanyName);
|
||||
state.Set(INPUT_ENTRY_DATE_STATE_KEY, this.inputEntryDate);
|
||||
state.Set(INPUT_VALID_UNTIL_STATE_KEY, this.inputValidUntil);
|
||||
state.Set(INPUT_WORK_LOCATION_STATE_KEY, this.inputWorkLocation);
|
||||
state.Set(INPUT_COUNTRY_LEGAL_FRAMEWORK_STATE_KEY, this.inputCountryLegalFramework);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_MANDATORY_INFORMATION_STATE_KEY, value => this.inputMandatoryInformation = value);
|
||||
state.Restore(INPUT_JOB_DESCRIPTION_STATE_KEY, value => this.inputJobDescription = value);
|
||||
state.Restore(INPUT_QUALIFICATIONS_STATE_KEY, value => this.inputQualifications = value);
|
||||
state.Restore(INPUT_RESPONSIBILITIES_STATE_KEY, value => this.inputResponsibilities = value);
|
||||
state.Restore(INPUT_COMPANY_NAME_STATE_KEY, value => this.inputCompanyName = value);
|
||||
state.Restore(INPUT_ENTRY_DATE_STATE_KEY, value => this.inputEntryDate = value);
|
||||
state.Restore(INPUT_VALID_UNTIL_STATE_KEY, value => this.inputValidUntil = value);
|
||||
state.Restore(INPUT_WORK_LOCATION_STATE_KEY, value => this.inputWorkLocation = value);
|
||||
state.Restore(INPUT_COUNTRY_LEGAL_FRAMEWORK_STATE_KEY, value => this.inputCountryLegalFramework = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.LegalCheck;
|
||||
|
||||
@@ -59,6 +60,31 @@ public partial class AssistantLegalCheck : AssistantBaseCore<SettingsDialogLegal
|
||||
private bool isAgentRunning;
|
||||
private string inputLegalDocument = string.Empty;
|
||||
private string inputQuestions = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_WEB_CONTENT_READER_STATE_KEY = new(nameof(showWebContentReader));
|
||||
private static readonly AssistantSessionStateKey<bool> USE_CONTENT_CLEANER_AGENT_STATE_KEY = new(nameof(useContentCleanerAgent));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_AGENT_RUNNING_STATE_KEY = new(nameof(isAgentRunning));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_LEGAL_DOCUMENT_STATE_KEY = new(nameof(inputLegalDocument));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_QUESTIONS_STATE_KEY = new(nameof(inputQuestions));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SHOW_WEB_CONTENT_READER_STATE_KEY, this.showWebContentReader);
|
||||
state.Set(USE_CONTENT_CLEANER_AGENT_STATE_KEY, this.useContentCleanerAgent);
|
||||
state.Set(IS_AGENT_RUNNING_STATE_KEY, this.isAgentRunning);
|
||||
state.Set(INPUT_LEGAL_DOCUMENT_STATE_KEY, this.inputLegalDocument);
|
||||
state.Set(INPUT_QUESTIONS_STATE_KEY, this.inputQuestions);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SHOW_WEB_CONTENT_READER_STATE_KEY, value => this.showWebContentReader = value);
|
||||
state.Restore(USE_CONTENT_CLEANER_AGENT_STATE_KEY, value => this.useContentCleanerAgent = value);
|
||||
state.Restore(IS_AGENT_RUNNING_STATE_KEY, value => this.isAgentRunning = value);
|
||||
state.Restore(INPUT_LEGAL_DOCUMENT_STATE_KEY, value => this.inputLegalDocument = value);
|
||||
state.Restore(INPUT_QUESTIONS_STATE_KEY, value => this.inputQuestions = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.MyTasks;
|
||||
|
||||
@@ -59,6 +60,25 @@ public partial class AssistantMyTasks : AssistantBaseCore<SettingsDialogMyTasks>
|
||||
private string inputText = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage = CommonLanguages.AS_IS;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Text.RegularExpressions;
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Dialogs;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
using Microsoft.AspNetCore.Components;
|
||||
|
||||
#if !DEBUG
|
||||
@@ -176,6 +177,67 @@ public partial class AssistantPromptOptimizer : AssistantBaseCore<SettingsDialog
|
||||
private string recStructureMarkers = string.Empty;
|
||||
private string recRoleDefinition = string.Empty;
|
||||
private string recLanguageChoice = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_PROMPT_STATE_KEY = new(nameof(inputPrompt));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> IMPORTANT_ASPECTS_STATE_KEY = new(nameof(importantAspects));
|
||||
private static readonly AssistantSessionStateKey<bool> USE_CUSTOM_PROMPT_GUIDE_STATE_KEY = new(nameof(useCustomPromptGuide));
|
||||
private static readonly AssistantSessionStateKey<HashSet<FileAttachment>> CUSTOM_PROMPT_GUIDE_FILES_STATE_KEY = new(nameof(customPromptGuideFiles));
|
||||
private static readonly AssistantSessionStateKey<string> CURRENT_CUSTOM_PROMPT_GUIDE_PATH_STATE_KEY = new(nameof(currentCustomPromptGuidePath));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_PROMPTING_GUIDELINE_CONTENT_STATE_KEY = new(nameof(customPromptingGuidelineContent));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_LOADING_CUSTOM_PROMPT_GUIDE_STATE_KEY = new(nameof(isLoadingCustomPromptGuide));
|
||||
private static readonly AssistantSessionStateKey<bool> HAS_UPDATED_DEFAULT_RECOMMENDATIONS_STATE_KEY = new(nameof(hasUpdatedDefaultRecommendations));
|
||||
private static readonly AssistantSessionStateKey<string> OPTIMIZED_PROMPT_STATE_KEY = new(nameof(optimizedPrompt));
|
||||
private static readonly AssistantSessionStateKey<string> REC_CLARITY_DIRECTNESS_STATE_KEY = new(nameof(recClarityDirectness));
|
||||
private static readonly AssistantSessionStateKey<string> REC_EXAMPLES_CONTEXT_STATE_KEY = new(nameof(recExamplesContext));
|
||||
private static readonly AssistantSessionStateKey<string> REC_SEQUENTIAL_STEPS_STATE_KEY = new(nameof(recSequentialSteps));
|
||||
private static readonly AssistantSessionStateKey<string> REC_STRUCTURE_MARKERS_STATE_KEY = new(nameof(recStructureMarkers));
|
||||
private static readonly AssistantSessionStateKey<string> REC_ROLE_DEFINITION_STATE_KEY = new(nameof(recRoleDefinition));
|
||||
private static readonly AssistantSessionStateKey<string> REC_LANGUAGE_CHOICE_STATE_KEY = new(nameof(recLanguageChoice));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_PROMPT_STATE_KEY, this.inputPrompt);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(IMPORTANT_ASPECTS_STATE_KEY, this.importantAspects);
|
||||
state.Set(USE_CUSTOM_PROMPT_GUIDE_STATE_KEY, this.useCustomPromptGuide);
|
||||
state.SetHashSet(CUSTOM_PROMPT_GUIDE_FILES_STATE_KEY, this.customPromptGuideFiles);
|
||||
state.Set(CURRENT_CUSTOM_PROMPT_GUIDE_PATH_STATE_KEY, this.currentCustomPromptGuidePath);
|
||||
state.Set(CUSTOM_PROMPTING_GUIDELINE_CONTENT_STATE_KEY, this.customPromptingGuidelineContent);
|
||||
state.Set(IS_LOADING_CUSTOM_PROMPT_GUIDE_STATE_KEY, this.isLoadingCustomPromptGuide);
|
||||
state.Set(HAS_UPDATED_DEFAULT_RECOMMENDATIONS_STATE_KEY, this.hasUpdatedDefaultRecommendations);
|
||||
state.Set(OPTIMIZED_PROMPT_STATE_KEY, this.optimizedPrompt);
|
||||
state.Set(REC_CLARITY_DIRECTNESS_STATE_KEY, this.recClarityDirectness);
|
||||
state.Set(REC_EXAMPLES_CONTEXT_STATE_KEY, this.recExamplesContext);
|
||||
state.Set(REC_SEQUENTIAL_STEPS_STATE_KEY, this.recSequentialSteps);
|
||||
state.Set(REC_STRUCTURE_MARKERS_STATE_KEY, this.recStructureMarkers);
|
||||
state.Set(REC_ROLE_DEFINITION_STATE_KEY, this.recRoleDefinition);
|
||||
state.Set(REC_LANGUAGE_CHOICE_STATE_KEY, this.recLanguageChoice);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_PROMPT_STATE_KEY, value => this.inputPrompt = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(IMPORTANT_ASPECTS_STATE_KEY, value => this.importantAspects = value);
|
||||
state.Restore(USE_CUSTOM_PROMPT_GUIDE_STATE_KEY, value => this.useCustomPromptGuide = value);
|
||||
state.RestoreHashSet(CUSTOM_PROMPT_GUIDE_FILES_STATE_KEY, this.customPromptGuideFiles);
|
||||
state.Restore(CURRENT_CUSTOM_PROMPT_GUIDE_PATH_STATE_KEY, value => this.currentCustomPromptGuidePath = value);
|
||||
state.Restore(CUSTOM_PROMPTING_GUIDELINE_CONTENT_STATE_KEY, value => this.customPromptingGuidelineContent = value);
|
||||
state.Restore(IS_LOADING_CUSTOM_PROMPT_GUIDE_STATE_KEY, value => this.isLoadingCustomPromptGuide = value);
|
||||
state.Restore(HAS_UPDATED_DEFAULT_RECOMMENDATIONS_STATE_KEY, value => this.hasUpdatedDefaultRecommendations = value);
|
||||
state.Restore(OPTIMIZED_PROMPT_STATE_KEY, value => this.optimizedPrompt = value);
|
||||
state.Restore(REC_CLARITY_DIRECTNESS_STATE_KEY, value => this.recClarityDirectness = value);
|
||||
state.Restore(REC_EXAMPLES_CONTEXT_STATE_KEY, value => this.recExamplesContext = value);
|
||||
state.Restore(REC_SEQUENTIAL_STEPS_STATE_KEY, value => this.recSequentialSteps = value);
|
||||
state.Restore(REC_STRUCTURE_MARKERS_STATE_KEY, value => this.recStructureMarkers = value);
|
||||
state.Restore(REC_ROLE_DEFINITION_STATE_KEY, value => this.recRoleDefinition = value);
|
||||
state.Restore(REC_LANGUAGE_CHOICE_STATE_KEY, value => this.recLanguageChoice = value);
|
||||
}
|
||||
|
||||
private bool ShowUpdatedPromptGuidelinesIndicator => !this.useCustomPromptGuide && this.hasUpdatedDefaultRecommendations;
|
||||
private bool CanPreviewCustomPromptGuide => this.useCustomPromptGuide && this.customPromptGuideFiles.Count > 0;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.RewriteImprove;
|
||||
|
||||
@@ -91,6 +92,34 @@ public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogR
|
||||
private string rewrittenText = string.Empty;
|
||||
private WritingStyles selectedWritingStyle;
|
||||
private SentenceStructure selectedSentenceStructure;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> REWRITTEN_TEXT_STATE_KEY = new(nameof(rewrittenText));
|
||||
private static readonly AssistantSessionStateKey<WritingStyles> SELECTED_WRITING_STYLE_STATE_KEY = new(nameof(selectedWritingStyle));
|
||||
private static readonly AssistantSessionStateKey<SentenceStructure> SELECTED_SENTENCE_STRUCTURE_STATE_KEY = new(nameof(selectedSentenceStructure));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(REWRITTEN_TEXT_STATE_KEY, this.rewrittenText);
|
||||
state.Set(SELECTED_WRITING_STYLE_STATE_KEY, this.selectedWritingStyle);
|
||||
state.Set(SELECTED_SENTENCE_STRUCTURE_STATE_KEY, this.selectedSentenceStructure);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(REWRITTEN_TEXT_STATE_KEY, value => this.rewrittenText = value);
|
||||
state.Restore(SELECTED_WRITING_STYLE_STATE_KEY, value => this.selectedWritingStyle = value);
|
||||
state.Restore(SELECTED_SENTENCE_STRUCTURE_STATE_KEY, value => this.selectedSentenceStructure = value);
|
||||
}
|
||||
|
||||
private string? ValidateText(string text)
|
||||
{
|
||||
@@ -134,6 +163,13 @@ public partial class AssistantRewriteImprove : AssistantBaseCore<SettingsDialogR
|
||||
var time = this.AddUserRequest(this.inputText);
|
||||
|
||||
this.rewrittenText = await this.AddAIResponseAsync(time);
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText);
|
||||
if (!this.IsAssistantComponentDisposed)
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText);
|
||||
}
|
||||
|
||||
protected override async Task OnAssistantSessionRenderedAsync(AssistantSessionSnapshot snapshot)
|
||||
{
|
||||
if (!snapshot.IsActive && !string.IsNullOrWhiteSpace(this.inputText) && !string.IsNullOrWhiteSpace(this.rewrittenText))
|
||||
await this.JsRuntime.GenerateAndShowDiff(this.inputText, this.rewrittenText);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Text;
|
||||
using AIStudio.Chat;
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.SlideBuilder;
|
||||
|
||||
@@ -197,6 +198,58 @@ public partial class SlideAssistant : AssistantBaseCore<SettingsDialogSlideBuild
|
||||
private int calculatedNumberOfSlides;
|
||||
private string importantAspects = string.Empty;
|
||||
private HashSet<FileAttachment> loadedDocumentPaths = [];
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TITLE_STATE_KEY = new(nameof(inputTitle));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_CONTENT_STATE_KEY = new(nameof(inputContent));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<AudienceProfile> SELECTED_AUDIENCE_PROFILE_STATE_KEY = new(nameof(selectedAudienceProfile));
|
||||
private static readonly AssistantSessionStateKey<AudienceAgeGroup> SELECTED_AUDIENCE_AGE_GROUP_STATE_KEY = new(nameof(selectedAudienceAgeGroup));
|
||||
private static readonly AssistantSessionStateKey<AudienceOrganizationalLevel> SELECTED_AUDIENCE_ORGANIZATIONAL_LEVEL_STATE_KEY = new(nameof(selectedAudienceOrganizationalLevel));
|
||||
private static readonly AssistantSessionStateKey<AudienceExpertise> SELECTED_AUDIENCE_EXPERTISE_STATE_KEY = new(nameof(selectedAudienceExpertise));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<int> NUMBER_OF_SHEETS_STATE_KEY = new(nameof(numberOfSheets));
|
||||
private static readonly AssistantSessionStateKey<int> NUMBER_OF_BULLET_POINTS_STATE_KEY = new(nameof(numberOfBulletPoints));
|
||||
private static readonly AssistantSessionStateKey<int> TIME_SPECIFICATION_STATE_KEY = new(nameof(timeSpecification));
|
||||
private static readonly AssistantSessionStateKey<int> CALCULATED_NUMBER_OF_SLIDES_STATE_KEY = new(nameof(calculatedNumberOfSlides));
|
||||
private static readonly AssistantSessionStateKey<string> IMPORTANT_ASPECTS_STATE_KEY = new(nameof(importantAspects));
|
||||
private static readonly AssistantSessionStateKey<HashSet<FileAttachment>> LOADED_DOCUMENT_PATHS_STATE_KEY = new(nameof(loadedDocumentPaths));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TITLE_STATE_KEY, this.inputTitle);
|
||||
state.Set(INPUT_CONTENT_STATE_KEY, this.inputContent);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(SELECTED_AUDIENCE_PROFILE_STATE_KEY, this.selectedAudienceProfile);
|
||||
state.Set(SELECTED_AUDIENCE_AGE_GROUP_STATE_KEY, this.selectedAudienceAgeGroup);
|
||||
state.Set(SELECTED_AUDIENCE_ORGANIZATIONAL_LEVEL_STATE_KEY, this.selectedAudienceOrganizationalLevel);
|
||||
state.Set(SELECTED_AUDIENCE_EXPERTISE_STATE_KEY, this.selectedAudienceExpertise);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(NUMBER_OF_SHEETS_STATE_KEY, this.numberOfSheets);
|
||||
state.Set(NUMBER_OF_BULLET_POINTS_STATE_KEY, this.numberOfBulletPoints);
|
||||
state.Set(TIME_SPECIFICATION_STATE_KEY, this.timeSpecification);
|
||||
state.Set(CALCULATED_NUMBER_OF_SLIDES_STATE_KEY, this.calculatedNumberOfSlides);
|
||||
state.Set(IMPORTANT_ASPECTS_STATE_KEY, this.importantAspects);
|
||||
state.SetHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TITLE_STATE_KEY, value => this.inputTitle = value);
|
||||
state.Restore(INPUT_CONTENT_STATE_KEY, value => this.inputContent = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(SELECTED_AUDIENCE_PROFILE_STATE_KEY, value => this.selectedAudienceProfile = value);
|
||||
state.Restore(SELECTED_AUDIENCE_AGE_GROUP_STATE_KEY, value => this.selectedAudienceAgeGroup = value);
|
||||
state.Restore(SELECTED_AUDIENCE_ORGANIZATIONAL_LEVEL_STATE_KEY, value => this.selectedAudienceOrganizationalLevel = value);
|
||||
state.Restore(SELECTED_AUDIENCE_EXPERTISE_STATE_KEY, value => this.selectedAudienceExpertise = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(NUMBER_OF_SHEETS_STATE_KEY, value => this.numberOfSheets = value);
|
||||
state.Restore(NUMBER_OF_BULLET_POINTS_STATE_KEY, value => this.numberOfBulletPoints = value);
|
||||
state.Restore(TIME_SPECIFICATION_STATE_KEY, value => this.timeSpecification = value);
|
||||
state.Restore(CALCULATED_NUMBER_OF_SLIDES_STATE_KEY, value => this.calculatedNumberOfSlides = value);
|
||||
state.Restore(IMPORTANT_ASPECTS_STATE_KEY, value => this.importantAspects = value);
|
||||
state.RestoreHashSet(LOADED_DOCUMENT_PATHS_STATE_KEY, this.loadedDocumentPaths);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.Synonym;
|
||||
|
||||
@@ -103,6 +104,28 @@ public partial class AssistantSynonyms : AssistantBaseCore<SettingsDialogSynonym
|
||||
private string inputContext = string.Empty;
|
||||
private CommonLanguages selectedLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_CONTEXT_STATE_KEY = new(nameof(inputContext));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_LANGUAGE_STATE_KEY = new(nameof(selectedLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(INPUT_CONTEXT_STATE_KEY, this.inputContext);
|
||||
state.Set(SELECTED_LANGUAGE_STATE_KEY, this.selectedLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(INPUT_CONTEXT_STATE_KEY, value => this.inputContext = value);
|
||||
state.Restore(SELECTED_LANGUAGE_STATE_KEY, value => this.selectedLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.TextSummarizer;
|
||||
|
||||
@@ -72,6 +73,43 @@ public partial class AssistantTextSummarizer : AssistantBaseCore<SettingsDialogT
|
||||
private Complexity selectedComplexity;
|
||||
private string expertInField = string.Empty;
|
||||
private string importantAspects = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_WEB_CONTENT_READER_STATE_KEY = new(nameof(showWebContentReader));
|
||||
private static readonly AssistantSessionStateKey<bool> USE_CONTENT_CLEANER_AGENT_STATE_KEY = new(nameof(useContentCleanerAgent));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_AGENT_RUNNING_STATE_KEY = new(nameof(isAgentRunning));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<Complexity> SELECTED_COMPLEXITY_STATE_KEY = new(nameof(selectedComplexity));
|
||||
private static readonly AssistantSessionStateKey<string> EXPERT_IN_FIELD_STATE_KEY = new(nameof(expertInField));
|
||||
private static readonly AssistantSessionStateKey<string> IMPORTANT_ASPECTS_STATE_KEY = new(nameof(importantAspects));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SHOW_WEB_CONTENT_READER_STATE_KEY, this.showWebContentReader);
|
||||
state.Set(USE_CONTENT_CLEANER_AGENT_STATE_KEY, this.useContentCleanerAgent);
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(IS_AGENT_RUNNING_STATE_KEY, this.isAgentRunning);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
state.Set(SELECTED_COMPLEXITY_STATE_KEY, this.selectedComplexity);
|
||||
state.Set(EXPERT_IN_FIELD_STATE_KEY, this.expertInField);
|
||||
state.Set(IMPORTANT_ASPECTS_STATE_KEY, this.importantAspects);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SHOW_WEB_CONTENT_READER_STATE_KEY, value => this.showWebContentReader = value);
|
||||
state.Restore(USE_CONTENT_CLEANER_AGENT_STATE_KEY, value => this.useContentCleanerAgent = value);
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(IS_AGENT_RUNNING_STATE_KEY, value => this.isAgentRunning = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
state.Restore(SELECTED_COMPLEXITY_STATE_KEY, value => this.selectedComplexity = value);
|
||||
state.Restore(EXPERT_IN_FIELD_STATE_KEY, value => this.expertInField = value);
|
||||
state.Restore(IMPORTANT_ASPECTS_STATE_KEY, value => this.importantAspects = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using AIStudio.Dialogs.Settings;
|
||||
using AIStudio.Tools.AssistantSessions;
|
||||
|
||||
namespace AIStudio.Assistants.Translation;
|
||||
|
||||
@@ -79,6 +80,40 @@ public partial class AssistantTranslation : AssistantBaseCore<SettingsDialogTran
|
||||
private string inputTextLastTranslation = string.Empty;
|
||||
private CommonLanguages selectedTargetLanguage;
|
||||
private string customTargetLanguage = string.Empty;
|
||||
private static readonly AssistantSessionStateKey<bool> SHOW_WEB_CONTENT_READER_STATE_KEY = new(nameof(showWebContentReader));
|
||||
private static readonly AssistantSessionStateKey<bool> USE_CONTENT_CLEANER_AGENT_STATE_KEY = new(nameof(useContentCleanerAgent));
|
||||
private static readonly AssistantSessionStateKey<bool> LIVE_TRANSLATION_STATE_KEY = new(nameof(liveTranslation));
|
||||
private static readonly AssistantSessionStateKey<bool> IS_AGENT_RUNNING_STATE_KEY = new(nameof(isAgentRunning));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_STATE_KEY = new(nameof(inputText));
|
||||
private static readonly AssistantSessionStateKey<string> INPUT_TEXT_LAST_TRANSLATION_STATE_KEY = new(nameof(inputTextLastTranslation));
|
||||
private static readonly AssistantSessionStateKey<CommonLanguages> SELECTED_TARGET_LANGUAGE_STATE_KEY = new(nameof(selectedTargetLanguage));
|
||||
private static readonly AssistantSessionStateKey<string> CUSTOM_TARGET_LANGUAGE_STATE_KEY = new(nameof(customTargetLanguage));
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void CaptureCustomAssistantSessionState(AssistantSessionStateWriter state)
|
||||
{
|
||||
state.Set(SHOW_WEB_CONTENT_READER_STATE_KEY, this.showWebContentReader);
|
||||
state.Set(USE_CONTENT_CLEANER_AGENT_STATE_KEY, this.useContentCleanerAgent);
|
||||
state.Set(LIVE_TRANSLATION_STATE_KEY, this.liveTranslation);
|
||||
state.Set(IS_AGENT_RUNNING_STATE_KEY, this.isAgentRunning);
|
||||
state.Set(INPUT_TEXT_STATE_KEY, this.inputText);
|
||||
state.Set(INPUT_TEXT_LAST_TRANSLATION_STATE_KEY, this.inputTextLastTranslation);
|
||||
state.Set(SELECTED_TARGET_LANGUAGE_STATE_KEY, this.selectedTargetLanguage);
|
||||
state.Set(CUSTOM_TARGET_LANGUAGE_STATE_KEY, this.customTargetLanguage);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override void RestoreCustomAssistantSessionState(AssistantSessionStateReader state)
|
||||
{
|
||||
state.Restore(SHOW_WEB_CONTENT_READER_STATE_KEY, value => this.showWebContentReader = value);
|
||||
state.Restore(USE_CONTENT_CLEANER_AGENT_STATE_KEY, value => this.useContentCleanerAgent = value);
|
||||
state.Restore(LIVE_TRANSLATION_STATE_KEY, value => this.liveTranslation = value);
|
||||
state.Restore(IS_AGENT_RUNNING_STATE_KEY, value => this.isAgentRunning = value);
|
||||
state.Restore(INPUT_TEXT_STATE_KEY, value => this.inputText = value);
|
||||
state.Restore(INPUT_TEXT_LAST_TRANSLATION_STATE_KEY, value => this.inputTextLastTranslation = value);
|
||||
state.Restore(SELECTED_TARGET_LANGUAGE_STATE_KEY, value => this.selectedTargetLanguage = value);
|
||||
state.Restore(CUSTOM_TARGET_LANGUAGE_STATE_KEY, value => this.customTargetLanguage = value);
|
||||
}
|
||||
|
||||
#region Overrides of ComponentBase
|
||||
|
||||
|
||||
Reference in new issue
Block a user