code-squad-cli 1.2.10 → 1.2.11

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.
@@ -73,18 +73,22 @@ async function pasteToOriginalSession(sessionId) {
73
73
  // Write script to temp file and execute via detached process
74
74
  const tmpScript = path.join(os.tmpdir(), `flip-paste-${Date.now()}.scpt`);
75
75
  fs.writeFileSync(tmpScript, script);
76
+ const cleanupScript = () => {
77
+ try {
78
+ fs.unlinkSync(tmpScript);
79
+ }
80
+ catch { /* ignore */ }
81
+ };
76
82
  const child = spawn('osascript', [tmpScript], {
77
83
  detached: true,
78
84
  stdio: 'ignore',
79
85
  });
86
+ // Cleanup on process exit or error
87
+ child.on('exit', cleanupScript);
88
+ child.on('error', cleanupScript);
80
89
  child.unref();
81
- // Schedule cleanup
82
- setTimeout(() => {
83
- try {
84
- fs.unlinkSync(tmpScript);
85
- }
86
- catch { }
87
- }, 5000);
90
+ // Fallback cleanup in case events don't fire (safety net)
91
+ setTimeout(cleanupScript, 10000);
88
92
  }
89
93
  catch (e) {
90
94
  console.error('Failed to paste to iTerm:', e);
@@ -6,56 +6,50 @@ import os from 'os';
6
6
  * Copy text to system clipboard
7
7
  */
8
8
  export async function copyToClipboard(text) {
9
+ const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
10
+ const cleanupTmpFile = () => {
11
+ try {
12
+ fs.unlinkSync(tmpFile);
13
+ }
14
+ catch { /* ignore */ }
15
+ };
16
+ const spawnWithCleanup = (command, args) => {
17
+ const child = spawn(command, args, {
18
+ detached: true,
19
+ stdio: 'ignore',
20
+ });
21
+ child.on('error', cleanupTmpFile);
22
+ child.on('exit', cleanupTmpFile);
23
+ child.unref();
24
+ };
9
25
  if (process.platform === 'darwin') {
10
- // Write to temp file first, then use pbcopy via shell
11
- const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
12
26
  try {
13
27
  fs.writeFileSync(tmpFile, text);
14
- // Use a detached process to avoid EBADF
15
- const child = spawn('sh', ['-c', `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`], {
16
- detached: true,
17
- stdio: 'ignore',
18
- });
19
- child.unref();
28
+ spawnWithCleanup('sh', ['-c', `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`]);
20
29
  }
21
30
  catch (e) {
22
- // Fallback: just leave the file for manual copy
23
31
  console.log(`Output saved to: ${tmpFile}`);
24
32
  throw e;
25
33
  }
26
34
  }
27
35
  else if (process.platform === 'linux') {
28
- const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
29
- fs.writeFileSync(tmpFile, text);
30
36
  try {
31
- const child = spawn('sh', ['-c', `cat "${tmpFile}" | xclip -selection clipboard && rm "${tmpFile}"`], {
32
- detached: true,
33
- stdio: 'ignore',
34
- });
35
- child.unref();
37
+ fs.writeFileSync(tmpFile, text);
38
+ spawnWithCleanup('sh', ['-c', `(xclip -selection clipboard < "${tmpFile}" || xsel --clipboard --input < "${tmpFile}") && rm "${tmpFile}"`]);
36
39
  }
37
- catch {
38
- try {
39
- const child = spawn('sh', ['-c', `cat "${tmpFile}" | xsel --clipboard --input && rm "${tmpFile}"`], {
40
- detached: true,
41
- stdio: 'ignore',
42
- });
43
- child.unref();
44
- }
45
- catch (e) {
46
- // Final fallback if both xclip and xsel fail
47
- console.log(`Output saved to: ${tmpFile}`);
48
- throw e;
49
- }
40
+ catch (e) {
41
+ console.log(`Output saved to: ${tmpFile}`);
42
+ throw e;
50
43
  }
51
44
  }
52
45
  else if (process.platform === 'win32') {
53
- const tmpFile = path.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
54
- fs.writeFileSync(tmpFile, text);
55
- const child = spawn('cmd', ['/c', `type "${tmpFile}" | clip && del "${tmpFile}"`], {
56
- detached: true,
57
- stdio: 'ignore',
58
- });
59
- child.unref();
46
+ try {
47
+ fs.writeFileSync(tmpFile, text);
48
+ spawnWithCleanup('cmd', ['/c', `type "${tmpFile}" | clip && del "${tmpFile}"`]);
49
+ }
50
+ catch (e) {
51
+ console.log(`Output saved to: ${tmpFile}`);
52
+ throw e;
53
+ }
60
54
  }
61
55
  }
@@ -16,9 +16,10 @@ export function createEventsRouter(sseManager) {
16
16
  const heartbeat = setInterval(() => {
17
17
  res.write(':heartbeat\n\n');
18
18
  }, 30000);
19
- // Cleanup on close (removeClient is handled by SSEManager)
19
+ // Cleanup on close (removeClient is handled by SSEManager's close listener)
20
20
  req.on('close', () => {
21
21
  clearInterval(heartbeat);
22
+ res.end();
22
23
  });
23
24
  });
24
25
  return router;
@@ -8,4 +8,4 @@ export declare class Server {
8
8
  constructor(cwd: string, port: number);
9
9
  run(): Promise<string | null>;
10
10
  }
11
- export declare function findFreePort(preferred: number): Promise<number>;
11
+ export declare function findFreePort(preferred: number, maxPort?: number): Promise<number>;
@@ -69,8 +69,12 @@ export class Server {
69
69
  });
70
70
  }
71
71
  }
72
- export async function findFreePort(preferred) {
73
- return new Promise((resolve) => {
72
+ export async function findFreePort(preferred, maxPort = 65535) {
73
+ return new Promise((resolve, reject) => {
74
+ if (preferred > maxPort) {
75
+ reject(new Error(`No available port found in range up to ${maxPort}`));
76
+ return;
77
+ }
74
78
  const server = net.createServer();
75
79
  server.listen(preferred, '127.0.0.1', () => {
76
80
  server.close(() => {
@@ -78,8 +82,9 @@ export async function findFreePort(preferred) {
78
82
  });
79
83
  });
80
84
  server.on('error', () => {
81
- // Port in use, try next
82
- findFreePort(preferred + 1).then(resolve);
85
+ server.close(() => {
86
+ findFreePort(preferred + 1, maxPort).then(resolve).catch(reject);
87
+ });
83
88
  });
84
89
  });
85
90
  }
package/dist/index.js CHANGED
@@ -923,48 +923,46 @@ import fs5 from "fs";
923
923
  import path5 from "path";
924
924
  import os from "os";
925
925
  async function copyToClipboard(text) {
926
+ const tmpFile = path5.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
927
+ const cleanupTmpFile = () => {
928
+ try {
929
+ fs5.unlinkSync(tmpFile);
930
+ } catch {
931
+ }
932
+ };
933
+ const spawnWithCleanup = (command, args) => {
934
+ const child = spawn(command, args, {
935
+ detached: true,
936
+ stdio: "ignore"
937
+ });
938
+ child.on("error", cleanupTmpFile);
939
+ child.on("exit", cleanupTmpFile);
940
+ child.unref();
941
+ };
926
942
  if (process.platform === "darwin") {
927
- const tmpFile = path5.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
928
943
  try {
929
944
  fs5.writeFileSync(tmpFile, text);
930
- const child = spawn("sh", ["-c", `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`], {
931
- detached: true,
932
- stdio: "ignore"
933
- });
934
- child.unref();
945
+ spawnWithCleanup("sh", ["-c", `cat "${tmpFile}" | pbcopy && rm "${tmpFile}"`]);
935
946
  } catch (e) {
936
947
  console.log(`Output saved to: ${tmpFile}`);
937
948
  throw e;
938
949
  }
939
950
  } else if (process.platform === "linux") {
940
- const tmpFile = path5.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
941
- fs5.writeFileSync(tmpFile, text);
942
951
  try {
943
- const child = spawn("sh", ["-c", `cat "${tmpFile}" | xclip -selection clipboard && rm "${tmpFile}"`], {
944
- detached: true,
945
- stdio: "ignore"
946
- });
947
- child.unref();
948
- } catch {
949
- try {
950
- const child = spawn("sh", ["-c", `cat "${tmpFile}" | xsel --clipboard --input && rm "${tmpFile}"`], {
951
- detached: true,
952
- stdio: "ignore"
953
- });
954
- child.unref();
955
- } catch (e) {
956
- console.log(`Output saved to: ${tmpFile}`);
957
- throw e;
958
- }
952
+ fs5.writeFileSync(tmpFile, text);
953
+ spawnWithCleanup("sh", ["-c", `(xclip -selection clipboard < "${tmpFile}" || xsel --clipboard --input < "${tmpFile}") && rm "${tmpFile}"`]);
954
+ } catch (e) {
955
+ console.log(`Output saved to: ${tmpFile}`);
956
+ throw e;
959
957
  }
960
958
  } else if (process.platform === "win32") {
961
- const tmpFile = path5.join(os.tmpdir(), `flip-clipboard-${Date.now()}.txt`);
962
- fs5.writeFileSync(tmpFile, text);
963
- const child = spawn("cmd", ["/c", `type "${tmpFile}" | clip && del "${tmpFile}"`], {
964
- detached: true,
965
- stdio: "ignore"
966
- });
967
- child.unref();
959
+ try {
960
+ fs5.writeFileSync(tmpFile, text);
961
+ spawnWithCleanup("cmd", ["/c", `type "${tmpFile}" | clip && del "${tmpFile}"`]);
962
+ } catch (e) {
963
+ console.log(`Output saved to: ${tmpFile}`);
964
+ throw e;
965
+ }
968
966
  }
969
967
  }
970
968
 
@@ -1030,17 +1028,20 @@ async function pasteToOriginalSession(sessionId) {
1030
1028
  try {
1031
1029
  const tmpScript = path6.join(os2.tmpdir(), `flip-paste-${Date.now()}.scpt`);
1032
1030
  fs6.writeFileSync(tmpScript, script);
1031
+ const cleanupScript = () => {
1032
+ try {
1033
+ fs6.unlinkSync(tmpScript);
1034
+ } catch {
1035
+ }
1036
+ };
1033
1037
  const child = spawn2("osascript", [tmpScript], {
1034
1038
  detached: true,
1035
1039
  stdio: "ignore"
1036
1040
  });
1041
+ child.on("exit", cleanupScript);
1042
+ child.on("error", cleanupScript);
1037
1043
  child.unref();
1038
- setTimeout(() => {
1039
- try {
1040
- fs6.unlinkSync(tmpScript);
1041
- } catch {
1042
- }
1043
- }, 5e3);
1044
+ setTimeout(cleanupScript, 1e4);
1044
1045
  } catch (e) {
1045
1046
  console.error("Failed to paste to iTerm:", e);
1046
1047
  }
@@ -1144,6 +1145,7 @@ function createEventsRouter(sseManager) {
1144
1145
  }, 3e4);
1145
1146
  req.on("close", () => {
1146
1147
  clearInterval(heartbeat);
1148
+ res.end();
1147
1149
  });
1148
1150
  });
1149
1151
  return router6;
@@ -1347,8 +1349,12 @@ var Server = class {
1347
1349
  });
1348
1350
  }
1349
1351
  };
1350
- async function findFreePort(preferred) {
1351
- return new Promise((resolve2) => {
1352
+ async function findFreePort(preferred, maxPort = 65535) {
1353
+ return new Promise((resolve2, reject) => {
1354
+ if (preferred > maxPort) {
1355
+ reject(new Error(`No available port found in range up to ${maxPort}`));
1356
+ return;
1357
+ }
1352
1358
  const server = net.createServer();
1353
1359
  server.listen(preferred, "127.0.0.1", () => {
1354
1360
  server.close(() => {
@@ -1356,7 +1362,9 @@ async function findFreePort(preferred) {
1356
1362
  });
1357
1363
  });
1358
1364
  server.on("error", () => {
1359
- findFreePort(preferred + 1).then(resolve2);
1365
+ server.close(() => {
1366
+ findFreePort(preferred + 1, maxPort).then(resolve2).catch(reject);
1367
+ });
1360
1368
  });
1361
1369
  });
1362
1370
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "code-squad-cli",
3
- "version": "1.2.10",
3
+ "version": "1.2.11",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "csq": "./dist/index.js"