claude-issue-solver 1.43.2 → 1.43.3

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.
@@ -25,6 +25,14 @@ export declare function generateVSCodeCloseScript(patterns: string[]): string;
25
25
  * Execute AppleScript and handle errors gracefully
26
26
  */
27
27
  export declare function executeAppleScript(script: string, timeout?: number): boolean;
28
+ /**
29
+ * Find TTYs associated with processes in the given directory
30
+ */
31
+ export declare function findTTYsInDirectory(dirPath: string): string[];
32
+ /**
33
+ * Generate AppleScript to close iTerm2 windows by TTY
34
+ */
35
+ export declare function generateITermCloseByTTYScript(ttys: string[]): string;
28
36
  /**
29
37
  * Find and terminate shell processes running in the given directory
30
38
  * This is a fallback approach when AppleScript matching fails
@@ -38,6 +38,8 @@ exports.generateITermCloseScript = generateITermCloseScript;
38
38
  exports.generateTerminalCloseScript = generateTerminalCloseScript;
39
39
  exports.generateVSCodeCloseScript = generateVSCodeCloseScript;
40
40
  exports.executeAppleScript = executeAppleScript;
41
+ exports.findTTYsInDirectory = findTTYsInDirectory;
42
+ exports.generateITermCloseByTTYScript = generateITermCloseByTTYScript;
41
43
  exports.killProcessesInDirectory = killProcessesInDirectory;
42
44
  exports.closeWindowsForWorktree = closeWindowsForWorktree;
43
45
  const child_process_1 = require("child_process");
@@ -208,6 +210,84 @@ function executeAppleScript(script, timeout = 5000) {
208
210
  return false;
209
211
  }
210
212
  }
213
+ /**
214
+ * Find TTYs associated with processes in the given directory
215
+ */
216
+ function findTTYsInDirectory(dirPath) {
217
+ if (os.platform() !== 'darwin' && os.platform() !== 'linux') {
218
+ return [];
219
+ }
220
+ try {
221
+ // Use lsof to find processes with files open in the directory
222
+ const output = (0, child_process_1.execSync)(`lsof +D "${dirPath}" 2>/dev/null || true`, {
223
+ encoding: 'utf8',
224
+ timeout: 5000,
225
+ });
226
+ if (!output.trim()) {
227
+ return [];
228
+ }
229
+ // Parse lsof output to get TTYs
230
+ const lines = output.split('\n').slice(1); // Skip header
231
+ const ttys = new Set();
232
+ for (const line of lines) {
233
+ const parts = line.split(/\s+/);
234
+ // lsof output: COMMAND PID USER FD TYPE DEVICE SIZE/OFF NODE NAME
235
+ // We want to find the FD column that shows the tty
236
+ if (parts.length >= 9) {
237
+ const fd = parts[3];
238
+ const type = parts[4];
239
+ const name = parts[8];
240
+ // Look for tty file descriptors
241
+ if ((fd === '0u' || fd === '1u' || fd === '2u') && name.startsWith('/dev/ttys')) {
242
+ ttys.add(name);
243
+ }
244
+ }
245
+ }
246
+ return Array.from(ttys);
247
+ }
248
+ catch {
249
+ return [];
250
+ }
251
+ }
252
+ /**
253
+ * Generate AppleScript to close iTerm2 windows by TTY
254
+ */
255
+ function generateITermCloseByTTYScript(ttys) {
256
+ if (ttys.length === 0)
257
+ return '';
258
+ const ttyConditions = ttys.map(tty => `tty of s is "${tty}"`).join(' or ');
259
+ return `
260
+ tell application "iTerm"
261
+ set windowsToClose to {}
262
+
263
+ repeat with w in windows
264
+ set windowId to id of w
265
+ repeat with t in tabs of w
266
+ repeat with s in sessions of t
267
+ try
268
+ if ${ttyConditions} then
269
+ if windowsToClose does not contain windowId then
270
+ set end of windowsToClose to windowId
271
+ end if
272
+ end if
273
+ end try
274
+ end repeat
275
+ end repeat
276
+ end repeat
277
+
278
+ repeat with targetWindowId in windowsToClose
279
+ try
280
+ repeat with w in windows
281
+ if id of w is targetWindowId then
282
+ close w
283
+ exit repeat
284
+ end if
285
+ end repeat
286
+ end try
287
+ end repeat
288
+ end tell
289
+ `;
290
+ }
211
291
  /**
212
292
  * Find and terminate shell processes running in the given directory
213
293
  * This is a fallback approach when AppleScript matching fails
@@ -264,10 +344,21 @@ function closeWindowsForWorktree(options) {
264
344
  return { iTerm: false, terminal: false, vscode: false, processes: false };
265
345
  }
266
346
  const patterns = getSearchPatterns(options);
267
- // Try to close iTerm2 windows/sessions
268
- const iTermScript = generateITermCloseScript(patterns);
269
- const iTermResult = executeAppleScript(iTermScript);
270
- // Try to close Terminal.app windows
347
+ // First, find TTYs associated with processes in the worktree
348
+ // This is the most reliable way to identify the terminal
349
+ const ttys = findTTYsInDirectory(options.folderPath);
350
+ let iTermResult = false;
351
+ // Try to close iTerm2 by TTY first (most reliable)
352
+ if (ttys.length > 0) {
353
+ const iTermTTYScript = generateITermCloseByTTYScript(ttys);
354
+ iTermResult = executeAppleScript(iTermTTYScript);
355
+ }
356
+ // Fall back to pattern-based matching if TTY approach didn't work
357
+ if (!iTermResult) {
358
+ const iTermScript = generateITermCloseScript(patterns);
359
+ iTermResult = executeAppleScript(iTermScript);
360
+ }
361
+ // Try to close Terminal.app windows (pattern-based)
271
362
  const terminalScript = generateTerminalCloseScript(patterns);
272
363
  const terminalResult = executeAppleScript(terminalScript);
273
364
  // Try to close VS Code windows
@@ -218,4 +218,30 @@ const terminal_1 = require("./terminal");
218
218
  (0, vitest_1.expect)(typeof result).toBe('boolean');
219
219
  });
220
220
  });
221
+ (0, vitest_1.describe)('findTTYsInDirectory', () => {
222
+ (0, vitest_1.it)('should return empty array for non-existent directory', () => {
223
+ const result = (0, terminal_1.findTTYsInDirectory)('/nonexistent/path/that/does/not/exist');
224
+ (0, vitest_1.expect)(result).toEqual([]);
225
+ });
226
+ (0, vitest_1.it)('should return array', () => {
227
+ const result = (0, terminal_1.findTTYsInDirectory)('/tmp');
228
+ (0, vitest_1.expect)(Array.isArray(result)).toBe(true);
229
+ });
230
+ });
231
+ (0, vitest_1.describe)('generateITermCloseByTTYScript', () => {
232
+ (0, vitest_1.it)('should return empty string for empty TTY array', () => {
233
+ const script = (0, terminal_1.generateITermCloseByTTYScript)([]);
234
+ (0, vitest_1.expect)(script).toBe('');
235
+ });
236
+ (0, vitest_1.it)('should generate valid AppleScript for single TTY', () => {
237
+ const script = (0, terminal_1.generateITermCloseByTTYScript)(['/dev/ttys001']);
238
+ (0, vitest_1.expect)(script).toContain('tell application "iTerm"');
239
+ (0, vitest_1.expect)(script).toContain('tty of s is "/dev/ttys001"');
240
+ (0, vitest_1.expect)(script).toContain('close w');
241
+ });
242
+ (0, vitest_1.it)('should generate OR conditions for multiple TTYs', () => {
243
+ const script = (0, terminal_1.generateITermCloseByTTYScript)(['/dev/ttys001', '/dev/ttys002']);
244
+ (0, vitest_1.expect)(script).toContain('tty of s is "/dev/ttys001" or tty of s is "/dev/ttys002"');
245
+ });
246
+ });
221
247
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-issue-solver",
3
- "version": "1.43.2",
3
+ "version": "1.43.3",
4
4
  "description": "Automatically solve GitHub issues using Claude Code",
5
5
  "main": "dist/index.js",
6
6
  "bin": {