Skip to content

Commit 52c34ac

Browse files
CopilotByron
andcommitted
Add custom PR message prompt support for concistency
Co-authored-by: Byron <63622+Byron@users.noreply.github.com>
1 parent 5aa0404 commit 52c34ac

File tree

6 files changed

+61
-12
lines changed

6 files changed

+61
-12
lines changed

apps/desktop/src/components/AIPromptEdit.svelte

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import type { Prompts, UserPrompt } from '$lib/ai/types';
88
99
interface Props {
10-
promptUse: 'commits' | 'branches';
10+
promptUse: 'commits' | 'branches' | 'pullRequests';
1111
}
1212
1313
const { promptUse }: Props = $props();
@@ -18,8 +18,10 @@
1818
1919
if (promptUse === 'commits') {
2020
prompts = promptService.commitPrompts;
21-
} else {
21+
} else if (promptUse === 'branches') {
2222
prompts = promptService.branchPrompts;
23+
} else {
24+
prompts = promptService.prPrompts;
2325
}
2426
2527
const userPrompts = $derived(prompts.userPrompts);
@@ -42,7 +44,11 @@
4244
{#if prompts && $userPrompts}
4345
<div class="prompt-item__title">
4446
<h3 class="text-15 text-bold">
45-
{promptUse === 'commits' ? 'Commit message' : 'Branch name'}
47+
{promptUse === 'commits'
48+
? 'Commit message'
49+
: promptUse === 'branches'
50+
? 'Branch name'
51+
: 'PR message'}
4652
</h3>
4753
<Button kind="outline" icon="plus-small" onclick={createNewPrompt}>New prompt</Button>
4854
</div>

apps/desktop/src/components/AIPromptSelect.svelte

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
99
type Props = {
1010
projectId: string;
11-
promptUse: 'commits' | 'branches';
11+
promptUse: 'commits' | 'branches' | 'pullRequests';
1212
};
1313
1414
const { projectId, promptUse }: Props = $props();
@@ -21,9 +21,12 @@
2121
if (promptUse === 'commits') {
2222
prompts = promptService.commitPrompts;
2323
selectedPromptId = promptService.selectedCommitPromptId(projectId);
24-
} else {
24+
} else if (promptUse === 'branches') {
2525
prompts = promptService.branchPrompts;
2626
selectedPromptId = promptService.selectedBranchPromptId(projectId);
27+
} else {
28+
prompts = promptService.prPrompts;
29+
selectedPromptId = promptService.selectedPrPromptId(projectId);
2730
}
2831
2932
let userPrompts = prompts.userPrompts;
@@ -52,7 +55,11 @@
5255
<Select
5356
value={$selectedPromptId}
5457
options={allPrompts.map((p) => ({ label: p.name, value: p.id }))}
55-
label={promptUse === 'commits' ? 'Commit message' : 'Branch name'}
58+
label={promptUse === 'commits'
59+
? 'Commit message'
60+
: promptUse === 'branches'
61+
? 'Branch name'
62+
: 'PR message'}
5663
wide={true}
5764
searchable
5865
disabled={allPrompts.length === 1}

apps/desktop/src/components/CloudForm.svelte

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181

8282
<AiPromptSelect {projectId} promptUse="commits" />
8383
<AiPromptSelect {projectId} promptUse="branches" />
84+
<AiPromptSelect {projectId} promptUse="pullRequests" />
8485

8586
<Spacer margin={8} />
8687

apps/desktop/src/components/ReviewCreation.svelte

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import PrTemplateSection from '$components/PrTemplateSection.svelte';
1414
import MessageEditor from '$components/editor/MessageEditor.svelte';
1515
import MessageEditorInput from '$components/editor/MessageEditorInput.svelte';
16+
import { PROMPT_SERVICE } from '$lib/ai/promptService';
1617
import { AI_SERVICE } from '$lib/ai/service';
1718
import { BASE_BRANCH_SERVICE } from '$lib/baseBranch/baseBranchService.svelte';
1819
import { type Commit } from '$lib/branches/v3';
@@ -59,6 +60,7 @@
5960
const prService = $derived(forge.current.prService);
6061
const stackService = inject(STACK_SERVICE);
6162
const aiService = inject(AI_SERVICE);
63+
const promptService = inject(PROMPT_SERVICE);
6264
const remotesService = inject(REMOTES_SERVICE);
6365
const uiState = inject(UI_STATE);
6466
const settingsService = inject(SETTINGS_SERVICE);
@@ -352,11 +354,13 @@
352354
let firstToken = true;
353355
354356
try {
357+
const prTemplate = promptService.selectedPrPrompt(projectId);
355358
const description = await aiService?.describePR({
356359
title: $prTitle,
357360
body: $prBody,
358361
commitMessages: commits.map((c) => c.message),
359362
prBodyTemplate: prBody.default,
363+
prTemplate,
360364
onToken: (token) => {
361365
if (firstToken) {
362366
prBody.reset();

apps/desktop/src/components/profileSettings/AiSettings.svelte

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -463,14 +463,16 @@
463463
Custom AI prompts
464464
{/snippet}
465465
{#snippet description()}
466-
GitButler's AI assistant generates commit messages and branch names. Use default prompts or
467-
create your own. Assign prompts in the project settings.
466+
GitButler's AI assistant generates commit messages, branch names, and PR messages. Use default
467+
prompts or create your own. Assign prompts in the project settings.
468468
{/snippet}
469469

470470
<div class="prompt-groups">
471471
<AIPromptEdit promptUse="commits" />
472472
<Spacer margin={12} />
473473
<AIPromptEdit promptUse="branches" />
474+
<Spacer margin={12} />
475+
<AIPromptEdit promptUse="pullRequests" />
474476
</div>
475477
</Section>
476478

apps/desktop/src/lib/ai/promptService.ts

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import {
22
LONG_DEFAULT_BRANCH_TEMPLATE,
33
SHORT_DEFAULT_BRANCH_TEMPLATE,
44
LONG_DEFAULT_COMMIT_TEMPLATE,
5-
SHORT_DEFAULT_COMMIT_TEMPLATE
5+
SHORT_DEFAULT_COMMIT_TEMPLATE,
6+
SHORT_DEFAULT_PR_TEMPLATE
67
} from '$lib/ai/prompts';
78
import { InjectionToken } from '@gitbutler/core/context';
89
import { persisted, type Persisted } from '@gitbutler/shared/persisted';
@@ -11,7 +12,8 @@ import type { Prompt, Prompts, UserPrompt } from '$lib/ai/types';
1112

1213
enum PromptPersistedKey {
1314
Branch = 'aiBranchPrompts',
14-
Commit = 'aiCommitPrompts'
15+
Commit = 'aiCommitPrompts',
16+
PullRequest = 'aiPullRequestPrompts'
1517
}
1618

1719
export const PROMPT_SERVICE = new InjectionToken<PromptService>('PromptService');
@@ -31,6 +33,13 @@ export class PromptService {
3133
};
3234
}
3335

36+
get prPrompts(): Prompts {
37+
return {
38+
defaultPrompt: SHORT_DEFAULT_PR_TEMPLATE,
39+
userPrompts: persisted<UserPrompt[]>([], PromptPersistedKey.PullRequest)
40+
};
41+
}
42+
3443
selectedBranchPromptId(projectId: string): Persisted<string | undefined> {
3544
return persisted<string | undefined>(undefined, `${PromptPersistedKey.Branch}-${projectId}`);
3645
}
@@ -55,6 +64,21 @@ export class PromptService {
5564
return this.findPrompt(get(this.commitPrompts.userPrompts), id);
5665
}
5766

67+
selectedPrPromptId(projectId: string): Persisted<string | undefined> {
68+
return persisted<string | undefined>(
69+
undefined,
70+
`${PromptPersistedKey.PullRequest}-${projectId}`
71+
);
72+
}
73+
74+
selectedPrPrompt(projectId: string): Prompt | undefined {
75+
const id = get(this.selectedPrPromptId(projectId));
76+
77+
if (!id) return;
78+
79+
return this.findPrompt(get(this.prPrompts.userPrompts), id);
80+
}
81+
5882
findPrompt(prompts: UserPrompt[], promptId: string) {
5983
const prompt = prompts.find((userPrompt) => userPrompt.id === promptId)?.prompt;
6084

@@ -89,11 +113,16 @@ export class PromptService {
89113
return false;
90114
}
91115

92-
createDefaultUserPrompt(type: 'commits' | 'branches'): UserPrompt {
116+
createDefaultUserPrompt(type: 'commits' | 'branches' | 'pullRequests'): UserPrompt {
93117
return {
94118
id: crypto.randomUUID(),
95119
name: 'My prompt',
96-
prompt: type === 'branches' ? SHORT_DEFAULT_BRANCH_TEMPLATE : SHORT_DEFAULT_COMMIT_TEMPLATE
120+
prompt:
121+
type === 'branches'
122+
? SHORT_DEFAULT_BRANCH_TEMPLATE
123+
: type === 'commits'
124+
? SHORT_DEFAULT_COMMIT_TEMPLATE
125+
: SHORT_DEFAULT_PR_TEMPLATE
97126
};
98127
}
99128
}

0 commit comments

Comments
 (0)