Added PowerPoint templates to the Slide Assistant (#1055)

Co-authored-by: Thorsten Sommer <SommerEngineering@users.noreply.github.com>
This commit is contained in:
Sabrina-devopsandThorsten Sommer authored and GitHub committed 2026-10-25 18:52:39 +01:00
1 parent 8c5cfa78b6
commit 6eb23ebbcb
136 files changed
+16535 -522

No files matched your search

@@ -107,6 +107,11 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected virtual bool ShowProfileSelection => true;
protected virtual bool ShowDedicatedProgress => false;
/// <summary>
/// What the assistant is doing right now, shown below the dedicated progress bar; empty for no text.
/// </summary>
protected virtual string ProgressText => string.Empty;
protected virtual bool ShowSendTo => true;
@@ -124,6 +129,15 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
protected virtual bool ShowReset => true;
/// <summary>
/// Whether the system prompt starts with the current date and time.
/// </summary>
/// <remarks>
/// Off for most assistants, whose results do not depend on the date. An assistant which writes
/// the date into its result, or plans around it, turns this on rather than guessing the date.
/// </remarks>
protected virtual bool IncludeDateTime => false;
protected virtual string? SendToChatVisibleUserPromptPrefix => null;
protected virtual string? SendToChatVisibleUserPromptContent => null;
@@ -385,7 +399,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
{
this.ChatThread = new()
{
IncludeDateTime = false,
IncludeDateTime = this.IncludeDateTime,
SelectedProvider = this.ProviderSettings.Id,
SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id,
SystemPrompt = this.SystemPrompt,
@@ -403,7 +417,7 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
var chatId = Guid.NewGuid();
this.ChatThread = new()
{
IncludeDateTime = false,
IncludeDateTime = this.IncludeDateTime,
SelectedProvider = this.ProviderSettings.Id,
SelectedProfile = this.AllowProfiles ? this.CurrentProfile.Id : Profile.NO_PROFILE.Id,
SystemPrompt = this.SystemPrompt,
@@ -527,10 +541,46 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
InitialRemoteWait = true,
};
//
// The stream calls this for every chunk and waits for it. A checkpoint captures the whole
// state of the assistant and makes the main layout render as well, so both happen only now
// and then. When the stream is done, both happen in any case:
//
var lastRendering = DateTimeOffset.MinValue;
var lastCheckpoint = DateTimeOffset.MinValue;
string? lastProgressText = null;
aiText.StreamingEvent = async () =>
{
await this.CheckpointAssistantSession();
await this.RefreshAssistantUIAsync();
var now = DateTimeOffset.Now;
if (now - lastCheckpoint >= STREAMING_CHECKPOINT_MIN_TIME)
{
lastCheckpoint = now;
await this.CheckpointAssistantSession();
}
if (now - lastRendering < STREAMING_RENDER_MIN_TIME)
return;
lastRendering = now;
if (!hideContentFromUser)
{
await this.RefreshAssistantUIAsync();
return;
}
//
// A hidden answer shows nothing but the progress text, so the whole form renders only
// when that text changed. Thinking models stream for minutes before they write a word:
//
await this.RefreshAssistantUIAsync(() =>
{
var progressText = this.ProgressText;
if (progressText == lastProgressText)
return false;
lastProgressText = progressText;
return true;
});
};
aiText.StreamingDone = async () =>
@@ -995,15 +1045,20 @@ public abstract partial class AssistantBase<TSettings> : AssistantLowerBase wher
/// <summary>
/// Refreshes the component when it is still mounted.
/// </summary>
/// <param name="hasChanged">Decides whether anything visible changed, asked on the thread of the renderer, so it may read what the rendering reads; null to render in any case.</param>
/// <returns>A task that completes after the renderer was notified.</returns>
protected async Task RefreshAssistantUIAsync()
protected async Task RefreshAssistantUIAsync(Func<bool>? hasChanged = null)
{
if (this.isDisposed)
return;
try
{
await this.InvokeAsync(this.StateHasChanged);
await this.InvokeAsync(() =>
{
if (hasChanged is null || hasChanged())
this.StateHasChanged();
});
}
catch (InvalidOperationException)
{