claude-issue-solver 1.32.0 ā 1.34.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/commands/review.js +23 -128
- package/dist/commands/solve.js +2 -1
- package/package.json +1 -1
package/dist/commands/review.js
CHANGED
|
@@ -43,6 +43,7 @@ const ora_1 = __importDefault(require("ora"));
|
|
|
43
43
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
44
44
|
const fs = __importStar(require("fs"));
|
|
45
45
|
const path = __importStar(require("path"));
|
|
46
|
+
const os = __importStar(require("os"));
|
|
46
47
|
const child_process_1 = require("child_process");
|
|
47
48
|
const github_1 = require("../utils/github");
|
|
48
49
|
const git_1 = require("../utils/git");
|
|
@@ -57,22 +58,21 @@ async function reviewCommand(issueNumber, options = {}) {
|
|
|
57
58
|
}
|
|
58
59
|
spinner.succeed(`Found issue #${issueNumber}`);
|
|
59
60
|
const projectRoot = (0, git_1.getProjectRoot)();
|
|
60
|
-
|
|
61
|
-
const baseBranch = (0, git_1.getDefaultBranch)();
|
|
62
|
-
const branchSlug = (0, helpers_1.slugify)(issue.title);
|
|
63
|
-
const branchName = `issue-${issueNumber}-${branchSlug}`;
|
|
64
|
-
const worktreePath = path.join(path.dirname(projectRoot), `${projectName}-${branchName}`);
|
|
65
|
-
// Check if there's a PR for this issue
|
|
61
|
+
// Check if there's a PR for this issue - search by issue number in all PRs
|
|
66
62
|
const prCheckSpinner = (0, ora_1.default)('Checking for PR...').start();
|
|
67
63
|
let prNumber = null;
|
|
64
|
+
let branchName = null;
|
|
68
65
|
try {
|
|
69
|
-
|
|
66
|
+
// Search for PRs that mention the issue number in their branch name
|
|
67
|
+
const prOutput = (0, child_process_1.execSync)(`gh pr list --state open --json number,headRefName --jq '.[] | select(.headRefName | test("issue-${issueNumber}-")) | "\\(.number) \\(.headRefName)"'`, {
|
|
70
68
|
cwd: projectRoot,
|
|
71
69
|
encoding: 'utf-8',
|
|
72
70
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
73
71
|
}).trim();
|
|
74
72
|
if (prOutput) {
|
|
75
|
-
|
|
73
|
+
const [num, branch] = prOutput.split(' ');
|
|
74
|
+
prNumber = num;
|
|
75
|
+
branchName = branch;
|
|
76
76
|
prCheckSpinner.succeed(`Found PR #${prNumber}`);
|
|
77
77
|
}
|
|
78
78
|
else {
|
|
@@ -90,55 +90,6 @@ async function reviewCommand(issueNumber, options = {}) {
|
|
|
90
90
|
console.log(chalk_1.default.bold(`š Reviewing: ${issue.title}`));
|
|
91
91
|
console.log(chalk_1.default.dim(`š PR: https://github.com/${getRepoName(projectRoot)}/pull/${prNumber}`));
|
|
92
92
|
console.log();
|
|
93
|
-
// Fetch latest
|
|
94
|
-
const fetchSpinner = (0, ora_1.default)(`Fetching latest changes...`).start();
|
|
95
|
-
try {
|
|
96
|
-
(0, child_process_1.execSync)(`git fetch origin ${branchName} --quiet`, { cwd: projectRoot, stdio: 'pipe' });
|
|
97
|
-
fetchSpinner.succeed('Fetched latest changes');
|
|
98
|
-
}
|
|
99
|
-
catch {
|
|
100
|
-
fetchSpinner.warn('Could not fetch branch');
|
|
101
|
-
}
|
|
102
|
-
// Check if worktree already exists
|
|
103
|
-
if (fs.existsSync(worktreePath)) {
|
|
104
|
-
console.log(chalk_1.default.yellow(`\nšæ Using existing worktree at: ${worktreePath}`));
|
|
105
|
-
// Pull latest changes
|
|
106
|
-
try {
|
|
107
|
-
(0, child_process_1.execSync)('git pull --quiet', { cwd: worktreePath, stdio: 'pipe' });
|
|
108
|
-
}
|
|
109
|
-
catch {
|
|
110
|
-
// Ignore pull errors
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
else {
|
|
114
|
-
const worktreeSpinner = (0, ora_1.default)(`Creating worktree for review...`).start();
|
|
115
|
-
try {
|
|
116
|
-
if ((0, git_1.branchExists)(branchName)) {
|
|
117
|
-
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" "${branchName}"`, {
|
|
118
|
-
cwd: projectRoot,
|
|
119
|
-
stdio: 'pipe',
|
|
120
|
-
});
|
|
121
|
-
}
|
|
122
|
-
else {
|
|
123
|
-
// Branch should exist if PR exists, but handle edge case
|
|
124
|
-
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" "origin/${branchName}"`, {
|
|
125
|
-
cwd: projectRoot,
|
|
126
|
-
stdio: 'pipe',
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
worktreeSpinner.succeed(`Created worktree at: ${worktreePath}`);
|
|
130
|
-
}
|
|
131
|
-
catch (error) {
|
|
132
|
-
worktreeSpinner.fail('Failed to create worktree');
|
|
133
|
-
console.error(error);
|
|
134
|
-
process.exit(1);
|
|
135
|
-
}
|
|
136
|
-
// Copy env files and symlink node_modules
|
|
137
|
-
const setupSpinner = (0, ora_1.default)('Setting up worktree...').start();
|
|
138
|
-
(0, helpers_1.copyEnvFiles)(projectRoot, worktreePath);
|
|
139
|
-
(0, helpers_1.symlinkNodeModules)(projectRoot, worktreePath);
|
|
140
|
-
setupSpinner.succeed('Worktree setup complete');
|
|
141
|
-
}
|
|
142
93
|
// Get the diff for context
|
|
143
94
|
let diffContent = '';
|
|
144
95
|
try {
|
|
@@ -247,8 +198,9 @@ The \`suggestion\` code block creates a "Commit suggestion" button on GitHub.
|
|
|
247
198
|
${diffContent ? `\n\`\`\`diff\n${diffContent.slice(0, 50000)}\n\`\`\`\n` : 'Run `gh pr diff ' + prNumber + '` to see the changes.'}
|
|
248
199
|
|
|
249
200
|
Start by examining the diff and the changed files, then provide your review.`;
|
|
250
|
-
// Write prompt to
|
|
251
|
-
const
|
|
201
|
+
// Write prompt and runner script to temp directory
|
|
202
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cis-review-'));
|
|
203
|
+
const promptFile = path.join(tempDir, '.claude-review-prompt.txt');
|
|
252
204
|
fs.writeFileSync(promptFile, prompt);
|
|
253
205
|
// Bot token already fetched above
|
|
254
206
|
const botTokenEnv = botToken ? `export BOT_TOKEN="${botToken}"\nexport GH_TOKEN="${botToken}"` : '# No bot token configured';
|
|
@@ -256,9 +208,9 @@ Start by examining the diff and the changed files, then provide your review.`;
|
|
|
256
208
|
? 'Using bot token for reviews (can approve/request changes)'
|
|
257
209
|
: 'No bot token - using your account (may have limitations on own PRs)';
|
|
258
210
|
// Create runner script for review
|
|
259
|
-
const runnerScript = path.join(
|
|
211
|
+
const runnerScript = path.join(tempDir, '.claude-review-runner.sh');
|
|
260
212
|
const runnerContent = `#!/bin/bash
|
|
261
|
-
cd "${
|
|
213
|
+
cd "${projectRoot}"
|
|
262
214
|
|
|
263
215
|
# Set bot token if configured
|
|
264
216
|
${botTokenEnv}
|
|
@@ -282,8 +234,8 @@ echo ""
|
|
|
282
234
|
# Run Claude interactively
|
|
283
235
|
claude --dangerously-skip-permissions "$(cat '${promptFile}')"
|
|
284
236
|
|
|
285
|
-
# Clean up
|
|
286
|
-
rm -
|
|
237
|
+
# Clean up temp files
|
|
238
|
+
rm -rf '${tempDir}'
|
|
287
239
|
|
|
288
240
|
echo ""
|
|
289
241
|
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā"
|
|
@@ -300,13 +252,6 @@ ${options.merge ? ` echo "š¤ Auto-merging PR #${prNumber}..."
|
|
|
300
252
|
if gh pr merge ${prNumber} --squash --delete-branch; then
|
|
301
253
|
echo ""
|
|
302
254
|
echo "ā
PR merged successfully!"
|
|
303
|
-
echo ""
|
|
304
|
-
echo "Cleaning up worktree..."
|
|
305
|
-
cd "${projectRoot}"
|
|
306
|
-
git worktree remove "${worktreePath}" --force 2>/dev/null || rm -rf "${worktreePath}"
|
|
307
|
-
git worktree prune 2>/dev/null
|
|
308
|
-
git branch -D "${branchName}" 2>/dev/null
|
|
309
|
-
echo "ā
Cleanup complete!"
|
|
310
255
|
else
|
|
311
256
|
echo ""
|
|
312
257
|
echo "ā ļø Merge failed. You can try manually: gh pr merge ${prNumber} --squash"
|
|
@@ -330,7 +275,6 @@ exec bash
|
|
|
330
275
|
console.log(chalk_1.default.dim(` Claude is reviewing in a new terminal window.`));
|
|
331
276
|
console.log();
|
|
332
277
|
console.log(chalk_1.default.dim(` View PR: gh pr view ${prNumber} --web`));
|
|
333
|
-
console.log(chalk_1.default.dim(` To clean up later: claude-issue clean ${issueNumber}`));
|
|
334
278
|
}
|
|
335
279
|
function getRepoName(projectRoot) {
|
|
336
280
|
try {
|
|
@@ -424,50 +368,7 @@ async function selectReviewCommand(options = {}) {
|
|
|
424
368
|
console.log(chalk_1.default.green(`ā
Started ${selected.length} review session(s)!`));
|
|
425
369
|
console.log(chalk_1.default.dim(' Each review is running in its own terminal window.'));
|
|
426
370
|
}
|
|
427
|
-
async function launchReviewForPR(pr, projectRoot,
|
|
428
|
-
const baseBranch = (0, git_1.getDefaultBranch)();
|
|
429
|
-
const branchName = pr.headRefName;
|
|
430
|
-
const worktreePath = path.join(path.dirname(projectRoot), `${projectName}-${branchName}`);
|
|
431
|
-
// Fetch latest
|
|
432
|
-
try {
|
|
433
|
-
(0, child_process_1.execSync)(`git fetch origin ${branchName} --quiet`, { cwd: projectRoot, stdio: 'pipe' });
|
|
434
|
-
}
|
|
435
|
-
catch {
|
|
436
|
-
// Ignore fetch errors
|
|
437
|
-
}
|
|
438
|
-
// Check if worktree already exists
|
|
439
|
-
if (!fs.existsSync(worktreePath)) {
|
|
440
|
-
try {
|
|
441
|
-
if ((0, git_1.branchExists)(branchName)) {
|
|
442
|
-
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" "${branchName}"`, {
|
|
443
|
-
cwd: projectRoot,
|
|
444
|
-
stdio: 'pipe',
|
|
445
|
-
});
|
|
446
|
-
}
|
|
447
|
-
else {
|
|
448
|
-
(0, child_process_1.execSync)(`git worktree add "${worktreePath}" "origin/${branchName}"`, {
|
|
449
|
-
cwd: projectRoot,
|
|
450
|
-
stdio: 'pipe',
|
|
451
|
-
});
|
|
452
|
-
}
|
|
453
|
-
// Copy env files and symlink node_modules
|
|
454
|
-
(0, helpers_1.copyEnvFiles)(projectRoot, worktreePath);
|
|
455
|
-
(0, helpers_1.symlinkNodeModules)(projectRoot, worktreePath);
|
|
456
|
-
}
|
|
457
|
-
catch (error) {
|
|
458
|
-
console.log(chalk_1.default.yellow(`ā ļø Could not create worktree for PR #${pr.number}`));
|
|
459
|
-
return;
|
|
460
|
-
}
|
|
461
|
-
}
|
|
462
|
-
else {
|
|
463
|
-
// Pull latest changes
|
|
464
|
-
try {
|
|
465
|
-
(0, child_process_1.execSync)('git pull --quiet', { cwd: worktreePath, stdio: 'pipe' });
|
|
466
|
-
}
|
|
467
|
-
catch {
|
|
468
|
-
// Ignore pull errors
|
|
469
|
-
}
|
|
470
|
-
}
|
|
371
|
+
async function launchReviewForPR(pr, projectRoot, _projectName, options = {}) {
|
|
471
372
|
// Get the diff for context
|
|
472
373
|
let diffContent = '';
|
|
473
374
|
try {
|
|
@@ -580,18 +481,19 @@ The \`suggestion\` code block creates a "Commit suggestion" button on GitHub.
|
|
|
580
481
|
${diffContent ? `\n\`\`\`diff\n${diffContent.slice(0, 50000)}\n\`\`\`\n` : 'Run `gh pr diff ' + pr.number + '` to see the changes.'}
|
|
581
482
|
|
|
582
483
|
Start by examining the diff and the changed files, then provide your review.`;
|
|
583
|
-
// Write prompt to
|
|
584
|
-
const
|
|
484
|
+
// Write prompt and runner script to temp directory
|
|
485
|
+
const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'cis-review-'));
|
|
486
|
+
const promptFile = path.join(tempDir, '.claude-review-prompt.txt');
|
|
585
487
|
fs.writeFileSync(promptFile, prompt);
|
|
586
488
|
const botTokenEnv = botToken ? `export BOT_TOKEN="${botToken}"\nexport GH_TOKEN="${botToken}"` : '# No bot token configured';
|
|
587
489
|
const botNote = botToken
|
|
588
490
|
? 'Using bot token for reviews (can approve/request changes)'
|
|
589
491
|
: 'No bot token - using your account (may have limitations on own PRs)';
|
|
590
492
|
// Create runner script for review
|
|
591
|
-
const runnerScript = path.join(
|
|
493
|
+
const runnerScript = path.join(tempDir, '.claude-review-runner.sh');
|
|
592
494
|
const escapedTitle = pr.title.replace(/"/g, '\\"').slice(0, 50);
|
|
593
495
|
const runnerContent = `#!/bin/bash
|
|
594
|
-
cd "${
|
|
496
|
+
cd "${projectRoot}"
|
|
595
497
|
|
|
596
498
|
# Set bot token if configured
|
|
597
499
|
${botTokenEnv}
|
|
@@ -615,8 +517,8 @@ echo ""
|
|
|
615
517
|
# Run Claude interactively
|
|
616
518
|
claude --dangerously-skip-permissions "$(cat '${promptFile}')"
|
|
617
519
|
|
|
618
|
-
# Clean up
|
|
619
|
-
rm -
|
|
520
|
+
# Clean up temp files
|
|
521
|
+
rm -rf '${tempDir}'
|
|
620
522
|
|
|
621
523
|
echo ""
|
|
622
524
|
echo "āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā"
|
|
@@ -633,13 +535,6 @@ ${options.merge ? ` echo "š¤ Auto-merging PR #${pr.number}..."
|
|
|
633
535
|
if gh pr merge ${pr.number} --squash --delete-branch; then
|
|
634
536
|
echo ""
|
|
635
537
|
echo "ā
PR merged successfully!"
|
|
636
|
-
echo ""
|
|
637
|
-
echo "Cleaning up worktree..."
|
|
638
|
-
cd "${projectRoot}"
|
|
639
|
-
git worktree remove "${worktreePath}" --force 2>/dev/null || rm -rf "${worktreePath}"
|
|
640
|
-
git worktree prune 2>/dev/null
|
|
641
|
-
git branch -D "${branchName}" 2>/dev/null
|
|
642
|
-
echo "ā
Cleanup complete!"
|
|
643
538
|
else
|
|
644
539
|
echo ""
|
|
645
540
|
echo "ā ļø Merge failed. You can try manually: gh pr merge ${pr.number} --squash"
|
package/dist/commands/solve.js
CHANGED
|
@@ -118,7 +118,8 @@ Instructions:
|
|
|
118
118
|
1. Analyze the issue and understand what needs to be done
|
|
119
119
|
2. Implement the necessary changes
|
|
120
120
|
3. Make sure to run tests if applicable
|
|
121
|
-
4. When done, commit your changes with a descriptive message that references the issue
|
|
121
|
+
4. When done, commit your changes with a descriptive message that references the issue
|
|
122
|
+
5. A PR will be created automatically when you commit - no need to create one manually`;
|
|
122
123
|
// Write prompt to a file to avoid shell escaping issues with backticks, <>, etc.
|
|
123
124
|
const promptFile = path.join(worktreePath, '.claude-prompt.txt');
|
|
124
125
|
fs.writeFileSync(promptFile, prompt);
|