From e607d1c73507f9a8e51edb0d68edb235e9dc4e07 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Wies=C5=82aw=20S=CC=8Colte=CC=81s?= Date: Fri, 26 Apr 2024 20:13:29 +0200 Subject: [PATCH] Remove usage of the Ioc.Default --- Directory.Build.props | 2 +- README.md | 1 - samples/ChatGPT.CLI.Chaining/Program.cs | 7 +- .../ChatGPT.CLI.FunctionCalling/Program.cs | 26 +- samples/ChatGPT.CLI.Repl/Program.cs | 18 +- .../ChatGPT.UI.Designer/MainWindow.axaml.cs | 9 +- samples/ChatGPT.UI.Game/Game.cs | 34 +- samples/ChatGPT.UI.Game/MainWindow.axaml.cs | 2 - src/ChatGPT.CLI/Chat.cs | 16 +- src/ChatGPT.CLI/Program.cs | 2 - src/ChatGPT.Core/ChatGPT.Core.csproj | 1 - src/ChatGPT.Core/Defaults.cs | 33 -- src/ChatGPT.Core/Model/Plugins/IChatPlugin.cs | 13 - .../Model/Plugins/IPluginContext.cs | 10 - .../Model/Services/IPluginsService.cs | 9 - src/ChatGPT.Core/Plugins/DummyChatPlugin.cs | 31 -- src/ChatGPT.Core/Services/PluginsService.cs | 51 --- .../ViewModels/Chat/ChatMessageViewModel.cs | 16 +- .../ViewModels/Chat/ChatViewModel.cs | 337 +++++++++--------- .../Chat/ChatViewModelExtensions.cs | 15 + ...ModelJsonContext.cs => CoreJsonContext.cs} | 5 +- src/ChatGPT.UI.Android/MainActivity.cs | 2 - src/ChatGPT.UI.Browser/Program.cs | 37 +- src/ChatGPT.UI.Desktop/Program.cs | 5 - src/ChatGPT.UI.iOS/AppDelegate.cs | 3 - src/ChatGPT.UI/App.axaml.cs | 155 +++----- src/ChatGPT.UI/ChatGPT.UI.csproj | 5 +- .../Plugins/ClipboardListenerChatPlugin.cs | 190 ---------- .../Services/BrowserStorageFactory.cs | 2 +- .../Services/BrowserStorageService.cs | 2 +- .../ViewModels/MainViewModel.Actions.cs | 9 +- .../ViewModels/MainViewModel.Chats.cs | 33 +- .../ViewModels/MainViewModel.Import.cs | 4 +- .../ViewModels/MainViewModel.Prompts.cs | 25 +- .../ViewModels/MainViewModel.cs | 55 +-- .../Views/History/HistoryActionsView.axaml | 2 +- .../Views/History/HistoryView.axaml | 2 +- .../Views/Layouts/DesktopLayoutView.axaml | 2 +- .../Views/Layouts/MobileLayoutView.axaml | 2 +- src/ChatGPT.UI/Views/MainView.axaml | 2 +- .../Views/MainViewActionsView.axaml | 2 +- src/ChatGPT.UI/Views/MainWindow.axaml | 2 +- .../Views/Prompts/PromptsActionsView.axaml | 2 +- .../Views/Prompts/PromptsView.axaml | 2 +- .../Views/Settings/SettingsActionsView.axaml | 2 +- .../Views/Settings/SettingsView.axaml | 2 +- src/ChatGptCom/Chat.cs | 42 +-- 47 files changed, 437 insertions(+), 792 deletions(-) delete mode 100644 src/ChatGPT.Core/Model/Plugins/IChatPlugin.cs delete mode 100644 src/ChatGPT.Core/Model/Plugins/IPluginContext.cs delete mode 100644 src/ChatGPT.Core/Model/Services/IPluginsService.cs delete mode 100644 src/ChatGPT.Core/Plugins/DummyChatPlugin.cs delete mode 100644 src/ChatGPT.Core/Services/PluginsService.cs create mode 100644 src/ChatGPT.Core/ViewModels/Chat/ChatViewModelExtensions.cs rename src/ChatGPT.Core/ViewModels/{MainViewModelJsonContext.cs => CoreJsonContext.cs} (88%) delete mode 100644 src/ChatGPT.UI/Plugins/ClipboardListenerChatPlugin.cs rename src/{ChatGPT.UI.Browser => ChatGPT.UI}/Services/BrowserStorageFactory.cs (82%) rename src/{ChatGPT.UI.Browser => ChatGPT.UI}/Services/BrowserStorageService.cs (98%) rename src/{ChatGPT.Core => ChatGPT.UI}/ViewModels/MainViewModel.Actions.cs (92%) rename src/{ChatGPT.Core => ChatGPT.UI}/ViewModels/MainViewModel.Chats.cs (89%) rename src/{ChatGPT.Core => ChatGPT.UI}/ViewModels/MainViewModel.Import.cs (94%) rename src/{ChatGPT.Core => ChatGPT.UI}/ViewModels/MainViewModel.Prompts.cs (89%) rename src/{ChatGPT.Core => ChatGPT.UI}/ViewModels/MainViewModel.cs (79%) diff --git a/Directory.Build.props b/Directory.Build.props index 2da61ada..cf33b781 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -1,7 +1,7 @@  1.0.0 - preview.22 + preview.23 Wiesław Šoltés Wiesław Šoltés Copyright © Wiesław Šoltés 2024 diff --git a/README.md b/README.md index e4f9c117..3d1dff92 100644 --- a/README.md +++ b/README.md @@ -54,7 +54,6 @@ You can import [OpenAI ChatGPT web version](https://chat.openai.com/chat) chats - [Markdown.Avalonia](https://github.com/whistyun/Markdown.Avalonia) - [Avalonia.HtmlRenderer](https://github.com/AvaloniaUI/Avalonia.HtmlRenderer) - [CommunityToolkit.Mvvm](https://github.com/CommunityToolkit/dotnet) -- [Microsoft.Extensions.DependencyInjection](https://www.nuget.org/packages/Microsoft.Extensions.DependencyInjection/) # .NET tool diff --git a/samples/ChatGPT.CLI.Chaining/Program.cs b/samples/ChatGPT.CLI.Chaining/Program.cs index c4e7d3b2..fb743250 100644 --- a/samples/ChatGPT.CLI.Chaining/Program.cs +++ b/samples/ChatGPT.CLI.Chaining/Program.cs @@ -1,7 +1,8 @@ -using ChatGPT; +using AI.Services; using ChatGPT.ViewModels.Chat; -Defaults.ConfigureDefaultServices(); +var chatSerializer = new SystemTextJsonChatSerializer(); +var chatService = new ChatService(chatSerializer); using var cts = new CancellationTokenSource(); var input1 = "Some random test string."; @@ -17,7 +18,7 @@ async Task SendAsync(string directions, string input, CancellationToken token) { - var chat = new ChatViewModel(directions); + var chat = new ChatViewModel(chatService, chatSerializer,directions); chat.AddSystemMessage(directions); chat.AddUserMessage(input); var result = await chat.SendAsync(chat.CreateChatMessages(), token); diff --git a/samples/ChatGPT.CLI.FunctionCalling/Program.cs b/samples/ChatGPT.CLI.FunctionCalling/Program.cs index 6d219f3f..72bc4e0b 100644 --- a/samples/ChatGPT.CLI.FunctionCalling/Program.cs +++ b/samples/ChatGPT.CLI.FunctionCalling/Program.cs @@ -1,7 +1,8 @@ -using ChatGPT; +using AI.Services; using ChatGPT.ViewModels.Chat; -Defaults.ConfigureDefaultServices(); +var chatSerializer = new SystemTextJsonChatSerializer(); +var chatService = new ChatService(chatSerializer); var directions = """ @@ -20,15 +21,18 @@ Only use the functions you have been provided with. var functions = GetFunctions(); -var chat = new ChatViewModel(new ChatSettingsViewModel -{ - MaxTokens = 2000, - Model = "gpt-3.5-turbo-0613", - Functions = functions, - FunctionCall = "auto" - // Force function call by setting FunctionCall property. - // FunctionCall = new { name = "GetCurrentWeather" } -}); +var chat = new ChatViewModel( + chatService, + chatSerializer, + new ChatSettingsViewModel + { + MaxTokens = 2000, + Model = "gpt-3.5-turbo-0613", + Functions = functions, + FunctionCall = "auto" + // Force function call by setting FunctionCall property. + // FunctionCall = new { name = "GetCurrentWeather" } + }); // Enable to debug json requests and responses. // chat.Debug = true; diff --git a/samples/ChatGPT.CLI.Repl/Program.cs b/samples/ChatGPT.CLI.Repl/Program.cs index 97179ec8..4a63971e 100644 --- a/samples/ChatGPT.CLI.Repl/Program.cs +++ b/samples/ChatGPT.CLI.Repl/Program.cs @@ -1,7 +1,8 @@ -using ChatGPT; +using AI.Services; using ChatGPT.ViewModels.Chat; -Defaults.ConfigureDefaultServices(); +var chatSerializer = new SystemTextJsonChatSerializer(); +var chatService = new ChatService(chatSerializer); var directions = """ @@ -17,11 +18,14 @@ Do not use markdown. using var cts = new CancellationTokenSource(); -var chat = new ChatViewModel(new ChatSettingsViewModel -{ - MaxTokens = 2000, - Model = "gpt-3.5-turbo" -}); +var chat = new ChatViewModel( + chatService, + chatSerializer, + new ChatSettingsViewModel + { + MaxTokens = 2000, + Model = "gpt-3.5-turbo" + }); chat.AddSystemMessage(directions); diff --git a/samples/ChatGPT.UI.Designer/MainWindow.axaml.cs b/samples/ChatGPT.UI.Designer/MainWindow.axaml.cs index 48338de4..0e2ba7ae 100644 --- a/samples/ChatGPT.UI.Designer/MainWindow.axaml.cs +++ b/samples/ChatGPT.UI.Designer/MainWindow.axaml.cs @@ -1,5 +1,6 @@ using System; using System.Threading; +using AI.Services; using Avalonia; using Avalonia.Controls; using Avalonia.Interactivity; @@ -10,13 +11,17 @@ namespace ChatGPT; public partial class MainWindow : Window { + private readonly SystemTextJsonChatSerializer _chatSerializer; + private readonly ChatService _chatService; + public MainWindow() { InitializeComponent(); #if DEBUG this.AttachDevTools(); #endif - Defaults.ConfigureDefaultServices(); + _chatSerializer = new SystemTextJsonChatSerializer(); + _chatService = new ChatService(_chatSerializer); } private async void SendButton_OnClick(object? sender, RoutedEventArgs e) @@ -53,7 +58,7 @@ Write XAML as plain text. }; var cts = new CancellationTokenSource(); - var chat = new ChatViewModel(chatSettings); + var chat = new ChatViewModel(_chatService, _chatSerializer, chatSettings); chat.AddSystemMessage(chatSettings.Directions); chat.AddUserMessage(prompt); var result = await chat.SendAsync(chat.CreateChatMessages(), cts.Token); diff --git a/samples/ChatGPT.UI.Game/Game.cs b/samples/ChatGPT.UI.Game/Game.cs index 2ab85ab7..4a2babce 100644 --- a/samples/ChatGPT.UI.Game/Game.cs +++ b/samples/ChatGPT.UI.Game/Game.cs @@ -2,6 +2,7 @@ using System.Text.Json; using System.Threading; using System.Threading.Tasks; +using AI.Services; using ChatGPT.ViewModels.Chat; namespace ChatGPT; @@ -11,7 +12,15 @@ public class Game private string? _directions; private CancellationTokenSource? _cts; private ChatViewModel? _chat; + private readonly SystemTextJsonChatSerializer _chatSerializer; + private readonly ChatService _chatService; + public Game() + { + _chatSerializer = new SystemTextJsonChatSerializer(); + _chatService = new ChatService(_chatSerializer); + } + public void New() { _directions = @@ -35,17 +44,20 @@ Player has always three options to choose. } """; - _chat = new ChatViewModel(new ChatSettingsViewModel - { - Temperature = 0.7m, - TopP = 1m, - PresencePenalty = 0m, - FrequencyPenalty = 0m, - MaxTokens = 3000, - ApiKey = null, - // Model = "gpt-3.5-turbo", - Model = "gpt-4", - }); + _chat = new ChatViewModel( + _chatService, + _chatSerializer, + new ChatSettingsViewModel + { + Temperature = 0.7m, + TopP = 1m, + PresencePenalty = 0m, + FrequencyPenalty = 0m, + MaxTokens = 3000, + ApiKey = null, + // Model = "gpt-3.5-turbo", + Model = "gpt-4", + }); _chat.AddSystemMessage(_directions); } diff --git a/samples/ChatGPT.UI.Game/MainWindow.axaml.cs b/samples/ChatGPT.UI.Game/MainWindow.axaml.cs index 05843b02..cdbdd91c 100644 --- a/samples/ChatGPT.UI.Game/MainWindow.axaml.cs +++ b/samples/ChatGPT.UI.Game/MainWindow.axaml.cs @@ -15,8 +15,6 @@ public MainWindow() #if DEBUG this.AttachDevTools(); #endif - Defaults.ConfigureDefaultServices(); - _game = new Game(); _game.New(); diff --git a/src/ChatGPT.CLI/Chat.cs b/src/ChatGPT.CLI/Chat.cs index 50fdcea3..7827da95 100644 --- a/src/ChatGPT.CLI/Chat.cs +++ b/src/ChatGPT.CLI/Chat.cs @@ -1,5 +1,9 @@ using System.Diagnostics; using System.Text.Json; +using AI.Model.Services; +using AI.Services; +using ChatGPT.Model.Services; +using ChatGPT.Services; using ChatGPT.ViewModels; using ChatGPT.ViewModels.Chat; @@ -8,6 +12,14 @@ namespace ChatGPT.CLI; internal static class Chat { private static readonly Action? s_log = Console.WriteLine; + private static readonly IChatSerializer s_chatSerializer; + private static readonly IChatService s_chatService; + + static Chat() + { + s_chatSerializer = new SystemTextJsonChatSerializer(); + s_chatService = new ChatService(s_chatSerializer); + } private static async Task RunJob(ChatJob job, CancellationToken token) { @@ -19,7 +31,7 @@ private static async Task RunJob(ChatJob job, CancellationToken token) } var input = await File.ReadAllTextAsync(job.InputPath, token); - var chat = new ChatViewModel(job.Settings); + var chat = new ChatViewModel(s_chatService, s_chatSerializer, job.Settings); chat.AddSystemMessage(job.Settings.Directions); chat.AddUserMessage(input); var result = await chat.SendAsync(chat.CreateChatMessages(), token); @@ -129,7 +141,7 @@ private static List GetJobs(CliSettings cliSettings, List pat using var stream = File.OpenRead(cliSettings.SettingsFile.FullName); fileSettings = JsonSerializer.Deserialize( stream, - MainViewModelJsonContext.s_instance.ChatSettingsViewModel); + CoreJsonContext.s_instance.ChatSettingsViewModel); } var chatSettings = fileSettings ?? new ChatSettingsViewModel diff --git a/src/ChatGPT.CLI/Program.cs b/src/ChatGPT.CLI/Program.cs index 14499f5f..641d52dc 100644 --- a/src/ChatGPT.CLI/Program.cs +++ b/src/ChatGPT.CLI/Program.cs @@ -3,8 +3,6 @@ using ChatGPT; using ChatGPT.CLI; -Defaults.ConfigureDefaultServices(); - await CreateRootCommand().InvokeAsync(args); RootCommand CreateRootCommand() diff --git a/src/ChatGPT.Core/ChatGPT.Core.csproj b/src/ChatGPT.Core/ChatGPT.Core.csproj index db931461..81107250 100644 --- a/src/ChatGPT.Core/ChatGPT.Core.csproj +++ b/src/ChatGPT.Core/ChatGPT.Core.csproj @@ -18,7 +18,6 @@ - diff --git a/src/ChatGPT.Core/Defaults.cs b/src/ChatGPT.Core/Defaults.cs index 2ebeb310..3556e9e6 100644 --- a/src/ChatGPT.Core/Defaults.cs +++ b/src/ChatGPT.Core/Defaults.cs @@ -1,13 +1,3 @@ -using System; -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; - namespace ChatGPT; public static class Defaults @@ -35,27 +25,4 @@ public static class Defaults public const string MarkdownMessageFormat = "Markdown"; public const string HtmlMessageTextFormat = "Html"; - - public static Ioc Locator = Ioc.Default; - - public static IServiceProvider ConfigureDefaultServices() - { - IServiceCollection serviceCollection = new ServiceCollection(); - - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - - Locator.ConfigureServices(serviceProvider); - - return serviceProvider; - } } diff --git a/src/ChatGPT.Core/Model/Plugins/IChatPlugin.cs b/src/ChatGPT.Core/Model/Plugins/IChatPlugin.cs deleted file mode 100644 index 919984d0..00000000 --- a/src/ChatGPT.Core/Model/Plugins/IChatPlugin.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System.Threading.Tasks; - -namespace ChatGPT.Model.Plugins; - -public interface IChatPlugin -{ - string Id { get; } - string Name { get; } - Task StartAsync(); - Task StopAsync(); - Task InitializeAsync(IPluginContext context); - Task ShutdownAsync(); -} diff --git a/src/ChatGPT.Core/Model/Plugins/IPluginContext.cs b/src/ChatGPT.Core/Model/Plugins/IPluginContext.cs deleted file mode 100644 index adf334ff..00000000 --- a/src/ChatGPT.Core/Model/Plugins/IPluginContext.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Collections.ObjectModel; -using ChatGPT.ViewModels.Chat; - -namespace ChatGPT.Model.Plugins; - -public interface IPluginContext -{ - ObservableCollection Chats { get; set; } - ChatViewModel? CurrentChat { get; set; } -} diff --git a/src/ChatGPT.Core/Model/Services/IPluginsService.cs b/src/ChatGPT.Core/Model/Services/IPluginsService.cs deleted file mode 100644 index 18a85223..00000000 --- a/src/ChatGPT.Core/Model/Services/IPluginsService.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace ChatGPT.Model.Services; - -public interface IPluginsService -{ - void DiscoverPlugins(); - void InitPlugins(); - void StartPlugins(); - void ShutdownPlugins(); -} diff --git a/src/ChatGPT.Core/Plugins/DummyChatPlugin.cs b/src/ChatGPT.Core/Plugins/DummyChatPlugin.cs deleted file mode 100644 index 0e3f4b94..00000000 --- a/src/ChatGPT.Core/Plugins/DummyChatPlugin.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Threading.Tasks; -using ChatGPT.Model.Plugins; - -namespace ChatGPT.Plugins; - -public class DummyChatPlugin : IChatPlugin -{ - public string Id => "Dummy"; - - public string Name => "Dummy"; - - public async Task StartAsync() - { - await Task.Yield(); - } - - public async Task StopAsync() - { - await Task.Yield(); - } - - public async Task InitializeAsync(IPluginContext context) - { - await Task.Yield(); - } - - public async Task ShutdownAsync() - { - await Task.Yield(); - } -} diff --git a/src/ChatGPT.Core/Services/PluginsService.cs b/src/ChatGPT.Core/Services/PluginsService.cs deleted file mode 100644 index 344e093f..00000000 --- a/src/ChatGPT.Core/Services/PluginsService.cs +++ /dev/null @@ -1,51 +0,0 @@ -using System.Collections.Generic; -using ChatGPT.Model.Plugins; -using ChatGPT.Model.Services; -using Microsoft.Extensions.DependencyInjection; - -namespace ChatGPT.Services; - -public class PluginsService : IPluginsService -{ - private readonly List _plugins = new(); - private readonly IPluginContext _pluginContext; - - public PluginsService(IPluginContext pluginContext) - { - _pluginContext = pluginContext; - } - - public void DiscoverPlugins() - { - var plugins = Defaults.Locator.GetServices(); - - foreach (var plugin in plugins) - { - _plugins.Add(plugin); - } - } - - public void InitPlugins() - { - foreach (var plugin in _plugins) - { - plugin.InitializeAsync(_pluginContext); - } - } - - public void StartPlugins() - { - foreach (var plugin in _plugins) - { - plugin.StartAsync(); - } - } - - public void ShutdownPlugins() - { - foreach (var plugin in _plugins) - { - plugin.ShutdownAsync(); - } - } -} diff --git a/src/ChatGPT.Core/ViewModels/Chat/ChatMessageViewModel.cs b/src/ChatGPT.Core/ViewModels/Chat/ChatMessageViewModel.cs index 20d47698..4230d0e6 100644 --- a/src/ChatGPT.Core/ViewModels/Chat/ChatMessageViewModel.cs +++ b/src/ChatGPT.Core/ViewModels/Chat/ChatMessageViewModel.cs @@ -281,18 +281,29 @@ private void SetFormatAction(string? format) private async Task OpenActionAsync() { + // TODO: + await Task.Yield(); + + // TODO: + /* var app = Defaults.Locator.GetService(); if (app is { }) { await app.OpenFileAsync( - OpenCallbackAsync, - new List(new[] { "All" }), + OpenCallbackAsync, + new List(new[] { "All" }), "Open"); } + */ } private async Task SaveActionAsync() { + // TODO: + await Task.Yield(); + + // TODO: + /* var app = Defaults.Locator.GetService(); if (app is { } && Message is { }) { @@ -303,6 +314,7 @@ await app.SaveFileAsync( "message", "txt"); } + */ } private async Task OpenCallbackAsync(Stream stream) diff --git a/src/ChatGPT.Core/ViewModels/Chat/ChatViewModel.cs b/src/ChatGPT.Core/ViewModels/Chat/ChatViewModel.cs index aa4ee70f..5e5c6a91 100644 --- a/src/ChatGPT.Core/ViewModels/Chat/ChatViewModel.cs +++ b/src/ChatGPT.Core/ViewModels/Chat/ChatViewModel.cs @@ -10,11 +10,14 @@ using AI.Model.Services; using ChatGPT.Model.Services; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; namespace ChatGPT.ViewModels.Chat; public class ChatViewModel : ObservableObject { + private readonly IChatService _chatService; + private readonly IChatSerializer _chatSerializer; private string? _name; private ChatSettingsViewModel? _settings; private ObservableCollection _messages; @@ -25,20 +28,30 @@ public class ChatViewModel : ObservableObject private CancellationTokenSource? _cts; [JsonConstructor] - public ChatViewModel() + public ChatViewModel( + IChatService chatService, + IChatSerializer chatSerializer) { + _chatService = chatService; + _chatSerializer = chatSerializer; _messages = new ObservableCollection(); _isEnabled = true; _debug = false; _requireApiKey = true; } - public ChatViewModel(ChatSettingsViewModel settings) : this() + public ChatViewModel( + IChatService chatService, + IChatSerializer chatSerializer, + ChatSettingsViewModel settings) + : this(chatService, chatSerializer) { _settings = settings; } public ChatViewModel( + IChatService chatService, + IChatSerializer chatSerializer, string directions = "You are a helpful assistant.", decimal temperature = 0.7m, decimal topP = 1m, @@ -46,7 +59,8 @@ public ChatViewModel( decimal frequencyPenalty = 0m, int maxTokens = 2000, string? apiKey = null, - string model = "gpt-3.5-turbo") : this() + string model = "gpt-3.5-turbo") + : this(chatService, chatSerializer) { _settings = new ChatSettingsViewModel { @@ -110,6 +124,158 @@ public bool RequireApiKey set => SetProperty(ref _requireApiKey, value); } + public async Task SendAsync(ChatMessage[] messages, CancellationToken token) + { + var settings = Settings; + if (settings is null) + { + return default; + } + + var chatServiceSettings = new ChatServiceSettings + { + Model = settings.Model, + Messages = messages, + Functions = settings.Functions, + FunctionCall = settings.FunctionCall, + Suffix = null, + Temperature = settings.Temperature, + MaxTokens = settings.MaxTokens, + TopP = 1.0m, + Stop = null, + ApiUrl = settings.ApiUrl, + Debug = Debug, + RequireApiKey = RequireApiKey, + }; + + var result = new ChatResultViewModel + { + Message = default, + IsError = false + }; + + var responseData = await GetResponseDataAsync(chatServiceSettings, settings, token); + if (responseData is null) + { + result.Message = "Response data is empty."; + result.IsError = true; + } + else if (responseData is ChatResponseError error) + { + var message = error.Error?.Message; + result.Message = message ?? "Response error."; + result.IsError = true; + } + else if (responseData is ChatResponseSuccess success) + { + var choice = success.Choices?.FirstOrDefault(); + var message = choice?.Message?.Content?.Trim(); + result.Message = message; + result.IsError = false; + + if (choice is { } && choice.Message?.FunctionCall is { } functionCall) + { + var arguments = functionCall.Arguments is { } + ? _chatSerializer?.Deserialize>(functionCall.Arguments) + : null; + + result.FunctionCall = new () + { + Name = functionCall.Name, + Arguments = arguments + }; + } + } + + return result; + } + + private async Task GetResponseDataAsync(ChatServiceSettings chatServiceSettings, ChatSettingsViewModel chatSettings, CancellationToken token) + { + if (_chatService is null) + { + return new ChatResponseError + { + Error = new ChatError + { + Message = "Cant locate chat service." + } + }; + } + + // API Key + + var apiKey = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiKey); + var restoreApiKey = !string.IsNullOrWhiteSpace(chatSettings.ApiKey); + + if (chatServiceSettings.RequireApiKey) + { + if (string.IsNullOrWhiteSpace(chatSettings.ApiKey) && string.IsNullOrEmpty(apiKey)) + { + return new ChatResponseError + { + Error = new ChatError {Message = "The OpenAI api key is not set."} + }; + } + } + + // API Model + + var apiModel = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiModel); + var restoreApiModel = !string.IsNullOrWhiteSpace(chatSettings.Model); + + if (string.IsNullOrWhiteSpace(chatSettings.Model) && string.IsNullOrEmpty(apiModel)) + { + return new ChatResponseError + { + Error = new ChatError {Message = "The OpenAI api model is not set."} + }; + } + + // Settings + + if (restoreApiKey) + { + Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiKey, chatSettings.ApiKey); + } + + if (restoreApiModel) + { + Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiModel, chatSettings.Model); + } + + // Get + + ChatResponse? responseData; + + try + { + responseData = await _chatService.GetResponseDataAsync(chatServiceSettings, token); + } + catch (Exception e) + { + responseData = new ChatResponseError() + { + Error = new ChatError + { + Message = $"{e}" + } + }; + } + + if (restoreApiKey && !string.IsNullOrWhiteSpace(apiKey)) + { + Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiKey, apiKey); + } + + if (restoreApiModel && !string.IsNullOrWhiteSpace(apiModel)) + { + Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiModel, apiModel); + } + + return responseData; + } + public void SetMessageActions(ChatMessageViewModel message) { message.SetSendAction(SendAsync); @@ -119,7 +285,12 @@ public void SetMessageActions(ChatMessageViewModel message) public async Task CopyAsync(ChatMessageViewModel message) { - var app = Defaults.Locator.GetService(); + // TODO: + await Task.Yield(); + + // TODO: + /* + var app = Ioc.Locator.GetService(); if (app is { }) { if (message.Message is { } text) @@ -127,6 +298,7 @@ public async Task CopyAsync(ChatMessageViewModel message) await app.SetClipboardTextAsync(text); } } + */ } public void Remove(ChatMessageViewModel message) @@ -256,7 +428,7 @@ public async Task SendAsync(ChatMessageViewModel sendMessage, bool onlyAdd // Response - var result = await SendAsync(messages, token); + var result = await this.SendAsync(messages, token); // Update @@ -323,159 +495,6 @@ public ChatMessage[] CreateChatMessages() return chatMessages.ToArray(); } - private static async Task GetResponseDataAsync(ChatServiceSettings chatServiceSettings, ChatSettingsViewModel chatSettings, CancellationToken token) - { - var chat = Defaults.Locator.GetService(); - if (chat is null) - { - return new ChatResponseError - { - Error = new ChatError - { - Message = "Cant locate chat service." - } - }; - } - - // API Key - - var apiKey = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiKey); - var restoreApiKey = !string.IsNullOrWhiteSpace(chatSettings.ApiKey); - - if (chatServiceSettings.RequireApiKey) - { - if (string.IsNullOrWhiteSpace(chatSettings.ApiKey) && string.IsNullOrEmpty(apiKey)) - { - return new ChatResponseError - { - Error = new ChatError {Message = "The OpenAI api key is not set."} - }; - } - } - - // API Model - - var apiModel = Environment.GetEnvironmentVariable(Constants.EnvironmentVariableApiModel); - var restoreApiModel = !string.IsNullOrWhiteSpace(chatSettings.Model); - - if (string.IsNullOrWhiteSpace(chatSettings.Model) && string.IsNullOrEmpty(apiModel)) - { - return new ChatResponseError - { - Error = new ChatError {Message = "The OpenAI api model is not set."} - }; - } - - // Settings - - if (restoreApiKey) - { - Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiKey, chatSettings.ApiKey); - } - - if (restoreApiModel) - { - Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiModel, chatSettings.Model); - } - - // Get - - ChatResponse? responseData; - - try - { - responseData = await chat.GetResponseDataAsync(chatServiceSettings, token); - } - catch (Exception e) - { - responseData = new ChatResponseError() - { - Error = new ChatError - { - Message = $"{e}" - } - }; - } - - if (restoreApiKey && !string.IsNullOrWhiteSpace(apiKey)) - { - Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiKey, apiKey); - } - - if (restoreApiModel && !string.IsNullOrWhiteSpace(apiModel)) - { - Environment.SetEnvironmentVariable(Constants.EnvironmentVariableApiModel, apiModel); - } - - return responseData; - } - - public async Task SendAsync(ChatMessage[] messages, CancellationToken token) - { - if (Settings is null) - { - return default; - } - - var chatServiceSettings = new ChatServiceSettings - { - Model = Settings.Model, - Messages = messages, - Functions = Settings.Functions, - FunctionCall = Settings.FunctionCall, - Suffix = null, - Temperature = Settings.Temperature, - MaxTokens = Settings.MaxTokens, - TopP = 1.0m, - Stop = null, - ApiUrl = Settings.ApiUrl, - Debug = Debug, - RequireApiKey = RequireApiKey, - }; - - var result = new ChatResultViewModel - { - Message = default, - IsError = false - }; - - var responseData = await GetResponseDataAsync(chatServiceSettings, Settings, token); - if (responseData is null) - { - result.Message = "Response data is empty."; - result.IsError = true; - } - else if (responseData is ChatResponseError error) - { - var message = error.Error?.Message; - result.Message = message ?? "Response error."; - result.IsError = true; - } - else if (responseData is ChatResponseSuccess success) - { - var choice = success.Choices?.FirstOrDefault(); - var message = choice?.Message?.Content?.Trim(); - result.Message = message; - result.IsError = false; - - if (choice is { } && choice.Message?.FunctionCall is { } functionCall) - { - var serializer = Defaults.Locator.GetService(); - var arguments = functionCall.Arguments is { } - ? serializer?.Deserialize>(functionCall.Arguments) - : null; - - result.FunctionCall = new () - { - Name = functionCall.Name, - Arguments = arguments - }; - } - } - - return result; - } - public ChatViewModel AddSystemMessage(string? message) { Messages.Add(new ChatMessageViewModel @@ -540,7 +559,7 @@ private ObservableCollection CopyMessages(out ChatMessageV public ChatViewModel Copy() { - return new ChatViewModel + return new ChatViewModel(_chatService, _chatSerializer) { Name = _name, Settings = _settings?.Copy(), diff --git a/src/ChatGPT.Core/ViewModels/Chat/ChatViewModelExtensions.cs b/src/ChatGPT.Core/ViewModels/Chat/ChatViewModelExtensions.cs new file mode 100644 index 00000000..4ac14eab --- /dev/null +++ b/src/ChatGPT.Core/ViewModels/Chat/ChatViewModelExtensions.cs @@ -0,0 +1,15 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using AI; +using AI.Model.Json.Chat; +using AI.Model.Services; + +namespace ChatGPT.ViewModels.Chat; + +public static class ChatViewModelExtensions +{ + +} diff --git a/src/ChatGPT.Core/ViewModels/MainViewModelJsonContext.cs b/src/ChatGPT.Core/ViewModels/CoreJsonContext.cs similarity index 88% rename from src/ChatGPT.Core/ViewModels/MainViewModelJsonContext.cs rename to src/ChatGPT.Core/ViewModels/CoreJsonContext.cs index e963ee65..40aba4b5 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModelJsonContext.cs +++ b/src/ChatGPT.Core/ViewModels/CoreJsonContext.cs @@ -15,7 +15,6 @@ namespace ChatGPT.ViewModels; [JsonSerializable(typeof(ObservableCollection))] [JsonSerializable(typeof(ChatSettingsViewModel))] [JsonSerializable(typeof(ObservableCollection))] -[JsonSerializable(typeof(MainViewModel))] [JsonSerializable(typeof(PromptViewModel))] [JsonSerializable(typeof(ObservableCollection))] [JsonSerializable(typeof(LayoutViewModel))] @@ -23,9 +22,9 @@ namespace ChatGPT.ViewModels; [JsonSerializable(typeof(DesktopLayoutViewModel))] [JsonSerializable(typeof(ObservableCollection))] [JsonSerializable(typeof(WorkspaceViewModel))] -public partial class MainViewModelJsonContext : JsonSerializerContext +public partial class CoreJsonContext : JsonSerializerContext { - public static readonly MainViewModelJsonContext s_instance = new( + public static readonly CoreJsonContext s_instance = new( new JsonSerializerOptions { WriteIndented = true, diff --git a/src/ChatGPT.UI.Android/MainActivity.cs b/src/ChatGPT.UI.Android/MainActivity.cs index 1ebd9fc2..1f932979 100644 --- a/src/ChatGPT.UI.Android/MainActivity.cs +++ b/src/ChatGPT.UI.Android/MainActivity.cs @@ -37,8 +37,6 @@ protected override void OnDestroy() protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) { - App.ConfigureMobileServices(); - builder.WithInterFont(); return base.CustomizeAppBuilder(builder); diff --git a/src/ChatGPT.UI.Browser/Program.cs b/src/ChatGPT.UI.Browser/Program.cs index e87d54c3..1abe8c5b 100644 --- a/src/ChatGPT.UI.Browser/Program.cs +++ b/src/ChatGPT.UI.Browser/Program.cs @@ -4,16 +4,13 @@ using AI.Services; using Avalonia; using Avalonia.Browser; -using Avalonia.Fonts.Inter; -using ChatGPT.Model.Plugins; using ChatGPT.Model.Services; using ChatGPT.Services; -using ChatGPT.UI.Browser.Services; using ChatGPT.ViewModels; using ChatGPT.ViewModels.Chat; using ChatGPT.ViewModels.Layouts; using ChatGPT.ViewModels.Settings; -using Microsoft.Extensions.DependencyInjection; +using CommunityToolkit.Mvvm.DependencyInjection; [assembly:SupportedOSPlatform("browser")] @@ -27,35 +24,5 @@ private static async Task Main(string[] args) public static AppBuilder BuildAvaloniaApp() => AppBuilder .Configure() - .WithInterFont() - .AfterSetup(_ => - { - ConfigureDefaultServices(); - }); - - private static void ConfigureDefaultServices() - { - IServiceCollection serviceCollection = new ServiceCollection(); - - // Services - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(x => x.GetRequiredService()); - - // ViewModels - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - Defaults.Locator.ConfigureServices(serviceCollection.BuildServiceProvider()); - } + .WithInterFont(); } diff --git a/src/ChatGPT.UI.Desktop/Program.cs b/src/ChatGPT.UI.Desktop/Program.cs index a26b2224..a1c02f42 100644 --- a/src/ChatGPT.UI.Desktop/Program.cs +++ b/src/ChatGPT.UI.Desktop/Program.cs @@ -1,6 +1,5 @@ using Avalonia; using System; -using Avalonia.Fonts.Inter; namespace ChatGPT; @@ -23,10 +22,6 @@ public static void Main(string[] args) public static AppBuilder BuildAvaloniaApp() => AppBuilder .Configure() - .AfterSetup(_ => - { - App.ConfigureDesktopServices(); - }) .WithInterFont() .UsePlatformDetect() .LogToTrace(); diff --git a/src/ChatGPT.UI.iOS/AppDelegate.cs b/src/ChatGPT.UI.iOS/AppDelegate.cs index c0a1b5a1..8aa755f4 100644 --- a/src/ChatGPT.UI.iOS/AppDelegate.cs +++ b/src/ChatGPT.UI.iOS/AppDelegate.cs @@ -1,5 +1,4 @@ using Avalonia; -using Avalonia.Fonts.Inter; using Avalonia.iOS; using Foundation; @@ -13,8 +12,6 @@ public class AppDelegate : AvaloniaAppDelegate { protected override AppBuilder CustomizeAppBuilder(AppBuilder builder) { - App.ConfigureMobileServices(); - builder.WithInterFont(); return base.CustomizeAppBuilder(builder); diff --git a/src/ChatGPT.UI/App.axaml.cs b/src/ChatGPT.UI/App.axaml.cs index 3d6ebbb1..d16df14f 100644 --- a/src/ChatGPT.UI/App.axaml.cs +++ b/src/ChatGPT.UI/App.axaml.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using System.Runtime.InteropServices; using System.Threading.Tasks; using AI.Model.Services; using AI.Services; @@ -9,85 +10,61 @@ using Avalonia.Markup.Xaml; using Avalonia.Platform; using Avalonia.Styling; -using ChatGPT.Model.Plugins; using ChatGPT.Model.Services; -using ChatGPT.Plugins; using ChatGPT.Services; using ChatGPT.ViewModels; -using ChatGPT.ViewModels.Chat; using ChatGPT.ViewModels.Layouts; -using ChatGPT.ViewModels.Settings; using ChatGPT.Views; -using Microsoft.Extensions.DependencyInjection; +using CommunityToolkit.Mvvm.DependencyInjection; namespace ChatGPT; public partial class App : Application { // private IDisposable? _settingsDisposable; + private readonly IChatSerializer _chatSerializer; + private readonly IChatService _chatService; + private readonly IStorageFactory _storageFactory; + private readonly IApplicationService _applicationService; + private readonly MainViewModel _mainViewModel; public App() { - } + _chatSerializer = new SystemTextJsonChatSerializer(); + _chatService = new ChatService(_chatSerializer); - public static void ConfigureDesktopServices() - { - IServiceCollection serviceCollection = new ServiceCollection(); - - // Services - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(x => x.GetRequiredService()); - - // ViewModels - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - // Plugins - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - Defaults.Locator.ConfigureServices(serviceCollection.BuildServiceProvider()); - } + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + || RuntimeInformation.IsOSPlatform(OSPlatform.OSX) + || RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + _storageFactory = new ApplicationDataStorageFactory(); + _applicationService = new ApplicationService(); + } + else if (IsOSPlatform("ANDROID") + || IsOSPlatform("IOS")) + { + _storageFactory = new IsolatedStorageFactory(); + _applicationService = new ApplicationService(); + } + else if (IsOSPlatform("BROWSER")) + { + _storageFactory = new BrowserStorageFactory(); + _applicationService = new ApplicationService(); + } + else + { + _storageFactory = new IsolatedStorageFactory(); + _applicationService = new ApplicationService(); + } - public static void ConfigureMobileServices() - { - IServiceCollection serviceCollection = new ServiceCollection(); - - // Services - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(x => x.GetRequiredService()); - - // ViewModels - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - // Plugins - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - Defaults.Locator.ConfigureServices(serviceCollection.BuildServiceProvider()); + _mainViewModel = new MainViewModel( + _chatService, + _chatSerializer, + _applicationService, + _storageFactory); + + static bool IsOSPlatform(string platform) + => RuntimeInformation.IsOSPlatform(OSPlatform.Create(platform)); } public override void Initialize() @@ -97,13 +74,11 @@ public override void Initialize() public override async void OnFrameworkInitializationCompleted() { - Defaults.Locator.GetService()?.DiscoverPlugins(); - if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) { var mainWindow = new MainWindow { - DataContext = Defaults.Locator.GetService() + DataContext = _mainViewModel }; desktop.MainWindow = mainWindow; @@ -115,16 +90,12 @@ public override async void OnFrameworkInitializationCompleted() await InitSettingsAsync(); SetTheme(); - - // TODO: Enable plugins. - Defaults.Locator.GetService()?.InitPlugins(); - // Defaults.Locator.GetService()?.StartPlugins(); } else if (ApplicationLifetime is ISingleViewApplicationLifetime single) { single.MainView = new MainView { - DataContext = Defaults.Locator.GetService() + DataContext = _mainViewModel }; await InitSettingsAsync(); @@ -158,8 +129,7 @@ private async Task InitSettingsAsync() private void SetTheme() { - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel?.Theme is { } theme) + if (_mainViewModel?.Theme is { } theme) { switch (theme) { @@ -175,8 +145,7 @@ private void SetTheme() public async Task LoadWindowLayoutAsync(Window window) { - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is null) { return; @@ -225,8 +194,7 @@ public async Task SaveWindowLayoutAsync(Window window) Topmost = window.Topmost }; - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is { }) { await storage.SaveObjectAsync( @@ -249,8 +217,6 @@ private void DesktopOnExit(object? sender, ControlledApplicationLifetimeExitEven try { // _settingsDisposable?.Dispose(); - - Defaults.Locator.GetService()?.ShutdownPlugins(); SaveTheme(); SaveSettings(); @@ -263,44 +229,41 @@ private void DesktopOnExit(object? sender, ControlledApplicationLifetimeExitEven public async Task LoadSettingsAsync() { - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel is null) + if (_mainViewModel is null) { return; } - await mainViewModel.LoadSettingsAsync(); + await _mainViewModel.LoadSettingsAsync(); } public async Task SaveSettingsAsync() { - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel is null) + if (_mainViewModel is null) { return; } - await mainViewModel.SaveSettingsAsync(); + await _mainViewModel.SaveSettingsAsync(); } public void LoadSettings() { - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel is null) + if (_mainViewModel is null) { return; } - mainViewModel.LoadSettings(); + + _mainViewModel.LoadSettings(); } public void SaveSettings() { - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel is null) + if (_mainViewModel is null) { return; } - mainViewModel.SaveSettings(); + _mainViewModel.SaveSettings(); } public void SaveTheme() @@ -311,10 +274,9 @@ public void SaveTheme() theme = "Dark"; } - var mainViewModel = Defaults.Locator.GetService(); - if (mainViewModel is { }) + if (_mainViewModel is { }) { - mainViewModel.Theme = theme; + _mainViewModel.Theme = theme; } } @@ -383,10 +345,9 @@ private void ToggleAcrylic_OnClick(object? sender, EventArgs e) private void Quit_OnClick(object? sender, EventArgs e) { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - app.Exit(); + _applicationService.Exit(); } } } diff --git a/src/ChatGPT.UI/ChatGPT.UI.csproj b/src/ChatGPT.UI/ChatGPT.UI.csproj index f4ccaab5..50930ad1 100644 --- a/src/ChatGPT.UI/ChatGPT.UI.csproj +++ b/src/ChatGPT.UI/ChatGPT.UI.csproj @@ -5,6 +5,7 @@ enable true ChatGPT + true ChatGPT.UI @@ -19,10 +20,6 @@ - - - - diff --git a/src/ChatGPT.UI/Plugins/ClipboardListenerChatPlugin.cs b/src/ChatGPT.UI/Plugins/ClipboardListenerChatPlugin.cs deleted file mode 100644 index d9f0bfa3..00000000 --- a/src/ChatGPT.UI/Plugins/ClipboardListenerChatPlugin.cs +++ /dev/null @@ -1,190 +0,0 @@ -using System; -using System.Collections.Concurrent; -using System.Linq; -using System.Threading; -using System.Threading.Tasks; -using Avalonia; -using Avalonia.Controls.ApplicationLifetimes; -using ChatGPT.Model.Plugins; - -namespace ChatGPT.Plugins; - -public class ClipboardListenerChatPlugin : IChatPlugin -{ - private IPluginContext? _context; - private CancellationTokenSource? _cts; - private bool _sync; - private string? _text; - private readonly ConcurrentQueue _queue = new(); - private bool _skipFirst = true; - - public string Id => "ClipboardListener"; - - public string Name => "Clipboard Listener"; - - public async Task StartAsync() - { - Run(); - - await Task.Yield(); - } - - public async Task StopAsync() - { - Cancel(); - - await Task.Yield(); - } - - public async Task InitializeAsync(IPluginContext context) - { - _context = context; - - await Task.Yield(); - } - - public async Task ShutdownAsync() - { - Cancel(); - - await Task.Yield(); - } - - private void Run() - { - if (_cts is not null) - { - return; - } - - _cts = new CancellationTokenSource(); - -#pragma warning disable CS4014 - Task.Run(async () => -#pragma warning restore CS4014 - { - await RunTaskPeriodicallyAsync( - _cts.Token, - CheckClipboardTextAsync, - TimeSpan.FromMilliseconds(20)); - }); - -#pragma warning disable CS4014 - Task.Run(async () => -#pragma warning restore CS4014 - { - await RunTaskPeriodicallyAsync( - _cts.Token, - RunSendPeriodicallyAsync, - TimeSpan.FromMilliseconds(20)); - }); - } - - private void Cancel() - { - _cts?.Cancel(); - _cts = null; - } - - private async Task RunTaskPeriodicallyAsync(CancellationToken ct, Func func, TimeSpan interval) - { - while (true) - { - if (ct.IsCancellationRequested) - { - break; - } - await func(ct); - await Task.Delay(interval, ct); - } - } - - private async Task CheckClipboardTextAsync(CancellationToken ct) - { - if (_sync) - { - return; - } - - _sync = true; - - if (Application.Current?.ApplicationLifetime is IClassicDesktopStyleApplicationLifetime lifetime - && lifetime.MainWindow is { } mainWindow - && mainWindow.Clipboard is { } clipboard) - { - var text = await clipboard.GetTextAsync(); - if (!string.IsNullOrEmpty(text) && _text != text) - { - _text = text; - - if (_skipFirst) - { - _skipFirst = false; - } - else - { - // Console.WriteLine($"[Clipboard] {text}"); - _queue.Enqueue(text); - } - } - } - - _sync = false; - } - - private async Task RunSendPeriodicallyAsync(CancellationToken ct) - { - if (_context is null) - { - return; - } - - while (true) - { - if (ct.IsCancellationRequested) - { - break; - } - - if (_queue.TryDequeue(out var text)) - { - // Console.WriteLine($"[Send] {text}"); - await Send(text); - } - } - } - - private async Task Send(string prompt) - { - if (_context is null) - { - return; - } - - if (_context.CurrentChat is {} chat) - { - // var message = new ChatMessageViewModel - // { - // Prompt = prompt, - // Message = "Clipboard", - // Format = chat.Settings?.Format ?? Defaults.TextMessageFormat, - // IsSent = false, - // CanRemove = true - // }; - // chat.SetMessageActions(message); - // chat.Messages.Add(message); - // chat.CurrentMessage = message; - // await chat.Send(message); - - // Console.WriteLine($"[InsertPrompt] {prompt}, {chat.CurrentMessage}"); - - var message = chat.CurrentMessage ?? chat.Messages.LastOrDefault(); - if (message is { }) - { - message.Role = "user"; - message.Message = prompt; - await chat.SendAsync(message, true); - } - } - } -} diff --git a/src/ChatGPT.UI.Browser/Services/BrowserStorageFactory.cs b/src/ChatGPT.UI/Services/BrowserStorageFactory.cs similarity index 82% rename from src/ChatGPT.UI.Browser/Services/BrowserStorageFactory.cs rename to src/ChatGPT.UI/Services/BrowserStorageFactory.cs index cbaf68a3..bd3e5390 100644 --- a/src/ChatGPT.UI.Browser/Services/BrowserStorageFactory.cs +++ b/src/ChatGPT.UI/Services/BrowserStorageFactory.cs @@ -1,6 +1,6 @@ using ChatGPT.Model.Services; -namespace ChatGPT.UI.Browser.Services; +namespace ChatGPT.Services; public class BrowserStorageFactory : IStorageFactory { diff --git a/src/ChatGPT.UI.Browser/Services/BrowserStorageService.cs b/src/ChatGPT.UI/Services/BrowserStorageService.cs similarity index 98% rename from src/ChatGPT.UI.Browser/Services/BrowserStorageService.cs rename to src/ChatGPT.UI/Services/BrowserStorageService.cs index 5cc4e369..abb163ca 100644 --- a/src/ChatGPT.UI.Browser/Services/BrowserStorageService.cs +++ b/src/ChatGPT.UI/Services/BrowserStorageService.cs @@ -8,7 +8,7 @@ using System.Threading.Tasks; using ChatGPT.Model.Services; -namespace ChatGPT.UI.Browser.Services; +namespace ChatGPT.Services; public partial class BrowserStorageService : IStorageService { diff --git a/src/ChatGPT.Core/ViewModels/MainViewModel.Actions.cs b/src/ChatGPT.UI/ViewModels/MainViewModel.Actions.cs similarity index 92% rename from src/ChatGPT.Core/ViewModels/MainViewModel.Actions.cs rename to src/ChatGPT.UI/ViewModels/MainViewModel.Actions.cs index 1024528f..8cef8a2a 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModel.Actions.cs +++ b/src/ChatGPT.UI/ViewModels/MainViewModel.Actions.cs @@ -2,6 +2,7 @@ using System.Text.Json.Serialization; using ChatGPT.Model.Services; using ChatGPT.ViewModels.Layouts; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; namespace ChatGPT.ViewModels; @@ -80,16 +81,14 @@ public bool Topmost private void ExitAction() { - var app = Defaults.Locator.GetService(); - app?.Exit(); + _applicationService?.Exit(); } private void ChangeThemeAction() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - app.ToggleTheme(); + _applicationService.ToggleTheme(); } } diff --git a/src/ChatGPT.Core/ViewModels/MainViewModel.Chats.cs b/src/ChatGPT.UI/ViewModels/MainViewModel.Chats.cs similarity index 89% rename from src/ChatGPT.Core/ViewModels/MainViewModel.Chats.cs rename to src/ChatGPT.UI/ViewModels/MainViewModel.Chats.cs index b381f2b9..368ae47f 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModel.Chats.cs +++ b/src/ChatGPT.UI/ViewModels/MainViewModel.Chats.cs @@ -7,8 +7,10 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; using AI.Model.Json.ChatGPT; +using AI.Model.Services; using ChatGPT.Model.Services; using ChatGPT.ViewModels.Chat; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; namespace ChatGPT.ViewModels; @@ -86,10 +88,9 @@ private async Task DeleteChatActionAsync() private async Task OpenChatActionAsync() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - await app.OpenFileAsync( + await _applicationService.OpenFileAsync( OpenChatCallbackAsync, new List(new[] { "Json", "All" }), "Open"); @@ -98,10 +99,9 @@ await app.OpenFileAsync( private async Task SaveChatActionAsync() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentChat is { }) + if (_applicationService is { } && CurrentChat is { }) { - await app.SaveFileAsync( + await _applicationService.SaveFileAsync( SaveChatCallbackAsync, new List(new[] { "Json", "All" }), "Save", @@ -112,10 +112,9 @@ await app.SaveFileAsync( private async Task ExportChatActionAsync() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentChat is { }) + if (_applicationService is { } && CurrentChat is { }) { - await app.SaveFileAsync( + await _applicationService.SaveFileAsync( ExportChatCallbackAsync, new List(new[] { "Text", "All" }), "Export", @@ -126,8 +125,7 @@ await app.SaveFileAsync( private async Task CopyChatActionAsync() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentChat is { }) + if (_applicationService is { } && CurrentChat is { }) { var sb = new StringBuilder(); #if NETFRAMEWORK @@ -136,7 +134,7 @@ private async Task CopyChatActionAsync() await using var writer = new StringWriter(sb); #endif await ExportChatAsync(CurrentChat, writer); - await app.SetClipboardTextAsync(sb.ToString()); + await _applicationService.SetClipboardTextAsync(sb.ToString()); } } @@ -157,10 +155,9 @@ private void DefaultChatSettingsAction() private async Task ImportGptChatsActionAsync() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - await app.OpenFileAsync( + await _applicationService.OpenFileAsync( ImportGptChatsCallbackAsync, new List(new[] { "Json", "All" }), "Import"); @@ -169,7 +166,7 @@ await app.OpenFileAsync( private void NewChatCallback() { - var chat = new ChatViewModel + var chat = new ChatViewModel(_chatService, _chatSerializer) { Name = "Chat", Settings = CurrentChat?.Settings?.Copy() ?? CreateDefaultChatSettings() @@ -216,7 +213,7 @@ private async Task OpenChatCallbackAsync(Stream stream) { var chat = await JsonSerializer.DeserializeAsync( stream, - MainViewModelJsonContext.s_instance.ChatViewModel); + CoreJsonContext.s_instance.ChatViewModel); if (chat is { }) { foreach (var message in chat.Messages) @@ -239,7 +236,7 @@ private async Task SaveChatCallbackAsync(Stream stream) await JsonSerializer.SerializeAsync( stream, CurrentChat, - MainViewModelJsonContext.s_instance.ChatViewModel); + CoreJsonContext.s_instance.ChatViewModel); } private async Task ExportChatCallbackAsync(Stream stream) diff --git a/src/ChatGPT.Core/ViewModels/MainViewModel.Import.cs b/src/ChatGPT.UI/ViewModels/MainViewModel.Import.cs similarity index 94% rename from src/ChatGPT.Core/ViewModels/MainViewModel.Import.cs rename to src/ChatGPT.UI/ViewModels/MainViewModel.Import.cs index 1dec4461..358787b4 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModel.Import.cs +++ b/src/ChatGPT.UI/ViewModels/MainViewModel.Import.cs @@ -7,8 +7,10 @@ using System.Text.Json.Serialization; using System.Threading.Tasks; using AI.Model.Json.ChatGPT; +using AI.Model.Services; using ChatGPT.Model.Services; using ChatGPT.ViewModels.Chat; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; namespace ChatGPT.ViewModels; @@ -21,7 +23,7 @@ private void ImportChats(ChatGpt[] gptChats) foreach (var gptChat in gptChats.Reverse()) { - var chat = new ChatViewModel() + var chat = new ChatViewModel(_chatService, _chatSerializer) { Name = gptChat.Title, Settings = CreateDefaultChatSettings() diff --git a/src/ChatGPT.Core/ViewModels/MainViewModel.Prompts.cs b/src/ChatGPT.UI/ViewModels/MainViewModel.Prompts.cs similarity index 89% rename from src/ChatGPT.Core/ViewModels/MainViewModel.Prompts.cs rename to src/ChatGPT.UI/ViewModels/MainViewModel.Prompts.cs index 1f7d006c..5070a94d 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModel.Prompts.cs +++ b/src/ChatGPT.UI/ViewModels/MainViewModel.Prompts.cs @@ -7,6 +7,7 @@ using System.Threading.Tasks; using ChatGPT.Model.Services; using ChatGPT.ViewModels.Settings; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; using Microsoft.VisualBasic.FileIO; @@ -90,10 +91,9 @@ private async Task DeletePromptAction() private async Task OpenPromptsAction() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - await app.OpenFileAsync( + await _applicationService.OpenFileAsync( OpenPromptsCallbackAsync, new List(new[] { "Json", "All" }), "Open"); @@ -102,10 +102,9 @@ await app.OpenFileAsync( private async Task SavePromptsAction() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentChat is { }) + if (_applicationService is { } && CurrentChat is { }) { - await app.SaveFileAsync( + await _applicationService.SaveFileAsync( SavePromptsCallbackAsync, new List(new[] { "Json", "All" }), "Save", @@ -116,10 +115,9 @@ await app.SaveFileAsync( private async Task ImportPromptsAction() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - await app.OpenFileAsync( + await _applicationService.OpenFileAsync( ImportPromptsCallbackAsync, new List(new[] { "Csv", "All" }), "Import"); @@ -128,10 +126,9 @@ await app.OpenFileAsync( private async Task CopyPromptAction() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentPrompt?.Prompt is { }) + if (_applicationService is { } && CurrentPrompt?.Prompt is { }) { - await app.SetClipboardTextAsync(CurrentPrompt.Prompt); + await _applicationService.SetClipboardTextAsync(CurrentPrompt.Prompt); } } @@ -182,7 +179,7 @@ private async Task OpenPromptsCallbackAsync(Stream stream) { var prompts = await JsonSerializer.DeserializeAsync( stream, - MainViewModelJsonContext.s_instance.ObservableCollectionPromptViewModel); + CoreJsonContext.s_instance.ObservableCollectionPromptViewModel); if (prompts is { }) { foreach (var prompt in prompts) @@ -197,7 +194,7 @@ private async Task SavePromptsCallbackAsync(Stream stream) await JsonSerializer.SerializeAsync( stream, Prompts, - MainViewModelJsonContext.s_instance.ObservableCollectionPromptViewModel); + CoreJsonContext.s_instance.ObservableCollectionPromptViewModel); } private async Task ImportPromptsCallbackAsync(Stream stream) diff --git a/src/ChatGPT.Core/ViewModels/MainViewModel.cs b/src/ChatGPT.UI/ViewModels/MainViewModel.cs similarity index 79% rename from src/ChatGPT.Core/ViewModels/MainViewModel.cs rename to src/ChatGPT.UI/ViewModels/MainViewModel.cs index e21af959..b43b29df 100644 --- a/src/ChatGPT.Core/ViewModels/MainViewModel.cs +++ b/src/ChatGPT.UI/ViewModels/MainViewModel.cs @@ -4,20 +4,35 @@ using System.Linq; using System.Text.Json; using System.Threading.Tasks; -using ChatGPT.Model.Plugins; +using AI.Model.Services; using ChatGPT.Model.Services; using ChatGPT.ViewModels.Chat; using ChatGPT.ViewModels.Layouts; using ChatGPT.ViewModels.Settings; using CommunityToolkit.Mvvm.ComponentModel; +using CommunityToolkit.Mvvm.DependencyInjection; using CommunityToolkit.Mvvm.Input; namespace ChatGPT.ViewModels; -public partial class MainViewModel : ObservableObject, IPluginContext +public partial class MainViewModel : ObservableObject { - public MainViewModel() + private readonly IChatService _chatService; + private readonly IChatSerializer _chatSerializer; + private readonly IApplicationService _applicationService; + private readonly IStorageFactory _storageFactory; + + public MainViewModel( + IChatService chatService, + IChatSerializer chatSerializer, + IApplicationService applicationService, + IStorageFactory storageFactory) { + _chatService = chatService; + _chatSerializer = chatSerializer; + _applicationService = applicationService; + _storageFactory = storageFactory; + _chats = new ObservableCollection(); _prompts = new ObservableCollection(); @@ -94,10 +109,9 @@ public MainViewModel() private async Task LoadWorkspaceAction() { - var app = Defaults.Locator.GetService(); - if (app is { }) + if (_applicationService is { }) { - await app.OpenFileAsync( + await _applicationService.OpenFileAsync( LoadWorkspaceCallbackAsync, new List(new[] { "Json", "All" }), "Open"); @@ -111,10 +125,9 @@ private async Task SaveWorkspaceAction() private async Task ExportWorkspaceAction() { - var app = Defaults.Locator.GetService(); - if (app is { } && CurrentChat is { }) + if (_applicationService is { } && CurrentChat is { }) { - await app.SaveFileAsync( + await _applicationService.SaveFileAsync( ExportWorkspaceCallbackAsync, new List(new[] { "Json", "All" }), "Export", @@ -127,7 +140,7 @@ private async Task LoadWorkspaceCallbackAsync(Stream stream) { var workspace = await JsonSerializer.DeserializeAsync( stream, - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); if (workspace is { }) { LoadWorkspace(workspace); @@ -140,7 +153,7 @@ private async Task ExportWorkspaceCallbackAsync(Stream stream) await JsonSerializer.SerializeAsync( stream, workspace, - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); } private WorkspaceViewModel CreateWorkspace() @@ -199,15 +212,14 @@ private void LoadWorkspace(WorkspaceViewModel workspace) public async Task LoadSettingsAsync() { - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is null) { return; } var workspace = await storage.LoadObjectAsync( "Settings", - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); if (workspace is { }) { LoadWorkspace(workspace); @@ -217,28 +229,26 @@ public async Task LoadSettingsAsync() public async Task SaveSettingsAsync() { var workspace = CreateWorkspace(); - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is { }) { await storage.SaveObjectAsync( workspace, "Settings", - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); } } public void LoadSettings() { - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is null) { return; } var workspace = storage.LoadObject( "Settings", - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); if (workspace is { }) { LoadWorkspace(workspace); @@ -248,14 +258,13 @@ public void LoadSettings() public void SaveSettings() { var workspace = CreateWorkspace(); - var factory = Defaults.Locator.GetService(); - var storage = factory?.CreateStorageService(); + var storage = _storageFactory?.CreateStorageService(); if (storage is { }) { storage.SaveObject( workspace, "Settings", - MainViewModelJsonContext.s_instance.WorkspaceViewModel); + CoreJsonContext.s_instance.WorkspaceViewModel); } } } diff --git a/src/ChatGPT.UI/Views/History/HistoryActionsView.axaml b/src/ChatGPT.UI/Views/History/HistoryActionsView.axaml index b6c215d4..02b3c8ab 100644 --- a/src/ChatGPT.UI/Views/History/HistoryActionsView.axaml +++ b/src/ChatGPT.UI/Views/History/HistoryActionsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="450" x:Class="ChatGPT.Views.History.HistoryActionsView" x:CompileBindings="True" x:DataType="vm:MainViewModel"> diff --git a/src/ChatGPT.UI/Views/History/HistoryView.axaml b/src/ChatGPT.UI/Views/History/HistoryView.axaml index c64556cf..e110e849 100644 --- a/src/ChatGPT.UI/Views/History/HistoryView.axaml +++ b/src/ChatGPT.UI/Views/History/HistoryView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vmc="clr-namespace:ChatGPT.ViewModels.Chat;assembly=ChatGPT.Core" xmlns:history="clr-namespace:ChatGPT.Views.History" xmlns:views="clr-namespace:ChatGPT.Views" diff --git a/src/ChatGPT.UI/Views/Layouts/DesktopLayoutView.axaml b/src/ChatGPT.UI/Views/Layouts/DesktopLayoutView.axaml index e2abc4d2..98a0ea7b 100644 --- a/src/ChatGPT.UI/Views/Layouts/DesktopLayoutView.axaml +++ b/src/ChatGPT.UI/Views/Layouts/DesktopLayoutView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vmc="clr-namespace:ChatGPT.ViewModels.Chat;assembly=ChatGPT.Core" xmlns:vml="clr-namespace:ChatGPT.ViewModels.Layouts;assembly=ChatGPT.Core" xmlns:chat="clr-namespace:ChatGPT.Views.Chat" diff --git a/src/ChatGPT.UI/Views/Layouts/MobileLayoutView.axaml b/src/ChatGPT.UI/Views/Layouts/MobileLayoutView.axaml index b115a38a..1e2e39a4 100644 --- a/src/ChatGPT.UI/Views/Layouts/MobileLayoutView.axaml +++ b/src/ChatGPT.UI/Views/Layouts/MobileLayoutView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vmc="clr-namespace:ChatGPT.ViewModels.Chat;assembly=ChatGPT.Core" xmlns:vml="clr-namespace:ChatGPT.ViewModels.Layouts;assembly=ChatGPT.Core" xmlns:chat="clr-namespace:ChatGPT.Views.Chat" diff --git a/src/ChatGPT.UI/Views/MainView.axaml b/src/ChatGPT.UI/Views/MainView.axaml index dbca3226..cd4244e4 100644 --- a/src/ChatGPT.UI/Views/MainView.axaml +++ b/src/ChatGPT.UI/Views/MainView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vmc="clr-namespace:ChatGPT.ViewModels.Chat;assembly=ChatGPT.Core" xmlns:objectModel="clr-namespace:System.Collections.ObjectModel;assembly=System.ObjectModel" xmlns:converters="clr-namespace:ChatGPT.Converters" diff --git a/src/ChatGPT.UI/Views/MainViewActionsView.axaml b/src/ChatGPT.UI/Views/MainViewActionsView.axaml index a5fae1a4..0ed98e0f 100644 --- a/src/ChatGPT.UI/Views/MainViewActionsView.axaml +++ b/src/ChatGPT.UI/Views/MainViewActionsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:converters="clr-namespace:ChatGPT.Converters" mc:Ignorable="d" d:DesignWidth="400" d:DesignHeight="700" x:Class="ChatGPT.Views.MainViewActionsView" diff --git a/src/ChatGPT.UI/Views/MainWindow.axaml b/src/ChatGPT.UI/Views/MainWindow.axaml index 81fd7f29..88059985 100644 --- a/src/ChatGPT.UI/Views/MainWindow.axaml +++ b/src/ChatGPT.UI/Views/MainWindow.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:views="clr-namespace:ChatGPT.Views" mc:Ignorable="d" d:DesignWidth="450" d:DesignHeight="740" x:Class="ChatGPT.Views.MainWindow" diff --git a/src/ChatGPT.UI/Views/Prompts/PromptsActionsView.axaml b/src/ChatGPT.UI/Views/Prompts/PromptsActionsView.axaml index 47375d99..aee4731a 100644 --- a/src/ChatGPT.UI/Views/Prompts/PromptsActionsView.axaml +++ b/src/ChatGPT.UI/Views/Prompts/PromptsActionsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="450" x:Class="ChatGPT.Views.Prompts.PromptsActionsView" x:CompileBindings="True" x:DataType="vm:MainViewModel"> diff --git a/src/ChatGPT.UI/Views/Prompts/PromptsView.axaml b/src/ChatGPT.UI/Views/Prompts/PromptsView.axaml index 19ee719a..c2071621 100644 --- a/src/ChatGPT.UI/Views/Prompts/PromptsView.axaml +++ b/src/ChatGPT.UI/Views/Prompts/PromptsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vms="clr-namespace:ChatGPT.ViewModels.Settings;assembly=ChatGPT.Core" xmlns:promtps="clr-namespace:ChatGPT.Views.Prompts" xmlns:views="clr-namespace:ChatGPT.Views" diff --git a/src/ChatGPT.UI/Views/Settings/SettingsActionsView.axaml b/src/ChatGPT.UI/Views/Settings/SettingsActionsView.axaml index 63015420..8e4abdb8 100644 --- a/src/ChatGPT.UI/Views/Settings/SettingsActionsView.axaml +++ b/src/ChatGPT.UI/Views/Settings/SettingsActionsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" mc:Ignorable="d" d:DesignWidth="250" d:DesignHeight="450" x:Class="ChatGPT.Views.Settings.SettingsActionsView" x:CompileBindings="True" x:DataType="vm:MainViewModel"> diff --git a/src/ChatGPT.UI/Views/Settings/SettingsView.axaml b/src/ChatGPT.UI/Views/Settings/SettingsView.axaml index 026af949..47a14428 100644 --- a/src/ChatGPT.UI/Views/Settings/SettingsView.axaml +++ b/src/ChatGPT.UI/Views/Settings/SettingsView.axaml @@ -2,7 +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:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.Core" + xmlns:vm="clr-namespace:ChatGPT.ViewModels;assembly=ChatGPT.UI" xmlns:vmc="clr-namespace:ChatGPT.ViewModels.Chat;assembly=ChatGPT.Core" xmlns:chat="clr-namespace:ChatGPT.Views.Chat" xmlns:settings="clr-namespace:ChatGPT.Views.Settings" diff --git a/src/ChatGptCom/Chat.cs b/src/ChatGptCom/Chat.cs index cb2fec15..565d3ab8 100644 --- a/src/ChatGptCom/Chat.cs +++ b/src/ChatGptCom/Chat.cs @@ -1,13 +1,7 @@ using System.Runtime.InteropServices; -using AI.Model.Services; using AI.Services; -using ChatGPT; -using ChatGPT.Model.Services; -using ChatGPT.Services; using ChatGPT.ViewModels.Chat; -using ChatGPT.ViewModels.Settings; using ChatGptCom.Services; -using Microsoft.Extensions.DependencyInjection; namespace ChatGptCom; @@ -19,6 +13,8 @@ namespace ChatGptCom; public class Chat : IChat { private ChatViewModel? _chat; + private readonly NewtonsoftChatSerializer _chatSerializer; + private readonly ChatService _chatService; public delegate void SendCompletedDelegate(); @@ -26,23 +22,10 @@ public class Chat : IChat public string? Result { get; set; } - static Chat() + public Chat() { - IServiceCollection serviceCollection = new ServiceCollection(); - - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - serviceCollection.AddSingleton(); - - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - serviceCollection.AddTransient(); - - IServiceProvider serviceProvider = serviceCollection.BuildServiceProvider(); - - Defaults.Locator.ConfigureServices(serviceProvider); + _chatSerializer = new NewtonsoftChatSerializer(); + _chatService = new ChatService(_chatSerializer); } private async Task Send(ChatViewModel chat) @@ -60,11 +43,14 @@ private async Task Send(ChatViewModel chat) public void Create(string? directions, int maxTokens = 2000, string model = "gpt-3.5-turbo") { - _chat = new ChatViewModel(new ChatSettingsViewModel - { - MaxTokens = maxTokens, - Model = model - }); + _chat = new ChatViewModel( + _chatService, + _chatSerializer, + new ChatSettingsViewModel + { + MaxTokens = maxTokens, + Model = model + }); if (directions is { }) { @@ -113,7 +99,7 @@ public async Task AskAsync(string directions, string message) { try { - var chat = new ChatViewModel(directions); + var chat = new ChatViewModel(_chatService, _chatSerializer, directions); chat.AddSystemMessage(directions); chat.AddUserMessage(message); await Send(chat);