edsger 0.2.13 → 0.3.0
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.
- package/dist/phases/code-refine/analyzer.d.ts +25 -0
- package/dist/phases/code-refine/analyzer.js +425 -0
- package/dist/phases/code-refine/context-fetcher.d.ts +78 -0
- package/dist/phases/code-refine/context-fetcher.js +315 -0
- package/dist/phases/code-refine/index.d.ts +7 -0
- package/dist/phases/code-refine/index.js +7 -0
- package/dist/phases/code-refine-verification/index.d.ts +6 -0
- package/dist/phases/code-refine-verification/index.js +6 -0
- package/dist/phases/code-refine-verification/verifier.d.ts +25 -0
- package/dist/phases/code-refine-verification/verifier.js +205 -0
- package/dist/phases/technical-design/analyzer.js +12 -9
- package/dist/services/audit-logs.d.ts +2 -2
- package/dist/services/feedbacks.d.ts +8 -4
- package/dist/services/feedbacks.js +23 -12
- package/dist/types/features.d.ts +1 -0
- package/dist/types/pipeline.d.ts +1 -1
- package/dist/workflow-runner/config/phase-configs.js +52 -0
- package/dist/workflow-runner/executors/phase-executor.d.ts +2 -2
- package/dist/workflow-runner/executors/phase-executor.js +2 -2
- package/dist/workflow-runner/feature-workflow-runner.js +2 -0
- package/dist/workflow-runner/pipeline-runner.js +22 -1
- package/package.json +1 -1
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Refine Analyzer
|
|
3
|
+
* Processes GitHub PR review feedback and refines code accordingly
|
|
4
|
+
*/
|
|
5
|
+
import { EdsgerConfig } from '../../types/index.js';
|
|
6
|
+
export interface CodeRefineOptions {
|
|
7
|
+
featureId: string;
|
|
8
|
+
mcpServerUrl: string;
|
|
9
|
+
mcpToken: string;
|
|
10
|
+
githubToken: string;
|
|
11
|
+
verbose?: boolean;
|
|
12
|
+
}
|
|
13
|
+
export interface CodeRefineResult {
|
|
14
|
+
featureId: string;
|
|
15
|
+
status: 'success' | 'error';
|
|
16
|
+
message: string;
|
|
17
|
+
summary?: string;
|
|
18
|
+
filesModified?: string[];
|
|
19
|
+
commitsCreated?: number;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Main code refine function
|
|
23
|
+
*/
|
|
24
|
+
export declare const refineCodeFromPRFeedback: (options: CodeRefineOptions, config: EdsgerConfig) => Promise<CodeRefineResult>;
|
|
25
|
+
export declare function checkCodeRefineRequirements(): Promise<boolean>;
|
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Code Refine Analyzer
|
|
3
|
+
* Processes GitHub PR review feedback and refines code accordingly
|
|
4
|
+
*/
|
|
5
|
+
import { query } from '@anthropic-ai/claude-code';
|
|
6
|
+
import { logInfo, logError } from '../../utils/logger.js';
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { fetchCodeRefineContext, formatContextForPrompt, } from './context-fetcher.js';
|
|
9
|
+
import { getFeedbacksForPhase, formatFeedbacksForContext, } from '../../services/feedbacks.js';
|
|
10
|
+
function userMessage(content) {
|
|
11
|
+
return {
|
|
12
|
+
type: 'user',
|
|
13
|
+
message: { role: 'user', content: content },
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
async function* prompt(refinePrompt) {
|
|
17
|
+
yield userMessage(refinePrompt);
|
|
18
|
+
await new Promise((res) => setTimeout(res, 10000));
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Get current Git branch name
|
|
22
|
+
*/
|
|
23
|
+
const getCurrentBranch = () => {
|
|
24
|
+
try {
|
|
25
|
+
return execSync('git branch --show-current', { encoding: 'utf-8' }).trim();
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
throw new Error(`Failed to get current branch: ${error instanceof Error ? error.message : String(error)}`);
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Switch to a specific Git branch
|
|
33
|
+
*/
|
|
34
|
+
const switchToBranch = (branch, verbose) => {
|
|
35
|
+
try {
|
|
36
|
+
if (verbose) {
|
|
37
|
+
logInfo(`🔄 Switching to branch ${branch}...`);
|
|
38
|
+
}
|
|
39
|
+
execSync(`git checkout ${branch}`, { encoding: 'utf-8' });
|
|
40
|
+
if (verbose) {
|
|
41
|
+
logInfo(`✅ Switched to ${branch} branch`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
catch (error) {
|
|
45
|
+
throw new Error(`Failed to switch to ${branch} branch: ${error instanceof Error ? error.message : String(error)}`);
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/**
|
|
49
|
+
* Pull latest changes from remote
|
|
50
|
+
*/
|
|
51
|
+
const pullLatestChanges = (verbose) => {
|
|
52
|
+
try {
|
|
53
|
+
if (verbose) {
|
|
54
|
+
logInfo(`📥 Pulling latest changes from remote...`);
|
|
55
|
+
}
|
|
56
|
+
execSync('git pull origin $(git branch --show-current) --rebase', {
|
|
57
|
+
encoding: 'utf-8',
|
|
58
|
+
});
|
|
59
|
+
if (verbose) {
|
|
60
|
+
logInfo(`✅ Successfully pulled latest changes`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new Error(`Failed to pull latest changes: ${error instanceof Error ? error.message : String(error)}`);
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
/**
|
|
68
|
+
* Push changes to remote branch
|
|
69
|
+
*/
|
|
70
|
+
const pushChanges = (verbose) => {
|
|
71
|
+
try {
|
|
72
|
+
if (verbose) {
|
|
73
|
+
logInfo(`📤 Pushing changes to remote...`);
|
|
74
|
+
}
|
|
75
|
+
execSync('git push origin $(git branch --show-current)', {
|
|
76
|
+
encoding: 'utf-8',
|
|
77
|
+
});
|
|
78
|
+
if (verbose) {
|
|
79
|
+
logInfo(`✅ Successfully pushed changes`);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
throw new Error(`Failed to push changes: ${error instanceof Error ? error.message : String(error)}`);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Main code refine function
|
|
88
|
+
*/
|
|
89
|
+
export const refineCodeFromPRFeedback = async (options, config) => {
|
|
90
|
+
const { featureId, mcpServerUrl, mcpToken, githubToken, verbose } = options;
|
|
91
|
+
if (verbose) {
|
|
92
|
+
logInfo(`Starting code refine for feature ID: ${featureId}`);
|
|
93
|
+
logInfo(`Using MCP server: ${mcpServerUrl}`);
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
// Fetch code refine context (PR reviews and comments)
|
|
97
|
+
if (verbose) {
|
|
98
|
+
logInfo('Fetching code refine context from GitHub PR...');
|
|
99
|
+
}
|
|
100
|
+
const context = await fetchCodeRefineContext(mcpServerUrl, mcpToken, featureId, githubToken, verbose);
|
|
101
|
+
// Check if there are any reviews or comments to address
|
|
102
|
+
if (context.reviews.length === 0 && context.reviewComments.length === 0) {
|
|
103
|
+
if (verbose) {
|
|
104
|
+
logInfo('✅ No review comments or change requests found. Nothing to refine.');
|
|
105
|
+
}
|
|
106
|
+
return {
|
|
107
|
+
featureId,
|
|
108
|
+
status: 'success',
|
|
109
|
+
message: 'No review feedback to address',
|
|
110
|
+
summary: 'No change requests or review comments found on the PR',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (verbose) {
|
|
114
|
+
logInfo(`📋 Found ${context.reviews.length} reviews and ${context.reviewComments.length} comments to address`);
|
|
115
|
+
}
|
|
116
|
+
// Fetch additional feedbacks for code-refine phase
|
|
117
|
+
let feedbacksInfo;
|
|
118
|
+
try {
|
|
119
|
+
const feedbacksContext = await getFeedbacksForPhase({ featureId, mcpServerUrl, mcpToken, verbose }, 'code_refine');
|
|
120
|
+
if (feedbacksContext.feedbacks.length > 0) {
|
|
121
|
+
feedbacksInfo = formatFeedbacksForContext(feedbacksContext);
|
|
122
|
+
if (verbose) {
|
|
123
|
+
logInfo(`Added ${feedbacksContext.feedbacks.length} human feedbacks to code refine context`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
catch (error) {
|
|
128
|
+
if (verbose) {
|
|
129
|
+
logInfo(`Note: Could not fetch feedbacks (${error instanceof Error ? error.message : String(error)})`);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Get current branch and switch to dev/feature-id if needed
|
|
133
|
+
const currentBranch = getCurrentBranch();
|
|
134
|
+
const targetBranch = `dev/${featureId}`;
|
|
135
|
+
if (currentBranch !== targetBranch) {
|
|
136
|
+
if (verbose) {
|
|
137
|
+
logInfo(`Current branch is ${currentBranch}, switching to ${targetBranch}...`);
|
|
138
|
+
}
|
|
139
|
+
switchToBranch(targetBranch, verbose);
|
|
140
|
+
}
|
|
141
|
+
// Pull latest changes
|
|
142
|
+
pullLatestChanges(verbose);
|
|
143
|
+
// Create prompt for code refine
|
|
144
|
+
const systemPrompt = createSystemPrompt(config);
|
|
145
|
+
const refinePrompt = createCodeRefinePrompt(featureId, context, feedbacksInfo);
|
|
146
|
+
let lastAssistantResponse = '';
|
|
147
|
+
let structuredRefineResult = null;
|
|
148
|
+
if (verbose) {
|
|
149
|
+
logInfo('Starting Claude Code query for code refine...');
|
|
150
|
+
}
|
|
151
|
+
// Use Claude Code SDK to refine the code
|
|
152
|
+
for await (const message of query({
|
|
153
|
+
prompt: prompt(refinePrompt),
|
|
154
|
+
options: {
|
|
155
|
+
appendSystemPrompt: systemPrompt,
|
|
156
|
+
model: config.claude.model || 'sonnet',
|
|
157
|
+
maxTurns: 2000,
|
|
158
|
+
permissionMode: 'bypassPermissions',
|
|
159
|
+
},
|
|
160
|
+
})) {
|
|
161
|
+
if (verbose) {
|
|
162
|
+
logInfo(`Received message type: ${message.type}`);
|
|
163
|
+
}
|
|
164
|
+
// Stream the code refine process
|
|
165
|
+
if (message.type === 'assistant' && message.message?.content) {
|
|
166
|
+
for (const content of message.message.content) {
|
|
167
|
+
if (content.type === 'text') {
|
|
168
|
+
lastAssistantResponse += content.text + '\n';
|
|
169
|
+
if (verbose) {
|
|
170
|
+
console.log(`\n🔧 ${content.text}`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
else if (content.type === 'tool_use') {
|
|
174
|
+
if (verbose) {
|
|
175
|
+
console.log(`\n🛠️ ${content.name}: ${content.input.description || 'Running...'}`);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
else if (message.type === 'result') {
|
|
181
|
+
if (message.subtype === 'success') {
|
|
182
|
+
logInfo('\n🛠️ Code refine completed, parsing results...');
|
|
183
|
+
try {
|
|
184
|
+
const responseText = message.result || lastAssistantResponse;
|
|
185
|
+
let jsonResult = null;
|
|
186
|
+
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
187
|
+
if (jsonBlockMatch) {
|
|
188
|
+
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
jsonResult = JSON.parse(responseText);
|
|
192
|
+
}
|
|
193
|
+
if (jsonResult && jsonResult.refine_result) {
|
|
194
|
+
structuredRefineResult = jsonResult.refine_result;
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
throw new Error('Invalid JSON structure');
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
catch (error) {
|
|
201
|
+
logError(`Failed to parse structured refine result: ${error}`);
|
|
202
|
+
structuredRefineResult = parseCodeRefineResponse(message.result || lastAssistantResponse);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
206
|
+
logError(`\n⚠️ Code refine incomplete: ${message.subtype}`);
|
|
207
|
+
if (message.subtype === 'error_max_turns') {
|
|
208
|
+
logError('💡 Try simplifying the changes or reducing scope');
|
|
209
|
+
}
|
|
210
|
+
if (lastAssistantResponse) {
|
|
211
|
+
try {
|
|
212
|
+
const responseText = lastAssistantResponse;
|
|
213
|
+
let jsonResult = null;
|
|
214
|
+
const jsonBlockMatch = responseText.match(/```json\s*\n([\s\S]*?)\n\s*```/);
|
|
215
|
+
if (jsonBlockMatch) {
|
|
216
|
+
jsonResult = JSON.parse(jsonBlockMatch[1]);
|
|
217
|
+
if (jsonResult && jsonResult.refine_result) {
|
|
218
|
+
structuredRefineResult = jsonResult.refine_result;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
else {
|
|
222
|
+
structuredRefineResult = parseCodeRefineResponse(lastAssistantResponse);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
catch (error) {
|
|
226
|
+
logError(`Failed to parse assistant response: ${error}`);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
// Push changes to remote
|
|
233
|
+
if (structuredRefineResult) {
|
|
234
|
+
if (verbose) {
|
|
235
|
+
logInfo('📤 Pushing refined code to remote...');
|
|
236
|
+
}
|
|
237
|
+
try {
|
|
238
|
+
pushChanges(verbose);
|
|
239
|
+
const { summary, files_modified, commits_created } = structuredRefineResult;
|
|
240
|
+
if (verbose) {
|
|
241
|
+
logInfo(`Code refine completed for feature: ${featureId}`);
|
|
242
|
+
if (files_modified?.length > 0) {
|
|
243
|
+
logInfo(`Files modified: ${files_modified.join(', ')}`);
|
|
244
|
+
}
|
|
245
|
+
if (commits_created) {
|
|
246
|
+
logInfo(`Commits created: ${commits_created}`);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return {
|
|
250
|
+
featureId,
|
|
251
|
+
status: 'success',
|
|
252
|
+
message: 'Code successfully refined based on PR feedback',
|
|
253
|
+
summary: summary || 'Code refined based on PR review feedback',
|
|
254
|
+
filesModified: files_modified || [],
|
|
255
|
+
commitsCreated: commits_created || 1,
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
catch (pushError) {
|
|
259
|
+
logError(`Failed to push changes: ${pushError}`);
|
|
260
|
+
return {
|
|
261
|
+
featureId,
|
|
262
|
+
status: 'error',
|
|
263
|
+
message: `Code refined but failed to push: ${pushError}`,
|
|
264
|
+
};
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
return {
|
|
269
|
+
featureId,
|
|
270
|
+
status: 'error',
|
|
271
|
+
message: 'Code refine failed or incomplete',
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
catch (error) {
|
|
276
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
277
|
+
logError(`Code refine failed: ${errorMessage}`);
|
|
278
|
+
return {
|
|
279
|
+
featureId,
|
|
280
|
+
status: 'error',
|
|
281
|
+
message: `Code refine failed: ${errorMessage}`,
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
function createSystemPrompt(_config) {
|
|
286
|
+
return `You are an expert software engineer specializing in addressing code review feedback. Your goal is to carefully analyze review comments and refine the code to address all concerns raised by human reviewers.
|
|
287
|
+
|
|
288
|
+
**Your Role**: Refine code based on PR review feedback while maintaining code quality and functionality.
|
|
289
|
+
|
|
290
|
+
**Available Tools**:
|
|
291
|
+
- Bash: Run commands, tests, and git operations
|
|
292
|
+
- Glob: Find files and understand project structure
|
|
293
|
+
- Read: Examine existing code and files
|
|
294
|
+
- Edit: Modify existing files to address feedback
|
|
295
|
+
- Write: Create new files if necessary
|
|
296
|
+
- TodoWrite: Track code refine tasks (use proactively)
|
|
297
|
+
|
|
298
|
+
**Code Refine Process**:
|
|
299
|
+
1. **Analyze Feedback**: Carefully study all review comments and change requests
|
|
300
|
+
2. **Understand Context**: Review the code, technical design, and related files
|
|
301
|
+
3. **Plan Changes**: Create a systematic plan to address each review comment
|
|
302
|
+
4. **Refine Code**: Make targeted, thoughtful changes that address the feedback
|
|
303
|
+
5. **Test Changes**: Ensure your changes work and don't break functionality
|
|
304
|
+
6. **Commit Changes**: Create clear, descriptive commits for your refinements
|
|
305
|
+
7. **Document**: Explain what changes were made and why
|
|
306
|
+
|
|
307
|
+
**Important Guidelines**:
|
|
308
|
+
- Address ALL review comments and change requests
|
|
309
|
+
- Maintain code quality and follow best practices
|
|
310
|
+
- Preserve existing functionality
|
|
311
|
+
- Write clear commit messages that reference the feedback
|
|
312
|
+
- Test your changes thoroughly
|
|
313
|
+
- Be respectful of the reviewer's time and expertise
|
|
314
|
+
|
|
315
|
+
**CRITICAL - Result Format**:
|
|
316
|
+
You MUST end your response with a JSON object containing the code refine results in this EXACT format:
|
|
317
|
+
|
|
318
|
+
\`\`\`json
|
|
319
|
+
{
|
|
320
|
+
"refine_result": {
|
|
321
|
+
"feature_id": "FEATURE_ID_PLACEHOLDER",
|
|
322
|
+
"summary": "Brief description of changes made",
|
|
323
|
+
"files_modified": ["file1.ts", "file2.tsx"],
|
|
324
|
+
"commits_created": 1,
|
|
325
|
+
"feedback_addressed": [
|
|
326
|
+
{
|
|
327
|
+
"comment_id": "Comment reference or ID",
|
|
328
|
+
"issue": "Description of the reviewer's concern",
|
|
329
|
+
"resolution": "Description of how it was addressed",
|
|
330
|
+
"files": ["path/to/file.ts"]
|
|
331
|
+
}
|
|
332
|
+
]
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
\`\`\`
|
|
336
|
+
|
|
337
|
+
Focus on systematic code refinement based on the provided PR review feedback.`;
|
|
338
|
+
}
|
|
339
|
+
function createCodeRefinePrompt(featureId, context, feedbacksInfo) {
|
|
340
|
+
let contextInfo = formatContextForPrompt(context);
|
|
341
|
+
if (feedbacksInfo) {
|
|
342
|
+
contextInfo = contextInfo + '\n\n' + feedbacksInfo;
|
|
343
|
+
}
|
|
344
|
+
return `Refine code based on PR review feedback for feature: ${featureId}
|
|
345
|
+
|
|
346
|
+
${contextInfo}
|
|
347
|
+
|
|
348
|
+
## Code Refine Instructions
|
|
349
|
+
|
|
350
|
+
Follow this systematic approach:
|
|
351
|
+
|
|
352
|
+
1. **Analyze All Feedback**: Study all review comments and change requests above:
|
|
353
|
+
- What specific concerns were raised?
|
|
354
|
+
- Which files and code sections need changes?
|
|
355
|
+
- What are the underlying issues?
|
|
356
|
+
- Are there any patterns in the feedback?
|
|
357
|
+
|
|
358
|
+
2. **Examine Current Code**: Use Read and Glob tools to:
|
|
359
|
+
- Understand the current implementation
|
|
360
|
+
- Identify the code sections mentioned in reviews
|
|
361
|
+
- Review related files and dependencies
|
|
362
|
+
- Understand the broader context
|
|
363
|
+
|
|
364
|
+
3. **Plan Your Changes**: Create a systematic plan:
|
|
365
|
+
- Address each review comment one by one
|
|
366
|
+
- Prioritize critical feedback
|
|
367
|
+
- Consider how changes relate to each other
|
|
368
|
+
- Ensure changes align with technical design
|
|
369
|
+
|
|
370
|
+
4. **Refine the Code**: Make targeted improvements:
|
|
371
|
+
- Address each reviewer's concern thoughtfully
|
|
372
|
+
- Follow code quality best practices
|
|
373
|
+
- Maintain consistency with existing patterns
|
|
374
|
+
- Make code more maintainable and readable
|
|
375
|
+
|
|
376
|
+
5. **Test Your Changes**: Verify everything works:
|
|
377
|
+
- Run relevant tests
|
|
378
|
+
- Check that functionality still works
|
|
379
|
+
- Ensure no regressions were introduced
|
|
380
|
+
|
|
381
|
+
6. **Commit Your Changes**: Create clear commits:
|
|
382
|
+
- Write descriptive commit messages
|
|
383
|
+
- Reference the feedback being addressed
|
|
384
|
+
- Group related changes logically
|
|
385
|
+
|
|
386
|
+
## Important Notes
|
|
387
|
+
- Be thorough - address ALL review comments
|
|
388
|
+
- Be respectful - reviewers are trying to help improve the code
|
|
389
|
+
- Be systematic - don't rush through the feedback
|
|
390
|
+
- Test your changes - ensure nothing breaks
|
|
391
|
+
- Communicate clearly in commit messages
|
|
392
|
+
|
|
393
|
+
You are currently on the \`dev/${featureId}\` branch. Make your changes, commit them, and they will be pushed to the remote repository.
|
|
394
|
+
|
|
395
|
+
Begin by analyzing all the review feedback and creating a plan to address each comment.`;
|
|
396
|
+
}
|
|
397
|
+
function parseCodeRefineResponse(response) {
|
|
398
|
+
const summaryMatch = response.match(/## Refine Summary\n([\s\S]*?)(?=\n##|\n\n|$)/);
|
|
399
|
+
const summary = summaryMatch
|
|
400
|
+
? summaryMatch[1].trim()
|
|
401
|
+
: 'Code refined based on PR feedback';
|
|
402
|
+
const filesMatch = response.match(/## Files Modified\n([\s\S]*?)(?=\n##|\n\n|$)/);
|
|
403
|
+
let files_modified = [];
|
|
404
|
+
if (filesMatch) {
|
|
405
|
+
files_modified = filesMatch[1]
|
|
406
|
+
.split('\n')
|
|
407
|
+
.filter((line) => line.trim().startsWith('-'))
|
|
408
|
+
.map((line) => line.replace(/^-\s*/, '').trim());
|
|
409
|
+
}
|
|
410
|
+
return {
|
|
411
|
+
summary,
|
|
412
|
+
files_modified,
|
|
413
|
+
commits_created: 1,
|
|
414
|
+
feedback_addressed: [],
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
export function checkCodeRefineRequirements() {
|
|
418
|
+
try {
|
|
419
|
+
require.resolve('@anthropic-ai/claude-code');
|
|
420
|
+
return Promise.resolve(true);
|
|
421
|
+
}
|
|
422
|
+
catch {
|
|
423
|
+
return Promise.resolve(false);
|
|
424
|
+
}
|
|
425
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context fetcher for code refine phase
|
|
3
|
+
* Fetches GitHub PR review comments that request changes
|
|
4
|
+
*/
|
|
5
|
+
import { Octokit } from '@octokit/rest';
|
|
6
|
+
export interface PRReviewComment {
|
|
7
|
+
id: number;
|
|
8
|
+
body: string;
|
|
9
|
+
path: string | null;
|
|
10
|
+
line: number | null;
|
|
11
|
+
user: {
|
|
12
|
+
login: string;
|
|
13
|
+
};
|
|
14
|
+
created_at: string;
|
|
15
|
+
position: number | null;
|
|
16
|
+
original_position: number | null;
|
|
17
|
+
diff_hunk: string | null;
|
|
18
|
+
in_reply_to_id?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface PRReview {
|
|
21
|
+
id: number;
|
|
22
|
+
user: {
|
|
23
|
+
login: string;
|
|
24
|
+
};
|
|
25
|
+
body: string | null;
|
|
26
|
+
state: string;
|
|
27
|
+
submitted_at: string | null;
|
|
28
|
+
}
|
|
29
|
+
export interface CodeRefineContext {
|
|
30
|
+
featureId: string;
|
|
31
|
+
featureName: string;
|
|
32
|
+
featureDescription: string | null;
|
|
33
|
+
pullRequestUrl: string;
|
|
34
|
+
pullRequestNumber: number;
|
|
35
|
+
owner: string;
|
|
36
|
+
repo: string;
|
|
37
|
+
reviews: PRReview[];
|
|
38
|
+
reviewComments: PRReviewComment[];
|
|
39
|
+
technicalDesign?: string;
|
|
40
|
+
userStories?: any[];
|
|
41
|
+
testCases?: any[];
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Extract owner, repo, and PR number from GitHub PR URL
|
|
45
|
+
*/
|
|
46
|
+
export declare function parsePullRequestUrl(pullRequestUrl: string): {
|
|
47
|
+
owner: string;
|
|
48
|
+
repo: string;
|
|
49
|
+
prNumber: number;
|
|
50
|
+
} | null;
|
|
51
|
+
/**
|
|
52
|
+
* Fetch PR reviews that request changes
|
|
53
|
+
*/
|
|
54
|
+
export declare function fetchPRReviews(octokit: Octokit, owner: string, repo: string, prNumber: number, verbose?: boolean): Promise<PRReview[]>;
|
|
55
|
+
/**
|
|
56
|
+
* Fetch PR review comments
|
|
57
|
+
*/
|
|
58
|
+
export declare function fetchPRReviewComments(octokit: Octokit, owner: string, repo: string, prNumber: number, verbose?: boolean): Promise<PRReviewComment[]>;
|
|
59
|
+
/**
|
|
60
|
+
* Fetch technical design via MCP
|
|
61
|
+
*/
|
|
62
|
+
export declare function fetchTechnicalDesign(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<string | undefined>;
|
|
63
|
+
/**
|
|
64
|
+
* Fetch user stories via MCP
|
|
65
|
+
*/
|
|
66
|
+
export declare function fetchUserStories(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<any[]>;
|
|
67
|
+
/**
|
|
68
|
+
* Fetch test cases via MCP
|
|
69
|
+
*/
|
|
70
|
+
export declare function fetchTestCases(mcpServerUrl: string, mcpToken: string, featureId: string, verbose?: boolean): Promise<any[]>;
|
|
71
|
+
/**
|
|
72
|
+
* Fetch complete code refine context
|
|
73
|
+
*/
|
|
74
|
+
export declare function fetchCodeRefineContext(mcpServerUrl: string, mcpToken: string, featureId: string, githubToken: string, verbose?: boolean): Promise<CodeRefineContext>;
|
|
75
|
+
/**
|
|
76
|
+
* Format code refine context for prompt
|
|
77
|
+
*/
|
|
78
|
+
export declare function formatContextForPrompt(context: CodeRefineContext): string;
|