378
379
private _buildTitleAndDescriptionPrompt(branchName: string, base: string, conversation: string | undefined, changeSummary: string): ICopilotUtilityChatMessage[] {
381
>
`Branch: ${branchName}`,
382
>
`Base branch: ${base}`,
383
>
];
384
>
if (changeSummary) {
385
>
userSections.push(`Changed files:\n${changeSummary}`);
386
>
}
387
>
if (conversation) {
388
userSections.push(`Conversation (the request that produced these changes):\n${conversation}`);
389
}
391
>
{
392
>
role: 'system',
393
>
content: [
394
>
'You write clear, concise GitHub pull request titles and descriptions.',
395
>
'The first line of your reply is the PR title: a short imperative summary under 72 characters, with no "Title:" prefix, no surrounding quotes, and no markdown heading.',
396
>
'After the title, add one blank line, then write the PR description in GitHub-flavored markdown.',
397
>
'Summarize what changed and why, grounded in the conversation and changed files. Use a short paragraph and/or bullet points.',
398
>
'Do not invent changes that are not supported by the provided context, and do not wrap the whole reply in code fences.',
399
>
].join(' '),
400
>
},
401
>
{
402
>
role: 'user',
403
>
content: userSections.join('\n\n'),
404
>
},
405
>
];
406
>
}
407
408
private _summarizeDiffsForPrompt(diffs: readonly ISessionFileDiff[]): string {
410
>
let length = 0;
411
>
for (const diff of diffs) {
412
>
const before = diff.before?.uri;
413
>
const after = diff.after?.uri;
414
>
const path = after ?? before ?? '(unknown)';
415
>
let kind = 'Edit';
416
>
if (!before && after) {
417
>
kind = 'Create';
418
>
} else if (before && !after) {
419
kind = 'Delete';
420
} else if (before && after && before !== after) {
421
kind = 'Rename';
422
}
424
>
lines.push(line);
425
>
// `+ 1` accounts for the newline that joins this line to the previous one.
426
>
length += line.length + (lines.length > 1 ? 1 : 0);
427
>
if (length > MAX_PR_CHANGE_SUMMARY_CHARS) {
428
lines.push('[file list truncated]');
429
break;
430
}
432
>
return lines.join('\n');
433
>
}
434
435
private _displayUri(uri: string): string {
437
>
const parsed = URI.parse(uri);
438
>
return parsed.scheme === 'file' ? parsed.fsPath : parsed.path || uri;
439
>
} catch {
440
return uri;
441
}
443
444
private _parseTitleAndDescription(raw: string): { title: string; description: string } | undefined {