mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-23 20:47:25 -08:00
feat: improve commit message generation with AI prompts (#596)
- Refactor the commit message generation process to utilize default prompts and enhance clarity while eliminating redundancy. - Added new properties for subject and summary prompts, while improving cancellation support in async task handling. - feat: add AI prompts for commit message generation. - Updated the formatting of the package reference for consistency in the project file. - Add properties for managing OpenAI subject and summary prompts in the Preference view model. - Refactor layout and add new input fields for AI subject and summary prompts in the preferences view.
This commit is contained in:
parent
547c28adb8
commit
2f68aed817
6 changed files with 141 additions and 38 deletions
|
@ -10,6 +10,33 @@ namespace SourceGit.Commands
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class GenerateCommitMessage
|
public class GenerateCommitMessage
|
||||||
{
|
{
|
||||||
|
private const string DEFAULT_SUMMARY_PROMPT = """
|
||||||
|
You are an expert developer specialist in creating commits.
|
||||||
|
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
|
||||||
|
- Do not use any code snippets, imports, file routes or bullets points.
|
||||||
|
- Do not mention the route of file that has been change.
|
||||||
|
- Simply describe the MAIN GOAL of the changes.
|
||||||
|
- Output directly the summary in plain text.
|
||||||
|
""";
|
||||||
|
|
||||||
|
private const string DEFAULT_SUBJECT_PROMPT = """
|
||||||
|
You are an expert developer specialist in creating commits messages.
|
||||||
|
Your only goal is to retrieve a single commit message.
|
||||||
|
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
|
||||||
|
- Assign the commit {type} according to the next conditions:
|
||||||
|
feat: Only when adding a new feature.
|
||||||
|
fix: When fixing a bug.
|
||||||
|
docs: When updating documentation.
|
||||||
|
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
|
||||||
|
test: When adding or updating tests.
|
||||||
|
chore: When making changes to the build process or auxiliary tools and libraries.
|
||||||
|
revert: When undoing a previous commit.
|
||||||
|
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
|
||||||
|
- Do not add any issues numeration, explain your output nor introduce your answer.
|
||||||
|
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
|
||||||
|
- Be as concise as possible, keep the message under 50 characters.
|
||||||
|
""";
|
||||||
|
|
||||||
public class GetDiffContent : Command
|
public class GetDiffContent : Command
|
||||||
{
|
{
|
||||||
public GetDiffContent(string repo, Models.DiffOption opt)
|
public GetDiffContent(string repo, Models.DiffOption opt)
|
||||||
|
@ -70,15 +97,12 @@ namespace SourceGit.Commands
|
||||||
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
|
var rs = new GetDiffContent(_repo, new Models.DiffOption(change, false)).ReadToEnd();
|
||||||
var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
|
var diff = rs.IsSuccess ? rs.StdOut : "unknown change";
|
||||||
|
|
||||||
var prompt = new StringBuilder();
|
var prompt = string.IsNullOrWhiteSpace(Models.OpenAI.SummaryPrompt)
|
||||||
prompt.AppendLine("You are an expert developer specialist in creating commits.");
|
? DEFAULT_SUMMARY_PROMPT
|
||||||
prompt.AppendLine("Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:");
|
: Models.OpenAI.SummaryPrompt;
|
||||||
prompt.AppendLine("- Do not use any code snippets, imports, file routes or bullets points.");
|
|
||||||
prompt.AppendLine("- Do not mention the route of file that has been change.");
|
var rsp = Models.OpenAI.Chat(prompt, $"Here is the `git diff` output: {diff}", _cancelToken);
|
||||||
prompt.AppendLine("- Simply describe the MAIN GOAL of the changes.");
|
|
||||||
prompt.AppendLine("- Output directly the summary in plain text.`");
|
|
||||||
|
|
||||||
var rsp = Models.OpenAI.Chat(prompt.ToString(), $"Here is the `git diff` output: {diff}", _cancelToken);
|
|
||||||
if (rsp != null && rsp.Choices.Count > 0)
|
if (rsp != null && rsp.Choices.Count > 0)
|
||||||
return rsp.Choices[0].Message.Content;
|
return rsp.Choices[0].Message.Content;
|
||||||
|
|
||||||
|
@ -87,24 +111,12 @@ namespace SourceGit.Commands
|
||||||
|
|
||||||
private string GenerateSubject(string summary)
|
private string GenerateSubject(string summary)
|
||||||
{
|
{
|
||||||
var prompt = new StringBuilder();
|
var prompt = string.IsNullOrWhiteSpace(Models.OpenAI.SubjectPrompt)
|
||||||
prompt.AppendLine("You are an expert developer specialist in creating commits messages.");
|
? DEFAULT_SUBJECT_PROMPT
|
||||||
prompt.AppendLine("Your only goal is to retrieve a single commit message.");
|
: Models.OpenAI.SubjectPrompt;
|
||||||
prompt.AppendLine("Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:");
|
|
||||||
prompt.AppendLine("- Assign the commit {type} according to the next conditions:");
|
var rsp = Models.OpenAI.Chat(prompt, $"Here are the summaries changes: {summary}", _cancelToken);
|
||||||
prompt.AppendLine(" feat: Only when adding a new feature.");
|
|
||||||
prompt.AppendLine(" fix: When fixing a bug.");
|
|
||||||
prompt.AppendLine(" docs: When updating documentation.");
|
|
||||||
prompt.AppendLine(" style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.");
|
|
||||||
prompt.AppendLine(" test: When adding or updating tests. ");
|
|
||||||
prompt.AppendLine(" chore: When making changes to the build process or auxiliary tools and libraries. ");
|
|
||||||
prompt.AppendLine(" revert: When undoing a previous commit.");
|
|
||||||
prompt.AppendLine(" refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.");
|
|
||||||
prompt.AppendLine("- Do not add any issues numeration, explain your output nor introduce your answer.");
|
|
||||||
prompt.AppendLine("- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.");
|
|
||||||
prompt.AppendLine("- Be as concise as possible, keep the message under 50 characters.");
|
|
||||||
|
|
||||||
var rsp = Models.OpenAI.Chat(prompt.ToString(), $"Here are the summaries changes: {summary}", _cancelToken);
|
|
||||||
if (rsp != null && rsp.Choices.Count > 0)
|
if (rsp != null && rsp.Choices.Count > 0)
|
||||||
return rsp.Choices[0].Message.Content;
|
return rsp.Choices[0].Message.Content;
|
||||||
|
|
||||||
|
|
|
@ -94,6 +94,18 @@ namespace SourceGit.Models
|
||||||
set;
|
set;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static string SubjectPrompt
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string SummaryPrompt
|
||||||
|
{
|
||||||
|
get;
|
||||||
|
set;
|
||||||
|
}
|
||||||
|
|
||||||
public static bool IsValid
|
public static bool IsValid
|
||||||
{
|
{
|
||||||
get => !string.IsNullOrEmpty(Server) && !string.IsNullOrEmpty(Model);
|
get => !string.IsNullOrEmpty(Server) && !string.IsNullOrEmpty(Model);
|
||||||
|
@ -113,14 +125,14 @@ namespace SourceGit.Models
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var task = client.PostAsync(Server, req, cancellation);
|
var task = client.PostAsync(Server, req, cancellation);
|
||||||
task.Wait();
|
task.Wait(cancellation);
|
||||||
|
|
||||||
var rsp = task.Result;
|
var rsp = task.Result;
|
||||||
if (!rsp.IsSuccessStatusCode)
|
if (!rsp.IsSuccessStatusCode)
|
||||||
throw new Exception($"AI service returns error code {rsp.StatusCode}");
|
throw new Exception($"AI service returns error code {rsp.StatusCode}");
|
||||||
|
|
||||||
var reader = rsp.Content.ReadAsStringAsync(cancellation);
|
var reader = rsp.Content.ReadAsStringAsync(cancellation);
|
||||||
reader.Wait();
|
reader.Wait(cancellation);
|
||||||
|
|
||||||
return JsonSerializer.Deserialize(reader.Result, JsonCodeGen.Default.OpenAIChatResponse);
|
return JsonSerializer.Deserialize(reader.Result, JsonCodeGen.Default.OpenAIChatResponse);
|
||||||
}
|
}
|
||||||
|
|
|
@ -403,6 +403,31 @@
|
||||||
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Server</x:String>
|
<x:String x:Key="Text.Preference.AI.Server" xml:space="preserve">Server</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
<x:String x:Key="Text.Preference.AI.ApiKey" xml:space="preserve">API Key</x:String>
|
||||||
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Model</x:String>
|
<x:String x:Key="Text.Preference.AI.Model" xml:space="preserve">Model</x:String>
|
||||||
|
<x:String x:Key="Text.Preference.AI.SummaryPrompt" xml:space="preserve">Summary Prompt</x:String>
|
||||||
|
<x:String x:Key="Text.Preference.AI.SubjectPrompt" xml:space="preserve">Subject Prompt</x:String>
|
||||||
|
<x:String x:Key="Text.Preference.AI.SummaryPromptHint" xml:space="preserve">You are an expert developer specialist in creating commits.
|
||||||
|
Provide a super concise one sentence overall changes summary of the user `git diff` output following strictly the next rules:
|
||||||
|
- Do not use any code snippets, imports, file routes or bullets points.
|
||||||
|
- Do not mention the route of file that has been change.
|
||||||
|
- Simply describe the MAIN GOAL of the changes.
|
||||||
|
- Output directly the summary in plain text.
|
||||||
|
</x:String>
|
||||||
|
<x:String x:Key="Text.Preference.AI.SubjectPromptHint" xml:space="preserve">You are an expert developer specialist in creating commits messages.
|
||||||
|
Your only goal is to retrieve a single commit message.
|
||||||
|
Based on the provided user changes, combine them in ONE SINGLE commit message retrieving the global idea, following strictly the next rules:
|
||||||
|
- Assign the commit {type} according to the next conditions:
|
||||||
|
feat: Only when adding a new feature.
|
||||||
|
fix: When fixing a bug.
|
||||||
|
docs: When updating documentation.
|
||||||
|
style: When changing elements styles or design and/or making changes to the code style (formatting, missing semicolons, etc.) without changing the code logic.
|
||||||
|
test: When adding or updating tests.
|
||||||
|
chore: When making changes to the build process or auxiliary tools and libraries.
|
||||||
|
revert: When undoing a previous commit.
|
||||||
|
refactor: When restructuring code without changing its external behavior, or is any of the other refactor types.
|
||||||
|
- Do not add any issues numeration, explain your output nor introduce your answer.
|
||||||
|
- Output directly only one commit message in plain text with the next format: {type}: {commit_message}.
|
||||||
|
- Be as concise as possible, keep the message under 50 characters.
|
||||||
|
</x:String>
|
||||||
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
<x:String x:Key="Text.Preference.Appearance" xml:space="preserve">APPEARANCE</x:String>
|
||||||
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
<x:String x:Key="Text.Preference.Appearance.DefaultFont" xml:space="preserve">Default Font</x:String>
|
||||||
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Default Font Size</x:String>
|
<x:String x:Key="Text.Preference.Appearance.DefaultFontSize" xml:space="preserve">Default Font Size</x:String>
|
||||||
|
@ -621,7 +646,7 @@
|
||||||
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">Open All Repositories</x:String>
|
<x:String x:Key="Text.Welcome.OpenAllInNode" xml:space="preserve">Open All Repositories</x:String>
|
||||||
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Open Repository</x:String>
|
<x:String x:Key="Text.Welcome.OpenOrInit" xml:space="preserve">Open Repository</x:String>
|
||||||
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Open Terminal</x:String>
|
<x:String x:Key="Text.Welcome.OpenTerminal" xml:space="preserve">Open Terminal</x:String>
|
||||||
<x:String x:Key="Text.Welcome.ScanDefaultCloneDir" xml:space="preserve">Rescan Repositories in Default Clone Dir</x:String>
|
<x:String x:Key="Text.Welcome.ScanDefaultCloneDir" xml:space="preserve">Rescan Repositories in Default Clone Dir</x:String>
|
||||||
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories...</x:String>
|
<x:String x:Key="Text.Welcome.Search" xml:space="preserve">Search Repositories...</x:String>
|
||||||
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String>
|
<x:String x:Key="Text.Welcome.Sort" xml:space="preserve">Sort</x:String>
|
||||||
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
|
<x:String x:Key="Text.WorkingCopy" xml:space="preserve">Changes</x:String>
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<PackageReference Include="Avalonia.Diagnostics" Version="11.1.4" Condition="'$(Configuration)' == 'Debug'" />
|
<PackageReference Include="Avalonia.Diagnostics" Version="11.1.4" Condition="'$(Configuration)' == 'Debug'" />
|
||||||
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
|
<PackageReference Include="Avalonia.AvaloniaEdit" Version="11.1.0" />
|
||||||
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
|
<PackageReference Include="AvaloniaEdit.TextMate" Version="11.1.0" />
|
||||||
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
<PackageReference Include="CommunityToolkit.Mvvm" Version="8.3.2" />
|
||||||
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc3.3" />
|
<PackageReference Include="LiveChartsCore.SkiaSharpView.Avalonia" Version="2.0.0-rc3.3" />
|
||||||
<PackageReference Include="TextMateSharp" Version="1.0.63" />
|
<PackageReference Include="TextMateSharp" Version="1.0.63" />
|
||||||
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.63" />
|
<PackageReference Include="TextMateSharp.Grammars" Version="1.0.63" />
|
||||||
|
|
|
@ -315,6 +315,32 @@ namespace SourceGit.ViewModels
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string OpenAISubjectPrompt
|
||||||
|
{
|
||||||
|
get => Models.OpenAI.SubjectPrompt;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != Models.OpenAI.SubjectPrompt)
|
||||||
|
{
|
||||||
|
Models.OpenAI.SubjectPrompt = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public string OpenAISummaryPrompt
|
||||||
|
{
|
||||||
|
get => Models.OpenAI.SummaryPrompt;
|
||||||
|
set
|
||||||
|
{
|
||||||
|
if (value != Models.OpenAI.SummaryPrompt)
|
||||||
|
{
|
||||||
|
Models.OpenAI.SummaryPrompt = value;
|
||||||
|
OnPropertyChanged();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public uint StatisticsSampleColor
|
public uint StatisticsSampleColor
|
||||||
{
|
{
|
||||||
get => _statisticsSampleColor;
|
get => _statisticsSampleColor;
|
||||||
|
|
|
@ -52,7 +52,7 @@
|
||||||
<TabItem.Header>
|
<TabItem.Header>
|
||||||
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
|
<TextBlock Classes="tab_header" Text="{DynamicResource Text.Preference.General}"/>
|
||||||
</TabItem.Header>
|
</TabItem.Header>
|
||||||
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
<Grid Margin="8" RowDefinitions="32,32,32,32,32,32" ColumnDefinitions="Auto,*">
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
Text="{DynamicResource Text.Preference.General.Locale}"
|
Text="{DynamicResource Text.Preference.General.Locale}"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
Margin="0,0,16,0"/>
|
Margin="0,0,16,0"/>
|
||||||
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
|
<StackPanel Grid.Row="1" Grid.Column="1" Orientation="Horizontal">
|
||||||
<TextBlock Margin="0,0,8,0"
|
<TextBlock Margin="0,0,8,0"
|
||||||
Text="{Binding #ThisControl.GitVersion}"
|
Text="{Binding #ThisControl.GitVersion}"
|
||||||
IsVisible="{Binding #ThisControl.GitVersion, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
IsVisible="{Binding #ThisControl.GitVersion, Converter={x:Static StringConverters.IsNotNullOrEmpty}}"/>
|
||||||
|
|
||||||
<Border Background="Transparent"
|
<Border Background="Transparent"
|
||||||
|
@ -368,7 +368,7 @@
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
Text="{DynamicResource Text.Preference.Shell.Type}"
|
Text="{DynamicResource Text.Preference.Shell.Type}"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
|
@ -405,7 +405,7 @@
|
||||||
</Button>
|
</Button>
|
||||||
</TextBox.InnerRightContent>
|
</TextBox.InnerRightContent>
|
||||||
</TextBox>
|
</TextBox>
|
||||||
</Grid>
|
</Grid>
|
||||||
|
|
||||||
<StackPanel Orientation="Horizontal" Margin="0,24,0,0">
|
<StackPanel Orientation="Horizontal" Margin="0,24,0,0">
|
||||||
<Path Width="12" Height="12" Data="{StaticResource Icons.Diff}"/>
|
<Path Width="12" Height="12" Data="{StaticResource Icons.Diff}"/>
|
||||||
|
@ -417,7 +417,7 @@
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
Text="{DynamicResource Text.Preference.DiffMerge.Type}"
|
Text="{DynamicResource Text.Preference.DiffMerge.Type}"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
|
@ -465,12 +465,12 @@
|
||||||
<TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.AI}"/>
|
<TextBlock Classes="bold" Margin="4,0,0,0" Text="{DynamicResource Text.Preference.AI}"/>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
<Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/>
|
<Rectangle Margin="0,8" Fill="{DynamicResource Brush.Border2}" Height=".6" HorizontalAlignment="Stretch"/>
|
||||||
<Grid Margin="8,0,0,0" RowDefinitions="32,32,32">
|
<Grid Margin="8,0,0,0" RowDefinitions="32,32,32,128,128">
|
||||||
<Grid.ColumnDefinitions>
|
<Grid.ColumnDefinitions>
|
||||||
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
<ColumnDefinition Width="Auto" SharedSizeGroup="IntegrationLabel"/>
|
||||||
<ColumnDefinition Width="*"/>
|
<ColumnDefinition Width="*"/>
|
||||||
</Grid.ColumnDefinitions>
|
</Grid.ColumnDefinitions>
|
||||||
|
|
||||||
<TextBlock Grid.Row="0" Grid.Column="0"
|
<TextBlock Grid.Row="0" Grid.Column="0"
|
||||||
Text="{DynamicResource Text.Preference.AI.Server}"
|
Text="{DynamicResource Text.Preference.AI.Server}"
|
||||||
HorizontalAlignment="Right"
|
HorizontalAlignment="Right"
|
||||||
|
@ -497,10 +497,38 @@
|
||||||
Height="28"
|
Height="28"
|
||||||
CornerRadius="3"
|
CornerRadius="3"
|
||||||
Text="{Binding OpenAIApiKey, Mode=TwoWay}"/>
|
Text="{Binding OpenAIApiKey, Mode=TwoWay}"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="3" Grid.Column="0"
|
||||||
|
Text="{DynamicResource Text.Preference.AI.SubjectPrompt}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,16,0"/>
|
||||||
|
|
||||||
|
<TextBox Grid.Row="3" Grid.Column="1"
|
||||||
|
Height="120"
|
||||||
|
CornerRadius="3"
|
||||||
|
VerticalContentAlignment="Top"
|
||||||
|
Text="{Binding OpenAISubjectPrompt, Mode=TwoWay}"
|
||||||
|
AcceptsReturn="true"
|
||||||
|
Watermark="{DynamicResource Text.Preference.AI.SubjectPromptHint}"
|
||||||
|
TextWrapping="Wrap"/>
|
||||||
|
|
||||||
|
<TextBlock Grid.Row="4" Grid.Column="0"
|
||||||
|
Text="{DynamicResource Text.Preference.AI.SummaryPrompt}"
|
||||||
|
HorizontalAlignment="Right"
|
||||||
|
Margin="0,0,16,0"/>
|
||||||
|
|
||||||
|
<TextBox Grid.Row="4" Grid.Column="1"
|
||||||
|
Height="120"
|
||||||
|
CornerRadius="3"
|
||||||
|
VerticalContentAlignment="Top"
|
||||||
|
Text="{Binding OpenAISummaryPrompt, Mode=TwoWay}"
|
||||||
|
AcceptsReturn="true"
|
||||||
|
Watermark="{DynamicResource Text.Preference.AI.SummaryPromptHint}"
|
||||||
|
TextWrapping="Wrap"/>
|
||||||
</Grid>
|
</Grid>
|
||||||
</StackPanel>
|
</StackPanel>
|
||||||
</TabItem>
|
</TabItem>
|
||||||
</TabControl>
|
</TabControl>
|
||||||
</Border>
|
</Border>
|
||||||
</Grid>
|
</Grid>
|
||||||
</v:ChromelessWindow>
|
</v:ChromelessWindow>
|
||||||
|
|
Loading…
Reference in a new issue