Skip to content

Commit f8e06fa

Browse files
Send to chat (#77)
1 parent 8aeeda5 commit f8e06fa

26 files changed

+384
-121
lines changed

app/MindWork AI Studio/Chat/ChatThread.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ namespace AIStudio.Chat;
33
/// <summary>
44
/// Data structure for a chat thread.
55
/// </summary>
6-
public sealed class ChatThread
6+
public sealed record ChatThread
77
{
88
/// <summary>
99
/// The unique identifier of the chat thread.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace AIStudio.Chat;
2+
3+
public static class SystemPrompts
4+
{
5+
public const string DEFAULT = "You are a helpful assistant!";
6+
}

app/MindWork AI Studio/Components/AssistantBase.razor

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,22 +2,22 @@
22
@using AIStudio.Components.Pages
33
@using AIStudio.Tools
44
<MudText Typo="Typo.h3" Class="mb-2 mr-3">
5-
@this.Title
5+
@(this.Title)
66
</MudText>
77

88
<InnerScrolling HeaderHeight="12.3em">
99
<ChildContent>
10-
<MudForm @ref="@this.form" @bind-IsValid="@this.inputIsValid" @bind-Errors="@this.inputIssues" Class="pr-2">
10+
<MudForm @ref="@(this.form)" @bind-IsValid="@(this.inputIsValid)" @bind-Errors="@(this.inputIssues)" Class="pr-2">
1111
<MudText Typo="Typo.body1" Align="Align.Justify" Class="mb-6">
12-
@this.Description
12+
@(this.Description)
1313
</MudText>
1414

1515
@if (this.Body is not null)
1616
{
17-
@this.Body
17+
@(this.Body)
1818
}
1919
</MudForm>
20-
<Issues IssuesData="@this.inputIssues"/>
20+
<Issues IssuesData="@(this.inputIssues)"/>
2121

2222
@if (this.ShowDedicatedProgress && this.isProcessing)
2323
{
@@ -26,7 +26,7 @@
2626
<div id="@ASSISTANT_RESULT_DIV_ID" class="mr-2 mt-3">
2727
@if (this.ShowResult && this.resultingContentBlock is not null)
2828
{
29-
<ContentBlockComponent Role="@this.resultingContentBlock.Role" Type="@this.resultingContentBlock.ContentType" Time="@this.resultingContentBlock.Time" Content="@this.resultingContentBlock.Content"/>
29+
<ContentBlockComponent Role="@(this.resultingContentBlock.Role)" Type="@(this.resultingContentBlock.ContentType)" Time="@(this.resultingContentBlock.Time)" Content="@(this.resultingContentBlock.Content)"/>
3030
}
3131
</div>
3232

@@ -56,9 +56,9 @@
5656

5757
case SendToButton sendToButton:
5858
<MudMenu StartIcon="@Icons.Material.Filled.Apps" EndIcon="@Icons.Material.Filled.KeyboardArrowDown" Label="Send to ..." Variant="Variant.Filled" Color="Color.Info">
59-
@foreach (var assistant in Enum.GetValues<SendToAssistant>().OrderBy(n => n.Name().Length))
59+
@foreach (var assistant in Enum.GetValues<SendTo>().OrderBy(n => n.Name().Length))
6060
{
61-
if(assistant is Pages.SendToAssistant.NONE || sendToButton.Self == assistant)
61+
if(assistant is SendTo.NONE || sendToButton.Self == assistant)
6262
continue;
6363

6464
<MudMenuItem OnClick="() => this.SendToAssistant(assistant, sendToButton)">
@@ -69,6 +69,9 @@
6969
break;
7070
}
7171
}
72+
<MudButton Variant="Variant.Filled" Color="Color.Warning" StartIcon="@Icons.Material.Filled.Refresh" OnClick="() => this.InnerResetForm()">
73+
Reset
74+
</MudButton>
7275
</MudStack>
7376
}
7477
</ChildContent>

app/MindWork AI Studio/Components/AssistantBase.razor.cs

Lines changed: 49 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,19 @@ public abstract partial class AssistantBase : ComponentBase
3838
protected abstract string Description { get; }
3939

4040
protected abstract string SystemPrompt { get; }
41+
42+
protected abstract void ResetFrom();
43+
44+
protected abstract bool MightPreselectValues();
4145

4246
private protected virtual RenderFragment? Body => null;
4347

4448
protected virtual bool ShowResult => true;
4549

4650
protected virtual bool ShowDedicatedProgress => false;
4751

52+
protected virtual ChatThread ConvertToChatThread => this.chatThread ?? new();
53+
4854
protected virtual IReadOnlyList<IButtonData> FooterButtons => [];
4955

5056
protected static readonly Dictionary<string, object?> USER_INPUT_ATTRIBUTES = new();
@@ -53,7 +59,7 @@ public abstract partial class AssistantBase : ComponentBase
5359
protected MudForm? form;
5460
protected bool inputIsValid;
5561

56-
private ChatThread? chatThread;
62+
protected ChatThread? chatThread;
5763
private ContentBlock? resultingContentBlock;
5864
private string[] inputIssues = [];
5965
private bool isProcessing;
@@ -164,33 +170,63 @@ protected async Task CopyToClipboard(string text)
164170
return icon;
165171
}
166172

167-
private Task SendToAssistant(SendToAssistant assistant, SendToButton sendToButton)
173+
private Task SendToAssistant(SendTo destination, SendToButton sendToButton)
168174
{
169175
var contentToSend = sendToButton.UseResultingContentBlockData switch
170176
{
171-
false => sendToButton.GetData(),
177+
false => sendToButton.GetText(),
172178
true => this.resultingContentBlock?.Content switch
173179
{
174180
ContentText textBlock => textBlock.Text,
175181
_ => string.Empty,
176182
},
177183
};
178184

179-
var (eventItem, path) = assistant switch
185+
var (eventItem, path) = destination switch
180186
{
181-
Pages.SendToAssistant.AGENDA_ASSISTANT => (Event.SEND_TO_AGENDA_ASSISTANT, Path.ASSISTANT_AGENDA),
182-
Pages.SendToAssistant.CODING_ASSISTANT => (Event.SEND_TO_CODING_ASSISTANT, Path.ASSISTANT_CODING),
183-
Pages.SendToAssistant.REWRITE_ASSISTANT => (Event.SEND_TO_REWRITE_ASSISTANT, Path.ASSISTANT_REWRITE),
184-
Pages.SendToAssistant.TRANSLATION_ASSISTANT => (Event.SEND_TO_TRANSLATION_ASSISTANT, Path.ASSISTANT_TRANSLATION),
185-
Pages.SendToAssistant.ICON_FINDER_ASSISTANT => (Event.SEND_TO_ICON_FINDER_ASSISTANT, Path.ASSISTANT_ICON_FINDER),
186-
Pages.SendToAssistant.GRAMMAR_SPELLING_ASSISTANT => (Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT, Path.ASSISTANT_GRAMMAR_SPELLING),
187-
Pages.SendToAssistant.TEXT_SUMMARIZER_ASSISTANT => (Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Path.ASSISTANT_SUMMARIZER),
187+
SendTo.AGENDA_ASSISTANT => (Event.SEND_TO_AGENDA_ASSISTANT, Path.ASSISTANT_AGENDA),
188+
SendTo.CODING_ASSISTANT => (Event.SEND_TO_CODING_ASSISTANT, Path.ASSISTANT_CODING),
189+
SendTo.REWRITE_ASSISTANT => (Event.SEND_TO_REWRITE_ASSISTANT, Path.ASSISTANT_REWRITE),
190+
SendTo.TRANSLATION_ASSISTANT => (Event.SEND_TO_TRANSLATION_ASSISTANT, Path.ASSISTANT_TRANSLATION),
191+
SendTo.ICON_FINDER_ASSISTANT => (Event.SEND_TO_ICON_FINDER_ASSISTANT, Path.ASSISTANT_ICON_FINDER),
192+
SendTo.GRAMMAR_SPELLING_ASSISTANT => (Event.SEND_TO_GRAMMAR_SPELLING_ASSISTANT, Path.ASSISTANT_GRAMMAR_SPELLING),
193+
SendTo.TEXT_SUMMARIZER_ASSISTANT => (Event.SEND_TO_TEXT_SUMMARIZER_ASSISTANT, Path.ASSISTANT_SUMMARIZER),
194+
195+
SendTo.CHAT => (Event.SEND_TO_CHAT, Path.CHAT),
188196

189197
_ => (Event.NONE, Path.ASSISTANTS),
190198
};
191-
192-
MessageBus.INSTANCE.DeferMessage(this, eventItem, contentToSend);
199+
200+
switch (destination)
201+
{
202+
case SendTo.CHAT:
203+
MessageBus.INSTANCE.DeferMessage(this, eventItem, this.ConvertToChatThread);
204+
break;
205+
206+
default:
207+
MessageBus.INSTANCE.DeferMessage(this, eventItem, contentToSend);
208+
break;
209+
}
210+
193211
this.NavigationManager.NavigateTo(path);
194212
return Task.CompletedTask;
195213
}
214+
215+
private async Task InnerResetForm()
216+
{
217+
this.resultingContentBlock = null;
218+
this.providerSettings = default;
219+
220+
await this.JsRuntime.ClearDiv(ASSISTANT_RESULT_DIV_ID);
221+
await this.JsRuntime.ClearDiv(AFTER_RESULT_DIV_ID);
222+
223+
this.ResetFrom();
224+
225+
this.inputIsValid = false;
226+
this.inputIssues = [];
227+
228+
this.form?.ResetValidation();
229+
this.StateHasChanged();
230+
this.form?.ResetValidation();
231+
}
196232
}

app/MindWork AI Studio/Components/Blocks/Changelog.Logs.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ public readonly record struct Log(int Build, string Display, string Filename)
1313

1414
public static readonly Log[] LOGS =
1515
[
16+
new (172, "v0.8.10, build 172 (2024-08-18 19:44 UTC)", "v0.8.10.md"),
1617
new (171, "v0.8.9, build 171 (2024-08-18 10:35 UTC)", "v0.8.9.md"),
1718
new (170, "v0.8.8, build 170 (2024-08-14 06:30 UTC)", "v0.8.8.md"),
1819
new (169, "v0.8.7, build 169 (2024-08-01 19:08 UTC)", "v0.8.7.md"),

app/MindWork AI Studio/Components/Pages/Agenda/AssistantAgenda.razor.cs

Lines changed: 67 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System.Text;
22

3+
using AIStudio.Chat;
34
using AIStudio.Tools;
45

56
namespace AIStudio.Components.Pages.Agenda;
@@ -97,9 +98,73 @@ the logistical challenges that come with an increasing number of participants.
9798
[
9899
new SendToButton
99100
{
100-
Self = SendToAssistant.AGENDA_ASSISTANT,
101+
Self = SendTo.AGENDA_ASSISTANT,
101102
},
102103
];
104+
105+
protected override ChatThread ConvertToChatThread => (this.chatThread ?? new()) with
106+
{
107+
SystemPrompt = SystemPrompts.DEFAULT,
108+
};
109+
110+
protected override void ResetFrom()
111+
{
112+
this.inputContent = string.Empty;
113+
this.contentLines.Clear();
114+
this.selectedFoci = [];
115+
this.justBriefly = [];
116+
this.inputWhoIsPresenting = string.Empty;
117+
if (!this.MightPreselectValues())
118+
{
119+
this.inputTopic = string.Empty;
120+
this.inputName = string.Empty;
121+
this.inputDuration = string.Empty;
122+
this.inputStartTime = string.Empty;
123+
this.inputObjective = string.Empty;
124+
this.inputModerator = string.Empty;
125+
this.selectedTargetLanguage = CommonLanguages.AS_IS;
126+
this.customTargetLanguage = string.Empty;
127+
this.introduceParticipants = false;
128+
this.isMeetingVirtual = true;
129+
this.inputLocation = string.Empty;
130+
this.goingToDinner = false;
131+
this.doingSocialActivity = false;
132+
this.needToArriveAndDepart = false;
133+
this.durationLunchBreak = 0;
134+
this.durationBreaks = 0;
135+
this.activeParticipation = false;
136+
this.numberParticipants = NumberParticipants.NOT_SPECIFIED;
137+
}
138+
}
139+
140+
protected override bool MightPreselectValues()
141+
{
142+
if (this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)
143+
{
144+
this.inputTopic = this.SettingsManager.ConfigurationData.Agenda.PreselectTopic;
145+
this.inputName = this.SettingsManager.ConfigurationData.Agenda.PreselectName;
146+
this.inputDuration = this.SettingsManager.ConfigurationData.Agenda.PreselectDuration;
147+
this.inputStartTime = this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime;
148+
this.inputObjective = this.SettingsManager.ConfigurationData.Agenda.PreselectObjective;
149+
this.inputModerator = this.SettingsManager.ConfigurationData.Agenda.PreselectModerator;
150+
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage;
151+
this.customTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage;
152+
this.introduceParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants;
153+
this.isMeetingVirtual = this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual;
154+
this.inputLocation = this.SettingsManager.ConfigurationData.Agenda.PreselectLocation;
155+
this.goingToDinner = this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner;
156+
this.doingSocialActivity = this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity;
157+
this.needToArriveAndDepart = this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart;
158+
this.durationLunchBreak = this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime;
159+
this.durationBreaks = this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime;
160+
this.activeParticipation = this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation;
161+
this.numberParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants;
162+
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider);
163+
return true;
164+
}
165+
166+
return false;
167+
}
103168

104169
private string inputTopic = string.Empty;
105170
private string inputName = string.Empty;
@@ -130,29 +195,7 @@ the logistical challenges that come with an increasing number of participants.
130195

131196
protected override async Task OnInitializedAsync()
132197
{
133-
if (this.SettingsManager.ConfigurationData.Agenda.PreselectOptions)
134-
{
135-
this.inputTopic = this.SettingsManager.ConfigurationData.Agenda.PreselectTopic;
136-
this.inputName = this.SettingsManager.ConfigurationData.Agenda.PreselectName;
137-
this.inputDuration = this.SettingsManager.ConfigurationData.Agenda.PreselectDuration;
138-
this.inputStartTime = this.SettingsManager.ConfigurationData.Agenda.PreselectStartTime;
139-
this.inputObjective = this.SettingsManager.ConfigurationData.Agenda.PreselectObjective;
140-
this.inputModerator = this.SettingsManager.ConfigurationData.Agenda.PreselectModerator;
141-
this.selectedTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedTargetLanguage;
142-
this.customTargetLanguage = this.SettingsManager.ConfigurationData.Agenda.PreselectedOtherLanguage;
143-
this.introduceParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectIntroduceParticipants;
144-
this.isMeetingVirtual = this.SettingsManager.ConfigurationData.Agenda.PreselectIsMeetingVirtual;
145-
this.inputLocation = this.SettingsManager.ConfigurationData.Agenda.PreselectLocation;
146-
this.goingToDinner = this.SettingsManager.ConfigurationData.Agenda.PreselectJointDinner;
147-
this.doingSocialActivity = this.SettingsManager.ConfigurationData.Agenda.PreselectSocialActivity;
148-
this.needToArriveAndDepart = this.SettingsManager.ConfigurationData.Agenda.PreselectArriveAndDepart;
149-
this.durationLunchBreak = this.SettingsManager.ConfigurationData.Agenda.PreselectLunchTime;
150-
this.durationBreaks = this.SettingsManager.ConfigurationData.Agenda.PreselectBreakTime;
151-
this.activeParticipation = this.SettingsManager.ConfigurationData.Agenda.PreselectActiveParticipation;
152-
this.numberParticipants = this.SettingsManager.ConfigurationData.Agenda.PreselectNumberParticipants;
153-
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Agenda.PreselectedProvider);
154-
}
155-
198+
this.MightPreselectValues();
156199
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<string>(Event.SEND_TO_AGENDA_ASSISTANT).FirstOrDefault();
157200
if (deferredContent is not null)
158201
this.inputContent = deferredContent;

app/MindWork AI Studio/Components/Pages/Chat.razor.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,24 @@ protected override async Task OnInitializedAsync()
6262
this.providerSettings = this.SettingsManager.ConfigurationData.Providers.FirstOrDefault(x => x.Id == this.SettingsManager.ConfigurationData.Chat.PreselectedProvider);
6363
}
6464

65+
var deferredContent = MessageBus.INSTANCE.CheckDeferredMessages<ChatThread>(Event.SEND_TO_CHAT).FirstOrDefault();
66+
if (deferredContent is not null)
67+
{
68+
this.chatThread = deferredContent;
69+
if (this.chatThread is not null)
70+
{
71+
var firstUserBlock = this.chatThread.Blocks.FirstOrDefault(x => x.Role == ChatRole.USER);
72+
if (firstUserBlock is not null)
73+
{
74+
this.chatThread.Name = firstUserBlock.Content switch
75+
{
76+
ContentText textBlock => this.ExtractThreadName(textBlock.Text),
77+
_ => "Thread"
78+
};
79+
}
80+
}
81+
}
82+
6583
await base.OnInitializedAsync();
6684
}
6785

@@ -93,7 +111,7 @@ private async Task SendMessage()
93111
ChatId = Guid.NewGuid(),
94112
Name = threadName,
95113
Seed = this.RNG.Next(),
96-
SystemPrompt = "You are a helpful assistant!",
114+
SystemPrompt = SystemPrompts.DEFAULT,
97115
Blocks = [],
98116
};
99117
}

0 commit comments

Comments
 (0)