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
|
-
//
|
|
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
|
-
|
|
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
|
-
|
|
32
|
-
|
|
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
|
-
|
|
39
|
-
|
|
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
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
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
|
-
|
|
82
|
-
|
|
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
|
-
|
|
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
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
});
|
|
947
|
-
|
|
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
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
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
|
-
|
|
1365
|
+
server.close(() => {
|
|
1366
|
+
findFreePort(preferred + 1, maxPort).then(resolve2).catch(reject);
|
|
1367
|
+
});
|
|
1360
1368
|
});
|
|
1361
1369
|
});
|
|
1362
1370
|
}
|