From ac0f802e3c86b12ab443d8432a00b35d6aa1924e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:01:11 +0100 Subject: [PATCH 01/78] Add ChatGPT.Core package reference --- .../packages.lock.json | 34 +++++++++++++++++++ .../WalletWasabi.Fluent.csproj | 1 + WalletWasabi.Fluent/packages.lock.json | 34 +++++++++++++++++++ 3 files changed, 69 insertions(+) diff --git a/WalletWasabi.Fluent.Desktop/packages.lock.json b/WalletWasabi.Fluent.Desktop/packages.lock.json index 35a2d55aa1..3f7d977022 100644 --- a/WalletWasabi.Fluent.Desktop/packages.lock.json +++ b/WalletWasabi.Fluent.Desktop/packages.lock.json @@ -159,6 +159,26 @@ "Avalonia": "0.10.18" } }, + "ChatGPT": { + "type": "Transitive", + "resolved": "1.0.0-preview.4", + "contentHash": "QL1biptxZPAFzWPoNGXovFfGW7vDNdVS8te0L542X1tOhDZlm/LqXRywbbUQSV4dWTUcsVev/FOUcvX7dPOxGg==" + }, + "ChatGPT.Core": { + "type": "Transitive", + "resolved": "1.0.0-preview.4", + "contentHash": "GVAevfLlSi43Ox9MwWr2haGEShr5svtxH9kP2RasA3IxY2x+ZLGVfHBnxxOmPCKiDHrYKDqkDkK9xIaZ8yO/3w==", + "dependencies": { + "ChatGPT": "1.0.0-preview.4", + "CommunityToolkit.Mvvm": "8.1.0", + "Microsoft.Extensions.DependencyInjection": "7.0.0" + } + }, + "CommunityToolkit.Mvvm": { + "type": "Transitive", + "resolved": "8.1.0", + "contentHash": "xxOt7lu9a5kB5Fs9RfcxzVlKnhuuPe+w7AXHtmCFtS3oldrsUhEMxHfNulluXSscUUoGxZ0jh55Om12ZP6abHA==" + }, "DynamicData": { "type": "Transitive", "resolved": "7.1.1", @@ -277,6 +297,19 @@ "resolved": "4.7.0", "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==" + }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", "resolved": "1.0.0", @@ -677,6 +710,7 @@ "Avalonia.ReactiveUI": "[0.10.18, )", "Avalonia.Skia": "[0.10.18, )", "Avalonia.Xaml.Behaviors": "[0.10.18, )", + "ChatGPT.Core": "[1.0.0-preview.4, )", "System.Drawing.Common": "[7.0.0, )", "System.Runtime": "[4.3.1, )", "WalletWasabi": "[1.0.0, )" diff --git a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj index 35328379c6..d927bdbfcb 100644 --- a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj +++ b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj @@ -28,6 +28,7 @@ + diff --git a/WalletWasabi.Fluent/packages.lock.json b/WalletWasabi.Fluent/packages.lock.json index b2e3701b89..da0ce53268 100644 --- a/WalletWasabi.Fluent/packages.lock.json +++ b/WalletWasabi.Fluent/packages.lock.json @@ -75,6 +75,17 @@ "Avalonia.Xaml.Interactivity": "0.10.18" } }, + "ChatGPT.Core": { + "type": "Direct", + "requested": "[1.0.0-preview.4, )", + "resolved": "1.0.0-preview.4", + "contentHash": "GVAevfLlSi43Ox9MwWr2haGEShr5svtxH9kP2RasA3IxY2x+ZLGVfHBnxxOmPCKiDHrYKDqkDkK9xIaZ8yO/3w==", + "dependencies": { + "ChatGPT": "1.0.0-preview.4", + "CommunityToolkit.Mvvm": "8.1.0", + "Microsoft.Extensions.DependencyInjection": "7.0.0" + } + }, "System.Drawing.Common": { "type": "Direct", "requested": "[7.0.0, )", @@ -127,6 +138,16 @@ "Avalonia": "0.10.18" } }, + "ChatGPT": { + "type": "Transitive", + "resolved": "1.0.0-preview.4", + "contentHash": "QL1biptxZPAFzWPoNGXovFfGW7vDNdVS8te0L542X1tOhDZlm/LqXRywbbUQSV4dWTUcsVev/FOUcvX7dPOxGg==" + }, + "CommunityToolkit.Mvvm": { + "type": "Transitive", + "resolved": "8.1.0", + "contentHash": "xxOt7lu9a5kB5Fs9RfcxzVlKnhuuPe+w7AXHtmCFtS3oldrsUhEMxHfNulluXSscUUoGxZ0jh55Om12ZP6abHA==" + }, "DynamicData": { "type": "Transitive", "resolved": "7.1.1", @@ -245,6 +266,19 @@ "resolved": "4.7.0", "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==" + }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", "resolved": "1.0.0", From 7fa0ad65b7f5b0dd28324b5b6b74c317dcbcf4d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:55:09 +0100 Subject: [PATCH 02/78] Add message view models --- .../ViewModels/ChatGPT/AssistantMessageViewModel.cs | 5 +++++ WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs | 8 ++++++++ .../ViewModels/ChatGPT/MessageViewModel.cs | 8 ++++++++ .../ViewModels/ChatGPT/UserMessageViewModel.cs | 5 +++++ 4 files changed, 26 insertions(+) create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs new file mode 100644 index 0000000000..3e8518ed7c --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public partial class AssistantMessageViewModel : MessageViewModel +{ +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs new file mode 100644 index 0000000000..35a413b310 --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs @@ -0,0 +1,8 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public class AssistantResult +{ + public string? Status { get; set; } + + public string? Command { get; set; } +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs new file mode 100644 index 0000000000..a936bc269a --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs @@ -0,0 +1,8 @@ +using ReactiveUI; + +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public partial class MessageViewModel : ReactiveObject +{ + [AutoNotify] private string? _message; +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs new file mode 100644 index 0000000000..7e675e60e0 --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public partial class UserMessageViewModel : MessageViewModel +{ +} From e85d329f232060415966eb4db6a14c87bfcbd240 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:55:18 +0100 Subject: [PATCH 03/78] Add initial ChatAssistantViewModel --- .../ChatGPT/ChatAssistantViewModel.cs | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs new file mode 100644 index 0000000000..f54f564c2d --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -0,0 +1,139 @@ +using System.Collections.ObjectModel; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Input; +using AI.Model.Services; +using AI.Services; +using ChatGPT.Model.Services; +using ChatGPT.Services; +using ChatGPT.ViewModels.Chat; +using ChatGPT.ViewModels.Settings; +using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.Extensions.DependencyInjection; +using ReactiveUI; + +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public partial class ChatAssistantViewModel : ReactiveObject +{ + static ChatAssistantViewModel() + { + ConfigureServices(); + } + + private string _initialDirections = """ +You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. +I will write text prompts and you will generate appropriate answers in json. + +Write answers as json: +{ + "status": "", + "command": "", +} + +Where "status" value is: +- "command": when command is an answer +- "error": when not possible to answer +- "message": when answer is valid + +Where "command" value is only set when "status"="command" +only following commands are available: "send", "receive", "balance" + +- send command requires address and amount +- receive command returns only address, does not require any params +- balance command returns only BTC or USD balance value, does not require any params + +If user does not provide valid param to execute command please ask followup question to provide that info. + +If not enough info is provided to execute command please set status=error and ask user to provide missing information. + +Never say you can not execute command, just return json with proper status. +"""; + + private ChatViewModel _chat; + private CancellationTokenSource _cts; + + [AutoNotify] private bool _isChatListVisible; + [AutoNotify] private string? _inputText = ""; + + public ChatAssistantViewModel() + { + _chat = new ChatViewModel + { + Settings = new ChatSettingsViewModel + { + Temperature = 0.7m, + TopP = 1m, + MaxTokens = 2000, + Model = "gpt-3.5-turbo" + } + }; + + _chat.AddSystemMessage(_initialDirections); + + SendCommand = ReactiveCommand.CreateFromTask(async () => + { + if (!string.IsNullOrWhiteSpace(InputText)) + { + await SendAsync(InputText); + } + }); + + Messages = new ObservableCollection(); + } + + public ICommand? SendCommand { get; protected set; } + + public ObservableCollection Messages { get; } + + private async Task SendAsync(string input) + { + try + { + Messages.Add(new UserMessageViewModel() + { + Message = input + }); + + _chat.AddUserMessage(input); + + _cts = new CancellationTokenSource(); + var result = await _chat.SendAsync(_chat.CreateChatMessages(), _cts.Token); + + _chat.AddAssistantMessage(result?.Message); + + Console.WriteLine(result?.Message); + + // TODO: Deserialize result json message and get message param and command. + + // TODO: AssistantResult + + var resultMessage = result?.Message; + + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); + } + catch (Exception ex) + { + Console.WriteLine("Error: " + ex.Message); + } + } + + private static void ConfigureServices() + { + IServiceCollection serviceCollection = new ServiceCollection(); + + serviceCollection.AddSingleton(); + serviceCollection.AddSingleton(); + + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + serviceCollection.AddTransient(); + + Ioc.Default.ConfigureServices(serviceCollection.BuildServiceProvider()); + } +} From 7fec147c5958e10cf38331945a3f19c5be9c682f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:55:34 +0100 Subject: [PATCH 04/78] Initialize ChatAssistant from main view model --- WalletWasabi.Fluent/ViewModels/MainViewModel.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/WalletWasabi.Fluent/ViewModels/MainViewModel.cs b/WalletWasabi.Fluent/ViewModels/MainViewModel.cs index 9d8d4e7593..eb08163651 100644 --- a/WalletWasabi.Fluent/ViewModels/MainViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/MainViewModel.cs @@ -8,6 +8,7 @@ using ReactiveUI; using WalletWasabi.Fluent.AppServices.Tor; using WalletWasabi.Fluent.ViewModels.AddWallet; +using WalletWasabi.Fluent.ViewModels.ChatGPT; using WalletWasabi.Fluent.ViewModels.Dialogs.Authorization; using WalletWasabi.Fluent.ViewModels.Dialogs.Base; using WalletWasabi.Fluent.ViewModels.HelpAndSupport; @@ -114,6 +115,8 @@ public MainViewModel() SearchBar = CreateSearchBar(); + ChatAssistant = CreateChatAssistant(); + NetworkBadgeName = Services.Config.Network == Network.Main ? "" : Services.Config.Network.Name; } @@ -127,6 +130,8 @@ public MainViewModel() public SearchBarViewModel SearchBar { get; } + public ChatAssistantViewModel ChatAssistant { get; } + public static MainViewModel Instance { get; } = new(); public bool IsBusy => @@ -339,4 +344,13 @@ private SearchBarViewModel CreateSearchBar() return searchBar; } + + private ChatAssistantViewModel CreateChatAssistant() + { + var chatAssistant = new ChatAssistantViewModel(); + + // TODO: Initialization? + + return chatAssistant; + } } From 5abd033f14b6d4daf2552217fec82c78acbb6e7d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:55:53 +0100 Subject: [PATCH 05/78] Add initial chat assistant view models --- .../Views/ChatGPT/ChatAssistant.axaml | 154 ++++++++++++++++++ .../Views/ChatGPT/ChatAssistant.axaml.cs | 17 ++ .../Views/ChatGPT/ChatAssistantDropdown.axaml | 58 +++++++ .../ChatGPT/ChatAssistantDropdown.axaml.cs | 17 ++ 4 files changed, 246 insertions(+) create mode 100644 WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml create mode 100644 WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml.cs create mode 100644 WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml create mode 100644 WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml new file mode 100644 index 0000000000..578854405b --- /dev/null +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -0,0 +1,154 @@ + + + 1 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml.cs b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml.cs new file mode 100644 index 0000000000..8676fd45b6 --- /dev/null +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml.cs @@ -0,0 +1,17 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace WalletWasabi.Fluent.Views.ChatGPT; + +public class ChatAssistant : UserControl +{ + public ChatAssistant() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml new file mode 100644 index 0000000000..f2566ef21f --- /dev/null +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -0,0 +1,58 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs new file mode 100644 index 0000000000..fc783b242e --- /dev/null +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs @@ -0,0 +1,17 @@ +using Avalonia.Controls; +using Avalonia.Markup.Xaml; + +namespace WalletWasabi.Fluent.Views.ChatGPT; + +public partial class ChatAssistantDropdown : UserControl +{ + public ChatAssistantDropdown() + { + InitializeComponent(); + } + + private void InitializeComponent() + { + AvaloniaXamlLoader.Load(this); + } +} From 1ed141e2d9ff64fd96fed9776519b59b6ecaf4f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 14:56:09 +0100 Subject: [PATCH 06/78] Use chat assistant instead search bar --- WalletWasabi.Fluent/Views/Shell/TitleBar.axaml | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml b/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml index 25e782202b..620c7d5b5f 100644 --- a/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml +++ b/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml @@ -3,6 +3,7 @@ xmlns:ext="using:WalletWasabi.Fluent.Helpers" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:searchBar="clr-namespace:WalletWasabi.Fluent.Views.SearchBar" + xmlns:chat="clr-namespace:WalletWasabi.Fluent.Views.ChatGPT" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:shell="clr-namespace:WalletWasabi.Fluent.Views.Shell" mc:Ignorable="d" d:DesignWidth="1000" @@ -54,6 +55,12 @@ Margin="5" /> + + + + @@ -72,7 +79,9 @@ VerticalAlignment="Center" ContentTemplate="{StaticResource Title}" /> - + + + From 028b1f67fcd23efce8946a1d3fa7f4080777e40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 15:12:13 +0100 Subject: [PATCH 07/78] Reset InputText before send --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index f54f564c2d..71c7576a43 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -73,9 +73,13 @@ public ChatAssistantViewModel() SendCommand = ReactiveCommand.CreateFromTask(async () => { - if (!string.IsNullOrWhiteSpace(InputText)) + var inputText = InputText; + + if (!string.IsNullOrWhiteSpace(inputText)) { - await SendAsync(InputText); + InputText = ""; + + await SendAsync(inputText); } }); From 09145a235cebcee64b3222b0dc2a15781911c815 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Wed, 22 Mar 2023 15:12:26 +0100 Subject: [PATCH 08/78] Execute SendCommand on Enter key --- WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml index 578854405b..0be87f953e 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -133,8 +133,11 @@ - - + + + From 6a3f5d372795745383b0568b2760c8e1862bdc5a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 13:38:50 +0100 Subject: [PATCH 09/78] Update result class --- WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs index 35a413b310..3fa8676d25 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantResult.cs @@ -1,8 +1,12 @@ -namespace WalletWasabi.Fluent.ViewModels.ChatGPT; +using Newtonsoft.Json; + +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; public class AssistantResult { + [JsonProperty(PropertyName = "status")] public string? Status { get; set; } - public string? Command { get; set; } + [JsonProperty(PropertyName = "message")] + public string? Message { get; set; } } From cb8df389299496ad404403c277d7c29dfe4d8f7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 13:39:09 +0100 Subject: [PATCH 10/78] Update directions --- .../ChatGPT/ChatAssistantViewModel.cs | 56 +++++++++++++------ 1 file changed, 39 insertions(+), 17 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 71c7576a43..d3a6fe981b 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -23,31 +23,53 @@ static ChatAssistantViewModel() private string _initialDirections = """ You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. -I will write text prompts and you will generate appropriate answers in json. +I will write text prompts and you will generate appropriate answers only in json format I have provided. -Write answers as json: +The json format for the answers is as follows: { "status": "", - "command": "", + "message": "", +} +The status and message properties are of type string. + +The json response "status" property value can be one of the following: +- "command": when wasabi api command is the answer +- "error": when not possible to answer or other problem +- "message": when answer is only text message but not error + +When "status"="command" the "message" value can only be set to + one of the following wasabi api commands available: +- send(address, amount): command requires address and amount, calls send method and displays send dialog +- address receive(): command returns only new BTC address, does not require any params, shows receive dialog with qr code +- value balance(): command returns BTC or USD balance value, does not require any params nor UI interaction +e.g.: +{ + "status": "command", + "message": "send(address, amount)", } -Where "status" value is: -- "command": when command is an answer -- "error": when not possible to answer -- "message": when answer is valid - -Where "command" value is only set when "status"="command" -only following commands are available: "send", "receive", "balance" - -- send command requires address and amount -- receive command returns only address, does not require any params -- balance command returns only BTC or USD balance value, does not require any params +If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: +e.g.: +{ + "status": "error", + "message": "Please provide valid address for send.", +} -If user does not provide valid param to execute command please ask followup question to provide that info. +If not enough info is provided to execute command please set status=error and ask user to provide missing information: +e.g.: +{ + "status": "error", + "message": "Please provide valid address.", +} -If not enough info is provided to execute command please set status=error and ask user to provide missing information. +If user ask question the answer please set status=message and ask user is in following format: +{ + "status": "message", + "message": "The address used the following format...", +} -Never say you can not execute command, just return json with proper status. +Never write answer as plain text (eg. I can not execute some api command etc.), +always write answers as json response with proper status. """; private ChatViewModel _chat; From 844ca95f6405e82177c3f35c65e1a31a687e4e91 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 13:39:32 +0100 Subject: [PATCH 11/78] Deserialize json result --- .../ChatGPT/ChatAssistantViewModel.cs | 53 ++++++++++++++----- 1 file changed, 40 insertions(+), 13 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index d3a6fe981b..bade2b9a63 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -10,6 +10,7 @@ using ChatGPT.ViewModels.Settings; using CommunityToolkit.Mvvm.DependencyInjection; using Microsoft.Extensions.DependencyInjection; +using Newtonsoft.Json; using ReactiveUI; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -126,20 +127,46 @@ private async Task SendAsync(string input) _cts = new CancellationTokenSource(); var result = await _chat.SendAsync(_chat.CreateChatMessages(), _cts.Token); - _chat.AddAssistantMessage(result?.Message); - - Console.WriteLine(result?.Message); - - // TODO: Deserialize result json message and get message param and command. - - // TODO: AssistantResult - - var resultMessage = result?.Message; - - Messages.Add(new AssistantMessageViewModel + if (result?.Message is { } assistantResultString) { - Message = resultMessage - }); + _chat.AddAssistantMessage(assistantResultString); + + Console.WriteLine(assistantResultString); + + AssistantResult? assistantResult; + string resultMessage = ""; + + try + { + assistantResult = JsonConvert.DeserializeObject(assistantResultString); + if (assistantResult is { }) + { + var message = assistantResult.Message; + if (assistantResult.Status == "command") + { + resultMessage = message; + } + else if (assistantResult.Status == "error") + { + resultMessage = message; + } + else if (assistantResult.Status == "message") + { + resultMessage = message; + } + } + } + catch (Exception e) + { + Console.WriteLine(e); + resultMessage = "ERROR"; + } + + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); + } } catch (Exception ex) { From 7d7e5a56be9b6f29bfa7225d4fee228a01935b84 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 13:42:40 +0100 Subject: [PATCH 12/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index bade2b9a63..bd6beac819 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -46,8 +46,9 @@ The status and message properties are of type string. e.g.: { "status": "command", - "message": "send(address, amount)", + "message": "send|address|amount", } +When message is api command write it using | separator between command name and command parameters e.g.: send|address|amount If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: e.g.: From a6be714a4467c361bb7a1d5de111c7a2dfdd1767 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 13:47:03 +0100 Subject: [PATCH 13/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index bd6beac819..398708f9cc 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -160,7 +160,7 @@ private async Task SendAsync(string input) catch (Exception e) { Console.WriteLine(e); - resultMessage = "ERROR"; + resultMessage = assistantResultString; } Messages.Add(new AssistantMessageViewModel From 86e340d7480478e61e0846531832c72578798f1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 14:04:24 +0100 Subject: [PATCH 14/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 398708f9cc..1a7872dbc8 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -70,8 +70,7 @@ The status and message properties are of type string. "message": "The address used the following format...", } -Never write answer as plain text (eg. I can not execute some api command etc.), -always write answers as json response with proper status. +Always write answers only as json, do not add additional text before or after json. """; private ChatViewModel _chat; From 11be8cc6fe9d93e84770122f6a514161bb948f71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 15:05:28 +0100 Subject: [PATCH 15/78] Update directions --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 1a7872dbc8..6bb38afa46 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -46,9 +46,13 @@ The status and message properties are of type string. e.g.: { "status": "command", - "message": "send|address|amount", + "message": "send|address|amount|void", } -When message is api command write it using | separator between command name and command parameters e.g.: send|address|amount +When message is api command write it using | separator between command name +and command parameters, last item is return value e.g.: +- send|address|amount|void +- receive|address +- balance|value If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: e.g.: @@ -70,7 +74,8 @@ The status and message properties are of type string. "message": "The address used the following format...", } -Always write answers only as json, do not add additional text before or after json. +You will always write answers only as json response. +Do not add additional text before or after json. """; private ChatViewModel _chat; From 5d44d551e1c285b0473019251f0d80f6d54ba15a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 15:05:37 +0100 Subject: [PATCH 16/78] Parse commands --- .../ChatGPT/ChatAssistantViewModel.cs | 66 ++++++++++++++++++- 1 file changed, 63 insertions(+), 3 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 6bb38afa46..046e2db370 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -147,17 +147,77 @@ private async Task SendAsync(string input) if (assistantResult is { }) { var message = assistantResult.Message; + if (assistantResult.Status == "command") { - resultMessage = message; + if (message is { }) + { + var args = message.Split(new char[] { '|' }); + + if (args.Length >= 1) + { + switch (args[0]) + { + case "send": + { + if (args.Length == 4) + { + var address = args[1]; + var value = args[2]; + resultMessage = $"Sending {value} to {address}..."; + } + else + { + resultMessage = "ERROR: Invalid command."; + } + break; + } + case "receive": + { + resultMessage = "Generating receive address..."; + break; + } + case "balance": + { + resultMessage = "Wallet balance is..."; + break; + } + } + } + else + { + resultMessage = "ERROR: Invalid command."; + } + } + else + { + // TODO: + resultMessage = message; + } } else if (assistantResult.Status == "error") { - resultMessage = message; + if (message is { }) + { + resultMessage = message; + } + else + { + // TODO: + resultMessage = message; + } } else if (assistantResult.Status == "message") { - resultMessage = message; + if (message is { }) + { + resultMessage = message; + } + else + { + // TODO: + resultMessage = message; + } } } } From 25b88010a18e2afb5e63f98bf1a3226ce5b16091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Thu, 23 Mar 2023 15:20:04 +0100 Subject: [PATCH 17/78] Update ChatAssistantViewModel.cs --- .../ChatGPT/ChatAssistantViewModel.cs | 51 ++++++++++++++++++- 1 file changed, 49 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 046e2db370..7557d3a0d7 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -12,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using ReactiveUI; +using WalletWasabi.Fluent.Helpers; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -165,6 +167,7 @@ private async Task SendAsync(string input) var address = args[1]; var value = args[2]; resultMessage = $"Sending {value} to {address}..."; + // TODO: Show send dialog but with send progress view. } else { @@ -174,12 +177,56 @@ private async Task SendAsync(string input) } case "receive": { - resultMessage = "Generating receive address..."; + // TODO: Show receive dialog but QR cod progress view. + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + // TODO: + if (currentWalletValue.ReceiveCommand.CanExecute(null)) + { + currentWalletValue.ReceiveCommand.Execute(null); + resultMessage = "Generating receive address..."; + } + else + { + resultMessage = "Can't generate receive address."; + } + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can't generate receive address."; + } + break; } case "balance": { - resultMessage = "Wallet balance is..."; + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); + + resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can not provide wallet balance."; + } + break; } } From d760980eb0dff899288637fcf6cfdb52e3f6715c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Thu, 23 Mar 2023 21:27:41 +0100 Subject: [PATCH 18/78] Use C# scripting for commands --- .../packages.lock.json | 114 ++++++++-------- .../ChatGPT/ChatAssistantViewModel.cs | 115 ++++++++++++++-- .../WalletWasabi.Fluent.csproj | 1 + WalletWasabi.Fluent/packages.lock.json | 124 +++++++++--------- WalletWasabi.Tests/WalletWasabi.Tests.csproj | 4 +- 5 files changed, 218 insertions(+), 140 deletions(-) diff --git a/WalletWasabi.Fluent.Desktop/packages.lock.json b/WalletWasabi.Fluent.Desktop/packages.lock.json index 3f7d977022..ab15f55f47 100644 --- a/WalletWasabi.Fluent.Desktop/packages.lock.json +++ b/WalletWasabi.Fluent.Desktop/packages.lock.json @@ -248,48 +248,46 @@ }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Transitive", - "resolved": "2.9.6", - "contentHash": "Kmms3TxGQMNb95Cu/3K+0bIcMnV4qf/phZBLAB0HUi65rBPxP4JO3aM2LoAcb+DFS600RQJMZ7ZLyYDTbLwJOQ==" + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" }, "Microsoft.CodeAnalysis.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "3ncA7cV+iXGA1VYwe2UEZXcvWyZSlbexWjM9AvocP7sik5UD93qt9Hq0fMRGk0jFRmvmE4T2g+bGfXiBVZEhLw==", + "resolved": "4.5.0", + "contentHash": "lwAbIZNdnY0SUNoDmZHkVUwLO8UyNnyyh1t/4XsbFxi4Ounb3xszIYZaWhyj5ZjyfcwqwmtMbE7fUTVCqQEIdQ==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "2.9.6", - "System.Collections.Immutable": "1.5.0", - "System.Memory": "4.5.3", - "System.Reflection.Metadata": "1.6.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.2", - "System.Text.Encoding.CodePages": "4.5.1", - "System.Threading.Tasks.Extensions": "4.5.3" + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "6.0.0", + "System.Reflection.Metadata": "6.0.1", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0" } }, "Microsoft.CodeAnalysis.CSharp": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "/LsTtgcMN6Tu1oo7/WYbRAHL4/ubXC/miEakwTpcZKJKtFo7D0AK95Hw0dbGxul6C8WJu60v6NP2435TDYZM+Q==", + "resolved": "4.5.0", + "contentHash": "cM59oMKAOxvdv76bdmaKPy5hfj+oR+zxikWoueEB7CwTko7mt9sVKZI8Qxlov0C/LuKEG+WQwifepqL3vuTiBQ==", "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CodeAnalysis.CSharp.Scripting": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "tLgqc76qXHmONUhWhxo7z3TcL/LmGFWIUJm1exbQmVJohuQvJnejUMxmVkdxDfMuMZU1fIyJXPZ6Fkp4FEneAg==", + "resolved": "4.5.0", + "contentHash": "LMapq8Ocdc1hGdvKt2sdvkHOrRO1Ymbl0EJEzRyrzxkxUfZRpUCsbGNCijnokmW1Zy3TBaj6LfV9WqRqE3fd+Q==", "dependencies": { - "Microsoft.CSharp": "4.3.0", - "Microsoft.CodeAnalysis.CSharp": "[3.4.0]", - "Microsoft.CodeAnalysis.Common": "[3.4.0]", - "Microsoft.CodeAnalysis.Scripting.Common": "[3.4.0]" + "Microsoft.CSharp": "4.7.0", + "Microsoft.CodeAnalysis.CSharp": "[4.5.0]", + "Microsoft.CodeAnalysis.Common": "[4.5.0]", + "Microsoft.CodeAnalysis.Scripting.Common": "[4.5.0]" } }, "Microsoft.CodeAnalysis.Scripting.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "+b6I3DZL2zvck+B/E/aiOveakj5U2G2BcYODQxcGh2IDbatNU3XXxGT1HumkWB5uIZI2Leu0opBgBpjScmjGMA==", + "resolved": "4.5.0", + "contentHash": "ruWwzk9H5uJ+BQOMZQh77bjd74Z2KZjJP01y/tpfB6qsRi8s+EjhvzNmG7wDx0uRwmOCksKDS0MeMu3D1uKzZQ==", "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CSharp": { @@ -328,8 +326,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "2.1.2", - "contentHash": "mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==" + "resolved": "1.1.1", + "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -445,8 +443,11 @@ }, "System.Collections.Immutable": { "type": "Transitive", - "resolved": "1.5.0", - "contentHash": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ==" + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.ComponentModel.Annotations": { "type": "Transitive", @@ -549,8 +550,11 @@ }, "System.Reflection.Metadata": { "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + "resolved": "6.0.1", + "contentHash": "III/lNMSn0ZRBuM9m5Cgbiho5j81u0FAEagFX5ta2DKbljZ3T0IpD8j+BIiHQPeKqJppWS9bGEp6JnKnWKze0g==", + "dependencies": { + "System.Collections.Immutable": "6.0.0" + } }, "System.Reflection.Primitives": { "type": "Transitive", @@ -585,8 +589,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "HxozeSlipUK7dAroTYwIcGwKDeOVpQnJlpVaOkBz7CM4TsE5b/tKlQBZecTjh6FzcSbxndYaxxpsBMz+wMJeyw==" + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -647,11 +651,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading": { @@ -673,11 +676,6 @@ "System.Runtime": "4.3.0" } }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.3", - "contentHash": "+MvhNtcvIbqmhANyKu91jQnvIRVSTiaOiFNfKWwXGHG48YAb4I/TyH8spsySiPYla7gKal5ZnF3teJqZAximyQ==" - }, "System.ValueTuple": { "type": "Transitive", "resolved": "4.5.0", @@ -711,6 +709,7 @@ "Avalonia.Skia": "[0.10.18, )", "Avalonia.Xaml.Behaviors": "[0.10.18, )", "ChatGPT.Core": "[1.0.0-preview.4, )", + "Microsoft.CodeAnalysis.CSharp.Scripting": "[4.5.0, )", "System.Drawing.Common": "[7.0.0, )", "System.Runtime": "[4.3.1, )", "WalletWasabi": "[1.0.0, )" @@ -1116,11 +1115,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1534,11 +1532,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1952,11 +1949,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2370,11 +2366,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2704,11 +2699,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 7557d3a0d7..4e820cf45e 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -10,6 +10,7 @@ using ChatGPT.ViewModels.Chat; using ChatGPT.ViewModels.Settings; using CommunityToolkit.Mvvm.DependencyInjection; +using Microsoft.CodeAnalysis.CSharp.Scripting; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using ReactiveUI; @@ -26,7 +27,8 @@ static ChatAssistantViewModel() private string _initialDirections = """ You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. -I will write text prompts and you will generate appropriate answers only in json format I have provided. +I will write text prompts and you will generate appropriate answers +only in json format I have provided. The json format for the answers is as follows: { @@ -36,25 +38,23 @@ I will write text prompts and you will generate appropriate answers only in json The status and message properties are of type string. The json response "status" property value can be one of the following: -- "command": when wasabi api command is the answer +- "command": when wasabi C# scripting api command is the answer - "error": when not possible to answer or other problem - "message": when answer is only text message but not error When "status"="command" the "message" value can only be set to - one of the following wasabi api commands available: -- send(address, amount): command requires address and amount, calls send method and displays send dialog -- address receive(): command returns only new BTC address, does not require any params, shows receive dialog with qr code -- value balance(): command returns BTC or USD balance value, does not require any params nor UI interaction -e.g.: +one of the following wasabi api C# scripting commands which will be executed as C# script: +- public async Task Send(string address, string amount) + command requires address and amount parameters +- public async Task Receive(string[] labels) + command requires labels array parameter +- public async Task Balance() + command does not require any parameters +e.g. for Send command (other follow similar pattern): { "status": "command", - "message": "send|address|amount|void", + "message": "await Send("valid BTC address", "valid BTC amount")", } -When message is api command write it using | separator between command name -and command parameters, last item is return value e.g.: -- send|address|amount|void -- receive|address -- balance|value If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: e.g.: @@ -120,6 +120,83 @@ public ChatAssistantViewModel() public ObservableCollection Messages { get; } + private class Globals + { + public ChatAssistantViewModel Chat { get; set; } + + public MainViewModel Main { get; set; } + + public async Task Send(string address, string amount) + { + // TODO: + + return $"Sending {amount} to {address}..."; + } + + public async Task Receive(string[] labels) + { + // TODO: Show receive dialog but QR cod progress view. + + var resultMessage = ""; + + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + // TODO: + if (currentWalletValue.ReceiveCommand.CanExecute(null)) + { + currentWalletValue.ReceiveCommand.Execute(null); + resultMessage = "Generating receive address..."; + } + else + { + resultMessage = "Can't generate receive address."; + } + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can't generate receive address."; + } + + return resultMessage; + } + + public async Task Balance() + { + // TODO: + + var resultMessage = ""; + + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); + + resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can not provide wallet balance."; + } + + return resultMessage; + } + } + private async Task SendAsync(string input) { try @@ -152,6 +229,17 @@ private async Task SendAsync(string input) if (assistantResult.Status == "command") { + if (message is { }) + { + var globals = new Globals + { + Chat = this, + Main = MainViewModel.Instance + }; + resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); + } + + /* if (message is { }) { var args = message.Split(new char[] { '|' }); @@ -241,6 +329,7 @@ private async Task SendAsync(string input) // TODO: resultMessage = message; } + */ } else if (assistantResult.Status == "error") { diff --git a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj index d927bdbfcb..7ee0a2868b 100644 --- a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj +++ b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj @@ -29,6 +29,7 @@ + diff --git a/WalletWasabi.Fluent/packages.lock.json b/WalletWasabi.Fluent/packages.lock.json index da0ce53268..c88b73e667 100644 --- a/WalletWasabi.Fluent/packages.lock.json +++ b/WalletWasabi.Fluent/packages.lock.json @@ -86,6 +86,18 @@ "Microsoft.Extensions.DependencyInjection": "7.0.0" } }, + "Microsoft.CodeAnalysis.CSharp.Scripting": { + "type": "Direct", + "requested": "[4.5.0, )", + "resolved": "4.5.0", + "contentHash": "LMapq8Ocdc1hGdvKt2sdvkHOrRO1Ymbl0EJEzRyrzxkxUfZRpUCsbGNCijnokmW1Zy3TBaj6LfV9WqRqE3fd+Q==", + "dependencies": { + "Microsoft.CSharp": "4.7.0", + "Microsoft.CodeAnalysis.CSharp": "[4.5.0]", + "Microsoft.CodeAnalysis.Common": "[4.5.0]", + "Microsoft.CodeAnalysis.Scripting.Common": "[4.5.0]" + } + }, "System.Drawing.Common": { "type": "Direct", "requested": "[7.0.0, )", @@ -217,48 +229,35 @@ }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Transitive", - "resolved": "2.9.6", - "contentHash": "Kmms3TxGQMNb95Cu/3K+0bIcMnV4qf/phZBLAB0HUi65rBPxP4JO3aM2LoAcb+DFS600RQJMZ7ZLyYDTbLwJOQ==" + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" }, "Microsoft.CodeAnalysis.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "3ncA7cV+iXGA1VYwe2UEZXcvWyZSlbexWjM9AvocP7sik5UD93qt9Hq0fMRGk0jFRmvmE4T2g+bGfXiBVZEhLw==", + "resolved": "4.5.0", + "contentHash": "lwAbIZNdnY0SUNoDmZHkVUwLO8UyNnyyh1t/4XsbFxi4Ounb3xszIYZaWhyj5ZjyfcwqwmtMbE7fUTVCqQEIdQ==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "2.9.6", - "System.Collections.Immutable": "1.5.0", - "System.Memory": "4.5.3", - "System.Reflection.Metadata": "1.6.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.2", - "System.Text.Encoding.CodePages": "4.5.1", - "System.Threading.Tasks.Extensions": "4.5.3" + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "6.0.0", + "System.Reflection.Metadata": "6.0.1", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0" } }, "Microsoft.CodeAnalysis.CSharp": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "/LsTtgcMN6Tu1oo7/WYbRAHL4/ubXC/miEakwTpcZKJKtFo7D0AK95Hw0dbGxul6C8WJu60v6NP2435TDYZM+Q==", - "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" - } - }, - "Microsoft.CodeAnalysis.CSharp.Scripting": { - "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "tLgqc76qXHmONUhWhxo7z3TcL/LmGFWIUJm1exbQmVJohuQvJnejUMxmVkdxDfMuMZU1fIyJXPZ6Fkp4FEneAg==", + "resolved": "4.5.0", + "contentHash": "cM59oMKAOxvdv76bdmaKPy5hfj+oR+zxikWoueEB7CwTko7mt9sVKZI8Qxlov0C/LuKEG+WQwifepqL3vuTiBQ==", "dependencies": { - "Microsoft.CSharp": "4.3.0", - "Microsoft.CodeAnalysis.CSharp": "[3.4.0]", - "Microsoft.CodeAnalysis.Common": "[3.4.0]", - "Microsoft.CodeAnalysis.Scripting.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CodeAnalysis.Scripting.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "+b6I3DZL2zvck+B/E/aiOveakj5U2G2BcYODQxcGh2IDbatNU3XXxGT1HumkWB5uIZI2Leu0opBgBpjScmjGMA==", + "resolved": "4.5.0", + "contentHash": "ruWwzk9H5uJ+BQOMZQh77bjd74Z2KZjJP01y/tpfB6qsRi8s+EjhvzNmG7wDx0uRwmOCksKDS0MeMu3D1uKzZQ==", "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CSharp": { @@ -297,8 +296,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "2.1.2", - "contentHash": "mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==" + "resolved": "1.1.1", + "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -414,8 +413,11 @@ }, "System.Collections.Immutable": { "type": "Transitive", - "resolved": "1.5.0", - "contentHash": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ==" + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.ComponentModel.Annotations": { "type": "Transitive", @@ -500,8 +502,11 @@ }, "System.Reflection.Metadata": { "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + "resolved": "6.0.1", + "contentHash": "III/lNMSn0ZRBuM9m5Cgbiho5j81u0FAEagFX5ta2DKbljZ3T0IpD8j+BIiHQPeKqJppWS9bGEp6JnKnWKze0g==", + "dependencies": { + "System.Collections.Immutable": "6.0.0" + } }, "System.Reflection.Primitives": { "type": "Transitive", @@ -527,8 +532,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "HxozeSlipUK7dAroTYwIcGwKDeOVpQnJlpVaOkBz7CM4TsE5b/tKlQBZecTjh6FzcSbxndYaxxpsBMz+wMJeyw==" + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -584,11 +589,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading": { @@ -610,11 +614,6 @@ "System.Runtime": "4.3.0" } }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.3", - "contentHash": "+MvhNtcvIbqmhANyKu91jQnvIRVSTiaOiFNfKWwXGHG48YAb4I/TyH8spsySiPYla7gKal5ZnF3teJqZAximyQ==" - }, "System.ValueTuple": { "type": "Transitive", "resolved": "4.5.0", @@ -1013,11 +1012,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1415,11 +1413,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1817,11 +1814,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2219,11 +2215,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2537,11 +2532,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { diff --git a/WalletWasabi.Tests/WalletWasabi.Tests.csproj b/WalletWasabi.Tests/WalletWasabi.Tests.csproj index facbfa0b4e..aa8f32db50 100644 --- a/WalletWasabi.Tests/WalletWasabi.Tests.csproj +++ b/WalletWasabi.Tests/WalletWasabi.Tests.csproj @@ -23,8 +23,8 @@ all - - + + From fc29ccaf398ea0153b546a18af93f66c9b546878 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Thu, 23 Mar 2023 21:30:56 +0100 Subject: [PATCH 19/78] Update TitleBar.axaml --- WalletWasabi.Fluent/Views/Shell/TitleBar.axaml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml b/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml index 620c7d5b5f..d510d4380f 100644 --- a/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml +++ b/WalletWasabi.Fluent/Views/Shell/TitleBar.axaml @@ -105,7 +105,8 @@ VerticalAlignment="Center" ContentTemplate="{StaticResource Title}" /> - + + @@ -133,7 +134,8 @@ - + + From 61e67b5d33273143453b32a1b3a68852a75a705a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Thu, 23 Mar 2023 21:51:55 +0100 Subject: [PATCH 20/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 4e820cf45e..7e1b6a2a53 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -28,7 +28,7 @@ static ChatAssistantViewModel() private string _initialDirections = """ You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. I will write text prompts and you will generate appropriate answers -only in json format I have provided. +only in json format I have provided, do not add text before or after json message. The json format for the answers is as follows: { From 0f28625c3a31f25cb1691b18667cd77119495616 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Thu, 23 Mar 2023 21:51:58 +0100 Subject: [PATCH 21/78] Update ChatAssistantViewModel.cs --- .../ChatGPT/ChatAssistantViewModel.cs | 92 ------------------- 1 file changed, 92 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 7e1b6a2a53..3414a166dc 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -238,98 +238,6 @@ private async Task SendAsync(string input) }; resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); } - - /* - if (message is { }) - { - var args = message.Split(new char[] { '|' }); - - if (args.Length >= 1) - { - switch (args[0]) - { - case "send": - { - if (args.Length == 4) - { - var address = args[1]; - var value = args[2]; - resultMessage = $"Sending {value} to {address}..."; - // TODO: Show send dialog but with send progress view. - } - else - { - resultMessage = "ERROR: Invalid command."; - } - break; - } - case "receive": - { - // TODO: Show receive dialog but QR cod progress view. - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) - { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - // TODO: - if (currentWalletValue.ReceiveCommand.CanExecute(null)) - { - currentWalletValue.ReceiveCommand.Execute(null); - resultMessage = "Generating receive address..."; - } - else - { - resultMessage = "Can't generate receive address."; - } - } - else - { - resultMessage = "Please select current wallet."; - } - } - else - { - resultMessage = "Can't generate receive address."; - } - - break; - } - case "balance": - { - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) - { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); - - resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; - } - else - { - resultMessage = "Please select current wallet."; - } - } - else - { - resultMessage = "Can not provide wallet balance."; - } - - break; - } - } - } - else - { - resultMessage = "ERROR: Invalid command."; - } - } - else - { - // TODO: - resultMessage = message; - } - */ } else if (assistantResult.Status == "error") { From 3d50c02ae625cfbb659b2e20ae0dd05874e9cf79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Thu, 23 Mar 2023 21:54:56 +0100 Subject: [PATCH 22/78] Move globals --- .../ChatGPT/ChatAssistantScriptGlobals.cs | 82 +++++++++++++++++++ .../ChatGPT/ChatAssistantViewModel.cs | 81 +----------------- 2 files changed, 83 insertions(+), 80 deletions(-) create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs new file mode 100644 index 0000000000..82782b9c4b --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -0,0 +1,82 @@ +using System.Reactive.Linq; +using System.Threading.Tasks; +using WalletWasabi.Fluent.Helpers; + +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public class ChatAssistantScriptGlobals +{ + public ChatAssistantViewModel Chat { get; set; } + + public MainViewModel Main { get; set; } + + public async Task Send(string address, string amount) + { + // TODO: + + return $"Sending {amount} to {address}..."; + } + + public async Task Receive(string[] labels) + { + // TODO: Show receive dialog but QR cod progress view. + + var resultMessage = ""; + + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + // TODO: + if (currentWalletValue.ReceiveCommand.CanExecute(null)) + { + currentWalletValue.ReceiveCommand.Execute(null); + resultMessage = "Generating receive address..."; + } + else + { + resultMessage = "Can't generate receive address."; + } + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can't generate receive address."; + } + + return resultMessage; + } + + public async Task Balance() + { + // TODO: + + var resultMessage = ""; + + if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + { + var currentWalletValue = await currentWallet.LastOrDefaultAsync(); + if (currentWalletValue is { }) + { + var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); + + resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; + } + else + { + resultMessage = "Please select current wallet."; + } + } + else + { + resultMessage = "Can not provide wallet balance."; + } + + return resultMessage; + } +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 3414a166dc..5b9b1c36ea 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -1,5 +1,4 @@ using System.Collections.ObjectModel; -using System.Reactive.Linq; using System.Threading; using System.Threading.Tasks; using System.Windows.Input; @@ -14,7 +13,6 @@ using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using ReactiveUI; -using WalletWasabi.Fluent.Helpers; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -120,83 +118,6 @@ public ChatAssistantViewModel() public ObservableCollection Messages { get; } - private class Globals - { - public ChatAssistantViewModel Chat { get; set; } - - public MainViewModel Main { get; set; } - - public async Task Send(string address, string amount) - { - // TODO: - - return $"Sending {amount} to {address}..."; - } - - public async Task Receive(string[] labels) - { - // TODO: Show receive dialog but QR cod progress view. - - var resultMessage = ""; - - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) - { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - // TODO: - if (currentWalletValue.ReceiveCommand.CanExecute(null)) - { - currentWalletValue.ReceiveCommand.Execute(null); - resultMessage = "Generating receive address..."; - } - else - { - resultMessage = "Can't generate receive address."; - } - } - else - { - resultMessage = "Please select current wallet."; - } - } - else - { - resultMessage = "Can't generate receive address."; - } - - return resultMessage; - } - - public async Task Balance() - { - // TODO: - - var resultMessage = ""; - - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) - { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); - - resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; - } - else - { - resultMessage = "Please select current wallet."; - } - } - else - { - resultMessage = "Can not provide wallet balance."; - } - - return resultMessage; - } - } - private async Task SendAsync(string input) { try @@ -231,7 +152,7 @@ private async Task SendAsync(string input) { if (message is { }) { - var globals = new Globals + var globals = new ChatAssistantScriptGlobals { Chat = this, Main = MainViewModel.Instance From 96e86195f4c3f9ddba447aeb0b973c1fd44d9346 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Fri, 24 Mar 2023 13:50:15 +0100 Subject: [PATCH 23/78] Add labels to Send api --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 4 ++-- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index 82782b9c4b..d2cb273d0c 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -10,11 +10,11 @@ public class ChatAssistantScriptGlobals public MainViewModel Main { get; set; } - public async Task Send(string address, string amount) + public async Task Send(string address, string amount, string[] labels) { // TODO: - return $"Sending {amount} to {address}..."; + return $"Sending {amount} to {address}, {labels}..."; } public async Task Receive(string[] labels) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 5b9b1c36ea..9b5321689d 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -42,7 +42,7 @@ The status and message properties are of type string. When "status"="command" the "message" value can only be set to one of the following wasabi api C# scripting commands which will be executed as C# script: -- public async Task Send(string address, string amount) +- public async Task Send(string address, string amount, string[] labels) command requires address and amount parameters - public async Task Receive(string[] labels) command requires labels array parameter @@ -51,7 +51,7 @@ command does not require any parameters e.g. for Send command (other follow similar pattern): { "status": "command", - "message": "await Send("valid BTC address", "valid BTC amount")", + "message": "await Send("valid BTC address", "valid BTC amount", "valid labels comma separated", } If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: From b6d096b269bc8aaacfed85d1c146ec41918d3106 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 19:50:15 +0100 Subject: [PATCH 24/78] Add message types and move directions --- .../ChatGPT/ChatAssistantScriptGlobals.cs | 21 +++- .../ChatAssistantViewModel.Directions.cs | 59 +++++++++++ .../ChatGPT/ChatAssistantViewModel.cs | 100 +++++++----------- .../Actions/BalanceActionMessageViewModel.cs | 5 + .../Actions/ReceiveActionMessageViewModel.cs | 5 + .../Actions/SendActionMessageViewModel.cs | 5 + .../AssistantMessageViewModel.cs | 2 +- .../ChatGPT/Messages/ErrorMessageViewModel.cs | 5 + .../{ => Messages}/MessageViewModel.cs | 2 +- .../{ => Messages}/UserMessageViewModel.cs | 2 +- .../Views/ChatGPT/ChatAssistant.axaml | 10 +- .../Views/ChatGPT/ChatAssistantDropdown.axaml | 48 +++++++-- 12 files changed, 186 insertions(+), 78 deletions(-) create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/SendActionMessageViewModel.cs rename WalletWasabi.Fluent/ViewModels/ChatGPT/{ => Messages}/AssistantMessageViewModel.cs (54%) create mode 100644 WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/ErrorMessageViewModel.cs rename WalletWasabi.Fluent/ViewModels/ChatGPT/{ => Messages}/MessageViewModel.cs (66%) rename WalletWasabi.Fluent/ViewModels/ChatGPT/{ => Messages}/UserMessageViewModel.cs (52%) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index d2cb273d0c..1acee64638 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -1,6 +1,8 @@ using System.Reactive.Linq; using System.Threading.Tasks; using WalletWasabi.Fluent.Helpers; +using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; +using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -12,9 +14,16 @@ public class ChatAssistantScriptGlobals public async Task Send(string address, string amount, string[] labels) { + var resultMessage = $"Sending {amount} to {address}, {labels}..."; + + Chat.Messages.Add(new SendActionMessageViewModel() + { + Message = resultMessage + }); + // TODO: - return $"Sending {amount} to {address}, {labels}..."; + return resultMessage; } public async Task Receive(string[] labels) @@ -49,6 +58,11 @@ public async Task Receive(string[] labels) resultMessage = "Can't generate receive address."; } + Chat.Messages.Add(new ReceiveActionMessageViewModel() + { + Message = resultMessage + }); + return resultMessage; } @@ -77,6 +91,11 @@ public async Task Balance() resultMessage = "Can not provide wallet balance."; } + Chat.Messages.Add(new BalanceActionMessageViewModel() + { + Message = resultMessage + }); + return resultMessage; } } diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs new file mode 100644 index 0000000000..98f961aa03 --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs @@ -0,0 +1,59 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT; + +public partial class ChatAssistantViewModel +{ + private readonly string _initialDirections = """ +You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. +I will write text prompts and you will generate appropriate answers +only in json format I have provided, do not add text before or after json message. + +The json format for the answers is as follows: +{ + "status": "", + "message": "", +} +The status and message properties are of type string. + +The json response "status" property value can be one of the following: +- "command": when wasabi C# scripting api command is the answer +- "error": when not possible to answer or other problem +- "message": when answer is only text message but not error + +When "status"="command" the "message" value can only be set to +one of the following wasabi api C# scripting commands which will be executed as C# script: +- public async Task Send(string address, string amount, string[] labels) + command requires address and amount parameters +- public async Task Receive(string[] labels) + command requires labels array parameter +- public async Task Balance() + command does not require any parameters +e.g. for Send command (other follow similar pattern): +{ + "status": "command", + "message": "await Send("valid BTC address", "valid BTC amount", "valid labels comma separated", +} + +If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: +e.g.: +{ + "status": "error", + "message": "Please provide valid address for send.", +} + +If not enough info is provided to execute command please set status=error and ask user to provide missing information: +e.g.: +{ + "status": "error", + "message": "Please provide valid address.", +} + +If user ask question the answer please set status=message and ask user is in following format: +{ + "status": "message", + "message": "The address used the following format...", +} + +You will always write answers only as json response. +Do not add additional text before or after json. +"""; +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 9b5321689d..e155f4370e 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -13,6 +13,7 @@ using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using ReactiveUI; +using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -23,64 +24,8 @@ static ChatAssistantViewModel() ConfigureServices(); } - private string _initialDirections = """ -You are a helpful assistant named Wasabito, you are Wasabi Wallet operator. -I will write text prompts and you will generate appropriate answers -only in json format I have provided, do not add text before or after json message. - -The json format for the answers is as follows: -{ - "status": "", - "message": "", -} -The status and message properties are of type string. - -The json response "status" property value can be one of the following: -- "command": when wasabi C# scripting api command is the answer -- "error": when not possible to answer or other problem -- "message": when answer is only text message but not error - -When "status"="command" the "message" value can only be set to -one of the following wasabi api C# scripting commands which will be executed as C# script: -- public async Task Send(string address, string amount, string[] labels) - command requires address and amount parameters -- public async Task Receive(string[] labels) - command requires labels array parameter -- public async Task Balance() - command does not require any parameters -e.g. for Send command (other follow similar pattern): -{ - "status": "command", - "message": "await Send("valid BTC address", "valid BTC amount", "valid labels comma separated", -} - -If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: -e.g.: -{ - "status": "error", - "message": "Please provide valid address for send.", -} - -If not enough info is provided to execute command please set status=error and ask user to provide missing information: -e.g.: -{ - "status": "error", - "message": "Please provide valid address.", -} - -If user ask question the answer please set status=message and ask user is in following format: -{ - "status": "message", - "message": "The address used the following format...", -} - -You will always write answers only as json response. -Do not add additional text before or after json. -"""; - private ChatViewModel _chat; - private CancellationTokenSource _cts; - + private CancellationTokenSource? _cts; [AutoNotify] private bool _isChatListVisible; [AutoNotify] private string? _inputText = ""; @@ -158,6 +103,15 @@ private async Task SendAsync(string input) Main = MainViewModel.Instance }; resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); + + if (resultMessage is null) + { + // TODO: "Error" message view model + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); + } } } else if (assistantResult.Status == "error") @@ -171,6 +125,12 @@ private async Task SendAsync(string input) // TODO: resultMessage = message; } + + // TODO: "Error" message view model + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); } else if (assistantResult.Status == "message") { @@ -183,19 +143,35 @@ private async Task SendAsync(string input) // TODO: resultMessage = message; } + + + // TODO: "Message" message view model + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); } } + else + { + // TODO: "Error" or "Assistant" message view model + Messages.Add(new AssistantMessageViewModel + { + Message = resultMessage + }); + } } catch (Exception e) { Console.WriteLine(e); resultMessage = assistantResultString; - } - Messages.Add(new AssistantMessageViewModel - { - Message = resultMessage - }); + // TODO: "Error" message view model + Messages.Add(new ErrorMessageViewModel() + { + Message = resultMessage + }); + } } } catch (Exception ex) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs new file mode 100644 index 0000000000..9cfb28e79e --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; + +public partial class BalanceActionMessageViewModel : MessageViewModel +{ +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs new file mode 100644 index 0000000000..c4169af549 --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; + +public partial class ReceiveActionMessageViewModel : MessageViewModel +{ +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/SendActionMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/SendActionMessageViewModel.cs new file mode 100644 index 0000000000..8f9490d2c3 --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/SendActionMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; + +public partial class SendActionMessageViewModel : MessageViewModel +{ +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/AssistantMessageViewModel.cs similarity index 54% rename from WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs rename to WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/AssistantMessageViewModel.cs index 3e8518ed7c..a4f9f70260 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/AssistantMessageViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/AssistantMessageViewModel.cs @@ -1,4 +1,4 @@ -namespace WalletWasabi.Fluent.ViewModels.ChatGPT; +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; public partial class AssistantMessageViewModel : MessageViewModel { diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/ErrorMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/ErrorMessageViewModel.cs new file mode 100644 index 0000000000..3faedff47f --- /dev/null +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/ErrorMessageViewModel.cs @@ -0,0 +1,5 @@ +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; + +public partial class ErrorMessageViewModel : MessageViewModel +{ +} diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/MessageViewModel.cs similarity index 66% rename from WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs rename to WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/MessageViewModel.cs index a936bc269a..0f92378394 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/MessageViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/MessageViewModel.cs @@ -1,6 +1,6 @@ using ReactiveUI; -namespace WalletWasabi.Fluent.ViewModels.ChatGPT; +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; public partial class MessageViewModel : ReactiveObject { diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/UserMessageViewModel.cs similarity index 52% rename from WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs rename to WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/UserMessageViewModel.cs index 7e675e60e0..e0e9a7df3a 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/UserMessageViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/UserMessageViewModel.cs @@ -1,4 +1,4 @@ -namespace WalletWasabi.Fluent.ViewModels.ChatGPT; +namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; public partial class UserMessageViewModel : MessageViewModel { diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml index 0be87f953e..3d33c6b82c 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -2,20 +2,20 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" - xmlns:s="clr-namespace:WalletWasabi.Fluent.Views.ChatGPT" + xmlns:cvm="clr-namespace:WalletWasabi.Fluent.Views.ChatGPT" mc:Ignorable="d" xmlns:i="clr-namespace:Avalonia.Xaml.Interactivity;assembly=Avalonia.Xaml.Interactivity" - xmlns:searchBar="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT" + xmlns:chat="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT" xmlns:behaviors="clr-namespace:WalletWasabi.Fluent.Behaviors" x:CompileBindings="True" - x:DataType="searchBar:ChatAssistantViewModel" + x:DataType="chat:ChatAssistantViewModel" x:Class="WalletWasabi.Fluent.Views.ChatGPT.ChatAssistant"> 1 - + @@ -150,7 +150,7 @@ - + diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index f2566ef21f..b1efc80e9a 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -2,13 +2,15 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:cvm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT" + xmlns:cmvm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT.Messages" + xmlns:cmavm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="450" x:Class="WalletWasabi.Fluent.Views.ChatGPT.ChatAssistantDropdown" x:CompileBindings="True" - x:DataType="sb:ChatAssistantViewModel" - xmlns:sb="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT"> + x:DataType="cvm:ChatAssistantViewModel"> - + @@ -41,14 +43,46 @@ - + + - + - + + - + + + + + + + + + + + + + + + + + + + + + + + + + From 96e23a4a6bf92cfca662633c8034c91d5599cd51 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 19:53:46 +0100 Subject: [PATCH 25/78] Wrap message text --- .../Views/ChatGPT/ChatAssistantDropdown.axaml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index b1efc80e9a..b8d8cc8fbf 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -47,6 +47,7 @@ @@ -54,6 +55,7 @@ @@ -61,6 +63,7 @@ @@ -68,6 +71,7 @@ @@ -75,6 +79,7 @@ @@ -82,6 +87,7 @@ From afe4e3e1c54e25bb6772070c450e76281ece7f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:00:58 +0100 Subject: [PATCH 26/78] Update Watermark --- WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml index 3d33c6b82c..edf9a04b49 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -128,7 +128,7 @@ - From 803b46cc10529102847fe160e71b4d5ab9e49fc7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:07:52 +0100 Subject: [PATCH 27/78] Update ChatAssistantViewModel.Directions.cs --- .../ChatGPT/ChatAssistantViewModel.Directions.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs index 98f961aa03..bde20daccb 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs @@ -21,16 +21,16 @@ The status and message properties are of type string. When "status"="command" the "message" value can only be set to one of the following wasabi api C# scripting commands which will be executed as C# script: -- public async Task Send(string address, string amount, string[] labels) +- public async Task Send(string address, string amount, string[] labels); command requires address and amount parameters -- public async Task Receive(string[] labels) +- public async Task Receive(string[] labels); command requires labels array parameter -- public async Task Balance() +- public async Task Balance(); command does not require any parameters e.g. for Send command (other follow similar pattern): { "status": "command", - "message": "await Send("valid BTC address", "valid BTC amount", "valid labels comma separated", + "message": "await Send("valid BTC address", "valid BTC amount", "valid labels comma separated");", } If user does not provide valid param to execute api command please set status=error and ask followup question to provide that info: From 5dbd9af183b456d39f5a0ba6305e56646f1817bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:08:00 +0100 Subject: [PATCH 28/78] Change icon --- WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml index edf9a04b49..9fb7aa0376 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -12,6 +12,7 @@ x:Class="WalletWasabi.Fluent.Views.ChatGPT.ChatAssistant"> 1 + M12 2c5.523 0 10 4.477 10 10s-4.477 10-10 10a9.96 9.96 0 0 1-4.587-1.112l-3.826 1.067a1.25 1.25 0 0 1-1.54-1.54l1.068-3.823A9.96 9.96 0 0 1 2 12C2 6.477 6.477 2 12 2Zm0 1.5A8.5 8.5 0 0 0 3.5 12c0 1.47.373 2.883 1.073 4.137l.15.27-1.112 3.984 3.987-1.112.27.15A8.5 8.5 0 1 0 12 3.5Zm0 12a1 1 0 1 1 0 2 1 1 0 0 1 0-2Zm0-8.75a2.75 2.75 0 0 1 2.75 2.75c0 1.01-.297 1.574-1.051 2.359l-.169.171c-.622.622-.78.886-.78 1.47a.75.75 0 0 1-1.5 0c0-1.01.297-1.574 1.051-2.359l.169-.171c.622-.622.78-.886.78-1.47a1.25 1.25 0 0 0-2.493-.128l-.007.128a.75.75 0 0 1-1.5 0A2.75 2.75 0 0 1 12 6.75Z @@ -145,7 +146,7 @@ - + From a8fef0764553f72017292237935a8adb9bc4fcb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:08:10 +0100 Subject: [PATCH 29/78] Update message styles --- .../Views/ChatGPT/ChatAssistantDropdown.axaml | 96 +++++++++++++------ 1 file changed, 66 insertions(+), 30 deletions(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index b8d8cc8fbf..e7b057ffef 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -42,54 +42,90 @@ + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + - - - + + + + + From a7de8f0527a4d2126e6ee47d53b70f433f87f806 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:36:20 +0100 Subject: [PATCH 30/78] Update actions --- .../ChatGPT/ChatAssistantScriptGlobals.cs | 53 +++++++------------ .../Actions/BalanceActionMessageViewModel.cs | 1 + .../Actions/ReceiveActionMessageViewModel.cs | 1 + 3 files changed, 20 insertions(+), 35 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index 1acee64638..a6ec594c11 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -1,8 +1,10 @@ using System.Reactive.Linq; using System.Threading.Tasks; +using WalletWasabi.Blockchain.Analysis.Clustering; using WalletWasabi.Fluent.Helpers; using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; +using WalletWasabi.Fluent.ViewModels.Wallets; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -31,36 +33,24 @@ public async Task Receive(string[] labels) // TODO: Show receive dialog but QR cod progress view. var resultMessage = ""; + var address = default(string); - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + if (MainViewModel.Instance.MainScreen.CurrentPage is WalletViewModel currentWallet) { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - // TODO: - if (currentWalletValue.ReceiveCommand.CanExecute(null)) - { - currentWalletValue.ReceiveCommand.Execute(null); - resultMessage = "Generating receive address..."; - } - else - { - resultMessage = "Can't generate receive address."; - } - } - else - { - resultMessage = "Please select current wallet."; - } + var newKey = currentWallet.Wallet.KeyManager.GetNextReceiveKey(new SmartLabel(labels)); + address = newKey.GetP2wpkhAddress( currentWallet.Wallet.Network).ToString(); + resultMessage = $"New receive address: {address}"; } else { - resultMessage = "Can't generate receive address."; + resultMessage = "Can't generate receive address, please login into wallet."; } Chat.Messages.Add(new ReceiveActionMessageViewModel() { - Message = resultMessage + Message = resultMessage, + // TODO: Enable copy new address (use copy button). + Address = address }); return resultMessage; @@ -71,29 +61,22 @@ public async Task Balance() // TODO: var resultMessage = ""; + var balance = default(string); - if (MainViewModel.Instance.CurrentWallet is { } currentWallet) + if (MainViewModel.Instance.MainScreen.CurrentPage is WalletViewModel currentWallet) { - var currentWalletValue = await currentWallet.LastOrDefaultAsync(); - if (currentWalletValue is { }) - { - var balance = currentWalletValue.Wallet.Coins.TotalAmount().ToFormattedString(); - - resultMessage = $"{currentWalletValue.Wallet.WalletName} balance is {balance}"; - } - else - { - resultMessage = "Please select current wallet."; - } + balance = currentWallet.Wallet.Coins.TotalAmount().ToFormattedString(); + resultMessage = $"{currentWallet.Wallet.WalletName} balance is {balance}"; } else { - resultMessage = "Can not provide wallet balance."; + resultMessage = "Can't provide wallet balance, please login into wallet."; } Chat.Messages.Add(new BalanceActionMessageViewModel() { - Message = resultMessage + Message = resultMessage, + Balance = balance }); return resultMessage; diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs index 9cfb28e79e..1506176463 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/BalanceActionMessageViewModel.cs @@ -2,4 +2,5 @@ namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; public partial class BalanceActionMessageViewModel : MessageViewModel { + [AutoNotify] private string? _balance; } diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs index c4169af549..3d256874ff 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/Messages/Actions/ReceiveActionMessageViewModel.cs @@ -2,4 +2,5 @@ namespace WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; public partial class ReceiveActionMessageViewModel : MessageViewModel { + [AutoNotify] private string? _address; } From a12b51a5bf52ae0497fdec81907e54b164e659ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:36:36 +0100 Subject: [PATCH 31/78] For some reason result is null, need to fix --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index e155f4370e..c1905586c5 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -103,7 +103,7 @@ private async Task SendAsync(string input) Main = MainViewModel.Instance }; resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); - +/* if (resultMessage is null) { // TODO: "Error" message view model @@ -112,6 +112,7 @@ private async Task SendAsync(string input) Message = resultMessage }); } +*/ } } else if (assistantResult.Status == "error") From d90a6d14cd6e0e30503aace3ada480a0189da41d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sat, 25 Mar 2023 20:36:45 +0100 Subject: [PATCH 32/78] Use PreviewItem for now --- .../Views/ChatGPT/ChatAssistantDropdown.axaml | 27 ++++++++++++------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index e7b057ffef..652a412925 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -2,6 +2,7 @@ xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" + xmlns:c="using:WalletWasabi.Fluent.Controls" xmlns:cvm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT" xmlns:cmvm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT.Messages" xmlns:cmavm="clr-namespace:WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions" @@ -98,22 +99,28 @@ - - - + + + + + - - - + + + + + From 6f858b500da4c548642bc0772cd1d99cc0314c99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Sun, 26 Mar 2023 13:59:27 +0200 Subject: [PATCH 33/78] Update --- .../packages.lock.json | 12 ++++----- .../ChatGPT/ChatAssistantScriptGlobals.cs | 2 -- .../ChatGPT/ChatAssistantViewModel.cs | 26 ++----------------- .../WalletWasabi.Fluent.csproj | 2 +- WalletWasabi.Fluent/packages.lock.json | 12 ++++----- 5 files changed, 15 insertions(+), 39 deletions(-) diff --git a/WalletWasabi.Fluent.Desktop/packages.lock.json b/WalletWasabi.Fluent.Desktop/packages.lock.json index ab15f55f47..34e86e0d7d 100644 --- a/WalletWasabi.Fluent.Desktop/packages.lock.json +++ b/WalletWasabi.Fluent.Desktop/packages.lock.json @@ -161,15 +161,15 @@ }, "ChatGPT": { "type": "Transitive", - "resolved": "1.0.0-preview.4", - "contentHash": "QL1biptxZPAFzWPoNGXovFfGW7vDNdVS8te0L542X1tOhDZlm/LqXRywbbUQSV4dWTUcsVev/FOUcvX7dPOxGg==" + "resolved": "1.0.0-preview.5", + "contentHash": "sEDWnmtN0E2qYbevlS6VcO8V70QDt6Y1aRdHRFYHKGjF8Z0XK/6Vy+lDoVeQiwspOE5Zkw8rhF34PB74J67g6A==" }, "ChatGPT.Core": { "type": "Transitive", - "resolved": "1.0.0-preview.4", - "contentHash": "GVAevfLlSi43Ox9MwWr2haGEShr5svtxH9kP2RasA3IxY2x+ZLGVfHBnxxOmPCKiDHrYKDqkDkK9xIaZ8yO/3w==", + "resolved": "1.0.0-preview.5", + "contentHash": "HIDaklt0feGfjXnMIauHZkTUk9WGACvvIVhy5AUKpV2giFUNYJCc5CeG+Dls52odV6O9hwfb/hP1y9jVk62hJA==", "dependencies": { - "ChatGPT": "1.0.0-preview.4", + "ChatGPT": "1.0.0-preview.5", "CommunityToolkit.Mvvm": "8.1.0", "Microsoft.Extensions.DependencyInjection": "7.0.0" } @@ -708,7 +708,7 @@ "Avalonia.ReactiveUI": "[0.10.18, )", "Avalonia.Skia": "[0.10.18, )", "Avalonia.Xaml.Behaviors": "[0.10.18, )", - "ChatGPT.Core": "[1.0.0-preview.4, )", + "ChatGPT.Core": "[1.0.0-preview.5, )", "Microsoft.CodeAnalysis.CSharp.Scripting": "[4.5.0, )", "System.Drawing.Common": "[7.0.0, )", "System.Runtime": "[4.3.1, )", diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index a6ec594c11..b9f006ac45 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -1,8 +1,6 @@ -using System.Reactive.Linq; using System.Threading.Tasks; using WalletWasabi.Blockchain.Analysis.Clustering; using WalletWasabi.Fluent.Helpers; -using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; using WalletWasabi.Fluent.ViewModels.Wallets; diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index c1905586c5..9186ac482f 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -2,15 +2,9 @@ using System.Threading; using System.Threading.Tasks; using System.Windows.Input; -using AI.Model.Services; -using AI.Services; -using ChatGPT.Model.Services; -using ChatGPT.Services; +using ChatGPT; using ChatGPT.ViewModels.Chat; -using ChatGPT.ViewModels.Settings; -using CommunityToolkit.Mvvm.DependencyInjection; using Microsoft.CodeAnalysis.CSharp.Scripting; -using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; using ReactiveUI; using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages; @@ -21,7 +15,7 @@ public partial class ChatAssistantViewModel : ReactiveObject { static ChatAssistantViewModel() { - ConfigureServices(); + Defaults.ConfigureDefaultServices(); } private ChatViewModel _chat; @@ -180,20 +174,4 @@ private async Task SendAsync(string input) Console.WriteLine("Error: " + ex.Message); } } - - private static void ConfigureServices() - { - IServiceCollection serviceCollection = new ServiceCollection(); - - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - Ioc.Default.ConfigureServices(serviceCollection.BuildServiceProvider()); - } } diff --git a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj index 7ee0a2868b..2e0f8cdc11 100644 --- a/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj +++ b/WalletWasabi.Fluent/WalletWasabi.Fluent.csproj @@ -28,7 +28,7 @@ - + diff --git a/WalletWasabi.Fluent/packages.lock.json b/WalletWasabi.Fluent/packages.lock.json index c88b73e667..e0f5107e17 100644 --- a/WalletWasabi.Fluent/packages.lock.json +++ b/WalletWasabi.Fluent/packages.lock.json @@ -77,11 +77,11 @@ }, "ChatGPT.Core": { "type": "Direct", - "requested": "[1.0.0-preview.4, )", - "resolved": "1.0.0-preview.4", - "contentHash": "GVAevfLlSi43Ox9MwWr2haGEShr5svtxH9kP2RasA3IxY2x+ZLGVfHBnxxOmPCKiDHrYKDqkDkK9xIaZ8yO/3w==", + "requested": "[1.0.0-preview.5, )", + "resolved": "1.0.0-preview.5", + "contentHash": "HIDaklt0feGfjXnMIauHZkTUk9WGACvvIVhy5AUKpV2giFUNYJCc5CeG+Dls52odV6O9hwfb/hP1y9jVk62hJA==", "dependencies": { - "ChatGPT": "1.0.0-preview.4", + "ChatGPT": "1.0.0-preview.5", "CommunityToolkit.Mvvm": "8.1.0", "Microsoft.Extensions.DependencyInjection": "7.0.0" } @@ -152,8 +152,8 @@ }, "ChatGPT": { "type": "Transitive", - "resolved": "1.0.0-preview.4", - "contentHash": "QL1biptxZPAFzWPoNGXovFfGW7vDNdVS8te0L542X1tOhDZlm/LqXRywbbUQSV4dWTUcsVev/FOUcvX7dPOxGg==" + "resolved": "1.0.0-preview.5", + "contentHash": "sEDWnmtN0E2qYbevlS6VcO8V70QDt6Y1aRdHRFYHKGjF8Z0XK/6Vy+lDoVeQiwspOE5Zkw8rhF34PB74J67g6A==" }, "CommunityToolkit.Mvvm": { "type": "Transitive", From 01f62c67fe024b99809ebe3590e7e23e37942be5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Mon, 27 Mar 2023 12:30:39 +0200 Subject: [PATCH 34/78] Update packages.lock.json --- .../packages.lock.json | 148 +++++++++++------- 1 file changed, 88 insertions(+), 60 deletions(-) diff --git a/WalletWasabi.Fluent.Desktop/packages.lock.json b/WalletWasabi.Fluent.Desktop/packages.lock.json index cc8def7e91..ee339fd7af 100644 --- a/WalletWasabi.Fluent.Desktop/packages.lock.json +++ b/WalletWasabi.Fluent.Desktop/packages.lock.json @@ -159,6 +159,26 @@ "Avalonia": "0.10.19" } }, + "ChatGPT": { + "type": "Transitive", + "resolved": "1.0.0-preview.5", + "contentHash": "sEDWnmtN0E2qYbevlS6VcO8V70QDt6Y1aRdHRFYHKGjF8Z0XK/6Vy+lDoVeQiwspOE5Zkw8rhF34PB74J67g6A==" + }, + "ChatGPT.Core": { + "type": "Transitive", + "resolved": "1.0.0-preview.5", + "contentHash": "HIDaklt0feGfjXnMIauHZkTUk9WGACvvIVhy5AUKpV2giFUNYJCc5CeG+Dls52odV6O9hwfb/hP1y9jVk62hJA==", + "dependencies": { + "ChatGPT": "1.0.0-preview.5", + "CommunityToolkit.Mvvm": "8.1.0", + "Microsoft.Extensions.DependencyInjection": "7.0.0" + } + }, + "CommunityToolkit.Mvvm": { + "type": "Transitive", + "resolved": "8.1.0", + "contentHash": "xxOt7lu9a5kB5Fs9RfcxzVlKnhuuPe+w7AXHtmCFtS3oldrsUhEMxHfNulluXSscUUoGxZ0jh55Om12ZP6abHA==" + }, "DynamicData": { "type": "Transitive", "resolved": "7.1.1", @@ -228,48 +248,46 @@ }, "Microsoft.CodeAnalysis.Analyzers": { "type": "Transitive", - "resolved": "2.9.6", - "contentHash": "Kmms3TxGQMNb95Cu/3K+0bIcMnV4qf/phZBLAB0HUi65rBPxP4JO3aM2LoAcb+DFS600RQJMZ7ZLyYDTbLwJOQ==" + "resolved": "3.3.3", + "contentHash": "j/rOZtLMVJjrfLRlAMckJLPW/1rze9MT1yfWqSIbUPGRu1m1P0fuo9PmqapwsmePfGB5PJrudQLvmUOAMF0DqQ==" }, "Microsoft.CodeAnalysis.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "3ncA7cV+iXGA1VYwe2UEZXcvWyZSlbexWjM9AvocP7sik5UD93qt9Hq0fMRGk0jFRmvmE4T2g+bGfXiBVZEhLw==", + "resolved": "4.5.0", + "contentHash": "lwAbIZNdnY0SUNoDmZHkVUwLO8UyNnyyh1t/4XsbFxi4Ounb3xszIYZaWhyj5ZjyfcwqwmtMbE7fUTVCqQEIdQ==", "dependencies": { - "Microsoft.CodeAnalysis.Analyzers": "2.9.6", - "System.Collections.Immutable": "1.5.0", - "System.Memory": "4.5.3", - "System.Reflection.Metadata": "1.6.0", - "System.Runtime.CompilerServices.Unsafe": "4.5.2", - "System.Text.Encoding.CodePages": "4.5.1", - "System.Threading.Tasks.Extensions": "4.5.3" + "Microsoft.CodeAnalysis.Analyzers": "3.3.3", + "System.Collections.Immutable": "6.0.0", + "System.Reflection.Metadata": "6.0.1", + "System.Runtime.CompilerServices.Unsafe": "6.0.0", + "System.Text.Encoding.CodePages": "6.0.0" } }, "Microsoft.CodeAnalysis.CSharp": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "/LsTtgcMN6Tu1oo7/WYbRAHL4/ubXC/miEakwTpcZKJKtFo7D0AK95Hw0dbGxul6C8WJu60v6NP2435TDYZM+Q==", + "resolved": "4.5.0", + "contentHash": "cM59oMKAOxvdv76bdmaKPy5hfj+oR+zxikWoueEB7CwTko7mt9sVKZI8Qxlov0C/LuKEG+WQwifepqL3vuTiBQ==", "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CodeAnalysis.CSharp.Scripting": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "tLgqc76qXHmONUhWhxo7z3TcL/LmGFWIUJm1exbQmVJohuQvJnejUMxmVkdxDfMuMZU1fIyJXPZ6Fkp4FEneAg==", + "resolved": "4.5.0", + "contentHash": "LMapq8Ocdc1hGdvKt2sdvkHOrRO1Ymbl0EJEzRyrzxkxUfZRpUCsbGNCijnokmW1Zy3TBaj6LfV9WqRqE3fd+Q==", "dependencies": { - "Microsoft.CSharp": "4.3.0", - "Microsoft.CodeAnalysis.CSharp": "[3.4.0]", - "Microsoft.CodeAnalysis.Common": "[3.4.0]", - "Microsoft.CodeAnalysis.Scripting.Common": "[3.4.0]" + "Microsoft.CSharp": "4.7.0", + "Microsoft.CodeAnalysis.CSharp": "[4.5.0]", + "Microsoft.CodeAnalysis.Common": "[4.5.0]", + "Microsoft.CodeAnalysis.Scripting.Common": "[4.5.0]" } }, "Microsoft.CodeAnalysis.Scripting.Common": { "type": "Transitive", - "resolved": "3.4.0", - "contentHash": "+b6I3DZL2zvck+B/E/aiOveakj5U2G2BcYODQxcGh2IDbatNU3XXxGT1HumkWB5uIZI2Leu0opBgBpjScmjGMA==", + "resolved": "4.5.0", + "contentHash": "ruWwzk9H5uJ+BQOMZQh77bjd74Z2KZjJP01y/tpfB6qsRi8s+EjhvzNmG7wDx0uRwmOCksKDS0MeMu3D1uKzZQ==", "dependencies": { - "Microsoft.CodeAnalysis.Common": "[3.4.0]" + "Microsoft.CodeAnalysis.Common": "[4.5.0]" } }, "Microsoft.CSharp": { @@ -277,6 +295,19 @@ "resolved": "4.7.0", "contentHash": "pTj+D3uJWyN3My70i2Hqo+OXixq3Os2D1nJ2x92FFo6sk8fYS1m1WLNTs0Dc1uPaViH0YvEEwvzddQ7y4rhXmA==" }, + "Microsoft.Extensions.DependencyInjection": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "elNeOmkeX3eDVG6pYVeV82p29hr+UKDaBhrZyWvWLw/EVZSYEkZlQdkp0V39k/Xehs2Qa0mvoCvkVj3eQxNQ1Q==", + "dependencies": { + "Microsoft.Extensions.DependencyInjection.Abstractions": "7.0.0" + } + }, + "Microsoft.Extensions.DependencyInjection.Abstractions": { + "type": "Transitive", + "resolved": "7.0.0", + "contentHash": "h3j/QfmFN4S0w4C2A6X7arXij/M/OVw3uQHSOFxnND4DyAzO1F9eMX7Eti7lU/OkSthEE0WzRsfT/Dmx86jzCw==" + }, "Microsoft.Extensions.Logging.Abstractions": { "type": "Transitive", "resolved": "1.0.0", @@ -295,8 +326,8 @@ }, "Microsoft.NETCore.Platforms": { "type": "Transitive", - "resolved": "2.1.2", - "contentHash": "mOJy3M0UN+LUG21dLGMxaWZEP6xYpQEpLuvuEQBaownaX4YuhH6NmNUlN9si+vNkAS6dwJ//N1O4DmLf2CikVg==" + "resolved": "1.1.1", + "contentHash": "TMBuzAHpTenGbGgk0SMTwyEkyijY/Eae4ZGsFNYJvAr/LDn1ku3Etp3FPxChmDp5HHF3kzJuoaa08N0xjqAJfQ==" }, "Microsoft.NETCore.Targets": { "type": "Transitive", @@ -412,8 +443,11 @@ }, "System.Collections.Immutable": { "type": "Transitive", - "resolved": "1.5.0", - "contentHash": "EXKiDFsChZW0RjrZ4FYHu9aW6+P4MCgEDCklsVseRfhoO0F+dXeMSsMRAlVXIo06kGJ/zv+2w1a2uc2+kxxSaQ==" + "resolved": "6.0.0", + "contentHash": "l4zZJ1WU2hqpQQHXz1rvC3etVZN+2DLmQMO79FhOTZHMn8tDRr+WU287sbomD0BETlmKDn0ygUgVy9k5xkkJdA==", + "dependencies": { + "System.Runtime.CompilerServices.Unsafe": "6.0.0" + } }, "System.ComponentModel.Annotations": { "type": "Transitive", @@ -516,8 +550,11 @@ }, "System.Reflection.Metadata": { "type": "Transitive", - "resolved": "1.6.0", - "contentHash": "COC1aiAJjCoA5GBF+QKL2uLqEBew4JsCkQmoHKbN3TlOZKa2fKLz5CpiRQKDz0RsAOEGsVKqOD5bomsXq/4STQ==" + "resolved": "6.0.1", + "contentHash": "III/lNMSn0ZRBuM9m5Cgbiho5j81u0FAEagFX5ta2DKbljZ3T0IpD8j+BIiHQPeKqJppWS9bGEp6JnKnWKze0g==", + "dependencies": { + "System.Collections.Immutable": "6.0.0" + } }, "System.Reflection.Primitives": { "type": "Transitive", @@ -552,8 +589,8 @@ }, "System.Runtime.CompilerServices.Unsafe": { "type": "Transitive", - "resolved": "4.6.0", - "contentHash": "HxozeSlipUK7dAroTYwIcGwKDeOVpQnJlpVaOkBz7CM4TsE5b/tKlQBZecTjh6FzcSbxndYaxxpsBMz+wMJeyw==" + "resolved": "6.0.0", + "contentHash": "/iUeP3tq1S0XdNNoMz5C9twLSrM/TH+qElHkXWaPvuNOt+99G75NrV0OS2EqHx5wMN7popYjpc8oTjC1y16DLg==" }, "System.Runtime.Extensions": { "type": "Transitive", @@ -614,11 +651,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading": { @@ -640,11 +676,6 @@ "System.Runtime": "4.3.0" } }, - "System.Threading.Tasks.Extensions": { - "type": "Transitive", - "resolved": "4.5.3", - "contentHash": "+MvhNtcvIbqmhANyKu91jQnvIRVSTiaOiFNfKWwXGHG48YAb4I/TyH8spsySiPYla7gKal5ZnF3teJqZAximyQ==" - }, "System.ValueTuple": { "type": "Transitive", "resolved": "4.5.0", @@ -677,6 +708,8 @@ "Avalonia.ReactiveUI": "[0.10.19, )", "Avalonia.Skia": "[0.10.19, )", "Avalonia.Xaml.Behaviors": "[0.10.19, )", + "ChatGPT.Core": "[1.0.0-preview.5, )", + "Microsoft.CodeAnalysis.CSharp.Scripting": "[4.5.0, )", "System.Drawing.Common": "[7.0.0, )", "System.Runtime": "[4.3.1, )", "WalletWasabi": "[1.0.0, )" @@ -1082,11 +1115,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1500,11 +1532,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -1918,11 +1949,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2336,11 +2366,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { @@ -2670,11 +2699,10 @@ }, "System.Text.Encoding.CodePages": { "type": "Transitive", - "resolved": "4.5.1", - "contentHash": "4J2JQXbftjPMppIHJ7IC+VXQ9XfEagN92vZZNoG12i+zReYlim5dMoXFC1Zzg7tsnKDM7JPo5bYfFK4Jheq44w==", + "resolved": "6.0.0", + "contentHash": "ZFCILZuOvtKPauZ/j/swhvw68ZRi9ATCfvGbk1QfydmcXBkIWecWKn/250UH7rahZ5OoDBaiAudJtPvLwzw85A==", "dependencies": { - "Microsoft.NETCore.Platforms": "2.1.2", - "System.Runtime.CompilerServices.Unsafe": "4.5.2" + "System.Runtime.CompilerServices.Unsafe": "6.0.0" } }, "System.Threading.Tasks": { From ccaa4ed3d27c0f0b3bd0fd443eb83ccefcb42a43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Mon, 27 Mar 2023 12:46:16 +0200 Subject: [PATCH 35/78] Fix main window focus --- WalletWasabi.Fluent/Views/MainWindow.axaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/Views/MainWindow.axaml b/WalletWasabi.Fluent/Views/MainWindow.axaml index 7461c1c534..c002ca929a 100644 --- a/WalletWasabi.Fluent/Views/MainWindow.axaml +++ b/WalletWasabi.Fluent/Views/MainWindow.axaml @@ -20,8 +20,9 @@ ExtendClientAreaChromeHints="Default, PreferSystemChrome, OSXThickTitleBar" Title="Wasabi Wallet" WindowState="{Binding WindowState, Mode=TwoWay}" - Focusable="{Binding SearchBar.IsSearchListVisible}" + Focusable="{Binding ChatAssistant.IsChatListVisible}" Icon="/Assets/WasabiLogo.ico"> + + + - From 6b8811c533514b3c48ee5bcefdb5e7e11d50e3e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Mon, 27 Mar 2023 23:07:15 +0200 Subject: [PATCH 44/78] Update ChatAssistantViewModel.Directions.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs index f883c41e36..b8e7a9e2f2 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.Directions.cs @@ -22,7 +22,7 @@ The status and message properties are of type string. When "status"="command" the "message" value can only be set to one of the following wasabi api C# scripting commands which will be executed as C# script: -- public async Task Send(string address, string amount, string[] labels); +- public async Task Send(string address, decimal amountBtc, string[] labels); Send command requires address, amount and labels parameters. Users must provide at least one label. - public async Task Receive(string[] labels); Receive command requires labels array parameter. Users must provide at least one label. From 302de692828be5c34ab13b704328b8dde2fdfe27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Mon, 27 Mar 2023 23:07:18 +0200 Subject: [PATCH 45/78] Update ChatAssistantScriptGlobals.cs --- .../ChatGPT/ChatAssistantScriptGlobals.cs | 97 +++++++++++++++++-- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index b9f006ac45..c066a87f9a 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -1,8 +1,14 @@ using System.Threading.Tasks; +using NBitcoin; using WalletWasabi.Blockchain.Analysis.Clustering; +using WalletWasabi.Blockchain.Transactions; +using WalletWasabi.Extensions; using WalletWasabi.Fluent.Helpers; +using WalletWasabi.Fluent.Models; using WalletWasabi.Fluent.ViewModels.ChatGPT.Messages.Actions; using WalletWasabi.Fluent.ViewModels.Wallets; +using WalletWasabi.Fluent.ViewModels.Wallets.Send; +using WalletWasabi.Logging; namespace WalletWasabi.Fluent.ViewModels.ChatGPT; @@ -12,16 +18,93 @@ public class ChatAssistantScriptGlobals public MainViewModel Main { get; set; } - public async Task Send(string address, string amount, string[] labels) + public async Task Send(string address, decimal amountBtc, string[] labels) { - var resultMessage = $"Sending {amount} to {address}, {labels}..."; + var resultMessage = ""; - Chat.Messages.Add(new SendActionMessageViewModel() + if (MainViewModel.Instance.MainScreen.CurrentPage is WalletViewModel currentWallet) { - Message = resultMessage - }); - - // TODO: + Chat.Messages.Add(new SendActionMessageViewModel() + { + Message = $"Sending {amountBtc} to {address}, {labels}..." + }); + + Chat.IsBusy = true; + + var IsFixedAmount = false; + var IsPayJoin = false; + + // TODO: + var amount = new Money(amountBtc, MoneyUnit.BTC); + var transactionInfo = new TransactionInfo(BitcoinAddress.Create(address, currentWallet.Wallet.Network), currentWallet.Wallet.AnonScoreTarget) + { + Amount = amount, + Recipient = new SmartLabel(labels), + // TODO: PayJoinClient = GetPayjoinClient(PayJoinEndPoint), + PayJoinClient = null, + IsFixedAmount = IsFixedAmount, + SubtractFee = amount == currentWallet.Wallet.Coins.TotalAmount() && !(IsFixedAmount || IsPayJoin) + }; + + var transaction = await Task.Run(() => TransactionHelpers.BuildTransaction(currentWallet.Wallet, transactionInfo)); + var transactionAuthorizationInfo = new TransactionAuthorizationInfo(transaction); + // TODO: + //var authResult = await AuthorizeAsync(transactionAuthorizationInfo); + //if (authResult) + { + try + { + var finalTransaction = + await GetFinalTransactionAsync(transactionAuthorizationInfo.Transaction, transactionInfo); + await SendTransactionAsync(finalTransaction); + // _cancellationTokenSource?.Cancel(); + //Navigate().To(new SendSuccessViewModel(currentWallet.Wallet, finalTransaction)); + Chat.Messages.Add(new SendActionMessageViewModel() + { + Message = $"Sent {amountBtc} to {address}, {labels}." + }); + } + catch (Exception ex) + { + Logger.LogError(ex); + // TODO: + //await ShowErrorAsync("Transaction", ex.ToUserFriendlyString(), + // "Wasabi was unable to send your transaction."); + } + } + + async Task GetFinalTransactionAsync(SmartTransaction transaction, + TransactionInfo transactionInfo) + { + if (transactionInfo.PayJoinClient is { }) + { + try + { + var payJoinTransaction = await Task.Run(() => + TransactionHelpers.BuildTransaction(currentWallet.Wallet, transactionInfo, isPayJoin: true)); + return payJoinTransaction.Transaction; + } + catch (Exception ex) + { + Logger.LogError(ex); + } + } + + return transaction; + } + + async Task SendTransactionAsync(SmartTransaction transaction) + { + await Services.TransactionBroadcaster.SendTransactionAsync(transaction); + } + + + Chat.IsBusy = false; + } + else + { + resultMessage = "Can't generate receive address, please login into wallet."; + } return resultMessage; } From e6267c00956757189f2f42b90757fac1f4110fa0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Mon, 27 Mar 2023 23:32:49 +0200 Subject: [PATCH 46/78] Update ChatAssistantScriptGlobals.cs --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index c066a87f9a..687d45863a 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -26,7 +26,7 @@ public async Task Send(string address, decimal amountBtc, string[] label { Chat.Messages.Add(new SendActionMessageViewModel() { - Message = $"Sending {amountBtc} to {address}, {labels}..." + Message = $"Sending {amountBtc} to {address}, {new SmartLabel(labels)}..." }); Chat.IsBusy = true; From ab4dca8b073f23078b3b4ca3a9fdbc4e40183f2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Mon, 27 Mar 2023 23:32:52 +0200 Subject: [PATCH 47/78] Update ChatAssistantScriptGlobals.cs --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index 687d45863a..81587d745f 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -43,7 +43,8 @@ public async Task Send(string address, decimal amountBtc, string[] label // TODO: PayJoinClient = GetPayjoinClient(PayJoinEndPoint), PayJoinClient = null, IsFixedAmount = IsFixedAmount, - SubtractFee = amount == currentWallet.Wallet.Coins.TotalAmount() && !(IsFixedAmount || IsPayJoin) + SubtractFee = amount == currentWallet.Wallet.Coins.TotalAmount() && !(IsFixedAmount || IsPayJoin), + FeeRate = new FeeRate(Money.Satoshis(1000)) }; var transaction = await Task.Run(() => TransactionHelpers.BuildTransaction(currentWallet.Wallet, transactionInfo)); From 5e57913f73b6ac5b0a251e9c64aa9b67494c4529 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Mon, 27 Mar 2023 23:32:56 +0200 Subject: [PATCH 48/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 5b42245a2d..7ac4ffc64b 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -212,7 +212,8 @@ private async Task SendAsync(string input) catch (Exception e) { Console.WriteLine(e); - resultMessage = assistantResultString; + //resultMessage = assistantResultString; + resultMessage = $"Error: {e.Message}"; // TODO: "Error" message view model Messages.Add(new ErrorMessageViewModel() From 2e5f2d2dda8a8f32f427f1109abd297ef0e64b4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Tue, 28 Mar 2023 00:04:33 +0200 Subject: [PATCH 49/78] Update ChatAssistantScriptGlobals.cs --- .../ChatGPT/ChatAssistantScriptGlobals.cs | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index 81587d745f..dd851bbdff 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -1,6 +1,9 @@ +using System.Collections.Generic; +using System.Linq; using System.Threading.Tasks; using NBitcoin; using WalletWasabi.Blockchain.Analysis.Clustering; +using WalletWasabi.Blockchain.TransactionOutputs; using WalletWasabi.Blockchain.Transactions; using WalletWasabi.Extensions; using WalletWasabi.Fluent.Helpers; @@ -47,6 +50,25 @@ public async Task Send(string address, decimal amountBtc, string[] label FeeRate = new FeeRate(Money.Satoshis(1000)) }; + + + var LabelSelection = new LabelSelectionViewModel(currentWallet.Wallet.KeyManager, currentWallet.Wallet.Kitchen.SaltSoup(), transactionInfo, true); + + void InitializeLabels() + { + var privateThreshold = currentWallet.Wallet.AnonScoreTarget; + + LabelSelection.Reset(currentWallet.Wallet.Coins.GetPockets(privateThreshold).Select(x => new Pocket(x)).ToArray()); + LabelSelection.SetUsedLabel(new List(), privateThreshold); + } + + + var autoSelectedPockets = LabelSelection.AutoSelectPockets(); + var coins = Pocket.Merge(autoSelectedPockets.ToArray()).Coins; + + transactionInfo.Coins = coins; + + var transaction = await Task.Run(() => TransactionHelpers.BuildTransaction(currentWallet.Wallet, transactionInfo)); var transactionAuthorizationInfo = new TransactionAuthorizationInfo(transaction); // TODO: From b11ffbcca6df818f976a63e374042047a21deb3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Tue, 28 Mar 2023 00:07:06 +0200 Subject: [PATCH 50/78] Update ChatAssistantScriptGlobals.cs --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index dd851bbdff..dad8631caf 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -62,6 +62,7 @@ void InitializeLabels() LabelSelection.SetUsedLabel(new List(), privateThreshold); } + InitializeLabels(); var autoSelectedPockets = LabelSelection.AutoSelectPockets(); var coins = Pocket.Merge(autoSelectedPockets.ToArray()).Coins; From d695331b30ca737ae04d06da010cde8646f9d465 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Tue, 28 Mar 2023 00:09:35 +0200 Subject: [PATCH 51/78] Update ChatAssistantScriptGlobals.cs --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index dad8631caf..caa4a7ca35 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -85,7 +85,7 @@ void InitializeLabels() //Navigate().To(new SendSuccessViewModel(currentWallet.Wallet, finalTransaction)); Chat.Messages.Add(new SendActionMessageViewModel() { - Message = $"Sent {amountBtc} to {address}, {labels}." + Message = $"Sent {amountBtc} to {address}, {new SmartLabel(labels)}." }); } catch (Exception ex) From f2a74173f60fb1426a92285559f707dd0a365f39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:01:50 +0200 Subject: [PATCH 52/78] Change welcome message --- .../ChatGPT/ChatAssistantViewModel.cs | 26 ++++++++++++------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 7ac4ffc64b..887c259dd2 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -20,6 +20,13 @@ static ChatAssistantViewModel() Defaults.ConfigureDefaultServices(); } + private static string[] WelcomeMessages = + { + "What do you wish my master", + "Speak, and I shall obey", + "Your wish is my command" + }; + private Subject _hasResultsSubject; private ChatViewModel? _chat; private CancellationTokenSource? _cts; @@ -31,20 +38,17 @@ static ChatAssistantViewModel() public ChatAssistantViewModel() { + void SwitchWelcomeMessage() + { + WelcomeMessage = WelcomeMessages[Random.Shared.Next(0, WelcomeMessages.Length - 1)]; + } + _hasResultsSubject = new Subject(); _hasResultsSubject.OnNext(false); _inputText = ""; - _welcomeMessage = """ -Welcome to the Assistant Chat! - -I'm here to help you with anything related to the Wasabi Wallet. - -Feel free to ask questions or request assistance with tasks such as creating a receiving address or sending BTC. - -I'm here to make your experience friendly, informative, and professional. -"""; + SwitchWelcomeMessage(); CreateChat(); Messages = new ObservableCollection(); @@ -53,6 +57,10 @@ Feel free to ask questions or request assistance with tasks such as creating a r .Select(x => x > 0) .Subscribe(x => HasResults = x); + this.WhenAnyValue(x => x.IsChatListVisible) + .Where(x => x == true) + .Subscribe(x => SwitchWelcomeMessage()); + SendCommand = ReactiveCommand.CreateFromTask(async () => { var inputText = InputText; From dc93843bbe2b568179f662645ced067218ec44bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:13:16 +0200 Subject: [PATCH 53/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 887c259dd2..9f978fbb7e 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -40,7 +40,9 @@ public ChatAssistantViewModel() { void SwitchWelcomeMessage() { - WelcomeMessage = WelcomeMessages[Random.Shared.Next(0, WelcomeMessages.Length - 1)]; + var index = Random.Shared.Next(0, WelcomeMessages.Length); + WelcomeMessage = WelcomeMessages[index]; + Console.WriteLine($"WelcomeMessage='{WelcomeMessage}'"); } _hasResultsSubject = new Subject(); @@ -58,8 +60,8 @@ void SwitchWelcomeMessage() .Subscribe(x => HasResults = x); this.WhenAnyValue(x => x.IsChatListVisible) - .Where(x => x == true) - .Subscribe(x => SwitchWelcomeMessage()); + .Where(x => x) + .Subscribe(_ => SwitchWelcomeMessage()); SendCommand = ReactiveCommand.CreateFromTask(async () => { From 2d6460c680c2e0d0307b7a68588c4da210137d83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:13:23 +0200 Subject: [PATCH 54/78] Update ChatAssistantViewModel.cs --- .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index 9f978fbb7e..cbf7bf5ee4 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -157,8 +157,16 @@ private async Task SendAsync(string input) Chat = this, Main = MainViewModel.Instance }; - resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); + try + { + resultMessage = await CSharpScript.EvaluateAsync(message, globals: globals); + } + catch (Exception e) + { + Console.WriteLine(e); + resultMessage = "Failed to execute command."; + } // TODO: Handle script result. /* if (resultMessage is null) @@ -222,8 +230,8 @@ private async Task SendAsync(string input) catch (Exception e) { Console.WriteLine(e); - //resultMessage = assistantResultString; - resultMessage = $"Error: {e.Message}"; + resultMessage = assistantResultString; + //resultMessage = $"Error: {e.Message}"; // TODO: "Error" message view model Messages.Add(new ErrorMessageViewModel() From 288f1cde577154a5f511f96cd84f56eb374b6e81 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:34:42 +0200 Subject: [PATCH 55/78] Add CurrentMessage --- .../ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs | 4 ++++ .../ViewModels/ChatGPT/ChatAssistantViewModel.cs | 9 +++++++++ 2 files changed, 13 insertions(+) diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs index caa4a7ca35..627fa2e654 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantScriptGlobals.cs @@ -31,6 +31,7 @@ public async Task Send(string address, decimal amountBtc, string[] label { Message = $"Sending {amountBtc} to {address}, {new SmartLabel(labels)}..." }); + Chat.CurrentMessage = Chat.Messages.LastOrDefault(); Chat.IsBusy = true; @@ -87,6 +88,7 @@ void InitializeLabels() { Message = $"Sent {amountBtc} to {address}, {new SmartLabel(labels)}." }); + Chat.CurrentMessage = Chat.Messages.LastOrDefault(); } catch (Exception ex) { @@ -157,6 +159,7 @@ public async Task Receive(string[] labels) // TODO: Enable copy new address (use copy button). Address = address }); + Chat.CurrentMessage = Chat.Messages.LastOrDefault(); return resultMessage; } @@ -183,6 +186,7 @@ public async Task Balance() Message = resultMessage, Balance = balance }); + Chat.CurrentMessage = Chat.Messages.LastOrDefault(); return resultMessage; } diff --git a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs index cbf7bf5ee4..8d69150832 100644 --- a/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs +++ b/WalletWasabi.Fluent/ViewModels/ChatGPT/ChatAssistantViewModel.cs @@ -1,4 +1,5 @@ using System.Collections.ObjectModel; +using System.Linq; using System.Reactive.Linq; using System.Reactive.Subjects; using System.Threading; @@ -35,6 +36,7 @@ static ChatAssistantViewModel() [AutoNotify] private string? _inputText; [AutoNotify] private string? _welcomeMessage; [AutoNotify(SetterModifier = AccessModifier.Private)] private bool _hasResults; + [AutoNotify] private MessageViewModel? _currentMessage; public ChatAssistantViewModel() { @@ -54,6 +56,7 @@ void SwitchWelcomeMessage() CreateChat(); Messages = new ObservableCollection(); + CurrentMessage = null; this.WhenAnyValue(x => x.Messages.Count) .Select(x => x > 0) @@ -79,6 +82,7 @@ void SwitchWelcomeMessage() { CreateChat(); Messages.Clear(); + CurrentMessage = null; _hasResultsSubject.OnNext(false); }); } @@ -121,6 +125,7 @@ private async Task SendAsync(string input) { Message = input }); + CurrentMessage = Messages.LastOrDefault(); if (Messages.Count >= 1) { @@ -197,6 +202,7 @@ private async Task SendAsync(string input) { Message = resultMessage }); + CurrentMessage = Messages.LastOrDefault(); } else if (assistantResult.Status == "message") { @@ -216,6 +222,7 @@ private async Task SendAsync(string input) { Message = resultMessage }); + CurrentMessage = Messages.LastOrDefault(); } } else @@ -225,6 +232,7 @@ private async Task SendAsync(string input) { Message = resultMessage }); + CurrentMessage = Messages.LastOrDefault(); } } catch (Exception e) @@ -238,6 +246,7 @@ private async Task SendAsync(string input) { Message = resultMessage }); + CurrentMessage = Messages.LastOrDefault(); } } } From bde12b37d1f8790801a49b7074beeecf53cd2e72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:35:24 +0200 Subject: [PATCH 56/78] Handle message scrolling --- .../Views/ChatGPT/ChatAssistant.axaml | 1 + .../Views/ChatGPT/ChatAssistantDropdown.axaml | 195 ++++++++++-------- .../ChatGPT/ChatAssistantDropdown.axaml.cs | 26 +++ 3 files changed, 136 insertions(+), 86 deletions(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml index efa5fef344..57f2a1d578 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistant.axaml @@ -126,6 +126,7 @@ diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index 601c1dbcd3..65f0f13195 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -41,6 +41,23 @@ + + @@ -65,102 +82,108 @@ Margin="0,5,0,10" Value="50" DockPanel.Dock="Bottom"/> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + - - - - - - - + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs index fc783b242e..bf5e71407a 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml.cs @@ -1,13 +1,39 @@ +using System.Reactive; +using Avalonia; using Avalonia.Controls; +using Avalonia.Controls.Primitives; using Avalonia.Markup.Xaml; namespace WalletWasabi.Fluent.Views.ChatGPT; public partial class ChatAssistantDropdown : UserControl { + private bool _scrollToEnd; + public ChatAssistantDropdown() { InitializeComponent(); + + var messagesItemsControl = this.FindControl("MessagesItemsControl"); + var chatScrollViewer = this.FindControl("ChatScrollViewer"); + + messagesItemsControl + .GetObservable(SelectingItemsControl.SelectedItemProperty) + .Subscribe(_ => + { + _scrollToEnd = true; + }); + + chatScrollViewer + .GetObservable(ScrollViewer.ExtentProperty) + .Subscribe(_ => + { + if (_scrollToEnd) + { + chatScrollViewer.ScrollToEnd(); + _scrollToEnd = false; + } + }); } private void InitializeComponent() From 0f6f2574e68a5833abc3ea5fe68ca960332e0e3c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20=C5=A0olt=C3=A9s?= Date: Tue, 28 Mar 2023 12:44:20 +0200 Subject: [PATCH 57/78] Adjust margins --- WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml index 65f0f13195..1d18a2b723 100644 --- a/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml +++ b/WalletWasabi.Fluent/Views/ChatGPT/ChatAssistantDropdown.axaml @@ -79,7 +79,7 @@ + Margin="12,0,12,0">