Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[UI] AI chat #12322

Draft
wants to merge 14 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,7 @@
<PackageVersion Include="Moq" Version="[4.18.4]" />
<PackageVersion Include="xunit" Version="2.6.6" />
<PackageVersion Include="xunit.runner.visualstudio" Version="2.5.6" />
<!-- ChatGPT. -->
<PackageVersion Include="CommunityToolkit.Mvvm" Version="8.1.0" />
</ItemGroup>
</Project>
3 changes: 3 additions & 0 deletions WalletWasabi.Fluent.Desktop/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@ public class Program
// yet and stuff might break.
public static async Task<int> Main(string[] args)
{
// TDOO: For testing only
// await Repl.RunAsync();

// Crash reporting must be before the "single instance checking".
Logger.InitializeDefaults(Path.Combine(Config.DataDir, "Logs.txt"), LogLevel.Info);
try
Expand Down
7 changes: 7 additions & 0 deletions WalletWasabi.Fluent.Desktop/packages.lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -830,6 +830,7 @@
"Avalonia.Skia": "[11.0.999-cibuild0044755-beta, )",
"Avalonia.Themes.Fluent": "[11.0.999-cibuild0044755-beta, )",
"Avalonia.Xaml.Behaviors": "[11.0.5, )",
"CommunityToolkit.Mvvm": "[8.1.0, )",
"DynamicData": "[8.1.1, )",
"QRackers": "[1.1.0, )",
"System.Private.Uri": "[4.3.2, )",
Expand Down Expand Up @@ -930,6 +931,12 @@
"Avalonia.Xaml.Interactivity": "11.0.5"
}
},
"CommunityToolkit.Mvvm": {
"type": "CentralTransitive",
"requested": "[8.1.0, )",
"resolved": "8.1.0",
"contentHash": "xxOt7lu9a5kB5Fs9RfcxzVlKnhuuPe+w7AXHtmCFtS3oldrsUhEMxHfNulluXSscUUoGxZ0jh55Om12ZP6abHA=="
},
"DynamicData": {
"type": "CentralTransitive",
"requested": "[8.1.1, )",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public void Initialize(GeneratorInitializationContext context)
{
foreach (var (fileName, source) in files)
{
ctx.AddSource(fileName, SourceText.From(source, Encoding.UTF8));
ctx.AddSource($"{Guid.NewGuid()}_{fileName}", SourceText.From(source, Encoding.UTF8));
}
});
}
Expand Down
3 changes: 2 additions & 1 deletion WalletWasabi.Fluent.Generators/Abstractions/GeneratorStep.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CodeAnalysis;
Expand All @@ -9,7 +10,7 @@
{
private readonly object _lock = new();

public GeneratorStepContext Context { get; private set; }

Check warning on line 13 in WalletWasabi.Fluent.Generators/Abstractions/GeneratorStep.cs

View workflow job for this annotation

GitHub Actions / Analyze (csharp)

Non-nullable property 'Context' must contain a non-null value when exiting constructor. Consider declaring the property as nullable.

public void Initialize(GeneratorExecutionContext context, Compilation compilation)
{
Expand All @@ -25,7 +26,7 @@
protected SyntaxTree AddSource(string name, string source)
{
var syntaxTree = SyntaxFactory.ParseSyntaxTree(source, Context.Context.ParseOptions);
Context.Context.AddSource(name, SourceText.From(source, Encoding.UTF8));
Context.Context.AddSource($"{Guid.NewGuid()}_{name}", SourceText.From(source, Encoding.UTF8));

lock (_lock)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -46,7 +47,7 @@ public void Execute(GeneratorExecutionContext context)
var classSource = ProcessClass(context.Compilation, namedTypeSymbol, attributeSymbol, metadataSymbol);
if (classSource is not null)
{
context.AddSource($"{namedTypeSymbol.Name}_NavigationMetaData.cs", SourceText.From(classSource, Encoding.UTF8));
context.AddSource($"{Guid.NewGuid()}_{namedTypeSymbol.Name}_NavigationMetaData.cs", SourceText.From(classSource, Encoding.UTF8));
}
}
}
Expand Down
5 changes: 3 additions & 2 deletions WalletWasabi.Fluent.Generators/StaticViewLocatorGenerator.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
Expand Down Expand Up @@ -33,7 +34,7 @@ public sealed class StaticViewLocatorAttribute : Attribute
public void Initialize(GeneratorInitializationContext context)
{
// System.Diagnostics.Debugger.Launch();
context.RegisterForPostInitialization((i) => i.AddSource("StaticViewLocatorAttribute.cs", SourceText.From(AttributeText, Encoding.UTF8)));
context.RegisterForPostInitialization((i) => i.AddSource($"{Guid.NewGuid()}_StaticViewLocatorAttribute.cs", SourceText.From(AttributeText, Encoding.UTF8)));

context.RegisterForSyntaxNotifications(() => new SyntaxReceiver());
}
Expand All @@ -59,7 +60,7 @@ public void Execute(GeneratorExecutionContext context)
var classSource = ProcessClass(context.Compilation, namedTypeSymbol, namedTypeSymbolViewModels);
if (classSource is not null)
{
context.AddSource($"{namedTypeSymbol.Name}_StaticViewLocator.cs", SourceText.From(classSource, Encoding.UTF8));
context.AddSource($"{{Guid.NewGuid()}}_{namedTypeSymbol.Name}_StaticViewLocator.cs", SourceText.From(classSource, Encoding.UTF8));
}
}
}
Expand Down
21 changes: 21 additions & 0 deletions WalletWasabi.Fluent/AI/.editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
root = true

[*.cs]

charset = utf-8

# Use hard tabs for indentation
indent_style = tab
indent_size = 4

# Disable all .NET analyzers
dotnet_analyzer_diagnostic.severity = none

dotnet_diagnostic.CS8600.severity = none
dotnet_diagnostic.CS8601.severity = none
dotnet_diagnostic.CS8603.severity = none
dotnet_diagnostic.CS8604.severity = none
dotnet_diagnostic.CS8618.severity = none
dotnet_diagnostic.CS8625.severity = none
dotnet_diagnostic.CS8765.severity = none
dotnet_diagnostic.CS8767.severity = none
28 changes: 28 additions & 0 deletions WalletWasabi.Fluent/AI/ChatGPT.Core/Defaults.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
namespace ChatGPT;

public static class Defaults
{
public const string WelcomeMessage = "Hi! I'm Clippy, your Windows Assistant. Would you like to get some assistance?";

public const decimal DefaultTemperature = 0.7m;

public const decimal DefaultTopP = 1m;

public const decimal DefaultPresencePenalty = 0m;

public const decimal DefaultFrequencyPenalty = 0m;

public const int DefaultMaxTokens = 2000;

public const string DefaultModel = "gpt-3.5-turbo";

public const string DefaultDirections = "You are a helpful assistant named Clippy. Write answers in Markdown blocks. For code blocks always define used language.";

public const string DefaultMessageFormat = "Markdown";

public const string TextMessageFormat = "Text";

public const string MarkdownMessageFormat = "Markdown";

public const string HtmlMessageTextFormat = "Html";
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Threading.Tasks;

namespace ChatGPT.Model.Services;

public interface IApplicationService
{
Task OpenFileAsync(Func<Stream, Task> callback, List<string> fileTypes, string title);
Task SaveFileAsync(Func<Stream, Task> callback, List<string> fileTypes, string title, string fileName, string defaultExtension);
void ToggleTheme();
void ToggleTopmost();
Task SetClipboardTextAsync(string text);
void Exit();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
namespace ChatGPT.Model.Services;

public interface IStorageFactory
{
IStorageService<T> CreateStorageService<T>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
using System.Text.Json.Serialization.Metadata;
using System.Threading.Tasks;

namespace ChatGPT.Model.Services;

public interface IStorageService<T>
{
Task SaveObjectAsync(T obj, string key, JsonTypeInfo<T> typeInfo);
Task<T?> LoadObjectAsync(string key, JsonTypeInfo<T> typeInfo);
void SaveObject(T obj, string key, JsonTypeInfo<T> typeInfo);
T? LoadObject(string key, JsonTypeInfo<T> typeInfo);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using ChatGPT.Model.Services;

namespace ChatGPT.Services;

public class ApplicationDataStorageFactory : IStorageFactory
{
public IStorageService<T> CreateStorageService<T>() => new ApplicationDataStorageService<T>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading.Tasks;
using ChatGPT.Model.Services;

namespace ChatGPT.Services;

public class ApplicationDataStorageService<T> : IStorageService<T>
{
private const string FolderName = "ChatGPT";
private const string FileExtension = ".json";

public async Task SaveObjectAsync(T obj, string key, JsonTypeInfo<T> typeInfo)
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appPath = Path.Combine(appDataPath, FolderName);
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
var appSettingPath = Path.Combine(appPath, key + FileExtension);
#if NETFRAMEWORK
using var stream = File.Open(appSettingPath, FileMode.Create);
#else
await using var stream = File.Open(appSettingPath, FileMode.Create);
#endif
await JsonSerializer.SerializeAsync(stream, obj, typeInfo);
}

public async Task<T?> LoadObjectAsync(string key, JsonTypeInfo<T> typeInfo)
{
try
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appSettingPath = Path.Combine(appDataPath, FolderName, key + FileExtension);
if (File.Exists(appSettingPath))
{
#if NETFRAMEWORK
using var stream = File.OpenRead(appSettingPath);
#else
await using var stream = File.OpenRead(appSettingPath);
#endif
var storedObj = await JsonSerializer.DeserializeAsync(stream, typeInfo);
return storedObj ?? default;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
}

return default;
}

public void SaveObject(T obj, string key, JsonTypeInfo<T> typeInfo)
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appPath = Path.Combine(appDataPath, FolderName);
if (!Directory.Exists(appPath))
{
Directory.CreateDirectory(appPath);
}
var appSettingPath = Path.Combine(appPath, key + FileExtension);
using var stream = File.Open(appSettingPath, FileMode.Create);
JsonSerializer.Serialize(stream, obj, typeInfo);
}

public T? LoadObject(string key, JsonTypeInfo<T> typeInfo)
{
try
{
var appDataPath = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData);
var appSettingPath = Path.Combine(appDataPath, FolderName, key + FileExtension);
if (File.Exists(appSettingPath))
{
using var stream = File.OpenRead(appSettingPath);
var storedObj = JsonSerializer.Deserialize(stream, typeInfo);
return storedObj ?? default;
}
}
catch (Exception e)
{
Debug.WriteLine(e);
}

return default;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
using ChatGPT.Model.Services;

namespace ChatGPT.Services;

public class IsolatedStorageFactory : IStorageFactory
{
public IStorageService<T> CreateStorageService<T>() => new IsolatedStorageService<T>();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
using System;
using System.Diagnostics;
using System.IO;
using System.IO.IsolatedStorage;
using System.Text.Json;
using System.Text.Json.Serialization.Metadata;
using System.Threading.Tasks;
using ChatGPT.Model.Services;

namespace ChatGPT.Services;

public class IsolatedStorageService<T> : IStorageService<T>
{
private static string Identifier { get; } = typeof(T).FullName?.Replace(".", string.Empty) ?? "default";

public async Task SaveObjectAsync(T obj, string key, JsonTypeInfo<T> typeInfo)
{
var store = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
null, null);
#if NETFRAMEWORK
using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Create, store);
#else
await using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Create, store);
#endif
await JsonSerializer.SerializeAsync(isoStream, obj, typeInfo);
}

public async Task<T?> LoadObjectAsync(string key, JsonTypeInfo<T> typeInfo)
{
try
{
var store = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
null, null);
#if NETFRAMEWORK
using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Open, store);
#else
await using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Open, store);
#endif
var storedObj = await JsonSerializer.DeserializeAsync(isoStream, typeInfo);
return storedObj ?? default;
}
catch (Exception e)
{
Debug.WriteLine(e);
}

return default;
}

public void SaveObject(T obj, string key, JsonTypeInfo<T> typeInfo)
{
var store = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
null, null);
using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Create, store);
JsonSerializer.Serialize(isoStream, obj, typeInfo);
}

public T? LoadObject(string key, JsonTypeInfo<T> typeInfo)
{
try
{
var store = IsolatedStorageFile.GetStore(
IsolatedStorageScope.User | IsolatedStorageScope.Domain | IsolatedStorageScope.Assembly,
null, null);
using var isoStream = new IsolatedStorageFileStream(Identifier + key, FileMode.Open, store);
var storedObj = JsonSerializer.Deserialize(isoStream, typeInfo);
return storedObj ?? default;
}
catch (Exception e)
{
Debug.WriteLine(e);
}

return default;
}
}