mirror of
https://github.com/MindWorkAI/AI-Studio.git
synced 2026-05-20 20:32:14 +00:00
239 lines
14 KiB
Plaintext
239 lines
14 KiB
Plaintext
@using AIStudio.Tools
|
|
@using MudBlazor
|
|
@using AIStudio.Components
|
|
@inherits AIStudio.Components.MSGComponentBase
|
|
|
|
<MudCard Class="@this.CardClasses" Outlined="@true">
|
|
<MudCardHeader>
|
|
<CardHeaderAvatar>
|
|
<MudAvatar Color="@this.Role.ToColor()">
|
|
<MudIcon Icon="@this.Role.ToIcon()"/>
|
|
</MudAvatar>
|
|
</CardHeaderAvatar>
|
|
<CardHeaderContent>
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
|
<MudText Typo="Typo.body1">
|
|
@this.Role.ToName() (@this.Time.LocalDateTime)
|
|
</MudText>
|
|
@if (this.HasToolTrace)
|
|
{
|
|
<MudTooltip Text="@this.GetToolTraceTooltip()" Placement="Placement.Bottom">
|
|
<MudButton Variant="Variant.Outlined"
|
|
Color="Color.Default"
|
|
Size="Size.Small"
|
|
Class="px-2 py-1 rounded-pill"
|
|
Style="min-width:auto; border-width:1px; text-transform:none;"
|
|
OnClick="@this.ToggleToolTrace">
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="1">
|
|
<MudIcon Icon="@Icons.Material.Filled.Build" Color="Color.Default" Size="Size.Small" />
|
|
<MudIcon Icon="@(this.showToolTrace ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)" Size="Size.Small" />
|
|
</MudStack>
|
|
</MudButton>
|
|
</MudTooltip>
|
|
}
|
|
</MudStack>
|
|
</CardHeaderContent>
|
|
<CardHeaderActions>
|
|
@if (this.Content.FileAttachments.Count > 0)
|
|
{
|
|
<MudTooltip Text="@T("Number of attachments")" Placement="Placement.Bottom">
|
|
<MudBadge Content="@this.Content.FileAttachments.Count" Color="Color.Primary" Overlap="true" BadgeClass="sources-card-header">
|
|
<MudIconButton Icon="@Icons.Material.Filled.AttachFile"
|
|
OnClick="@this.OpenAttachmentsDialog"/>
|
|
</MudBadge>
|
|
</MudTooltip>
|
|
}
|
|
@if (this.Content.Sources.Count > 0)
|
|
{
|
|
<MudTooltip Text="@T("Number of sources")" Placement="Placement.Bottom">
|
|
<MudBadge Content="@this.Content.Sources.Count" Color="Color.Primary" Overlap="true" BadgeClass="sources-card-header">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Link"/>
|
|
</MudBadge>
|
|
</MudTooltip>
|
|
}
|
|
@if (this.IsSecondToLastBlock && this.Role is ChatRole.USER && this.EditLastUserBlockFunc is not null)
|
|
{
|
|
<MudTooltip Text="@T("Edit")" Placement="Placement.Bottom">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Default" OnClick="@this.EditLastUserBlock"/>
|
|
</MudTooltip>
|
|
}
|
|
@if (this.IsLastContentBlock && this.Role is ChatRole.USER && this.EditLastBlockFunc is not null)
|
|
{
|
|
<MudTooltip Text="@T("Edit")" Placement="Placement.Bottom">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Edit" Color="Color.Default" OnClick="@this.EditLastBlock"/>
|
|
</MudTooltip>
|
|
}
|
|
@if (this.IsLastContentBlock && this.Role is ChatRole.AI && this.RegenerateFunc is not null)
|
|
{
|
|
<MudTooltip Text="@T("Regenerate")" Placement="Placement.Bottom">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Recycling" Color="Color.Default" Disabled="@(!this.RegenerateEnabled())" OnClick="@this.RegenerateBlock"/>
|
|
</MudTooltip>
|
|
}
|
|
@if (this.RemoveBlockFunc is not null)
|
|
{
|
|
<MudTooltip Text="@T("Removes this block")" Placement="Placement.Bottom">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Delete" Color="Color.Error" OnClick="@this.RemoveBlock"/>
|
|
</MudTooltip>
|
|
}
|
|
|
|
@if (this.Role is ChatRole.AI)
|
|
{
|
|
<MudTooltip Text="@T("Export Chat to Microsoft Word")" Placement="Placement.Bottom">
|
|
<MudIconButton Icon="@Icons.Material.Filled.Save" OnClick="@this.ExportToWord"/>
|
|
</MudTooltip>
|
|
}
|
|
<MudCopyClipboardButton Content="@this.Content" Type="@this.Type" Size="Size.Medium"/>
|
|
</CardHeaderActions>
|
|
</MudCardHeader>
|
|
<MudCardContent>
|
|
@if (!this.HideContent)
|
|
{
|
|
if (this.Content.IsStreaming)
|
|
{
|
|
<MudProgressLinear Color="Color.Primary" Indeterminate="true" Class="mb-6" />
|
|
}
|
|
|
|
switch (this.Type)
|
|
{
|
|
case ContentType.TEXT:
|
|
if (this.Content is ContentText textContent)
|
|
{
|
|
if (textContent.InitialRemoteWait)
|
|
{
|
|
<MudSkeleton Width="30%" Height="42px;"/>
|
|
<MudSkeleton Width="80%"/>
|
|
<MudSkeleton Width="100%"/>
|
|
}
|
|
else
|
|
{
|
|
@if (this.Content.IsStreaming)
|
|
{
|
|
<MudText Typo="Typo.body1" Style="white-space: pre-wrap;">
|
|
@textContent.Text.RemoveThinkTags()
|
|
</MudText>
|
|
}
|
|
else
|
|
{
|
|
@if (this.HasToolTrace && this.showToolTrace)
|
|
{
|
|
<MudPaper Class="pa-3 mb-3 border rounded-lg" Style="border-width:1px;">
|
|
<MudText Typo="Typo.subtitle2" Class="mb-2">
|
|
@string.Format(T("Tool Calls ({0})"), textContent.ToolInvocations.Count)
|
|
</MudText>
|
|
@foreach (var invocation in textContent.ToolInvocations.OrderBy(x => x.Order))
|
|
{
|
|
<MudPaper Class="pa-3 mb-3 border rounded-lg" Style="border-width:1px;">
|
|
<MudButton Variant="Variant.Text"
|
|
Color="Color.Default"
|
|
FullWidth="@true"
|
|
Class="px-0 py-0 justify-space-between"
|
|
Style="min-width:auto; text-transform:none;"
|
|
OnClick="@(() => this.ToggleToolInvocation(invocation.Order))">
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Justify="Justify.SpaceBetween" Class="w-100">
|
|
<MudStack Row="true" AlignItems="AlignItems.Center" Spacing="2">
|
|
<MudIcon Icon="@invocation.ToolIcon" Color="Color.Info" />
|
|
<MudText Typo="Typo.subtitle1">@($"{invocation.Order}. {invocation.ToolName}")</MudText>
|
|
<MudChip T="string" Color="@ContentBlockComponent.GetTraceColor(invocation.Status)" Size="Size.Small" Variant="Variant.Outlined">
|
|
@this.GetTraceStatusText(invocation)
|
|
</MudChip>
|
|
</MudStack>
|
|
<MudIcon Icon="@(this.IsToolInvocationExpanded(invocation.Order) ? Icons.Material.Filled.ExpandLess : Icons.Material.Filled.ExpandMore)" Size="Size.Small" />
|
|
</MudStack>
|
|
</MudButton>
|
|
|
|
@if (this.IsToolInvocationExpanded(invocation.Order))
|
|
{
|
|
@if (!string.IsNullOrWhiteSpace(invocation.StatusMessage))
|
|
{
|
|
<MudText Typo="Typo.body2" Color="Color.Warning" Class="mt-3 mb-3">@invocation.StatusMessage</MudText>
|
|
}
|
|
|
|
<MudText Typo="Typo.subtitle2">@T("Result")</MudText>
|
|
<MudPaper Class="pa-3 mt-2 mb-3">
|
|
<MudText Typo="Typo.body2" Style="white-space: pre-wrap;">@this.GetToolInvocationResult(invocation)</MudText>
|
|
</MudPaper>
|
|
|
|
<MudText Typo="Typo.subtitle2">@T("Arguments")</MudText>
|
|
@if (invocation.Arguments.Count == 0)
|
|
{
|
|
<MudText Typo="Typo.body2" Class="mb-3">@T("No arguments")</MudText>
|
|
}
|
|
else
|
|
{
|
|
<MudList T="string" Dense="@true" Class="mb-0">
|
|
@foreach (var argument in invocation.Arguments)
|
|
{
|
|
<MudListItem T="string">
|
|
<MudText Typo="Typo.body2"><strong>@argument.Key:</strong> @argument.Value</MudText>
|
|
</MudListItem>
|
|
}
|
|
</MudList>
|
|
}
|
|
}
|
|
</MudPaper>
|
|
}
|
|
</MudPaper>
|
|
}
|
|
|
|
var renderPlan = this.GetMarkdownRenderPlan(textContent.Text);
|
|
<div @ref="this.mathContentContainer" class="chat-math-container">
|
|
@foreach (var segment in renderPlan.Segments)
|
|
{
|
|
var segmentContent = segment.GetContent(renderPlan.Source);
|
|
if (segment.Type is MarkdownRenderSegmentType.MARKDOWN)
|
|
{
|
|
<MudMarkdown @key="@segment.RenderKey" Value="@segmentContent" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE" />
|
|
}
|
|
else
|
|
{
|
|
<MathJaxBlock @key="@segment.RenderKey" Value="@segmentContent" Class="mb-5" />
|
|
}
|
|
}
|
|
@if (textContent.Sources.Count > 0)
|
|
{
|
|
<MudMarkdown Value="@textContent.Sources.ToMarkdown()" Props="Markdown.DefaultConfig" Styling="@this.MarkdownStyling" MarkdownPipeline="Markdown.SAFE_MARKDOWN_PIPELINE" />
|
|
}
|
|
</div>
|
|
|
|
@if (this.Role is ChatRole.AI && !string.IsNullOrWhiteSpace(textContent.ToolRuntimeStatus.Message))
|
|
{
|
|
<MudAlert Dense="@true" Severity="Severity.Info" Variant="Variant.Outlined" Class="mt-4">
|
|
@textContent.ToolRuntimeStatus.Message
|
|
</MudAlert>
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ContentType.IMAGE:
|
|
if (this.Content is ContentImage imageContent)
|
|
{
|
|
var imageSrc = imageContent.SourceType switch
|
|
{
|
|
ContentImageSource.BASE64 => ImageHelpers.ToDataUrl(imageContent.Source),
|
|
ContentImageSource.URL => imageContent.Source,
|
|
ContentImageSource.LOCAL_PATH => imageContent.Source,
|
|
|
|
_ => string.Empty
|
|
};
|
|
|
|
if (!string.IsNullOrWhiteSpace(imageSrc))
|
|
{
|
|
<MudImage Src="@imageSrc" />
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
<MudText Typo="Typo.body2">
|
|
@string.Format(T("Cannot render content of type {0} yet."), this.Type)
|
|
</MudText>
|
|
break;
|
|
}
|
|
}
|
|
</MudCardContent>
|
|
</MudCard>
|