-
Notifications
You must be signed in to change notification settings - Fork 386
Expand file tree
/
Copy pathAIAssistant.cs
More file actions
124 lines (107 loc) · 3.71 KB
/
AIAssistant.cs
File metadata and controls
124 lines (107 loc) · 3.71 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
namespace SourceGit.ViewModels
{
public class AIAssistant : ObservableObject
{
public List<string> AvailableModels
{
get => _service.AvailableModels;
}
public string CurrentModel
{
get => _service.Model;
set => _service.Model = value;
}
public bool IsGenerating
{
get => _isGenerating;
private set => SetProperty(ref _isGenerating, value);
}
public string Text
{
get => _text;
private set => SetProperty(ref _text, value);
}
public AIAssistant(Repository repo, AI.Service service, List<Models.Change> changes)
{
_repo = repo;
_service = service;
_cancel = new CancellationTokenSource();
var builder = new StringBuilder();
foreach (var c in changes)
SerializeChange(c, builder);
_changeList = builder.ToString();
}
public async Task GenAsync()
{
if (_cancel is { IsCancellationRequested: false })
_cancel.Cancel();
_cancel = new CancellationTokenSource();
var agent = new AI.Agent(_service);
var builder = new StringBuilder();
builder.AppendLine("Asking AI to generate commit message...").AppendLine();
Text = builder.ToString();
IsGenerating = true;
try
{
await agent.GenerateCommitMessageAsync(_repo.FullPath, _changeList, message =>
{
builder.AppendLine(message);
Dispatcher.UIThread.Post(() => Text = builder.ToString());
}, _cancel.Token);
}
catch (OperationCanceledException)
{
// Do nothing and leave `IsGenerating` to current (may already changed), so that the UI can update accordingly.
return;
}
catch (Exception e)
{
builder
.AppendLine()
.AppendLine("[ERROR]")
.Append(e.Message);
Text = builder.ToString();
}
IsGenerating = false;
}
public void Use(string text)
{
_repo.SetCommitMessage(text);
}
public void Cancel()
{
_cancel?.Cancel();
}
private void SerializeChange(Models.Change c, StringBuilder builder)
{
var status = c.Index switch
{
Models.ChangeState.Added => "A",
Models.ChangeState.Modified => "M",
Models.ChangeState.Deleted => "D",
Models.ChangeState.TypeChanged => "T",
Models.ChangeState.Renamed => "R",
Models.ChangeState.Copied => "C",
_ => " ",
};
builder.Append(status).Append('\t');
if (c.Index == Models.ChangeState.Renamed || c.Index == Models.ChangeState.Copied)
builder.Append(c.OriginalPath).Append(" -> ").Append(c.Path).AppendLine();
else
builder.Append(c.Path).AppendLine();
}
private readonly Repository _repo = null;
private readonly AI.Service _service = null;
private readonly string _changeList = null;
private CancellationTokenSource _cancel = null;
private bool _isGenerating = false;
private string _text = string.Empty;
}
}