@g-abhishek/gitx 0.1.2 β†’ 0.1.5

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.
Files changed (165) hide show
  1. package/README.md +386 -3
  2. package/dist/ai/claudeAi.d.ts +35 -0
  3. package/dist/ai/claudeAi.d.ts.map +1 -0
  4. package/dist/ai/claudeAi.js +396 -0
  5. package/dist/ai/claudeAi.js.map +1 -0
  6. package/dist/ai/claudeCliAi.d.ts +27 -0
  7. package/dist/ai/claudeCliAi.d.ts.map +1 -0
  8. package/dist/ai/claudeCliAi.js +312 -0
  9. package/dist/ai/claudeCliAi.js.map +1 -0
  10. package/dist/ai/localClaudeAi.d.ts +2 -0
  11. package/dist/ai/localClaudeAi.d.ts.map +1 -0
  12. package/dist/ai/localClaudeAi.js +4 -0
  13. package/dist/ai/localClaudeAi.js.map +1 -0
  14. package/dist/ai/mockAi.d.ts +8 -1
  15. package/dist/ai/mockAi.d.ts.map +1 -1
  16. package/dist/ai/mockAi.js +57 -0
  17. package/dist/ai/mockAi.js.map +1 -1
  18. package/dist/ai/openAiAi.d.ts +33 -0
  19. package/dist/ai/openAiAi.d.ts.map +1 -0
  20. package/dist/ai/openAiAi.js +388 -0
  21. package/dist/ai/openAiAi.js.map +1 -0
  22. package/dist/ai/reviewHelpers.d.ts +66 -0
  23. package/dist/ai/reviewHelpers.d.ts.map +1 -0
  24. package/dist/ai/reviewHelpers.js +574 -0
  25. package/dist/ai/reviewHelpers.js.map +1 -0
  26. package/dist/ai/types.d.ts +247 -0
  27. package/dist/ai/types.d.ts.map +1 -1
  28. package/dist/ai/types.js.map +1 -1
  29. package/dist/cli/commands/ask.d.ts +27 -0
  30. package/dist/cli/commands/ask.d.ts.map +1 -0
  31. package/dist/cli/commands/ask.js +230 -0
  32. package/dist/cli/commands/ask.js.map +1 -0
  33. package/dist/cli/commands/commit.d.ts +16 -0
  34. package/dist/cli/commands/commit.d.ts.map +1 -0
  35. package/dist/cli/commands/commit.js +163 -0
  36. package/dist/cli/commands/commit.js.map +1 -0
  37. package/dist/cli/commands/config.d.ts +4 -0
  38. package/dist/cli/commands/config.d.ts.map +1 -0
  39. package/dist/cli/commands/config.js +666 -0
  40. package/dist/cli/commands/config.js.map +1 -0
  41. package/dist/cli/commands/implement.d.ts.map +1 -1
  42. package/dist/cli/commands/implement.js +149 -31
  43. package/dist/cli/commands/implement.js.map +1 -1
  44. package/dist/cli/commands/init.d.ts +4 -0
  45. package/dist/cli/commands/init.d.ts.map +1 -1
  46. package/dist/cli/commands/init.js +7 -69
  47. package/dist/cli/commands/init.js.map +1 -1
  48. package/dist/cli/commands/port.d.ts +32 -0
  49. package/dist/cli/commands/port.d.ts.map +1 -0
  50. package/dist/cli/commands/port.js +554 -0
  51. package/dist/cli/commands/port.js.map +1 -0
  52. package/dist/cli/commands/pr/close.d.ts +15 -0
  53. package/dist/cli/commands/pr/close.d.ts.map +1 -0
  54. package/dist/cli/commands/pr/close.js +71 -0
  55. package/dist/cli/commands/pr/close.js.map +1 -0
  56. package/dist/cli/commands/pr/create.d.ts +17 -0
  57. package/dist/cli/commands/pr/create.d.ts.map +1 -1
  58. package/dist/cli/commands/pr/create.js +208 -7
  59. package/dist/cli/commands/pr/create.js.map +1 -1
  60. package/dist/cli/commands/pr/fixComments.d.ts +5 -2
  61. package/dist/cli/commands/pr/fixComments.d.ts.map +1 -1
  62. package/dist/cli/commands/pr/fixComments.js +5 -13
  63. package/dist/cli/commands/pr/fixComments.js.map +1 -1
  64. package/dist/cli/commands/pr/index.d.ts.map +1 -1
  65. package/dist/cli/commands/pr/index.js +6 -2
  66. package/dist/cli/commands/pr/index.js.map +1 -1
  67. package/dist/cli/commands/pr/list.d.ts.map +1 -1
  68. package/dist/cli/commands/pr/list.js +24 -4
  69. package/dist/cli/commands/pr/list.js.map +1 -1
  70. package/dist/cli/commands/pr/merge.d.ts +23 -0
  71. package/dist/cli/commands/pr/merge.d.ts.map +1 -0
  72. package/dist/cli/commands/pr/merge.js +191 -0
  73. package/dist/cli/commands/pr/merge.js.map +1 -0
  74. package/dist/cli/commands/pr/resolve.d.ts +3 -0
  75. package/dist/cli/commands/pr/resolve.d.ts.map +1 -0
  76. package/dist/cli/commands/pr/resolve.js +92 -0
  77. package/dist/cli/commands/pr/resolve.js.map +1 -0
  78. package/dist/cli/commands/pr/review.d.ts.map +1 -1
  79. package/dist/cli/commands/pr/review.js +121 -6
  80. package/dist/cli/commands/pr/review.js.map +1 -1
  81. package/dist/cli/commands/push.d.ts +16 -0
  82. package/dist/cli/commands/push.d.ts.map +1 -0
  83. package/dist/cli/commands/push.js +166 -0
  84. package/dist/cli/commands/push.js.map +1 -0
  85. package/dist/cli/commands/sync.d.ts +24 -0
  86. package/dist/cli/commands/sync.d.ts.map +1 -0
  87. package/dist/cli/commands/sync.js +414 -0
  88. package/dist/cli/commands/sync.js.map +1 -0
  89. package/dist/cli/index.d.ts.map +1 -1
  90. package/dist/cli/index.js +34 -6
  91. package/dist/cli/index.js.map +1 -1
  92. package/dist/config/config.d.ts +20 -3
  93. package/dist/config/config.d.ts.map +1 -1
  94. package/dist/config/config.js +98 -45
  95. package/dist/config/config.js.map +1 -1
  96. package/dist/config/schema.d.ts.map +1 -1
  97. package/dist/config/schema.js +61 -6
  98. package/dist/config/schema.js.map +1 -1
  99. package/dist/core/context.d.ts +6 -0
  100. package/dist/core/context.d.ts.map +1 -1
  101. package/dist/core/context.js.map +1 -1
  102. package/dist/core/gitx.d.ts +43 -0
  103. package/dist/core/gitx.d.ts.map +1 -1
  104. package/dist/core/gitx.js +187 -20
  105. package/dist/core/gitx.js.map +1 -1
  106. package/dist/index.d.ts +1 -5
  107. package/dist/index.d.ts.map +1 -1
  108. package/dist/index.js +4 -1
  109. package/dist/index.js.map +1 -1
  110. package/dist/providers/azure.d.ts +26 -0
  111. package/dist/providers/azure.d.ts.map +1 -0
  112. package/dist/providers/azure.js +256 -0
  113. package/dist/providers/azure.js.map +1 -0
  114. package/dist/providers/base.d.ts +104 -0
  115. package/dist/providers/base.d.ts.map +1 -0
  116. package/dist/providers/base.js +5 -0
  117. package/dist/providers/base.js.map +1 -0
  118. package/dist/providers/factory.d.ts +8 -0
  119. package/dist/providers/factory.d.ts.map +1 -0
  120. package/dist/providers/factory.js +25 -0
  121. package/dist/providers/factory.js.map +1 -0
  122. package/dist/providers/github.d.ts +19 -0
  123. package/dist/providers/github.d.ts.map +1 -0
  124. package/dist/providers/github.js +291 -0
  125. package/dist/providers/github.js.map +1 -0
  126. package/dist/providers/gitlab.d.ts +19 -0
  127. package/dist/providers/gitlab.d.ts.map +1 -0
  128. package/dist/providers/gitlab.js +186 -0
  129. package/dist/providers/gitlab.js.map +1 -0
  130. package/dist/types/config.d.ts +50 -7
  131. package/dist/types/config.d.ts.map +1 -1
  132. package/dist/types/config.js.map +1 -1
  133. package/dist/utils/azureAuth.d.ts +51 -0
  134. package/dist/utils/azureAuth.d.ts.map +1 -0
  135. package/dist/utils/azureAuth.js +172 -0
  136. package/dist/utils/azureAuth.js.map +1 -0
  137. package/dist/utils/git.d.ts +19 -0
  138. package/dist/utils/git.d.ts.map +1 -1
  139. package/dist/utils/git.js +45 -8
  140. package/dist/utils/git.js.map +1 -1
  141. package/dist/utils/gitOps.d.ts +125 -0
  142. package/dist/utils/gitOps.d.ts.map +1 -0
  143. package/dist/utils/gitOps.js +396 -0
  144. package/dist/utils/gitOps.js.map +1 -0
  145. package/dist/utils/lockFile.d.ts +13 -0
  146. package/dist/utils/lockFile.d.ts.map +1 -0
  147. package/dist/utils/lockFile.js +54 -0
  148. package/dist/utils/lockFile.js.map +1 -0
  149. package/dist/utils/retry.d.ts +10 -0
  150. package/dist/utils/retry.d.ts.map +1 -0
  151. package/dist/utils/retry.js +31 -0
  152. package/dist/utils/retry.js.map +1 -0
  153. package/dist/workflows/implement.d.ts +41 -0
  154. package/dist/workflows/implement.d.ts.map +1 -0
  155. package/dist/workflows/implement.js +219 -0
  156. package/dist/workflows/implement.js.map +1 -0
  157. package/dist/workflows/pr.d.ts +41 -0
  158. package/dist/workflows/pr.d.ts.map +1 -0
  159. package/dist/workflows/pr.js +291 -0
  160. package/dist/workflows/pr.js.map +1 -0
  161. package/dist/workflows/prAddress.d.ts +55 -0
  162. package/dist/workflows/prAddress.d.ts.map +1 -0
  163. package/dist/workflows/prAddress.js +349 -0
  164. package/dist/workflows/prAddress.js.map +1 -0
  165. package/package.json +1 -1
@@ -0,0 +1,291 @@
1
+ /**
2
+ * PR Workflow helpers
3
+ *
4
+ * Shared logic used by the `pr review` and `pr fix-comments` CLI commands.
5
+ */
6
+ import ora from "ora";
7
+ import { createProvider } from "../providers/factory.js";
8
+ import { readRepoFile, listTrackedFiles } from "../utils/gitOps.js";
9
+ import { logger } from "../logger/logger.js";
10
+ // Files that add no review value β€” skip them even if they appear in the diff
11
+ const SKIP_FILE_PATTERNS = [
12
+ /package-lock\.json$/,
13
+ /yarn\.lock$/,
14
+ /pnpm-lock\.yaml$/,
15
+ /bun\.lockb$/,
16
+ /\.lock$/,
17
+ /dist\//,
18
+ /build\//,
19
+ /\.min\.(js|css)$/,
20
+ /\.map$/,
21
+ /node_modules\//,
22
+ /\.d\.ts$/, // generated TypeScript declarations
23
+ /generated\//,
24
+ /migrations\/.*\.sql$/,
25
+ ];
26
+ function isReviewableFile(path) {
27
+ return !SKIP_FILE_PATTERNS.some((re) => re.test(path));
28
+ }
29
+ /**
30
+ * Parse a unified diff and return the set of changed file paths.
31
+ */
32
+ function parseChangedPathsFromDiff(diff) {
33
+ const paths = new Set();
34
+ for (const line of diff.split("\n")) {
35
+ // Match "+++ b/src/foo.ts" lines
36
+ const m = line.match(/^\+\+\+ b\/(.+)/);
37
+ if (m?.[1] && m[1] !== "/dev/null") {
38
+ paths.add(m[1].trim());
39
+ }
40
+ }
41
+ return [...paths];
42
+ }
43
+ /**
44
+ * Given a list of changed file paths, find supporting context files that are
45
+ * closely related (imported by or importing changed files).
46
+ * Returns at most `maxFiles` file paths.
47
+ */
48
+ async function findContextFiles(changedPaths, allTrackedFiles, cwd, maxFiles = 8) {
49
+ const contextPaths = new Set();
50
+ for (const changedPath of changedPaths.slice(0, 10)) {
51
+ const content = await readRepoFile(changedPath, cwd);
52
+ if (!content)
53
+ continue;
54
+ // Extract relative import paths from TypeScript/JS files
55
+ const importMatches = content.matchAll(/from\s+['"]([^'"]+)['"]/g);
56
+ for (const [, importPath] of importMatches) {
57
+ if (!importPath || importPath.startsWith("node:") || !importPath.startsWith("."))
58
+ continue;
59
+ // Resolve the import path relative to the file's directory
60
+ const dir = changedPath.split("/").slice(0, -1).join("/");
61
+ const candidates = [
62
+ `${dir}/${importPath}.ts`,
63
+ `${dir}/${importPath}.tsx`,
64
+ `${dir}/${importPath}/index.ts`,
65
+ `${dir}/${importPath}`,
66
+ ].map((p) => p.replace(/\/\//g, "/").replace(/^\//, ""));
67
+ for (const candidate of candidates) {
68
+ if (allTrackedFiles.includes(candidate) && !changedPaths.includes(candidate)) {
69
+ contextPaths.add(candidate);
70
+ break;
71
+ }
72
+ }
73
+ }
74
+ if (contextPaths.size >= maxFiles)
75
+ break;
76
+ }
77
+ return [...contextPaths].slice(0, maxFiles);
78
+ }
79
+ /**
80
+ * Fetch a PR, its full diff, and all related codebase context;
81
+ * run a senior-developer quality AI review;
82
+ * submit as a formal review (with inline comments) to the hosting provider.
83
+ */
84
+ export async function runReviewWorkflow(gitx, prNumber, postComment = true) {
85
+ const ctx = await gitx.getRepoContext();
86
+ const provider = createProvider(ctx);
87
+ const cwd = gitx.cwd;
88
+ const fetchSpinner = ora("Fetching PR info, diff and comments…").start();
89
+ const pr = await provider.getPR(ctx.repoSlug, prNumber);
90
+ const [comments, diff] = await Promise.all([
91
+ provider.getPRComments(ctx.repoSlug, prNumber),
92
+ provider.getPRDiff(ctx.repoSlug, prNumber),
93
+ ]);
94
+ fetchSpinner.succeed(`PR #${prNumber}: "${pr.title}" (${pr.head} β†’ ${pr.base})`);
95
+ // ── Build codebase context ─────────────────────────────────────────────────
96
+ const ctxSpinner = ora("Building codebase context from changed files…").start();
97
+ const allTracked = await listTrackedFiles(cwd);
98
+ const allChangedPaths = parseChangedPathsFromDiff(diff);
99
+ // Filter out lockfiles / generated files β€” they waste tokens and add no review value.
100
+ // No file count cap β€” per-file budgets in buildSeniorReviewPrompt already control
101
+ // total size. Dropping files arbitrarily is worse than sending all of them.
102
+ const changedPaths = allChangedPaths.filter(isReviewableFile);
103
+ const skippedCount = allChangedPaths.length - changedPaths.length;
104
+ // Read full content of changed files
105
+ const changedFiles = {};
106
+ for (const p of changedPaths) {
107
+ const content = await readRepoFile(p, cwd);
108
+ if (content)
109
+ changedFiles[p] = content;
110
+ }
111
+ // Read supporting context files (imported by the changed files)
112
+ // 10 context files gives the AI a solid picture of the codebase structure
113
+ const ctxPaths = await findContextFiles(changedPaths, allTracked, cwd, 10);
114
+ const contextFiles = {};
115
+ for (const p of ctxPaths) {
116
+ const content = await readRepoFile(p, cwd);
117
+ if (content)
118
+ contextFiles[p] = content;
119
+ }
120
+ const skippedNote = skippedCount > 0 ? `, ${skippedCount} lock/generated files skipped` : "";
121
+ ctxSpinner.succeed(`Context: ${changedPaths.length} changed files, ${ctxPaths.length} context files${skippedNote}`);
122
+ const reviewSpinner = ora(`Running senior-dev AI review… (this may take up to 5 min for large PRs)`).start();
123
+ let review;
124
+ try {
125
+ review = await gitx.ai.reviewPRDetailed({
126
+ prTitle: pr.title,
127
+ prBody: pr.body,
128
+ author: pr.author,
129
+ headBranch: pr.head,
130
+ baseBranch: pr.base,
131
+ diff,
132
+ changedFiles,
133
+ contextFiles,
134
+ repoFileList: allTracked,
135
+ existingComments: comments.map((c) => ({
136
+ author: c.author,
137
+ body: c.body,
138
+ path: c.path,
139
+ line: c.line,
140
+ })),
141
+ });
142
+ reviewSpinner.succeed(`Review complete β€” verdict: ${review.verdict} | ${review.inlineComments.length} inline comment(s)`);
143
+ }
144
+ catch (err) {
145
+ reviewSpinner.fail("AI review failed.");
146
+ throw err;
147
+ }
148
+ // ── Build the formatted review body (for the summary comment) ─────────────
149
+ const verdictIcon = review.verdict === "approve" ? "βœ…" :
150
+ review.verdict === "request_changes" ? "πŸ”΄" : "πŸ’¬";
151
+ const checklistLines = review.checklist.map((c) => {
152
+ const icon = c.status === "pass" ? "βœ…" : c.status === "warn" ? "⚠️" : "❌";
153
+ return `| ${icon} | **${c.area}** | ${c.note} |`;
154
+ });
155
+ const issueLines = review.issues.map((i) => {
156
+ const sev = i.severity === "critical" ? "πŸ”΄" : i.severity === "warning" ? "🟑" : "πŸ’‘";
157
+ const loc = i.file ? ` (\`${i.file}${i.line ? `:${i.line}` : ""}\`)` : "";
158
+ return `${sev} ${i.description}${loc}`;
159
+ });
160
+ const posLines = review.positives.map((p) => `βœ” ${p}`);
161
+ const summaryBody = [
162
+ `## ${verdictIcon} Senior Dev AI Review (gitx) β€” ${review.verdict.replace("_", " ")}`,
163
+ "",
164
+ review.summary,
165
+ ...(checklistLines.length > 0
166
+ ? ["", "### Review Checklist", "| Status | Area | Note |", "|--------|------|------|", ...checklistLines]
167
+ : []),
168
+ ...(review.issues.length > 0 ? ["", "### Issues Found", ...issueLines] : []),
169
+ ...(review.positives.length > 0 ? ["", "### Positives", ...posLines] : []),
170
+ ...(review.testingNotes ? ["", "### How to Test", review.testingNotes] : []),
171
+ ...(review.inlineComments.length > 0
172
+ ? [`\n> πŸ’¬ ${review.inlineComments.length} inline comment(s) posted on specific lines.`]
173
+ : []),
174
+ "",
175
+ "*Generated by [gitx](https://github.com/g-abhishek/gitx)*",
176
+ ].join("\n");
177
+ // ── Post the formal review (inline comments + verdict) ────────────────────
178
+ let reviewPosted = false;
179
+ let inlineDelivery = "none";
180
+ if (postComment) {
181
+ const inlineCount = review.inlineComments.length;
182
+ const postSpinner = ora(`Submitting review to PR${inlineCount > 0 ? ` with ${inlineCount} inline comment(s)` : ""}…`).start();
183
+ try {
184
+ await provider.submitPRReview(ctx.repoSlug, prNumber, {
185
+ body: summaryBody,
186
+ event: review.verdict,
187
+ comments: review.inlineComments.map((c) => ({
188
+ path: c.path,
189
+ line: c.line,
190
+ body: c.suggestion
191
+ ? `${c.body}\n\n**Suggestion:**\n\`\`\`suggestion\n${c.suggestion}\n\`\`\``
192
+ : c.body,
193
+ })),
194
+ });
195
+ reviewPosted = true;
196
+ // Determine how inline comments were delivered.
197
+ // GitHub's submitPRReview will attempt inline first, then fall back to
198
+ // plain comments. We can't detect which path was taken from here, so
199
+ // we report "inline" optimistically β€” the user sees the real result on GitHub.
200
+ inlineDelivery = inlineCount > 0 ? "inline" : "none";
201
+ postSpinner.succeed(`Review submitted to PR.${inlineCount > 0 ? ` (${inlineCount} inline comment(s) β€” see PR for delivery method)` : ""}`);
202
+ }
203
+ catch (err) {
204
+ postSpinner.fail(`Could not post review to PR: ${String(err.message ?? err)}`);
205
+ // Don't rethrow β€” still return the review so the user can see it locally
206
+ }
207
+ }
208
+ return { pr, comments, aiSummary: summaryBody, review, reviewPosted, inlineDelivery };
209
+ }
210
+ /**
211
+ * Fetch PR review comments, ask AI to suggest fixes, apply them, and
212
+ * commit + push the changes.
213
+ */
214
+ export async function runFixCommentsWorkflow(gitx, prNumber, dryRun = false, noCommit = false) {
215
+ const { applyUnifiedDiff, stageAll, hasStagedChanges, commitChanges } = await import("../utils/gitOps.js");
216
+ const cwd = gitx.cwd;
217
+ const ctx = await gitx.getRepoContext();
218
+ const provider = createProvider(ctx);
219
+ logger.info(`πŸ” Fetching PR #${prNumber}…`);
220
+ const pr = await provider.getPR(ctx.repoSlug, prNumber);
221
+ logger.info("πŸ’¬ Fetching review comments…");
222
+ const comments = await provider.getPRComments(ctx.repoSlug, prNumber);
223
+ if (comments.length === 0) {
224
+ logger.info("No review comments found.");
225
+ return { pr, comments, appliedFixes: [], skippedFixes: [] };
226
+ }
227
+ // Gather file contents for files mentioned in comments
228
+ const mentionedPaths = [...new Set(comments.map((c) => c.path).filter(Boolean))];
229
+ const trackedFiles = await listTrackedFiles(cwd);
230
+ // Also include files mentioned in the PR body / title
231
+ const allSourceFiles = trackedFiles
232
+ .filter((f) => /\.(ts|js|tsx|jsx|py|go|rs|java|rb|cs|cpp|c|h)$/.test(f))
233
+ .slice(0, 15);
234
+ const relevantFiles = [...new Set([...mentionedPaths, ...allSourceFiles])].slice(0, 15);
235
+ const fileContents = {};
236
+ for (const f of relevantFiles) {
237
+ const content = await readRepoFile(f, cwd);
238
+ if (content)
239
+ fileContents[f] = content.slice(0, 4000);
240
+ }
241
+ logger.info("🧠 Generating AI-suggested fixes…");
242
+ const fixResult = await gitx.ai.suggestFixes({
243
+ comments: comments.map((c) => ({
244
+ body: c.body,
245
+ author: c.author,
246
+ path: c.path,
247
+ line: c.line,
248
+ })),
249
+ prTitle: pr.title,
250
+ prBody: pr.body,
251
+ fileContents,
252
+ });
253
+ const appliedFixes = [];
254
+ const skippedFixes = [];
255
+ for (const edit of fixResult.suggestedEdits) {
256
+ if (dryRun) {
257
+ logger.info(` ↳ [dry-run] Would apply fix to: ${edit.path}`);
258
+ logger.info(` Rationale: ${edit.rationale}`);
259
+ appliedFixes.push({ path: edit.path, rationale: edit.rationale });
260
+ continue;
261
+ }
262
+ const applyResult = await applyUnifiedDiff(edit.unifiedDiff, cwd);
263
+ if (applyResult.ok) {
264
+ logger.info(` ↳ Applied fix to: ${edit.path}`);
265
+ appliedFixes.push({ path: edit.path, rationale: edit.rationale });
266
+ }
267
+ else {
268
+ logger.warn(` ↳ Could not apply fix to ${edit.path}: ${applyResult.error ?? "unknown"}`);
269
+ skippedFixes.push({
270
+ path: edit.path,
271
+ reason: applyResult.error ?? "git apply failed",
272
+ });
273
+ }
274
+ }
275
+ if (!dryRun && !noCommit && appliedFixes.length > 0) {
276
+ await stageAll(cwd);
277
+ if (await hasStagedChanges(cwd)) {
278
+ const msg = `fix: address PR #${prNumber} review comments\n\n${appliedFixes.map((f) => `- ${f.path}: ${f.rationale}`).join("\n")}`;
279
+ const sha = await commitChanges(msg, cwd);
280
+ logger.success(`Committed fixes: ${sha.slice(0, 8)}`);
281
+ // Post summary comment
282
+ const fixSummary = appliedFixes.map((f) => `- \`${f.path}\`: ${f.rationale}`).join("\n");
283
+ await provider.addPRComment(ctx.repoSlug, prNumber, `## πŸ€– Auto-fixes applied (gitx)\n\n${fixSummary}\n\nCommit: \`${sha.slice(0, 8)}\``);
284
+ }
285
+ }
286
+ if (!dryRun && noCommit && appliedFixes.length > 0) {
287
+ logger.info("\nπŸ’‘ Fixes applied to working tree. Review the changes and commit when ready.");
288
+ }
289
+ return { pr, comments, appliedFixes, skippedFixes };
290
+ }
291
+ //# sourceMappingURL=pr.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pr.js","sourceRoot":"","sources":["../../src/workflows/pr.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * PR Workflow helpers\n *\n * Shared logic used by the `pr review` and `pr fix-comments` CLI commands.\n */\n\nimport ora from \"ora\";\nimport type { Gitx } from \"../core/gitx.js\";\nimport type { PullRequest, PullRequestComment } from \"../providers/base.js\";\nimport { createProvider } from \"../providers/factory.js\";\nimport { readRepoFile, listTrackedFiles } from \"../utils/gitOps.js\";\nimport { logger } from \"../logger/logger.js\";\n\n// Files that add no review value β€” skip them even if they appear in the diff\nconst SKIP_FILE_PATTERNS = [\n /package-lock\\.json$/,\n /yarn\\.lock$/,\n /pnpm-lock\\.yaml$/,\n /bun\\.lockb$/,\n /\\.lock$/,\n /dist\\//,\n /build\\//,\n /\\.min\\.(js|css)$/,\n /\\.map$/,\n /node_modules\\//,\n /\\.d\\.ts$/, // generated TypeScript declarations\n /generated\\//,\n /migrations\\/.*\\.sql$/,\n];\n\nfunction isReviewableFile(path: string): boolean {\n return !SKIP_FILE_PATTERNS.some((re) => re.test(path));\n}\n\n// ─── Review workflow ──────────────────────────────────────────────────────────\n\nexport interface ReviewResult {\n pr: PullRequest;\n comments: PullRequestComment[];\n aiSummary: string;\n review?: import(\"../ai/types.js\").AiDetailedReviewResponse;\n /** true = review was actually posted to the hosting provider */\n reviewPosted: boolean;\n /** How inline comments were delivered: formal inline, plain comments, or not posted */\n inlineDelivery: \"inline\" | \"plain-comments\" | \"none\";\n}\n\n/**\n * Parse a unified diff and return the set of changed file paths.\n */\nfunction parseChangedPathsFromDiff(diff: string): string[] {\n const paths = new Set<string>();\n for (const line of diff.split(\"\\n\")) {\n // Match \"+++ b/src/foo.ts\" lines\n const m = line.match(/^\\+\\+\\+ b\\/(.+)/);\n if (m?.[1] && m[1] !== \"/dev/null\") {\n paths.add(m[1].trim());\n }\n }\n return [...paths];\n}\n\n/**\n * Given a list of changed file paths, find supporting context files that are\n * closely related (imported by or importing changed files).\n * Returns at most `maxFiles` file paths.\n */\nasync function findContextFiles(\n changedPaths: string[],\n allTrackedFiles: string[],\n cwd: string,\n maxFiles = 8\n): Promise<string[]> {\n const contextPaths = new Set<string>();\n\n for (const changedPath of changedPaths.slice(0, 10)) {\n const content = await readRepoFile(changedPath, cwd);\n if (!content) continue;\n\n // Extract relative import paths from TypeScript/JS files\n const importMatches = content.matchAll(/from\\s+['\"]([^'\"]+)['\"]/g);\n for (const [, importPath] of importMatches) {\n if (!importPath || importPath.startsWith(\"node:\") || !importPath.startsWith(\".\")) continue;\n // Resolve the import path relative to the file's directory\n const dir = changedPath.split(\"/\").slice(0, -1).join(\"/\");\n const candidates = [\n `${dir}/${importPath}.ts`,\n `${dir}/${importPath}.tsx`,\n `${dir}/${importPath}/index.ts`,\n `${dir}/${importPath}`,\n ].map((p) => p.replace(/\\/\\//g, \"/\").replace(/^\\//, \"\"));\n\n for (const candidate of candidates) {\n if (allTrackedFiles.includes(candidate) && !changedPaths.includes(candidate)) {\n contextPaths.add(candidate);\n break;\n }\n }\n }\n\n if (contextPaths.size >= maxFiles) break;\n }\n\n return [...contextPaths].slice(0, maxFiles);\n}\n\n/**\n * Fetch a PR, its full diff, and all related codebase context;\n * run a senior-developer quality AI review;\n * submit as a formal review (with inline comments) to the hosting provider.\n */\nexport async function runReviewWorkflow(\n gitx: Gitx,\n prNumber: number,\n postComment = true\n): Promise<ReviewResult> {\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n const cwd = gitx.cwd;\n\n const fetchSpinner = ora(\"Fetching PR info, diff and comments…\").start();\n const pr = await provider.getPR(ctx.repoSlug, prNumber);\n const [comments, diff] = await Promise.all([\n provider.getPRComments(ctx.repoSlug, prNumber),\n provider.getPRDiff(ctx.repoSlug, prNumber),\n ]);\n fetchSpinner.succeed(`PR #${prNumber}: \"${pr.title}\" (${pr.head} β†’ ${pr.base})`);\n\n // ── Build codebase context ─────────────────────────────────────────────────\n const ctxSpinner = ora(\"Building codebase context from changed files…\").start();\n const allTracked = await listTrackedFiles(cwd);\n const allChangedPaths = parseChangedPathsFromDiff(diff);\n\n // Filter out lockfiles / generated files β€” they waste tokens and add no review value.\n // No file count cap β€” per-file budgets in buildSeniorReviewPrompt already control\n // total size. Dropping files arbitrarily is worse than sending all of them.\n const changedPaths = allChangedPaths.filter(isReviewableFile);\n const skippedCount = allChangedPaths.length - changedPaths.length;\n\n // Read full content of changed files\n const changedFiles: Record<string, string> = {};\n for (const p of changedPaths) {\n const content = await readRepoFile(p, cwd);\n if (content) changedFiles[p] = content;\n }\n\n // Read supporting context files (imported by the changed files)\n // 10 context files gives the AI a solid picture of the codebase structure\n const ctxPaths = await findContextFiles(changedPaths, allTracked, cwd, 10);\n const contextFiles: Record<string, string> = {};\n for (const p of ctxPaths) {\n const content = await readRepoFile(p, cwd);\n if (content) contextFiles[p] = content;\n }\n\n const skippedNote = skippedCount > 0 ? `, ${skippedCount} lock/generated files skipped` : \"\";\n ctxSpinner.succeed(\n `Context: ${changedPaths.length} changed files, ${ctxPaths.length} context files${skippedNote}`\n );\n\n const reviewSpinner = ora(\n `Running senior-dev AI review… (this may take up to 5 min for large PRs)`\n ).start();\n\n let review: Awaited<ReturnType<typeof gitx.ai.reviewPRDetailed>>;\n try {\n review = await gitx.ai.reviewPRDetailed({\n prTitle: pr.title,\n prBody: pr.body,\n author: pr.author,\n headBranch: pr.head,\n baseBranch: pr.base,\n diff,\n changedFiles,\n contextFiles,\n repoFileList: allTracked,\n existingComments: comments.map((c) => ({\n author: c.author,\n body: c.body,\n path: c.path,\n line: c.line,\n })),\n });\n reviewSpinner.succeed(\n `Review complete β€” verdict: ${review.verdict} | ${review.inlineComments.length} inline comment(s)`\n );\n } catch (err) {\n reviewSpinner.fail(\"AI review failed.\");\n throw err;\n }\n\n // ── Build the formatted review body (for the summary comment) ─────────────\n const verdictIcon =\n review.verdict === \"approve\" ? \"βœ…\" :\n review.verdict === \"request_changes\" ? \"πŸ”΄\" : \"πŸ’¬\";\n\n const checklistLines = review.checklist.map((c) => {\n const icon = c.status === \"pass\" ? \"βœ…\" : c.status === \"warn\" ? \"⚠️\" : \"❌\";\n return `| ${icon} | **${c.area}** | ${c.note} |`;\n });\n\n const issueLines = review.issues.map((i) => {\n const sev = i.severity === \"critical\" ? \"πŸ”΄\" : i.severity === \"warning\" ? \"🟑\" : \"πŸ’‘\";\n const loc = i.file ? ` (\\`${i.file}${i.line ? `:${i.line}` : \"\"}\\`)` : \"\";\n return `${sev} ${i.description}${loc}`;\n });\n\n const posLines = review.positives.map((p) => `βœ” ${p}`);\n\n const summaryBody = [\n `## ${verdictIcon} Senior Dev AI Review (gitx) β€” ${review.verdict.replace(\"_\", \" \")}`,\n \"\",\n review.summary,\n ...(checklistLines.length > 0\n ? [\"\", \"### Review Checklist\", \"| Status | Area | Note |\", \"|--------|------|------|\", ...checklistLines]\n : []),\n ...(review.issues.length > 0 ? [\"\", \"### Issues Found\", ...issueLines] : []),\n ...(review.positives.length > 0 ? [\"\", \"### Positives\", ...posLines] : []),\n ...(review.testingNotes ? [\"\", \"### How to Test\", review.testingNotes] : []),\n ...(review.inlineComments.length > 0\n ? [`\\n> πŸ’¬ ${review.inlineComments.length} inline comment(s) posted on specific lines.`]\n : []),\n \"\",\n \"*Generated by [gitx](https://github.com/g-abhishek/gitx)*\",\n ].join(\"\\n\");\n\n // ── Post the formal review (inline comments + verdict) ────────────────────\n let reviewPosted = false;\n let inlineDelivery: ReviewResult[\"inlineDelivery\"] = \"none\";\n\n if (postComment) {\n const inlineCount = review.inlineComments.length;\n const postSpinner = ora(\n `Submitting review to PR${inlineCount > 0 ? ` with ${inlineCount} inline comment(s)` : \"\"}…`\n ).start();\n try {\n await provider.submitPRReview(ctx.repoSlug, prNumber, {\n body: summaryBody,\n event: review.verdict,\n comments: review.inlineComments.map((c) => ({\n path: c.path,\n line: c.line,\n body: c.suggestion\n ? `${c.body}\\n\\n**Suggestion:**\\n\\`\\`\\`suggestion\\n${c.suggestion}\\n\\`\\`\\``\n : c.body,\n })),\n });\n reviewPosted = true;\n // Determine how inline comments were delivered.\n // GitHub's submitPRReview will attempt inline first, then fall back to\n // plain comments. We can't detect which path was taken from here, so\n // we report \"inline\" optimistically β€” the user sees the real result on GitHub.\n inlineDelivery = inlineCount > 0 ? \"inline\" : \"none\";\n postSpinner.succeed(\n `Review submitted to PR.${inlineCount > 0 ? ` (${inlineCount} inline comment(s) β€” see PR for delivery method)` : \"\"}`\n );\n } catch (err) {\n postSpinner.fail(`Could not post review to PR: ${String((err as Error).message ?? err)}`);\n // Don't rethrow β€” still return the review so the user can see it locally\n }\n }\n\n return { pr, comments, aiSummary: summaryBody, review, reviewPosted, inlineDelivery };\n}\n\n// ─── Fix-comments workflow ────────────────────────────────────────────────────\n\nexport interface FixCommentsResult {\n pr: PullRequest;\n comments: PullRequestComment[];\n appliedFixes: Array<{ path: string; rationale: string }>;\n skippedFixes: Array<{ path: string; reason: string }>;\n}\n\n/**\n * Fetch PR review comments, ask AI to suggest fixes, apply them, and\n * commit + push the changes.\n */\nexport async function runFixCommentsWorkflow(\n gitx: Gitx,\n prNumber: number,\n dryRun = false,\n noCommit = false\n): Promise<FixCommentsResult> {\n const { applyUnifiedDiff, stageAll, hasStagedChanges, commitChanges } = await import(\n \"../utils/gitOps.js\"\n );\n const cwd = gitx.cwd;\n const ctx = await gitx.getRepoContext();\n const provider = createProvider(ctx);\n\n logger.info(`πŸ” Fetching PR #${prNumber}…`);\n const pr = await provider.getPR(ctx.repoSlug, prNumber);\n\n logger.info(\"πŸ’¬ Fetching review comments…\");\n const comments = await provider.getPRComments(ctx.repoSlug, prNumber);\n\n if (comments.length === 0) {\n logger.info(\"No review comments found.\");\n return { pr, comments, appliedFixes: [], skippedFixes: [] };\n }\n\n // Gather file contents for files mentioned in comments\n const mentionedPaths = [...new Set(comments.map((c) => c.path).filter(Boolean) as string[])];\n const trackedFiles = await listTrackedFiles(cwd);\n\n // Also include files mentioned in the PR body / title\n const allSourceFiles = trackedFiles\n .filter((f) => /\\.(ts|js|tsx|jsx|py|go|rs|java|rb|cs|cpp|c|h)$/.test(f))\n .slice(0, 15);\n\n const relevantFiles = [...new Set([...mentionedPaths, ...allSourceFiles])].slice(0, 15);\n const fileContents: Record<string, string> = {};\n for (const f of relevantFiles) {\n const content = await readRepoFile(f, cwd);\n if (content) fileContents[f] = content.slice(0, 4000);\n }\n\n logger.info(\"🧠 Generating AI-suggested fixes…\");\n const fixResult = await gitx.ai.suggestFixes({\n comments: comments.map((c) => ({\n body: c.body,\n author: c.author,\n path: c.path,\n line: c.line,\n })),\n prTitle: pr.title,\n prBody: pr.body,\n fileContents,\n });\n\n const appliedFixes: Array<{ path: string; rationale: string }> = [];\n const skippedFixes: Array<{ path: string; reason: string }> = [];\n\n for (const edit of fixResult.suggestedEdits) {\n if (dryRun) {\n logger.info(` ↳ [dry-run] Would apply fix to: ${edit.path}`);\n logger.info(` Rationale: ${edit.rationale}`);\n appliedFixes.push({ path: edit.path, rationale: edit.rationale });\n continue;\n }\n\n const applyResult = await applyUnifiedDiff(edit.unifiedDiff, cwd);\n if (applyResult.ok) {\n logger.info(` ↳ Applied fix to: ${edit.path}`);\n appliedFixes.push({ path: edit.path, rationale: edit.rationale });\n } else {\n logger.warn(` ↳ Could not apply fix to ${edit.path}: ${applyResult.error ?? \"unknown\"}`);\n skippedFixes.push({\n path: edit.path,\n reason: applyResult.error ?? \"git apply failed\",\n });\n }\n }\n\n if (!dryRun && !noCommit && appliedFixes.length > 0) {\n await stageAll(cwd);\n if (await hasStagedChanges(cwd)) {\n const msg = `fix: address PR #${prNumber} review comments\\n\\n${appliedFixes.map((f) => `- ${f.path}: ${f.rationale}`).join(\"\\n\")}`;\n const sha = await commitChanges(msg, cwd);\n logger.success(`Committed fixes: ${sha.slice(0, 8)}`);\n\n // Post summary comment\n const fixSummary = appliedFixes.map((f) => `- \\`${f.path}\\`: ${f.rationale}`).join(\"\\n\");\n await provider.addPRComment(\n ctx.repoSlug,\n prNumber,\n `## πŸ€– Auto-fixes applied (gitx)\\n\\n${fixSummary}\\n\\nCommit: \\`${sha.slice(0, 8)}\\``\n );\n }\n }\n\n if (!dryRun && noCommit && appliedFixes.length > 0) {\n logger.info(\"\\nπŸ’‘ Fixes applied to working tree. Review the changes and commit when ready.\");\n }\n\n return { pr, comments, appliedFixes, skippedFixes };\n}\n"]}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * PR Address Workflow
3
+ *
4
+ * Reads unresolved review comments on a PR, generates AI fixes for each one,
5
+ * applies them to local files, and optionally commits, pushes, and replies
6
+ * to each thread marking it as addressed.
7
+ *
8
+ * Used by:
9
+ * - `gitx pr review <n>` β€” offered interactively after the review output
10
+ * - `gitx sync` β€” offered when unresolved comments are detected
11
+ */
12
+ import type { Gitx } from "../core/gitx.js";
13
+ import type { PullRequestComment } from "../providers/base.js";
14
+ import type { AiFixResponse } from "../ai/types.js";
15
+ export interface AddressedComment {
16
+ comment: PullRequestComment;
17
+ fix: AiFixResponse;
18
+ applied: boolean;
19
+ skipped: boolean;
20
+ /** Reason for skipping (user choice, low-confidence rejection, patch error) */
21
+ skipReason?: string;
22
+ }
23
+ export interface AddressWorkflowResult {
24
+ addressed: AddressedComment[];
25
+ filesChanged: string[];
26
+ pushed: boolean;
27
+ commitSha?: string;
28
+ repliedCount: number;
29
+ }
30
+ /**
31
+ * Given the full flat list of PR comments, return only the root inline comments
32
+ * that are genuinely unresolved β€” i.e.:
33
+ *
34
+ * 1. They are inline (have path + line > 0).
35
+ * 2. They are root comments, not replies (no inReplyToId).
36
+ * 3. None of their replies contain "βœ… Addressed" β€” our bot's resolution marker.
37
+ *
38
+ * This is the single source of truth used by both the address workflow and the
39
+ * sync pre-check. Replacing the old body-prefix heuristic which was fragile and
40
+ * incorrectly filtered out valid comments.
41
+ */
42
+ export declare function filterUnresolvedInlineComments(all: PullRequestComment[]): PullRequestComment[];
43
+ export interface AddressWorkflowOptions {
44
+ /**
45
+ * "interactive" (default) β€” show each fix and ask to apply; ask to commit+push at the end.
46
+ * "auto" β€” apply all high-confidence fixes silently, commit and push.
47
+ * "no-push" β€” interactive but never commits or pushes (local changes only).
48
+ * "commit-no-push" β€” interactive, commits the fixes but does NOT push.
49
+ * Used by `gitx sync` so sync can push everything together
50
+ * after rebasing/merging onto the base branch.
51
+ */
52
+ mode?: "interactive" | "auto" | "no-push" | "commit-no-push";
53
+ }
54
+ export declare function runAddressWorkflow(gitx: Gitx, prNumber: number, opts?: AddressWorkflowOptions): Promise<AddressWorkflowResult>;
55
+ //# sourceMappingURL=prAddress.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prAddress.d.ts","sourceRoot":"","sources":["../../src/workflows/prAddress.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAQH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAsBpD,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,kBAAkB,CAAC;IAC5B,GAAG,EAAE,aAAa,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,OAAO,CAAC;IACjB,+EAA+E;IAC/E,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,gBAAgB,EAAE,CAAC;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,MAAM,EAAE,OAAO,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqDD;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAC5C,GAAG,EAAE,kBAAkB,EAAE,GACxB,kBAAkB,EAAE,CAoBtB;AAID,MAAM,WAAW,sBAAsB;IACrC;;;;;;;OAOG;IACH,IAAI,CAAC,EAAE,aAAa,GAAG,MAAM,GAAG,SAAS,GAAG,gBAAgB,CAAC;CAC9D;AAED,wBAAsB,kBAAkB,CACtC,IAAI,EAAE,IAAI,EACV,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,sBAA2B,GAChC,OAAO,CAAC,qBAAqB,CAAC,CA8PhC"}