From c28e2035d2db99eb3ad7613f38962965b47008e2 Mon Sep 17 00:00:00 2001 From: ROKUMATE Date: Wed, 18 Feb 2026 15:07:23 +0530 Subject: [PATCH 1/2] init 4 --- package.json | 5 ++ src/agentRunner.ts | 167 +++++++++++++++++++++++++++++++++++++- src/contextManager.ts | 181 ++++++++++++++++++++++++++++++++++++++++++ src/extension.ts | 70 ++++++++++++++++ src/promptBuilder.ts | 100 ++++++++++++++++++++--- 5 files changed, 510 insertions(+), 13 deletions(-) diff --git a/package.json b/package.json index e5fe413..d225d25 100644 --- a/package.json +++ b/package.json @@ -57,6 +57,11 @@ "command": "issue-agent.openIssueComposer", "title": "Open Issue Composer", "icon": "$(edit)" + }, + { + "command": "issue-agent.commitAndPush", + "title": "Issue Agent: Commit and Push Changes", + "icon": "$(git-commit)" } ], "menus": { diff --git a/src/agentRunner.ts b/src/agentRunner.ts index b353cd3..6de0b7d 100644 --- a/src/agentRunner.ts +++ b/src/agentRunner.ts @@ -1,3 +1,4 @@ +import { Octokit } from '@octokit/rest'; import * as fs from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; @@ -125,6 +126,43 @@ export class AgentRunner { name: config.get('repo.name') || '', }; + // Get iteration history + const history = this.contextManager.getIterationHistory(issue.number); + const issueSummary = this.contextManager.getIssueSummary(issue.number); + + // Show iteration history if exists + if (history.hasHistory) { + this.sendToWebview({ + type: 'status', + message: `📚 Found ${history.iterations} previous iteration(s)...`, + }); + vscode.window.showInformationMessage( + `📚 This issue has ${history.iterations} previous iteration(s). Including context in prompt.`, + ); + } + + // Fetch PR comments if there's an associated PR + let prComments: any[] = []; + try { + this.sendToWebview({ + type: 'status', + message: '🔍 Checking for PR review comments...', + }); + prComments = await this.fetchPRComments(issue.number, repoMeta); + if (prComments.length > 0) { + await this.contextManager.savePRComments(issue.number, prComments); + this.sendToWebview({ + type: 'status', + message: `💬 Found ${prComments.length} PR review comment(s)`, + }); + vscode.window.showInformationMessage( + `💬 Found ${prComments.length} PR review comment(s). Including in prompt.`, + ); + } + } catch (error) { + console.log('No PR comments found or error fetching:', error); + } + // Get conversation history const conversationKey = `conversation-${issue.number}`; const conversation = this.context.workspaceState.get( @@ -132,12 +170,14 @@ export class AgentRunner { [], ); - // Build prompt (simplified - AI analyzes repo automatically) + // Build prompt with iteration history and PR comments const prompt = this.promptBuilder.buildPrompt( issue, data.userContext || '', repoMeta, conversation, + history, + prComments, ); // Get iteration count @@ -164,6 +204,33 @@ export class AgentRunner { contextPath: this.contextManager.getContextPath(issue.number), }); + // Step 1: Create and switch to a new branch BEFORE opening Copilot + const workspaceFolders = vscode.workspace.workspaceFolders; + if (workspaceFolders) { + const rootPath = workspaceFolders[0].uri.fsPath; + const branchName = `issue-${issue.number}-fix`; + + this.sendToWebview({ + type: 'status', + message: `Creating branch ${branchName}...`, + }); + + try { + console.log(`[Agent] Creating branch: ${branchName}`); + await this.gitUtils.createBranch(branchName, rootPath); + console.log(`[Agent] ✅ Branch created: ${branchName}`); + + vscode.window.showInformationMessage( + `✅ Created and switched to branch: ${branchName}`, + ); + } catch (error) { + console.error(`[Agent] Failed to create branch:`, error); + vscode.window.showWarningMessage( + `Could not create branch ${branchName}. Copilot will make changes on the current branch.`, + ); + } + } + this.sendToWebview({ type: 'status', message: '✨ Opening Copilot Chat with your prompt...', @@ -172,12 +239,25 @@ export class AgentRunner { // Open Copilot Chat and paste the prompt for user review await this.openInCopilotChat(prompt); - vscode.window.showInformationMessage( + const branchName = `issue-${issue.number}-fix`; + const choice = await vscode.window.showInformationMessage( '🚀 Copilot Chat is ready!\n\n' + + `✅ You're now on branch: ${branchName}\n\n` + '📋 Paste the prompt (Cmd+V), review it, and press Enter.\n\n' + - '✨ Copilot will analyze your code and make the necessary changes to fix the issue!', + '✨ Copilot will make the changes on this branch!', 'Got it!', + 'Commit & Push Later', ); + + // If user wants to commit later, show them how + if (choice === 'Commit & Push Later') { + vscode.window.showInformationMessage( + `After Copilot makes changes:\n\n` + + `1. Review the changes in Source Control\n` + + `2. Run "Issue Agent: Commit and Push" command (Cmd+Shift+P)\n` + + `3. Or manually: git add -A && git commit && git push`, + ); + } } catch (error) { const errorMsg = `Failed to run agent: ${error}`; this.sendToWebview({ @@ -740,4 +820,85 @@ export class AgentRunner { '\n\n... [Content truncated, file too large] ...' ); } + + /** + * Fetch PR review comments for an issue + */ + private async fetchPRComments( + issueNumber: number, + repoMeta: { owner: string; name: string }, + ): Promise< + Array<{ + user: string; + body: string; + created_at: string; + path?: string; + }> + > { + try { + const token = await this.context.secrets.get('github-token'); + if (!token) { + return []; + } + + const octokit = new Octokit({ auth: token }); + + // First, find if there's a PR associated with this issue + const prs = await octokit.pulls.list({ + owner: repoMeta.owner, + repo: repoMeta.name, + state: 'all', + per_page: 100, + }); + + // Find PR that mentions this issue in title or body + const associatedPR = prs.data.find( + (pr) => + pr.title.includes(`#${issueNumber}`) || + pr.body?.includes(`#${issueNumber}`) || + pr.title.includes(`issue-${issueNumber}`), + ); + + if (!associatedPR) { + console.log(`No PR found for issue #${issueNumber}`); + return []; + } + + console.log(`Found PR #${associatedPR.number} for issue #${issueNumber}`); + + // Fetch review comments + const reviewComments = await octokit.pulls.listReviewComments({ + owner: repoMeta.owner, + repo: repoMeta.name, + pull_number: associatedPR.number, + }); + + // Fetch regular comments + const issueComments = await octokit.issues.listComments({ + owner: repoMeta.owner, + repo: repoMeta.name, + issue_number: associatedPR.number, + }); + + // Combine and format comments + const allComments = [ + ...reviewComments.data.map((c) => ({ + user: c.user?.login || 'unknown', + body: c.body || '', + created_at: c.created_at, + path: c.path, + })), + ...issueComments.data.map((c) => ({ + user: c.user?.login || 'unknown', + body: c.body || '', + created_at: c.created_at, + })), + ]; + + return allComments; + } catch (error) { + console.error('Error fetching PR comments:', error); + return []; + } + } } diff --git a/src/contextManager.ts b/src/contextManager.ts index f71a9ab..17c0c8f 100644 --- a/src/contextManager.ts +++ b/src/contextManager.ts @@ -243,4 +243,185 @@ ${prompt} getContextPath(issueNumber: number): string { return path.relative(this.rootPath, this.getIssueContextDir(issueNumber)); } + + /** + * Save Copilot's response/changes after iteration + */ + async saveCopilotResponse( + issueNumber: number, + iteration: number, + summary: string, + filesChanged: string[], + ): Promise { + try { + const issueDir = this.getIssueContextDir(issueNumber); + this.ensureDir(issueDir); + + const responsePath = path.join( + issueDir, + `copilot-response-iteration-${iteration}.md`, + ); + + const content = `# Copilot Response - Issue #${issueNumber} - Iteration ${iteration} +Timestamp: ${new Date().toISOString()} + +## What Changed + +${summary} + +## Files Modified + +${filesChanged.map((f) => `- ${f}`).join('\n') || 'No files specified'} + +--- + +*This response was generated by GitHub Copilot* +`; + + fs.writeFileSync(responsePath, content, 'utf-8'); + console.log(`✅ Copilot response saved to: ${responsePath}`); + } catch (error) { + console.error( + `Failed to save Copilot response for issue ${issueNumber}:`, + error, + ); + } + } + + /** + * Save PR review comments + */ + async savePRComments( + issueNumber: number, + comments: Array<{ + user: string; + body: string; + created_at: string; + path?: string; + }>, + ): Promise { + try { + const issueDir = this.getIssueContextDir(issueNumber); + this.ensureDir(issueDir); + + const commentsPath = path.join(issueDir, 'pr-review-comments.md'); + + const content = `# PR Review Comments - Issue #${issueNumber} +Last Updated: ${new Date().toISOString()} + +--- + +${comments + .map( + (c) => ` +## Comment by @${c.user} +**Date:** ${c.created_at}${c.path ? `\n**File:** ${c.path}` : ''} + +${c.body} + +---`, + ) + .join('\n')} +`; + + fs.writeFileSync(commentsPath, content, 'utf-8'); + console.log(`✅ PR comments saved to: ${commentsPath}`); + } catch (error) { + console.error( + `Failed to save PR comments for issue ${issueNumber}:`, + error, + ); + } + } + + /** + * Get iteration history for an issue + */ + getIterationHistory(issueNumber: number): { + iterations: number; + prompts: string[]; + responses: string[]; + hasHistory: boolean; + } { + const issueDir = this.getIssueContextDir(issueNumber); + + if (!fs.existsSync(issueDir)) { + return { iterations: 0, prompts: [], responses: [], hasHistory: false }; + } + + const files = fs.readdirSync(issueDir); + const promptFiles = files + .filter((f) => f.startsWith('prompt-iteration-')) + .sort(); + const responseFiles = files + .filter((f) => f.startsWith('copilot-response-iteration-')) + .sort(); + + const prompts = promptFiles.map((f) => + fs.readFileSync(path.join(issueDir, f), 'utf-8'), + ); + const responses = responseFiles.map((f) => + fs.readFileSync(path.join(issueDir, f), 'utf-8'), + ); + + return { + iterations: promptFiles.length, + prompts, + responses, + hasHistory: promptFiles.length > 0, + }; + } + + /** + * Get PR comments for an issue + */ + getPRComments(issueNumber: number): string | null { + const issueDir = this.getIssueContextDir(issueNumber); + const commentsPath = path.join(issueDir, 'pr-review-comments.md'); + + if (!fs.existsSync(commentsPath)) { + return null; + } + + return fs.readFileSync(commentsPath, 'utf-8'); + } + + /** + * Get summary of issue context for display + */ + getIssueSummary(issueNumber: number): { + hasHistory: boolean; + iterationCount: number; + hasPRComments: boolean; + lastUpdated: string | null; + } { + const issueDir = this.getIssueContextDir(issueNumber); + + if (!fs.existsSync(issueDir)) { + return { + hasHistory: false, + iterationCount: 0, + hasPRComments: false, + lastUpdated: null, + }; + } + + const files = fs.readdirSync(issueDir); + const promptFiles = files.filter((f) => f.startsWith('prompt-iteration-')); + const hasPRComments = files.includes('pr-review-comments.md'); + + let lastUpdated: string | null = null; + if (files.length > 0) { + const stats = files.map((f) => fs.statSync(path.join(issueDir, f))); + const latestMtime = Math.max(...stats.map((s) => s.mtime.getTime())); + lastUpdated = new Date(latestMtime).toISOString(); + } + + return { + hasHistory: promptFiles.length > 0, + iterationCount: promptFiles.length, + hasPRComments, + lastUpdated, + }; + } } diff --git a/src/extension.ts b/src/extension.ts index 429a271..05f8ff5 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,5 +1,6 @@ import * as vscode from 'vscode'; import { AgentRunner } from './agentRunner'; +import { GitUtils } from './gitUtils'; import { IssueProvider } from './issueProvider'; import { RepoDetector } from './repoDetector'; @@ -83,6 +84,75 @@ export async function activate(context: vscode.ExtensionContext) { ), ); + context.subscriptions.push( + vscode.commands.registerCommand('issue-agent.commitAndPush', async () => { + const workspaceFolders = vscode.workspace.workspaceFolders; + if (!workspaceFolders) { + vscode.window.showErrorMessage('No workspace folder open'); + return; + } + + const rootPath = workspaceFolders[0].uri.fsPath; + const gitUtils = new GitUtils(); + + try { + // Get current branch name + const { execSync } = await import('child_process'); + const currentBranch = execSync('git branch --show-current', { + cwd: rootPath, + encoding: 'utf8', + }).trim(); + + // Check if there are changes to commit + const status = execSync('git status --short', { + cwd: rootPath, + encoding: 'utf8', + }); + + if (!status.trim()) { + vscode.window.showInformationMessage('No changes to commit'); + return; + } + + // Ask for commit message + const issueMatch = currentBranch.match(/issue-(\d+)-/); + const defaultMessage = issueMatch + ? `Fix issue #${issueMatch[1]}` + : 'Fix issue'; + + const commitMessage = await vscode.window.showInputBox({ + prompt: 'Enter commit message', + value: defaultMessage, + placeHolder: 'Fix issue #123: Description', + }); + + if (!commitMessage) { + return; + } + + // Commit changes + await gitUtils.commitChanges(commitMessage, rootPath); + vscode.window.showInformationMessage('✅ Changes committed!'); + + // Ask to push + const pushChoice = await vscode.window.showInformationMessage( + `Push ${currentBranch} to remote?`, + 'Yes, Push', + 'No', + ); + + if (pushChoice === 'Yes, Push') { + await gitUtils.pushBranch(currentBranch, rootPath); + vscode.window.showInformationMessage( + `✅ Pushed to ${currentBranch}!`, + ); + } + } catch (error) { + vscode.window.showErrorMessage(`Git error: ${error}`); + } + }), + ); + // Auto-configure on first launch if not configured const ghToken = await context.secrets.get('github-token'); if (!ghToken) { diff --git a/src/promptBuilder.ts b/src/promptBuilder.ts index 1ca68d4..067e7f4 100644 --- a/src/promptBuilder.ts +++ b/src/promptBuilder.ts @@ -7,6 +7,18 @@ export class PromptBuilder { userContext: string, repoMeta: { owner: string; name: string }, conversationHistory: any[], + iterationHistory?: { + iterations: number; + prompts: string[]; + responses: string[]; + hasHistory: boolean; + }, + prComments?: Array<{ + user: string; + body: string; + created_at: string; + path?: string; + }>, ): string { let prompt = ''; @@ -15,6 +27,12 @@ export class PromptBuilder { prompt += `repo: ${repoMeta.owner}/${repoMeta.name}\n`; prompt += `issue: #${issue.number}\n`; prompt += `test-command: npm test\n`; + if (iterationHistory?.hasHistory) { + prompt += `previous-iterations: ${iterationHistory.iterations}\n`; + } + if (prComments && prComments.length > 0) { + prompt += `pr-review-comments: ${prComments.length}\n`; + } prompt += '--METADATA-END--\n\n'; // INPUT section @@ -23,17 +41,56 @@ export class PromptBuilder { prompt += `Author: @${issue.user?.login || 'unknown'}\n\n`; prompt += `## Description\n${issue.body || 'No description provided'}\n\n`; + // Add PR review comments if available + if (prComments && prComments.length > 0) { + prompt += `## PR Review Comments\n`; + prompt += `**IMPORTANT**: This PR has received review feedback that must be addressed.\n\n`; + prComments.forEach((comment, idx) => { + prompt += `### Comment ${idx + 1} by @${comment.user}\n`; + if (comment.path) { + prompt += `**File**: ${comment.path}\n`; + } + prompt += `**Date**: ${comment.created_at}\n\n`; + prompt += `${comment.body}\n\n`; + prompt += `---\n\n`; + }); + } + + // Add iteration history if available + if (iterationHistory?.hasHistory && iterationHistory.iterations > 0) { + prompt += `## Previous Iteration History\n`; + prompt += `This issue has been worked on ${iterationHistory.iterations} time(s) before.\n`; + prompt += `Please review what was done previously to understand the context:\n\n`; + + // Show last 2 iterations to avoid too long prompts + const startIdx = Math.max(0, iterationHistory.iterations - 2); + for (let i = startIdx; i < iterationHistory.iterations; i++) { + prompt += `### Iteration ${i + 1}\n`; + if (iterationHistory.responses[i]) { + // Extract summary from the response + const lines = iterationHistory.responses[i].split('\\n'); + const summaryLines = lines.slice(0, 30).join('\\n'); // First 30 lines + prompt += summaryLines; + if (lines.length > 30) { + prompt += '\\n\\n[... truncated for brevity ...]'; + } + prompt += '\\n\\n'; + } + prompt += `---\\n\\n`; + } + } + if (userContext) { prompt += `## Additional Context from User\n${userContext}\n\n`; } - // Add conversation history + // Add conversation history (kept for backwards compatibility) if (conversationHistory.length > 0) { - prompt += `## Previous Conversation\n`; - for (const entry of conversationHistory.slice(-3)) { - // Last 3 entries + prompt += `## Recent Conversation\n`; + for (const entry of conversationHistory.slice(-2)) { + // Last 2 entries prompt += `[${entry.timestamp}] User: ${entry.userContext}\n`; - prompt += `Response: ${entry.response.substring(0, 200)}...\n\n`; + prompt += `Response: ${entry.response.substring(0, 150)}...\n\n`; } } @@ -47,15 +104,38 @@ export class PromptBuilder { // INSTRUCTIONS section prompt += '--INSTRUCTIONS-BEGIN--\n'; prompt += '1) Analyze the issue and the repository code.\n'; - prompt += - '2) Identify the files that need to be modified to fix this issue.\n'; - prompt += '3) Make the necessary code changes directly to fix the issue.\n'; - prompt += '4) Ensure the fix:\n'; + + if (prComments && prComments.length > 0) { + prompt += + '2) **CRITICALLY IMPORTANT**: Address ALL the PR review comments above. This is your top priority.\n'; + prompt += + '3) Identify the files that need to be modified to fix both the original issue AND the review comments.\n'; + } else if (iterationHistory?.hasHistory) { + prompt += + '2) Review the previous iteration(s) to understand what was already attempted.\n'; + prompt += + '3) Build upon or improve the previous work. Do NOT repeat the same approach if it did not work.\n'; + } else { + prompt += + '2) Identify the files that need to be modified to fix this issue.\n'; + } + + const nextStep = prComments && prComments.length > 0 ? '4' : '3'; + prompt += `${nextStep}) Make the necessary code changes directly to fix the issue${prComments && prComments.length > 0 ? ' and address the review comments' : ''}.\n`; + + const ensureStep = Number(nextStep) + 1; + prompt += `${ensureStep}) Ensure the fix:\n`; prompt += ' - Solves the reported problem\n'; + if (prComments && prComments.length > 0) { + prompt += ' - Addresses ALL review comments\n'; + } prompt += ' - Maintains code quality and style\n'; prompt += ' - Does not break existing functionality\n'; prompt += ' - Includes any necessary tests if applicable\n'; - prompt += '5) Provide a brief summary of what you changed and why.\n'; + + const summaryStep = Number(ensureStep) + 1; + prompt += `${summaryStep}) Provide a brief summary of what you changed and why.\n`; + prompt += '--INSTRUCTIONS-END--\n'; return prompt; From 44a894f92b2c9ae54bbc9e76320c8817315d7806 Mon Sep 17 00:00:00 2001 From: ROKUMATE Date: Wed, 18 Feb 2026 15:21:23 +0530 Subject: [PATCH 2/2] finished continious interationOC --- src/agentRunner.ts | 134 ++++++++++++++++++++++++++++--------------- src/promptBuilder.ts | 26 +++++++-- 2 files changed, 109 insertions(+), 51 deletions(-) diff --git a/src/agentRunner.ts b/src/agentRunner.ts index 6de0b7d..d6b22ba 100644 --- a/src/agentRunner.ts +++ b/src/agentRunner.ts @@ -822,7 +822,7 @@ export class AgentRunner { } /** - * Fetch PR review comments for an issue + * Fetch PR review comments and issue comments */ private async fetchPRComments( issueNumber: number, @@ -833,6 +833,7 @@ export class AgentRunner { body: string; created_at: string; path?: string; + type?: string; }> > { try { @@ -843,61 +844,102 @@ export class AgentRunner { const octokit = new Octokit({ auth: token }); - // First, find if there's a PR associated with this issue - const prs = await octokit.pulls.list({ - owner: repoMeta.owner, - repo: repoMeta.name, - state: 'all', - per_page: 100, - }); + const allComments: Array<{ + user: string; + body: string; + created_at: string; + path?: string; + type?: string; + }> = []; - // Find PR that mentions this issue in title or body - const associatedPR = prs.data.find( - (pr) => - pr.title.includes(`#${issueNumber}`) || - pr.body?.includes(`#${issueNumber}`) || - pr.title.includes(`issue-${issueNumber}`), - ); + // First, fetch comments directly on the issue itself + try { + const issueCommentsResponse = await octokit.issues.listComments({ + owner: repoMeta.owner, + repo: repoMeta.name, + issue_number: issueNumber, + }); - if (!associatedPR) { - console.log(`No PR found for issue #${issueNumber}`); - return []; + allComments.push( + ...issueCommentsResponse.data.map((c) => ({ + user: c.user?.login || 'unknown', + body: c.body || '', + created_at: c.created_at, + type: 'issue-comment', + })), + ); + + console.log( + `Found ${issueCommentsResponse.data.length} comments on issue #${issueNumber}`, + ); + } catch (error) { + console.error('Error fetching issue comments:', error); } - console.log(`Found PR #${associatedPR.number} for issue #${issueNumber}`); + // Now, find if there's a PR associated with this issue + try { + const prs = await octokit.pulls.list({ + owner: repoMeta.owner, + repo: repoMeta.name, + state: 'all', + per_page: 100, + }); - // Fetch review comments - const reviewComments = await octokit.pulls.listReviewComments({ - owner: repoMeta.owner, - repo: repoMeta.name, - pull_number: associatedPR.number, - }); + // Find PR that mentions this issue in title or body + const associatedPR = prs.data.find( + (pr) => + pr.title.includes(`#${issueNumber}`) || + pr.body?.includes(`#${issueNumber}`) || + pr.title.includes(`issue-${issueNumber}`), + ); - // Fetch regular comments - const issueComments = await octokit.issues.listComments({ - owner: repoMeta.owner, - repo: repoMeta.name, - issue_number: associatedPR.number, - }); + if (associatedPR) { + console.log( + `Found PR #${associatedPR.number} for issue #${issueNumber}`, + ); - // Combine and format comments - const allComments = [ - ...reviewComments.data.map((c) => ({ - user: c.user?.login || 'unknown', - body: c.body || '', - created_at: c.created_at, - path: c.path, - })), - ...issueComments.data.map((c) => ({ - user: c.user?.login || 'unknown', - body: c.body || '', - created_at: c.created_at, - })), - ]; + // Fetch review comments on the PR + const reviewComments = await octokit.pulls.listReviewComments({ + owner: repoMeta.owner, + repo: repoMeta.name, + pull_number: associatedPR.number, + }); + + allComments.push( + ...reviewComments.data.map((c) => ({ + user: c.user?.login || 'unknown', + body: c.body || '', + created_at: c.created_at, + path: c.path, + type: 'pr-review-comment', + })), + ); + + // Fetch regular comments on the PR + const prComments = await octokit.issues.listComments({ + owner: repoMeta.owner, + repo: repoMeta.name, + issue_number: associatedPR.number, + }); + + allComments.push( + ...prComments.data.map((c) => ({ + user: c.user?.login || 'unknown', + body: c.body || '', + created_at: c.created_at, + type: 'pr-comment', + })), + ); + } else { + console.log(`No PR found for issue #${issueNumber}`); + } + } catch (error) { + console.error('Error fetching PR comments:', error); + } return allComments; } catch (error) { - console.error('Error fetching PR comments:', error); + console.error('Error fetching comments:', error); return []; } } diff --git a/src/promptBuilder.ts b/src/promptBuilder.ts index 067e7f4..dde2bc2 100644 --- a/src/promptBuilder.ts +++ b/src/promptBuilder.ts @@ -18,6 +18,7 @@ export class PromptBuilder { body: string; created_at: string; path?: string; + type?: string; }>, ): string { let prompt = ''; @@ -31,7 +32,7 @@ export class PromptBuilder { prompt += `previous-iterations: ${iterationHistory.iterations}\n`; } if (prComments && prComments.length > 0) { - prompt += `pr-review-comments: ${prComments.length}\n`; + prompt += `total-comments: ${prComments.length}\n`; } prompt += '--METADATA-END--\n\n'; @@ -41,12 +42,14 @@ export class PromptBuilder { prompt += `Author: @${issue.user?.login || 'unknown'}\n\n`; prompt += `## Description\n${issue.body || 'No description provided'}\n\n`; - // Add PR review comments if available + // Add all comments if available if (prComments && prComments.length > 0) { - prompt += `## PR Review Comments\n`; - prompt += `**IMPORTANT**: This PR has received review feedback that must be addressed.\n\n`; + prompt += `## Comments & Feedback\n`; + prompt += `**IMPORTANT**: This issue/PR has received feedback that must be addressed.\n\n`; + prComments.forEach((comment, idx) => { - prompt += `### Comment ${idx + 1} by @${comment.user}\n`; + const commentTypeLabel = this.getCommentTypeLabel(comment.type); + prompt += `### ${commentTypeLabel} ${idx + 1} by @${comment.user}\n`; if (comment.path) { prompt += `**File**: ${comment.path}\n`; } @@ -140,4 +143,17 @@ export class PromptBuilder { return prompt; } + + private getCommentTypeLabel(type?: string): string { + switch (type) { + case 'issue-comment': + return '💬 Issue Comment'; + case 'pr-review-comment': + return '📝 PR Review Comment'; + case 'pr-comment': + return '💭 PR Comment'; + default: + return '💬 Comment'; + } + } }