claude-issue-solver 1.8.2 → 1.9.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/select.js +13 -1
- package/dist/utils/github.d.ts +5 -0
- package/dist/utils/github.js +23 -0
- package/dist/utils/helpers.js +38 -5
- package/package.json +1 -1
package/dist/commands/select.js
CHANGED
|
@@ -17,7 +17,19 @@ async function selectCommand() {
|
|
|
17
17
|
console.log(chalk_1.default.yellow('No open issues found.'));
|
|
18
18
|
return;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
// Filter out issues that already have open PRs
|
|
21
|
+
const issuesWithPRs = (0, github_1.getIssuesWithOpenPRs)();
|
|
22
|
+
const availableIssues = issues.filter((issue) => !issuesWithPRs.has(issue.number));
|
|
23
|
+
if (availableIssues.length === 0) {
|
|
24
|
+
console.log(chalk_1.default.yellow('All open issues already have PRs in progress.'));
|
|
25
|
+
console.log(chalk_1.default.dim('Use `claude-issue go` to navigate to existing worktrees.'));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (issuesWithPRs.size > 0) {
|
|
29
|
+
const skipped = issues.length - availableIssues.length;
|
|
30
|
+
console.log(chalk_1.default.dim(`(${skipped} issue${skipped > 1 ? 's' : ''} with open PRs hidden)\n`));
|
|
31
|
+
}
|
|
32
|
+
const choices = availableIssues.map((issue) => ({
|
|
21
33
|
name: `#${issue.number}\t${issue.title}`,
|
|
22
34
|
value: issue.number,
|
|
23
35
|
}));
|
package/dist/utils/github.d.ts
CHANGED
|
@@ -20,3 +20,8 @@ export interface PRStatus {
|
|
|
20
20
|
}
|
|
21
21
|
export declare function getIssueStatus(issueNumber: number): IssueStatus | null;
|
|
22
22
|
export declare function getPRForBranch(branch: string): PRStatus | null;
|
|
23
|
+
/**
|
|
24
|
+
* Get all open PRs with their head branch names (single API call)
|
|
25
|
+
* Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
|
|
26
|
+
*/
|
|
27
|
+
export declare function getIssuesWithOpenPRs(): Set<number>;
|
package/dist/utils/github.js
CHANGED
|
@@ -5,6 +5,7 @@ exports.listIssues = listIssues;
|
|
|
5
5
|
exports.createPullRequest = createPullRequest;
|
|
6
6
|
exports.getIssueStatus = getIssueStatus;
|
|
7
7
|
exports.getPRForBranch = getPRForBranch;
|
|
8
|
+
exports.getIssuesWithOpenPRs = getIssuesWithOpenPRs;
|
|
8
9
|
const child_process_1 = require("child_process");
|
|
9
10
|
function getIssue(issueNumber) {
|
|
10
11
|
try {
|
|
@@ -61,3 +62,25 @@ function getPRForBranch(branch) {
|
|
|
61
62
|
return null;
|
|
62
63
|
}
|
|
63
64
|
}
|
|
65
|
+
/**
|
|
66
|
+
* Get all open PRs with their head branch names (single API call)
|
|
67
|
+
* Returns a Set of issue numbers that have open PRs from issue-{number}-* branches
|
|
68
|
+
*/
|
|
69
|
+
function getIssuesWithOpenPRs() {
|
|
70
|
+
try {
|
|
71
|
+
const output = (0, child_process_1.execSync)(`gh pr list --state open --json headRefName --limit 100`, { encoding: 'utf-8', stdio: ['pipe', 'pipe', 'pipe'] });
|
|
72
|
+
const data = JSON.parse(output);
|
|
73
|
+
const issueNumbers = new Set();
|
|
74
|
+
for (const pr of data) {
|
|
75
|
+
// Match branches like "issue-42-fix-bug"
|
|
76
|
+
const match = pr.headRefName.match(/^issue-(\d+)-/);
|
|
77
|
+
if (match) {
|
|
78
|
+
issueNumbers.add(parseInt(match[1], 10));
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return issueNumbers;
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
return new Set();
|
|
85
|
+
}
|
|
86
|
+
}
|
package/dist/utils/helpers.js
CHANGED
|
@@ -136,12 +136,45 @@ function openInNewTerminal(script) {
|
|
|
136
136
|
console.log(script);
|
|
137
137
|
}
|
|
138
138
|
}
|
|
139
|
+
/**
|
|
140
|
+
* Recursively find all .env* files in a directory
|
|
141
|
+
*/
|
|
142
|
+
function findEnvFiles(dir, baseDir, results = []) {
|
|
143
|
+
const skipDirs = ['node_modules', '.git', 'dist', 'build', '.next', '.turbo'];
|
|
144
|
+
try {
|
|
145
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
146
|
+
for (const entry of entries) {
|
|
147
|
+
const fullPath = path.join(dir, entry.name);
|
|
148
|
+
if (entry.isDirectory()) {
|
|
149
|
+
if (!skipDirs.includes(entry.name)) {
|
|
150
|
+
findEnvFiles(fullPath, baseDir, results);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
else if (entry.isFile() && entry.name.startsWith('.env')) {
|
|
154
|
+
// Store relative path from base directory
|
|
155
|
+
const relativePath = path.relative(baseDir, fullPath);
|
|
156
|
+
results.push(relativePath);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// Ignore permission errors or inaccessible directories
|
|
162
|
+
}
|
|
163
|
+
return results;
|
|
164
|
+
}
|
|
139
165
|
function copyEnvFiles(from, to) {
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
const
|
|
144
|
-
|
|
166
|
+
// Find all .env* files recursively
|
|
167
|
+
const envFiles = findEnvFiles(from, from);
|
|
168
|
+
for (const relativePath of envFiles) {
|
|
169
|
+
const src = path.join(from, relativePath);
|
|
170
|
+
const dest = path.join(to, relativePath);
|
|
171
|
+
// Create parent directory if it doesn't exist
|
|
172
|
+
const destDir = path.dirname(dest);
|
|
173
|
+
if (!fs.existsSync(destDir)) {
|
|
174
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
175
|
+
}
|
|
176
|
+
// Only copy if destination doesn't exist
|
|
177
|
+
if (!fs.existsSync(dest)) {
|
|
145
178
|
fs.copyFileSync(src, dest);
|
|
146
179
|
}
|
|
147
180
|
}
|