mirror of
https://fastgit.cc/github.com/sourcegit-scm/sourcegit
synced 2026-04-22 05:40:43 +08:00
refactor: dynamic loading and choosing AI model in assistant dialog (#2228)
Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
@@ -17,6 +17,9 @@ namespace SourceGit.AI
|
||||
public async Task GenerateCommitMessageAsync(string repo, string changeList, Action<string> onUpdate, CancellationToken cancellation)
|
||||
{
|
||||
var chatClient = _service.GetChatClient();
|
||||
if (chatClient == null)
|
||||
throw new Exception("Failed to fetch available models from this service. Please check your configuration and try again.");
|
||||
|
||||
var options = new ChatCompletionOptions() { Tools = { ChatTools.GetDetailChangesInFile } };
|
||||
|
||||
var userMessageBuilder = new StringBuilder();
|
||||
|
||||
@@ -1,22 +1,90 @@
|
||||
using System;
|
||||
using System.ClientModel;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Azure.AI.OpenAI;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
using OpenAI;
|
||||
using OpenAI.Chat;
|
||||
|
||||
namespace SourceGit.AI
|
||||
{
|
||||
public class Service
|
||||
public class Service : ObservableObject
|
||||
{
|
||||
public string Name { get; set; } = string.Empty;
|
||||
public string Server { get; set; } = string.Empty;
|
||||
public string Model { get; set; } = string.Empty;
|
||||
public string ApiKey { get; set; } = string.Empty;
|
||||
public bool ReadApiKeyFromEnv { get; set; } = false;
|
||||
public string AdditionalPrompt { get; set; } = string.Empty;
|
||||
public string Name
|
||||
{
|
||||
get => _name;
|
||||
set => SetProperty(ref _name, value);
|
||||
}
|
||||
|
||||
public string Server
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
public string ApiKey
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
public bool ReadApiKeyFromEnv
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = false;
|
||||
|
||||
public string AdditionalPrompt
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
[JsonIgnore]
|
||||
public List<string> AvailableModels
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
} = [];
|
||||
|
||||
public string Model
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = string.Empty;
|
||||
|
||||
public async Task<List<string>> FetchAvailableModelsAsync()
|
||||
{
|
||||
var credential = new ApiKeyCredential(ReadApiKeyFromEnv ? Environment.GetEnvironmentVariable(ApiKey) : ApiKey);
|
||||
var client = Server.Contains("openai.azure.com/", StringComparison.Ordinal)
|
||||
? new AzureOpenAIClient(new Uri(Server), credential)
|
||||
: new OpenAIClient(credential, new() { Endpoint = new Uri(Server) });
|
||||
|
||||
var allModels = client.GetOpenAIModelClient().GetModels();
|
||||
AvailableModels = new List<string>();
|
||||
foreach (var model in allModels.Value)
|
||||
AvailableModels.Add(model.Id);
|
||||
|
||||
if (AvailableModels.Count > 0)
|
||||
{
|
||||
if (string.IsNullOrEmpty(Model) || !AvailableModels.Contains(Model))
|
||||
Model = AvailableModels[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
Model = null;
|
||||
}
|
||||
|
||||
return AvailableModels;
|
||||
}
|
||||
|
||||
public ChatClient GetChatClient()
|
||||
{
|
||||
if (string.IsNullOrEmpty(Model))
|
||||
return null;
|
||||
|
||||
var credential = new ApiKeyCredential(ReadApiKeyFromEnv ? Environment.GetEnvironmentVariable(ApiKey) : ApiKey);
|
||||
var client = Server.Contains("openai.azure.com/", StringComparison.Ordinal)
|
||||
? new AzureOpenAIClient(new Uri(Server), credential)
|
||||
@@ -24,5 +92,7 @@ namespace SourceGit.AI
|
||||
|
||||
return client.GetChatClient(Model);
|
||||
}
|
||||
|
||||
private string _name = string.Empty;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -602,7 +602,7 @@ $1, $2, … Werte der Eingabe-Steuerelemente</x:String>
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Einstellungen</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API-Schlüssel</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modell</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modell</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Der eingegebene Wert ist der Name der Umgebungsvariable, aus der der API-Schlüssel gelesen wird</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.CreateNew" xml:space="preserve">Create New Branch</x:String>
|
||||
<x:String x:Key="Text.AddWorktree.WhatToCheckout.Existing" xml:space="preserve">Existing Branch</x:String>
|
||||
<x:String x:Key="Text.AIAssistant" xml:space="preserve">AI Assistant</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">MODEL</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Regen" xml:space="preserve">RE-GENERATE</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Tip" xml:space="preserve">Use AI to generate commit message</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Use" xml:space="preserve">Use</x:String>
|
||||
@@ -616,7 +617,6 @@
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">Additional Prompt (Use `-` to list your requirements)</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Name</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Entered value is the name to load API key from ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">OPEN AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">Prompt adicional (Usa `-` para listar tus requerimientos)</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Clave API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modelo</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nombre</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">El valor ingresado es el nombre de la clave API a cargar desde ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>
|
||||
|
||||
@@ -561,7 +561,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Préférences</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">IA</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Clé d'API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modèle</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modèle</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nom</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">La valeur saisie est le nom pour charger la clé API depuis l'ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Serveur</x:String>
|
||||
|
||||
@@ -535,7 +535,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferensi</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Model</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Model</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nama</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Nilai yang dimasukkan adalah nama untuk memuat API key dari ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||
|
||||
@@ -598,7 +598,7 @@ ${pure_files:N} Come ${files:N}, ma senza cartelle</x:String>
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferenze</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Chiave API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modello</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modello</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nome</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Il valore inserito è il nome per caricare la chiave API da ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Server</x:String>
|
||||
|
||||
@@ -604,7 +604,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">設定</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API キー</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">モデル</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">モデル</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名前</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">この値を環境変数の名前とし、そこから API キーを読み込む</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">サーバー</x:String>
|
||||
|
||||
@@ -537,7 +537,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">환경설정</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API 키</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">모델</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">모델</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">이름</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">입력된 값은 환경변수(ENV)에서 API 키를 불러올 이름입니다</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">서버</x:String>
|
||||
|
||||
@@ -418,7 +418,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Preferências</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">INTELIGÊNCIA ARTIFICIAL</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Chave da API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Modelo</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Modelo</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Nome</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Servidor</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">APARÊNCIA</x:String>
|
||||
|
||||
@@ -616,7 +616,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">ОТКРЫТЬ ИИ</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">Дополнительная подсказка (Для перечисления ваших требований используйте `-`)</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Ключ API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Имя:</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">Введённое значение — это имя для загрузки API-ключа из ENV</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Сервер</x:String>
|
||||
|
||||
@@ -415,7 +415,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">விருப்பத்தேர்வுகள்</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">செநு</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">பநிஇ திறவுகோல்</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">மாதிரி</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">மாதிரி</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">பெயர்</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">சேவையகம்</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">தோற்றம்</x:String>
|
||||
|
||||
@@ -419,7 +419,7 @@
|
||||
<x:String x:Key="Text.Preferences" xml:space="preserve">Налаштування</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">Ключ API</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">Модель</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">Назва</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">Сервер</x:String>
|
||||
<x:String x:Key="Text.Preferences.Appearance" xml:space="preserve">ВИГЛЯД</x:String>
|
||||
|
||||
@@ -620,7 +620,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">附加提示词 (请使用 `-` 列出您的要求)</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API密钥</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">配置名称</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">从环境变量(填写环境变量名)中读取API密钥</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">服务地址</x:String>
|
||||
|
||||
@@ -620,7 +620,7 @@
|
||||
<x:String x:Key="Text.Preferences.AI" xml:space="preserve">AI</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.AdditionalPrompt" xml:space="preserve">附加提示詞 (請使用 '-' 列出您的要求)</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ApiKey" xml:space="preserve">API 金鑰</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.AIAssistant.Model" xml:space="preserve">模型</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Name" xml:space="preserve">名稱</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.ReadApiKeyFromEnv" xml:space="preserve">從環境變數中 (輸入環境變數名稱) 讀取 API 金鑰</x:String>
|
||||
<x:String x:Key="Text.Preferences.AI.Server" xml:space="preserve">伺服器</x:String>
|
||||
|
||||
@@ -10,6 +10,17 @@ 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;
|
||||
|
||||
@@ -3,6 +3,7 @@ using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
using System.Threading.Tasks;
|
||||
using Avalonia.Collections;
|
||||
using CommunityToolkit.Mvvm.ComponentModel;
|
||||
|
||||
@@ -616,6 +617,21 @@ namespace SourceGit.ViewModels
|
||||
RemoveInvalidRepositoriesRecursive(RepositoryNodes);
|
||||
}
|
||||
|
||||
public async Task UpdateAvailableAIModelsAsync()
|
||||
{
|
||||
foreach (var service in OpenAIServices)
|
||||
{
|
||||
try
|
||||
{
|
||||
await service.FetchAvailableModelsAsync();
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Ignore errors.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void Save()
|
||||
{
|
||||
if (_isLoading || _isReadonly)
|
||||
|
||||
@@ -46,18 +46,33 @@
|
||||
Content="{Binding Text}"/>
|
||||
|
||||
<!-- Options -->
|
||||
<Border Grid.Row="2" Margin="0,0,0,8">
|
||||
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center">
|
||||
<v:LoadingIcon Width="14" Height="14"
|
||||
Margin="0,0,8,0"
|
||||
IsVisible="{Binding IsGenerating}"/>
|
||||
<Button Classes="flat"
|
||||
<Grid Grid.Row="2" Margin="8,0,8,8" ColumnDefinitions="Auto,*,18,Auto">
|
||||
<TextBlock Grid.Column="0"
|
||||
Classes="group_header_label"
|
||||
Text="{DynamicResource Text.AIAssistant.Model}"/>
|
||||
|
||||
<ComboBox Grid.Column="1"
|
||||
Height="28"
|
||||
Padding="12,0"
|
||||
Content="{DynamicResource Text.AIAssistant.Regen}"
|
||||
IsEnabled="{Binding !IsGenerating}"
|
||||
Click="OnRegenClicked"/>
|
||||
</StackPanel>
|
||||
</Border>
|
||||
Margin="6,0" Padding="4,0"
|
||||
BorderThickness="0"
|
||||
Background="Transparent"
|
||||
VerticalAlignment="Center"
|
||||
ItemsSource="{Binding AvailableModels, Mode=OneWay}"
|
||||
SelectedItem="{Binding CurrentModel, Mode=TwoWay}"
|
||||
SelectionChanged="OnModelChanged"/>
|
||||
|
||||
<v:LoadingIcon Grid.Column="2"
|
||||
Width="14" Height="14"
|
||||
Margin="0,0,8,0"
|
||||
IsVisible="{Binding IsGenerating}"/>
|
||||
|
||||
<Button Grid.Column="3"
|
||||
Classes="flat"
|
||||
Height="28"
|
||||
Padding="12,0"
|
||||
Content="{DynamicResource Text.AIAssistant.Regen}"
|
||||
IsEnabled="{Binding !IsGenerating}"
|
||||
Click="OnRegenClicked"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</v:ChromelessWindow>
|
||||
|
||||
@@ -149,6 +149,13 @@ namespace SourceGit.Views
|
||||
(DataContext as ViewModels.AIAssistant)?.Cancel();
|
||||
}
|
||||
|
||||
private async void OnModelChanged(object sender, SelectionChangedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.AIAssistant vm && IsLoaded)
|
||||
await vm.GenAsync();
|
||||
e.Handled = true;
|
||||
}
|
||||
|
||||
private async void OnRegenClicked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (DataContext is ViewModels.AIAssistant vm)
|
||||
|
||||
@@ -106,13 +106,16 @@ namespace SourceGit.Views
|
||||
Activate();
|
||||
}
|
||||
|
||||
protected override void OnOpened(EventArgs e)
|
||||
protected override async void OnOpened(EventArgs e)
|
||||
{
|
||||
base.OnOpened(e);
|
||||
|
||||
var state = ViewModels.Preferences.Instance.Layout.LauncherWindowState;
|
||||
var preferences = ViewModels.Preferences.Instance;
|
||||
var state = preferences.Layout.LauncherWindowState;
|
||||
if (state == WindowState.Maximized || state == WindowState.FullScreen)
|
||||
WindowState = WindowState.Maximized;
|
||||
|
||||
await preferences.UpdateAvailableAIModelsAsync();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
|
||||
|
||||
@@ -868,9 +868,6 @@
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preferences.AI.Server}"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Server, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preferences.AI.Model}"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding Model, Mode=TwoWay}"/>
|
||||
|
||||
<TextBlock Margin="0,12,0,0" Text="{DynamicResource Text.Preferences.AI.ApiKey}"/>
|
||||
<TextBox Margin="0,4,0,0" CornerRadius="3" Height="28" Text="{Binding ApiKey, Mode=TwoWay}" PasswordChar="*" RevealPassword="{Binding ReadApiKeyFromEnv, Mode=OneWay}"/>
|
||||
<CheckBox Margin="0,4,0,0"
|
||||
|
||||
@@ -205,7 +205,9 @@ namespace SourceGit.Views
|
||||
await new Commands.Config(null).SetAsync($"gpg.{GPGFormat.Value}.program", GPGExecutableFile);
|
||||
}
|
||||
|
||||
ViewModels.Preferences.Instance.Save();
|
||||
var preferences = ViewModels.Preferences.Instance;
|
||||
await preferences.UpdateAvailableAIModelsAsync();
|
||||
preferences.Save();
|
||||
}
|
||||
|
||||
private async void SelectThemeOverrideFile(object _, RoutedEventArgs e)
|
||||
|
||||
Reference in New Issue
Block a user