Skip to content

Commit 984dd82

Browse files
committed
Fixes output format of generate-commits responses
1 parent 4cd36c4 commit 984dd82

File tree

2 files changed

+39
-85
lines changed

2 files changed

+39
-85
lines changed

src/plus/ai/aiProviderService.ts

Lines changed: 28 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,7 +1160,7 @@ export class AIProviderService implements Disposable {
11601160
return firstAttemptResult;
11611161
}
11621162

1163-
conversationMessages = firstAttemptResult.conversationMessages;
1163+
conversationMessages = [...firstAttemptResult.conversationMessages];
11641164
let rq = firstAttemptResult.response;
11651165

11661166
while (attempt < maxAttempts) {
@@ -1238,7 +1238,11 @@ export class AIProviderService implements Disposable {
12381238
progress?: ProgressOptions;
12391239
generateCommits?: boolean;
12401240
},
1241-
): Promise<{ response: AIRequestResult; conversationMessages: AIChatMessage[] } | 'cancelled' | undefined> {
1241+
): Promise<
1242+
| { readonly response: AIRequestResult; readonly conversationMessages: readonly AIChatMessage[] }
1243+
| 'cancelled'
1244+
| undefined
1245+
> {
12421246
let storedPrompt = '';
12431247
const rq = await this.sendRequest(
12441248
'generate-rebase',
@@ -2202,7 +2206,7 @@ export class AIProviderService implements Disposable {
22022206
}
22032207

22042208
let rq = firstAttemptResult.response;
2205-
conversationMessages = firstAttemptResult.conversationMessages;
2209+
conversationMessages = [...firstAttemptResult.conversationMessages];
22062210

22072211
while (attempt < maxAttempts) {
22082212
const validationResult = this.validateCommitsResponse(rq, hunks, existingCommits);
@@ -2368,29 +2372,17 @@ export class AIProviderService implements Disposable {
23682372
}
23692373
| { isValid: false; errorMessage: string; retryPrompt: string } {
23702374
try {
2375+
const rqContent = parseOutputResult(rq.content);
2376+
23712377
// Parse the JSON response
23722378
const commits: {
23732379
readonly message: string;
23742380
readonly explanation: string;
23752381
readonly hunks: { hunk: number }[];
2376-
}[] = JSON.parse(rq.content);
2382+
}[] = JSON.parse(rqContent);
23772383

23782384
if (!Array.isArray(commits)) {
2379-
const errorMessage = 'Invalid commits result: response is not an array';
2380-
const retryPrompt = dedent(`
2381-
Your previous response is not a valid JSON array. Please provide a JSON array of commits following this structure:
2382-
[
2383-
{
2384-
"message": "commit message",
2385-
"explanation": "detailed explanation",
2386-
"hunks": [{"hunk": 1}, {"hunk": 2}]
2387-
}
2388-
]
2389-
2390-
Here was your previous response:
2391-
${rq.content}
2392-
`);
2393-
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
2385+
throw new Error('Commits result is not an array');
23942386
}
23952387

23962388
// Collect all hunk indices used in the commits
@@ -2399,23 +2391,7 @@ export class AIProviderService implements Disposable {
23992391

24002392
for (const commit of commits) {
24012393
if (!commit.hunks || !Array.isArray(commit.hunks)) {
2402-
const errorMessage = 'Invalid commit structure: missing or invalid hunks array';
2403-
const retryPrompt = dedent(`
2404-
Your previous response has an invalid commit structure. Each commit must have "message", "explanation", and "hunks" properties, where "hunks" is an array of objects with "hunk" numbers.
2405-
2406-
Here was your previous response:
2407-
${rq.content}
2408-
2409-
Please provide a valid JSON array of commits following this structure:
2410-
[
2411-
{
2412-
"message": "commit message",
2413-
"explanation": "detailed explanation",
2414-
"hunks": [{"hunk": 1}, {"hunk": 2}]
2415-
}
2416-
]
2417-
`);
2418-
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
2394+
throw new Error('Invalid commit structure: missing or invalid hunks array');
24192395
}
24202396

24212397
for (const hunkRef of commit.hunks) {
@@ -2435,9 +2411,6 @@ export class AIProviderService implements Disposable {
24352411
24362412
Duplicate hunks: ${duplicateHunks.join(', ')}
24372413
2438-
Here was your previous response:
2439-
${rq.content}
2440-
24412414
Please provide a corrected response where each hunk is used only once.
24422415
`);
24432416
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
@@ -2461,9 +2434,6 @@ export class AIProviderService implements Disposable {
24612434
24622435
Missing hunks: ${missingHunkIndices.join(', ')}
24632436
2464-
Here was your previous response:
2465-
${rq.content}
2466-
24672437
Please provide a corrected response that includes all hunks.
24682438
`);
24692439
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
@@ -2477,9 +2447,6 @@ export class AIProviderService implements Disposable {
24772447
24782448
Extra hunks: ${extraHunkIndices.join(', ')}
24792449
2480-
Here was your previous response:
2481-
${rq.content}
2482-
24832450
Please provide a corrected response that only uses the provided hunks.
24842451
`);
24852452
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
@@ -2493,9 +2460,6 @@ export class AIProviderService implements Disposable {
24932460
24942461
Illegally assigned hunks: ${illegallyAssignedHunkIndices.join(', ')}
24952462
2496-
Here was your previous response:
2497-
${rq.content}
2498-
24992463
Please provide a corrected response that does not reassign existing hunks.
25002464
`);
25012465
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
@@ -2505,21 +2469,22 @@ export class AIProviderService implements Disposable {
25052469
return { isValid: true, commits: commits };
25062470
} catch {
25072471
// Handle any errors during hunk validation (e.g., malformed commit structure)
2508-
const errorMessage = 'Invalid commit structure in commits result';
2472+
const errorMessage = 'Invalid response from the AI model';
25092473
const retryPrompt = dedent(`
2510-
Your previous response has an invalid commit structure. Each commit must have "message", "explanation", and "hunks" properties, where "hunks" is an array of objects with "hunk" numbers.
2474+
Your previous response has an invalid commit structure. Ensure each commit has "message", "explanation", and "hunks" properties, where "hunks" is an array of objects with "hunk" numbers.
25112475
2512-
Here was your previous response:
2513-
${rq.content}
2514-
2515-
Please provide a valid JSON array of commits following this structure:
2476+
Please provide the valid JSON structure below inside a <output> tag and include no other text:
2477+
<output>
25162478
[
2517-
{
2518-
"message": "commit message",
2519-
"explanation": "detailed explanation",
2520-
"hunks": [{"hunk": 1}, {"hunk": 2}]
2521-
}
2479+
{
2480+
"message": "[commit message here]",
2481+
"explanation": "[detailed explanation of changes here]",
2482+
"hunks": [{"hunk": [index from hunk_map]}, {"hunk": [index from hunk_map]}]
2483+
}
25222484
]
2485+
</output>
2486+
2487+
Text in [] brackets above should be replaced with your own text, not including the brackets. Return only the <output> tag and no other text.
25232488
`);
25242489
return { isValid: false, errorMessage: errorMessage, retryPrompt: retryPrompt };
25252490
}
@@ -2555,6 +2520,10 @@ async function showConfirmAIProviderToS(storage: Storage): Promise<boolean> {
25552520
return false;
25562521
}
25572522

2523+
function parseOutputResult(result: string): string {
2524+
return result.match(/<output>([\s\S]*?)(?:<\/output>|$)/)?.[1]?.trim() ?? '';
2525+
}
2526+
25582527
function parseSummarizeResult(result: string): NonNullable<AISummarizeResult['parsed']> {
25592528
result = result.trim();
25602529
const summary = result.match(/<summary>([\s\S]*?)(?:<\/summary>|$)/)?.[1]?.trim() ?? undefined;

src/plus/ai/prompts.ts

Lines changed: 11 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ Convert the user's natural language query into the appropriate search operators.
371371
};
372372

373373
export const generateCommits: PromptTemplate<'generate-commits'> = {
374-
id: 'generate-commits',
374+
id: 'generate-commits_v2',
375375
variables: ['hunks', 'existingCommits', 'hunkMap', 'instructions'],
376376
template: `You are an advanced AI programming assistant tasked with organizing code changes into commits. Your goal is to create a complete set of commits that are related, grouped logically, atomic, and easy to review. You will be working with individual code hunks and may have some existing commits that already have hunks assigned.
377377
@@ -413,42 +413,27 @@ Output your complete commit organization as a JSON array. Each commit in the arr
413413
- "hunks": An array of objects, each representing a hunk in the commit. Each hunk object should have:
414414
- "hunk": The hunk index (number) from the hunk_map
415415
416-
Here's an example of the expected JSON structure:
417-
416+
Write the JSON structure below inside a <output> tag and include no other text:
417+
<output>
418418
[
419-
{
420-
"message": "feat: add user authentication",
421-
"explanation": "Implements user login and registration functionality with proper validation",
422-
"hunks": [
423-
{
424-
"hunk": 1
425-
},
426-
{
427-
"hunk": 3
428-
}
429-
]
430-
},
431-
{
432-
"message": "fix: handle edge cases in validation",
433-
"explanation": "Adds proper error handling for invalid input scenarios",
434-
"hunks": [
435-
{
436-
"hunk": 2
437-
}
438-
]
439-
}
419+
{
420+
"message": "[commit message here]",
421+
"explanation": "[detailed explanation of changes here]",
422+
"hunks": [{"hunk": [index from hunk_map]}, {"hunk": [index from hunk_map]}]
423+
}
440424
]
425+
</output>
441426
442427
Remember:
428+
- Text in [] brackets above should be replaced with your own text, not including the brackets
443429
- Include all existing commits unchanged
444430
- Organize all unassigned hunks into new commits
445431
- Every hunk must be assigned to exactly one commit
446432
- Base your organization on the actual code changes in the hunks
447433
448434
\${instructions}
449435
450-
Now, proceed with your analysis and organization of the commits. Output only the JSON array containing the complete commit organization, and nothing else.
451-
Do not include any preceeding or succeeding text or markup, such as "Here are the commits:" or "Here is a valid JSON array of commits:".
436+
Now, proceed with your analysis and organization of the commits. Return only the <output> tag and no other text.
452437
`,
453438
};
454439

0 commit comments

Comments
 (0)