edsger 0.19.9 → 0.19.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -16,6 +16,7 @@ import { logPhaseResult } from '../../utils/pipeline-logger.js';
|
|
|
16
16
|
import { runFeatureAnalysisPhase, runTechnicalDesignPhase, runBranchPlanningPhase, runCodeImplementationPhase, runFunctionalTestingPhase, runCodeRefinePhase, runCodeReviewPhase, } from './executors/phase-executor.js';
|
|
17
17
|
/**
|
|
18
18
|
* Map workflow phase names (underscore format) to phase runner functions
|
|
19
|
+
* Note: code_refine includes built-in verification loop (similar to technical_design)
|
|
19
20
|
*/
|
|
20
21
|
const PHASE_RUNNERS = {
|
|
21
22
|
feature_analysis: runFeatureAnalysisPhase,
|
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Code Refine Analyzer
|
|
3
3
|
* Processes GitHub PR review feedback and refines code accordingly
|
|
4
|
+
* Includes built-in verification loop that resolves PR comments and dismisses reviews
|
|
4
5
|
*/
|
|
5
6
|
import { EdsgerConfig } from '../../types/index.js';
|
|
7
|
+
import { type CodeRefineVerificationResult } from '../code-refine-verification/index.js';
|
|
8
|
+
export declare const MAX_REFINE_ITERATIONS = 10;
|
|
6
9
|
export interface CodeRefineOptions {
|
|
7
10
|
featureId: string;
|
|
8
11
|
githubToken: string;
|
|
@@ -34,8 +37,12 @@ export interface CodeRefineResult {
|
|
|
34
37
|
summary?: string;
|
|
35
38
|
filesModified?: string[];
|
|
36
39
|
commitsCreated?: number;
|
|
40
|
+
iterations?: number;
|
|
41
|
+
verificationResult?: CodeRefineVerificationResult;
|
|
37
42
|
}
|
|
38
43
|
/**
|
|
39
|
-
* Main code refine function
|
|
44
|
+
* Main code refine function with built-in verification loop
|
|
45
|
+
* Similar to technical-design, this includes an iterative improvement cycle:
|
|
46
|
+
* refine → verification → improve → re-refine (if needed)
|
|
40
47
|
*/
|
|
41
48
|
export declare const refineCodeFromPRFeedback: (options: CodeRefineOptions, config: EdsgerConfig) => Promise<CodeRefineResult>;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Code Refine Analyzer
|
|
3
3
|
* Processes GitHub PR review feedback and refines code accordingly
|
|
4
|
+
* Includes built-in verification loop that resolves PR comments and dismisses reviews
|
|
4
5
|
*/
|
|
5
6
|
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
6
7
|
import { logInfo, logError } from '../../utils/logger.js';
|
|
@@ -12,6 +13,9 @@ import { preparePhaseGitEnvironment, prepareCustomBranchGitEnvironment, hasUncom
|
|
|
12
13
|
import { getFeature } from '../../api/features/get-feature.js';
|
|
13
14
|
import { getReadyForReviewBranch, } from '../../services/branches.js';
|
|
14
15
|
import { parsePullRequestUrl } from './context.js';
|
|
16
|
+
import { verifyAndResolveComments, } from '../code-refine-verification/index.js';
|
|
17
|
+
// Maximum number of refine + verification iterations
|
|
18
|
+
export const MAX_REFINE_ITERATIONS = 10;
|
|
15
19
|
function userMessage(content) {
|
|
16
20
|
return {
|
|
17
21
|
type: 'user',
|
|
@@ -58,7 +62,9 @@ const pushChanges = (verbose) => {
|
|
|
58
62
|
}
|
|
59
63
|
};
|
|
60
64
|
/**
|
|
61
|
-
* Main code refine function
|
|
65
|
+
* Main code refine function with built-in verification loop
|
|
66
|
+
* Similar to technical-design, this includes an iterative improvement cycle:
|
|
67
|
+
* refine → verification → improve → re-refine (if needed)
|
|
62
68
|
*/
|
|
63
69
|
export const refineCodeFromPRFeedback = async (options, config) => {
|
|
64
70
|
const { featureId, githubToken, verbose } = options;
|
|
@@ -129,13 +135,14 @@ export const refineCodeFromPRFeedback = async (options, config) => {
|
|
|
129
135
|
? prepareCustomBranchGitEnvironment(branchName, 'main', verbose)
|
|
130
136
|
: preparePhaseGitEnvironment(featureId, 'main', verbose);
|
|
131
137
|
try {
|
|
132
|
-
// Fetch code refine context (PR reviews and comments)
|
|
138
|
+
// Fetch initial code refine context (PR reviews and comments)
|
|
133
139
|
if (verbose) {
|
|
134
140
|
logInfo('Fetching code refine context from GitHub PR...');
|
|
135
141
|
}
|
|
136
|
-
const
|
|
142
|
+
const initialContext = await fetchCodeRefineContext(featureId, githubToken, verbose, pullRequestUrl || undefined);
|
|
137
143
|
// Check if there are any reviews or comments to address
|
|
138
|
-
if (
|
|
144
|
+
if (initialContext.reviews.length === 0 &&
|
|
145
|
+
initialContext.reviewComments.length === 0) {
|
|
139
146
|
if (verbose) {
|
|
140
147
|
logInfo('✅ No review comments or change requests found. Nothing to refine.');
|
|
141
148
|
}
|
|
@@ -144,129 +151,43 @@ export const refineCodeFromPRFeedback = async (options, config) => {
|
|
|
144
151
|
status: 'success',
|
|
145
152
|
message: 'No review feedback to address',
|
|
146
153
|
summary: 'No change requests or review comments found on the PR',
|
|
154
|
+
iterations: 0,
|
|
147
155
|
};
|
|
148
156
|
}
|
|
149
157
|
if (verbose) {
|
|
150
|
-
logInfo(`📋 Found ${
|
|
158
|
+
logInfo(`📋 Found ${initialContext.reviews.length} reviews and ${initialContext.reviewComments.length} comments to address`);
|
|
151
159
|
}
|
|
152
|
-
//
|
|
153
|
-
|
|
154
|
-
let
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
|
|
160
|
-
if (verbose) {
|
|
161
|
-
logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to code refine context${currentBranch ? ` (including branch-specific for "${currentBranch.name}")` : ''}`);
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
catch (error) {
|
|
160
|
+
// Iterative refine → verification loop
|
|
161
|
+
let currentIteration = 0;
|
|
162
|
+
let verificationFailureContext;
|
|
163
|
+
let lastRefineResult = null;
|
|
164
|
+
let lastVerificationResult = null;
|
|
165
|
+
while (currentIteration < MAX_REFINE_ITERATIONS) {
|
|
166
|
+
currentIteration++;
|
|
166
167
|
if (verbose) {
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
}
|
|
170
|
-
// Feature branch switching is handled by preparePhaseGitEnvironment above
|
|
171
|
-
// Create prompt for code refine
|
|
172
|
-
const systemPrompt = createSystemPrompt();
|
|
173
|
-
const refinePrompt = createCodeRefinePrompt(featureId, context, feedbacksInfo, options.verificationFailureContext);
|
|
174
|
-
let lastAssistantResponse = '';
|
|
175
|
-
let structuredRefineResult = null;
|
|
176
|
-
if (verbose) {
|
|
177
|
-
logInfo('Starting Claude Code query for code refine...');
|
|
178
|
-
}
|
|
179
|
-
// Use Claude Code SDK to refine the code
|
|
180
|
-
for await (const message of query({
|
|
181
|
-
prompt: prompt(refinePrompt),
|
|
182
|
-
options: {
|
|
183
|
-
systemPrompt: {
|
|
184
|
-
type: 'preset',
|
|
185
|
-
preset: 'claude_code',
|
|
186
|
-
append: systemPrompt,
|
|
187
|
-
},
|
|
188
|
-
model: config.claude.model || 'sonnet',
|
|
189
|
-
maxTurns: 2000,
|
|
190
|
-
permissionMode: 'bypassPermissions',
|
|
191
|
-
},
|
|
192
|
-
})) {
|
|
193
|
-
if (verbose) {
|
|
194
|
-
logInfo(`Received message type: ${message.type}`);
|
|
195
|
-
}
|
|
196
|
-
// Stream the code refine process
|
|
197
|
-
if (message.type === 'assistant' && message.message?.content) {
|
|
198
|
-
for (const content of message.message.content) {
|
|
199
|
-
if (content.type === 'text') {
|
|
200
|
-
lastAssistantResponse += content.text + '\n';
|
|
201
|
-
if (verbose) {
|
|
202
|
-
console.log(`\n🔧 ${content.text}`);
|
|
203
|
-
}
|
|
204
|
-
}
|
|
205
|
-
else if (content.type === 'tool_use') {
|
|
206
|
-
if (verbose) {
|
|
207
|
-
console.log(`\n🛠️ ${content.name}: ${content.input.description || 'Running...'}`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
}
|
|
212
|
-
else if (message.type === 'result') {
|
|
213
|
-
if (message.subtype === 'success') {
|
|
214
|
-
logInfo('\n🛠️ Code refine completed, parsing results...');
|
|
215
|
-
try {
|
|
216
|
-
const responseText = message.result || lastAssistantResponse;
|
|
217
|
-
let jsonResult = null;
|
|
218
|
-
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
219
|
-
if (jsonBlockMatch) {
|
|
220
|
-
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
jsonResult = JSON.parse(responseText);
|
|
224
|
-
}
|
|
225
|
-
if (jsonResult && jsonResult.refine_result) {
|
|
226
|
-
structuredRefineResult = jsonResult.refine_result;
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
throw new Error('Invalid JSON structure');
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
catch (error) {
|
|
233
|
-
logError(`Failed to parse structured refine result: ${error}`);
|
|
234
|
-
structuredRefineResult = parseCodeRefineResponse(message.result || lastAssistantResponse);
|
|
235
|
-
}
|
|
168
|
+
if (currentIteration === 1) {
|
|
169
|
+
logInfo(`\n🔄 Starting refine iteration ${currentIteration}/${MAX_REFINE_ITERATIONS}`);
|
|
236
170
|
}
|
|
237
171
|
else {
|
|
238
|
-
|
|
239
|
-
if (message.subtype === 'error_max_turns') {
|
|
240
|
-
logError('💡 Try simplifying the changes or reducing scope');
|
|
241
|
-
}
|
|
242
|
-
if (lastAssistantResponse) {
|
|
243
|
-
try {
|
|
244
|
-
const responseText = lastAssistantResponse;
|
|
245
|
-
let jsonResult = null;
|
|
246
|
-
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
247
|
-
if (jsonBlockMatch) {
|
|
248
|
-
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
249
|
-
if (jsonResult && jsonResult.refine_result) {
|
|
250
|
-
structuredRefineResult = jsonResult.refine_result;
|
|
251
|
-
}
|
|
252
|
-
}
|
|
253
|
-
else {
|
|
254
|
-
structuredRefineResult = parseCodeRefineResponse(lastAssistantResponse);
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
catch (error) {
|
|
258
|
-
logError(`Failed to parse assistant response: ${error}`);
|
|
259
|
-
}
|
|
260
|
-
}
|
|
172
|
+
logInfo(`\n🔄 Retry iteration ${currentIteration}/${MAX_REFINE_ITERATIONS}: Improving based on verification feedback...`);
|
|
261
173
|
}
|
|
262
174
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
175
|
+
// Execute refine for this iteration
|
|
176
|
+
const refineResult = await executeRefineIteration(featureId, githubToken, config, pullRequestUrl || undefined, currentBranch, verificationFailureContext, verbose);
|
|
177
|
+
if (refineResult.status === 'error') {
|
|
178
|
+
// Refine failed - return error
|
|
179
|
+
return {
|
|
180
|
+
featureId,
|
|
181
|
+
status: 'error',
|
|
182
|
+
message: refineResult.message || 'Code refine failed',
|
|
183
|
+
iterations: currentIteration,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
186
|
+
lastRefineResult = refineResult;
|
|
187
|
+
// Push changes before verification
|
|
267
188
|
if (hasUncommittedChanges()) {
|
|
268
189
|
const uncommittedFiles = getUncommittedFiles();
|
|
269
|
-
const errorMsg = `Code refine completed but there are uncommitted changes.
|
|
190
|
+
const errorMsg = `Code refine completed but there are uncommitted changes.
|
|
270
191
|
|
|
271
192
|
Uncommitted files:
|
|
272
193
|
${uncommittedFiles.join('\n')}
|
|
@@ -277,6 +198,7 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
277
198
|
featureId,
|
|
278
199
|
status: 'error',
|
|
279
200
|
message: errorMsg,
|
|
201
|
+
iterations: currentIteration,
|
|
280
202
|
};
|
|
281
203
|
}
|
|
282
204
|
if (verbose) {
|
|
@@ -284,24 +206,6 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
284
206
|
}
|
|
285
207
|
try {
|
|
286
208
|
pushChanges(verbose);
|
|
287
|
-
const { summary, files_modified, commits_created } = structuredRefineResult;
|
|
288
|
-
if (verbose) {
|
|
289
|
-
logInfo(`Code refine completed for feature: ${featureId}`);
|
|
290
|
-
if (files_modified?.length > 0) {
|
|
291
|
-
logInfo(`Files modified: ${files_modified.join(', ')}`);
|
|
292
|
-
}
|
|
293
|
-
if (commits_created) {
|
|
294
|
-
logInfo(`Commits created: ${commits_created}`);
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
return {
|
|
298
|
-
featureId,
|
|
299
|
-
status: 'success',
|
|
300
|
-
message: 'Code successfully refined based on PR feedback',
|
|
301
|
-
summary: summary || 'Code refined based on PR review feedback',
|
|
302
|
-
filesModified: files_modified || [],
|
|
303
|
-
commitsCreated: commits_created || 1,
|
|
304
|
-
};
|
|
305
209
|
}
|
|
306
210
|
catch (pushError) {
|
|
307
211
|
logError(`Failed to push changes: ${pushError}`);
|
|
@@ -309,16 +213,77 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
309
213
|
featureId,
|
|
310
214
|
status: 'error',
|
|
311
215
|
message: `Code refined but failed to push: ${pushError}`,
|
|
216
|
+
iterations: currentIteration,
|
|
312
217
|
};
|
|
313
218
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
219
|
+
// Run verification
|
|
220
|
+
if (verbose) {
|
|
221
|
+
logInfo('\n🔍 Running verification to check if all comments are addressed...');
|
|
222
|
+
}
|
|
223
|
+
const verificationResult = await verifyAndResolveComments({
|
|
317
224
|
featureId,
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
225
|
+
githubToken,
|
|
226
|
+
config,
|
|
227
|
+
verbose,
|
|
228
|
+
});
|
|
229
|
+
lastVerificationResult = verificationResult;
|
|
230
|
+
// If verification passed, we're done!
|
|
231
|
+
if (verificationResult.status === 'success') {
|
|
232
|
+
if (verbose) {
|
|
233
|
+
logInfo('✅ Verification passed! All PR comments have been addressed and resolved.');
|
|
234
|
+
}
|
|
235
|
+
return {
|
|
236
|
+
featureId,
|
|
237
|
+
status: 'success',
|
|
238
|
+
message: verificationResult.message,
|
|
239
|
+
summary: lastRefineResult.summary || 'Code refined based on PR review feedback',
|
|
240
|
+
filesModified: lastRefineResult.files_modified || [],
|
|
241
|
+
commitsCreated: lastRefineResult.commits_created || 1,
|
|
242
|
+
iterations: currentIteration,
|
|
243
|
+
verificationResult,
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
// Verification failed - prepare context for retry
|
|
247
|
+
if (currentIteration < MAX_REFINE_ITERATIONS) {
|
|
248
|
+
const verificationData = verificationResult.data;
|
|
249
|
+
const suggestions = verificationData.suggestions || [];
|
|
250
|
+
const unresolvedCommentDetails = verificationData.unresolvedCommentDetails || [];
|
|
251
|
+
const unresolvedReviewDetails = verificationData.unresolvedReviewDetails;
|
|
252
|
+
verificationFailureContext = {
|
|
253
|
+
attempt: currentIteration + 1,
|
|
254
|
+
suggestions,
|
|
255
|
+
unresolvedCommentDetails,
|
|
256
|
+
unresolvedReviewDetails,
|
|
257
|
+
};
|
|
258
|
+
if (verbose) {
|
|
259
|
+
logInfo(`\n⚠️ Verification failed: ${verificationResult.message}`);
|
|
260
|
+
if (suggestions.length > 0) {
|
|
261
|
+
logInfo(`💡 Suggestions for next iteration:`);
|
|
262
|
+
suggestions.forEach((suggestion) => {
|
|
263
|
+
logInfo(` ${suggestion}`);
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
logInfo(`\n🔄 Will retry... (${MAX_REFINE_ITERATIONS - currentIteration} attempts remaining)`);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
else {
|
|
270
|
+
// Max iterations reached
|
|
271
|
+
if (verbose) {
|
|
272
|
+
logInfo(`\n⚠️ Maximum iterations (${MAX_REFINE_ITERATIONS}) reached. Verification still failing.`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
321
275
|
}
|
|
276
|
+
// Return last verification result (which failed)
|
|
277
|
+
return {
|
|
278
|
+
featureId,
|
|
279
|
+
status: 'error',
|
|
280
|
+
message: lastVerificationResult?.message || 'Verification failed after max iterations',
|
|
281
|
+
summary: lastRefineResult?.summary,
|
|
282
|
+
filesModified: lastRefineResult?.files_modified || [],
|
|
283
|
+
commitsCreated: lastRefineResult?.commits_created || 1,
|
|
284
|
+
iterations: currentIteration,
|
|
285
|
+
verificationResult: lastVerificationResult || undefined,
|
|
286
|
+
};
|
|
322
287
|
}
|
|
323
288
|
catch (error) {
|
|
324
289
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
@@ -334,6 +299,136 @@ Please ensure Claude Code commits all changes before completing the refine phase
|
|
|
334
299
|
cleanupGit();
|
|
335
300
|
}
|
|
336
301
|
};
|
|
302
|
+
/**
|
|
303
|
+
* Execute a single refine iteration
|
|
304
|
+
*/
|
|
305
|
+
async function executeRefineIteration(featureId, githubToken, config, pullRequestUrl, currentBranch, verificationFailureContext, verbose) {
|
|
306
|
+
// Fetch code refine context (PR reviews and comments)
|
|
307
|
+
const context = await fetchCodeRefineContext(featureId, githubToken, verbose, pullRequestUrl);
|
|
308
|
+
// Fetch additional feedbacks for code-refine phase
|
|
309
|
+
let feedbacksInfo;
|
|
310
|
+
try {
|
|
311
|
+
const feedbacksContext = await getFeedbacksForPhase({ featureId, verbose }, 'code_refine', currentBranch?.id);
|
|
312
|
+
if (feedbacksContext.feedbacks.length > 0) {
|
|
313
|
+
feedbacksInfo = await formatFeedbacksForContext(feedbacksContext);
|
|
314
|
+
if (verbose) {
|
|
315
|
+
logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to code refine context${currentBranch ? ` (including branch-specific for "${currentBranch.name}")` : ''}`);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
catch (error) {
|
|
320
|
+
if (verbose) {
|
|
321
|
+
logInfo(`Note: Could not fetch feedbacks (${error instanceof Error ? error.message : String(error)})`);
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
// Create prompt for code refine
|
|
325
|
+
const systemPrompt = createSystemPrompt();
|
|
326
|
+
const refinePrompt = createCodeRefinePrompt(featureId, context, feedbacksInfo, verificationFailureContext);
|
|
327
|
+
let lastAssistantResponse = '';
|
|
328
|
+
let structuredRefineResult = null;
|
|
329
|
+
if (verbose) {
|
|
330
|
+
logInfo('Starting Claude Code query for code refine...');
|
|
331
|
+
}
|
|
332
|
+
// Use Claude Code SDK to refine the code
|
|
333
|
+
for await (const message of query({
|
|
334
|
+
prompt: prompt(refinePrompt),
|
|
335
|
+
options: {
|
|
336
|
+
systemPrompt: {
|
|
337
|
+
type: 'preset',
|
|
338
|
+
preset: 'claude_code',
|
|
339
|
+
append: systemPrompt,
|
|
340
|
+
},
|
|
341
|
+
model: config.claude.model || 'sonnet',
|
|
342
|
+
maxTurns: 2000,
|
|
343
|
+
permissionMode: 'bypassPermissions',
|
|
344
|
+
},
|
|
345
|
+
})) {
|
|
346
|
+
if (verbose) {
|
|
347
|
+
logInfo(`Received message type: ${message.type}`);
|
|
348
|
+
}
|
|
349
|
+
// Stream the code refine process
|
|
350
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
351
|
+
for (const content of message.message.content) {
|
|
352
|
+
if (content.type === 'text') {
|
|
353
|
+
lastAssistantResponse += content.text + '\n';
|
|
354
|
+
if (verbose) {
|
|
355
|
+
console.log(`\n🔧 ${content.text}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
else if (content.type === 'tool_use') {
|
|
359
|
+
if (verbose) {
|
|
360
|
+
console.log(`\n🛠️ ${content.name}: ${content.input.description || 'Running...'}`);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (message.type === 'result') {
|
|
366
|
+
if (message.subtype === 'success') {
|
|
367
|
+
logInfo('\n🛠️ Code refine completed, parsing results...');
|
|
368
|
+
try {
|
|
369
|
+
const responseText = message.result || lastAssistantResponse;
|
|
370
|
+
let jsonResult = null;
|
|
371
|
+
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
372
|
+
if (jsonBlockMatch) {
|
|
373
|
+
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
jsonResult = JSON.parse(responseText);
|
|
377
|
+
}
|
|
378
|
+
if (jsonResult && jsonResult.refine_result) {
|
|
379
|
+
structuredRefineResult = jsonResult.refine_result;
|
|
380
|
+
}
|
|
381
|
+
else {
|
|
382
|
+
throw new Error('Invalid JSON structure');
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
catch (error) {
|
|
386
|
+
logError(`Failed to parse structured refine result: ${error}`);
|
|
387
|
+
structuredRefineResult = parseCodeRefineResponse(message.result || lastAssistantResponse);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
else {
|
|
391
|
+
logError(`\n⚠️ Code refine incomplete: ${message.subtype}`);
|
|
392
|
+
if (message.subtype === 'error_max_turns') {
|
|
393
|
+
logError('💡 Try simplifying the changes or reducing scope');
|
|
394
|
+
}
|
|
395
|
+
if (lastAssistantResponse) {
|
|
396
|
+
try {
|
|
397
|
+
const responseText = lastAssistantResponse;
|
|
398
|
+
let jsonResult = null;
|
|
399
|
+
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
400
|
+
if (jsonBlockMatch) {
|
|
401
|
+
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
402
|
+
if (jsonResult && jsonResult.refine_result) {
|
|
403
|
+
structuredRefineResult = jsonResult.refine_result;
|
|
404
|
+
}
|
|
405
|
+
}
|
|
406
|
+
else {
|
|
407
|
+
structuredRefineResult = parseCodeRefineResponse(lastAssistantResponse);
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
catch (error) {
|
|
411
|
+
logError(`Failed to parse assistant response: ${error}`);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (structuredRefineResult) {
|
|
418
|
+
return {
|
|
419
|
+
status: 'success',
|
|
420
|
+
summary: structuredRefineResult.summary,
|
|
421
|
+
files_modified: structuredRefineResult.files_modified,
|
|
422
|
+
commits_created: structuredRefineResult.commits_created,
|
|
423
|
+
};
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
return {
|
|
427
|
+
status: 'error',
|
|
428
|
+
message: 'Code refine failed or incomplete',
|
|
429
|
+
};
|
|
430
|
+
}
|
|
431
|
+
}
|
|
337
432
|
function parseCodeRefineResponse(response) {
|
|
338
433
|
const summaryMatch = response.match(/## Refine Summary\n([\s\S]*?)(?=\n##|\n\n|$)/);
|
|
339
434
|
const summary = summaryMatch
|