adhdev 0.1.7 → 0.1.8
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/index.js +187 -77
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -858,14 +858,14 @@ var import_child_process3 = require("child_process");
|
|
|
858
858
|
var net = __toESM(require("net"));
|
|
859
859
|
var os = __toESM(require("os"));
|
|
860
860
|
var CDP_PORTS = {
|
|
861
|
-
cursor: 9333,
|
|
862
|
-
antigravity: 9335,
|
|
863
|
-
vscode: 9229,
|
|
864
|
-
windsurf: 9337,
|
|
865
|
-
"vscode-insiders": 9231,
|
|
866
|
-
vscodium: 9233
|
|
861
|
+
cursor: [9333, 9334],
|
|
862
|
+
antigravity: [9335, 9336],
|
|
863
|
+
vscode: [9229, 9230],
|
|
864
|
+
windsurf: [9337, 9338],
|
|
865
|
+
"vscode-insiders": [9231, 9232],
|
|
866
|
+
vscodium: [9233, 9234]
|
|
867
867
|
};
|
|
868
|
-
var
|
|
868
|
+
var MAC_APP_IDENTIFIERS = {
|
|
869
869
|
cursor: "Cursor",
|
|
870
870
|
antigravity: "Antigravity",
|
|
871
871
|
vscode: "Visual Studio Code",
|
|
@@ -873,46 +873,120 @@ var MAC_APP_NAMES = {
|
|
|
873
873
|
"vscode-insiders": "Visual Studio Code - Insiders",
|
|
874
874
|
vscodium: "VSCodium"
|
|
875
875
|
};
|
|
876
|
-
|
|
876
|
+
var WIN_PROCESS_NAMES = {
|
|
877
|
+
cursor: "Cursor.exe",
|
|
878
|
+
antigravity: "Antigravity.exe",
|
|
879
|
+
vscode: "Code.exe",
|
|
880
|
+
windsurf: "Windsurf.exe",
|
|
881
|
+
"vscode-insiders": "Code - Insiders.exe",
|
|
882
|
+
vscodium: "VSCodium.exe"
|
|
883
|
+
};
|
|
884
|
+
async function findFreePort(ports) {
|
|
885
|
+
for (const port2 of ports) {
|
|
886
|
+
const free = await checkPortFree(port2);
|
|
887
|
+
if (free) return port2;
|
|
888
|
+
}
|
|
889
|
+
let port = ports[1] + 1;
|
|
890
|
+
while (port < ports[1] + 10) {
|
|
891
|
+
if (await checkPortFree(port)) return port;
|
|
892
|
+
port++;
|
|
893
|
+
}
|
|
894
|
+
throw new Error("No free port found");
|
|
895
|
+
}
|
|
896
|
+
function checkPortFree(port) {
|
|
877
897
|
return new Promise((resolve) => {
|
|
878
898
|
const server = net.createServer();
|
|
879
899
|
server.unref();
|
|
880
|
-
server.on("error", () => resolve(
|
|
881
|
-
server.listen(
|
|
882
|
-
server.close(() => resolve(
|
|
900
|
+
server.on("error", () => resolve(false));
|
|
901
|
+
server.listen(port, "127.0.0.1", () => {
|
|
902
|
+
server.close(() => resolve(true));
|
|
883
903
|
});
|
|
884
904
|
});
|
|
885
905
|
}
|
|
886
|
-
async function
|
|
906
|
+
async function isCdpActive(port) {
|
|
887
907
|
return new Promise((resolve) => {
|
|
888
|
-
const
|
|
889
|
-
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
908
|
+
const req = require("http").get(`http://127.0.0.1:${port}/json/version`, {
|
|
909
|
+
timeout: 2e3
|
|
910
|
+
}, (res) => {
|
|
911
|
+
let data = "";
|
|
912
|
+
res.on("data", (c) => data += c);
|
|
913
|
+
res.on("end", () => {
|
|
914
|
+
try {
|
|
915
|
+
const info = JSON.parse(data);
|
|
916
|
+
resolve(!!info["WebKit-Version"] || !!info["Browser"]);
|
|
917
|
+
} catch {
|
|
918
|
+
resolve(false);
|
|
919
|
+
}
|
|
920
|
+
});
|
|
897
921
|
});
|
|
898
|
-
|
|
899
|
-
|
|
922
|
+
req.on("error", () => resolve(false));
|
|
923
|
+
req.on("timeout", () => {
|
|
924
|
+
req.destroy();
|
|
900
925
|
resolve(false);
|
|
901
926
|
});
|
|
902
|
-
socket.connect(port, "127.0.0.1");
|
|
903
927
|
});
|
|
904
928
|
}
|
|
929
|
+
async function killIdeProcess(ideId) {
|
|
930
|
+
const platform3 = os.platform();
|
|
931
|
+
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
932
|
+
const winProcess = WIN_PROCESS_NAMES[ideId];
|
|
933
|
+
try {
|
|
934
|
+
if (platform3 === "darwin" && appName) {
|
|
935
|
+
try {
|
|
936
|
+
(0, import_child_process3.execSync)(`osascript -e 'tell application "${appName}" to quit' 2>/dev/null`, {
|
|
937
|
+
timeout: 5e3
|
|
938
|
+
});
|
|
939
|
+
} catch {
|
|
940
|
+
try {
|
|
941
|
+
(0, import_child_process3.execSync)(`pkill -f "${appName}" 2>/dev/null`);
|
|
942
|
+
} catch {
|
|
943
|
+
}
|
|
944
|
+
}
|
|
945
|
+
} else if (platform3 === "win32" && winProcess) {
|
|
946
|
+
try {
|
|
947
|
+
(0, import_child_process3.execSync)(`taskkill /IM "${winProcess}" /F 2>nul`, { timeout: 5e3 });
|
|
948
|
+
} catch {
|
|
949
|
+
}
|
|
950
|
+
} else {
|
|
951
|
+
try {
|
|
952
|
+
(0, import_child_process3.execSync)(`pkill -f "${ideId}" 2>/dev/null`);
|
|
953
|
+
} catch {
|
|
954
|
+
}
|
|
955
|
+
}
|
|
956
|
+
for (let i = 0; i < 30; i++) {
|
|
957
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
958
|
+
if (!isIdeRunning(ideId)) return true;
|
|
959
|
+
}
|
|
960
|
+
if (platform3 === "darwin" && appName) {
|
|
961
|
+
try {
|
|
962
|
+
(0, import_child_process3.execSync)(`pkill -9 -f "${appName}" 2>/dev/null`);
|
|
963
|
+
} catch {
|
|
964
|
+
}
|
|
965
|
+
} else if (platform3 === "win32" && winProcess) {
|
|
966
|
+
try {
|
|
967
|
+
(0, import_child_process3.execSync)(`taskkill /IM "${winProcess}" /F 2>nul`);
|
|
968
|
+
} catch {
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
await new Promise((r) => setTimeout(r, 2e3));
|
|
972
|
+
return !isIdeRunning(ideId);
|
|
973
|
+
} catch {
|
|
974
|
+
return false;
|
|
975
|
+
}
|
|
976
|
+
}
|
|
905
977
|
function isIdeRunning(ideId) {
|
|
906
978
|
const platform3 = os.platform();
|
|
907
|
-
const appName = MAC_APP_NAMES[ideId];
|
|
908
|
-
if (!appName) return false;
|
|
909
979
|
try {
|
|
910
980
|
if (platform3 === "darwin") {
|
|
981
|
+
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
982
|
+
if (!appName) return false;
|
|
911
983
|
const result = (0, import_child_process3.execSync)(`pgrep -f "${appName}" 2>/dev/null`, { encoding: "utf-8" });
|
|
912
984
|
return result.trim().length > 0;
|
|
913
985
|
} else if (platform3 === "win32") {
|
|
914
|
-
const
|
|
915
|
-
|
|
986
|
+
const winProc = WIN_PROCESS_NAMES[ideId];
|
|
987
|
+
if (!winProc) return false;
|
|
988
|
+
const result = (0, import_child_process3.execSync)(`tasklist /FI "IMAGENAME eq ${winProc}" /NH 2>nul`, { encoding: "utf-8" });
|
|
989
|
+
return result.includes(winProc);
|
|
916
990
|
} else {
|
|
917
991
|
const result = (0, import_child_process3.execSync)(`pgrep -f "${ideId}" 2>/dev/null`, { encoding: "utf-8" });
|
|
918
992
|
return result.trim().length > 0;
|
|
@@ -921,6 +995,22 @@ function isIdeRunning(ideId) {
|
|
|
921
995
|
return false;
|
|
922
996
|
}
|
|
923
997
|
}
|
|
998
|
+
function detectCurrentWorkspace(ideId) {
|
|
999
|
+
const platform3 = os.platform();
|
|
1000
|
+
if (platform3 !== "darwin") return void 0;
|
|
1001
|
+
try {
|
|
1002
|
+
const appName = MAC_APP_IDENTIFIERS[ideId];
|
|
1003
|
+
if (!appName) return void 0;
|
|
1004
|
+
const result = (0, import_child_process3.execSync)(
|
|
1005
|
+
`lsof -c "${appName}" 2>/dev/null | grep cwd | head -1 | awk '{print $NF}'`,
|
|
1006
|
+
{ encoding: "utf-8", timeout: 3e3 }
|
|
1007
|
+
);
|
|
1008
|
+
const dir = result.trim();
|
|
1009
|
+
if (dir && dir !== "/") return dir;
|
|
1010
|
+
} catch {
|
|
1011
|
+
}
|
|
1012
|
+
return void 0;
|
|
1013
|
+
}
|
|
924
1014
|
async function launchWithCdp(options = {}) {
|
|
925
1015
|
const platform3 = os.platform();
|
|
926
1016
|
let targetIde;
|
|
@@ -933,8 +1023,8 @@ async function launchWithCdp(options = {}) {
|
|
|
933
1023
|
ideId: options.ideId,
|
|
934
1024
|
ideName: options.ideId,
|
|
935
1025
|
port: 0,
|
|
936
|
-
|
|
937
|
-
|
|
1026
|
+
action: "failed",
|
|
1027
|
+
message: "",
|
|
938
1028
|
error: `IDE '${options.ideId}' not found or not installed`
|
|
939
1029
|
};
|
|
940
1030
|
}
|
|
@@ -952,42 +1042,66 @@ async function launchWithCdp(options = {}) {
|
|
|
952
1042
|
ideId: "unknown",
|
|
953
1043
|
ideName: "Unknown",
|
|
954
1044
|
port: 0,
|
|
955
|
-
|
|
956
|
-
|
|
1045
|
+
action: "failed",
|
|
1046
|
+
message: "",
|
|
957
1047
|
error: "No IDE found. Install VS Code, Cursor, or Antigravity first."
|
|
958
1048
|
};
|
|
959
1049
|
}
|
|
960
1050
|
}
|
|
961
|
-
const
|
|
962
|
-
const
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
}
|
|
1051
|
+
const portPair = CDP_PORTS[targetIde.id] || [9333, 9334];
|
|
1052
|
+
for (const port2 of portPair) {
|
|
1053
|
+
if (await isCdpActive(port2)) {
|
|
1054
|
+
return {
|
|
1055
|
+
success: true,
|
|
1056
|
+
ideId: targetIde.id,
|
|
1057
|
+
ideName: targetIde.displayName,
|
|
1058
|
+
port: port2,
|
|
1059
|
+
action: "reused",
|
|
1060
|
+
message: `CDP already active on port ${port2}`
|
|
1061
|
+
};
|
|
1062
|
+
}
|
|
973
1063
|
}
|
|
974
1064
|
const alreadyRunning = isIdeRunning(targetIde.id);
|
|
975
|
-
const
|
|
1065
|
+
const workspace = options.workspace || (alreadyRunning ? detectCurrentWorkspace(targetIde.id) : void 0);
|
|
1066
|
+
if (alreadyRunning) {
|
|
1067
|
+
const killed = await killIdeProcess(targetIde.id);
|
|
1068
|
+
if (!killed) {
|
|
1069
|
+
return {
|
|
1070
|
+
success: false,
|
|
1071
|
+
ideId: targetIde.id,
|
|
1072
|
+
ideName: targetIde.displayName,
|
|
1073
|
+
port: 0,
|
|
1074
|
+
action: "failed",
|
|
1075
|
+
message: "",
|
|
1076
|
+
error: `Could not stop ${targetIde.displayName}. Close it manually and try again.`
|
|
1077
|
+
};
|
|
1078
|
+
}
|
|
1079
|
+
await new Promise((r) => setTimeout(r, 3e3));
|
|
1080
|
+
}
|
|
1081
|
+
const port = await findFreePort(portPair);
|
|
976
1082
|
try {
|
|
977
1083
|
if (platform3 === "darwin") {
|
|
978
|
-
await launchMacOS(targetIde, port,
|
|
1084
|
+
await launchMacOS(targetIde, port, workspace, options.newWindow);
|
|
979
1085
|
} else if (platform3 === "win32") {
|
|
980
|
-
await launchWindows(targetIde, port,
|
|
1086
|
+
await launchWindows(targetIde, port, workspace, options.newWindow);
|
|
981
1087
|
} else {
|
|
982
|
-
await launchLinux(targetIde, port,
|
|
1088
|
+
await launchLinux(targetIde, port, workspace, options.newWindow);
|
|
1089
|
+
}
|
|
1090
|
+
let cdpReady = false;
|
|
1091
|
+
for (let i = 0; i < 30; i++) {
|
|
1092
|
+
await new Promise((r) => setTimeout(r, 500));
|
|
1093
|
+
if (await isCdpActive(port)) {
|
|
1094
|
+
cdpReady = true;
|
|
1095
|
+
break;
|
|
1096
|
+
}
|
|
983
1097
|
}
|
|
984
1098
|
return {
|
|
985
1099
|
success: true,
|
|
986
1100
|
ideId: targetIde.id,
|
|
987
1101
|
ideName: targetIde.displayName,
|
|
988
1102
|
port,
|
|
989
|
-
alreadyRunning,
|
|
990
|
-
|
|
1103
|
+
action: alreadyRunning ? "restarted" : "started",
|
|
1104
|
+
message: cdpReady ? `${targetIde.displayName} launched with CDP on port ${port}` : `${targetIde.displayName} launched (CDP may take a moment to initialize)`
|
|
991
1105
|
};
|
|
992
1106
|
} catch (e) {
|
|
993
1107
|
return {
|
|
@@ -995,30 +1109,25 @@ async function launchWithCdp(options = {}) {
|
|
|
995
1109
|
ideId: targetIde.id,
|
|
996
1110
|
ideName: targetIde.displayName,
|
|
997
1111
|
port,
|
|
998
|
-
|
|
999
|
-
|
|
1112
|
+
action: "failed",
|
|
1113
|
+
message: "",
|
|
1000
1114
|
error: e?.message || String(e)
|
|
1001
1115
|
};
|
|
1002
1116
|
}
|
|
1003
1117
|
}
|
|
1004
1118
|
async function launchMacOS(ide, port, workspace, newWindow) {
|
|
1005
|
-
const appName =
|
|
1006
|
-
if (!appName) {
|
|
1007
|
-
if (ide.cliCommand) {
|
|
1008
|
-
const args2 = ["--remote-debugging-port=" + port];
|
|
1009
|
-
if (newWindow) args2.push("--new-window");
|
|
1010
|
-
if (workspace) args2.push(workspace);
|
|
1011
|
-
(0, import_child_process3.spawn)(ide.cliCommand, args2, { detached: true, stdio: "ignore" }).unref();
|
|
1012
|
-
return;
|
|
1013
|
-
}
|
|
1014
|
-
throw new Error(`No app name or CLI for ${ide.displayName}`);
|
|
1015
|
-
}
|
|
1119
|
+
const appName = MAC_APP_IDENTIFIERS[ide.id];
|
|
1016
1120
|
const args = ["--remote-debugging-port=" + port];
|
|
1017
1121
|
if (newWindow) args.push("--new-window");
|
|
1018
1122
|
if (workspace) args.push(workspace);
|
|
1019
|
-
|
|
1020
|
-
|
|
1021
|
-
|
|
1123
|
+
if (appName) {
|
|
1124
|
+
const openArgs = ["-a", appName, "--args", ...args];
|
|
1125
|
+
(0, import_child_process3.spawn)("open", openArgs, { detached: true, stdio: "ignore" }).unref();
|
|
1126
|
+
} else if (ide.cliCommand) {
|
|
1127
|
+
(0, import_child_process3.spawn)(ide.cliCommand, args, { detached: true, stdio: "ignore" }).unref();
|
|
1128
|
+
} else {
|
|
1129
|
+
throw new Error(`No app identifier or CLI for ${ide.displayName}`);
|
|
1130
|
+
}
|
|
1022
1131
|
}
|
|
1023
1132
|
async function launchWindows(ide, port, workspace, newWindow) {
|
|
1024
1133
|
const cli = ide.cliCommand;
|
|
@@ -1032,7 +1141,6 @@ async function launchWindows(ide, port, workspace, newWindow) {
|
|
|
1032
1141
|
detached: true,
|
|
1033
1142
|
stdio: "ignore",
|
|
1034
1143
|
shell: true
|
|
1035
|
-
// Windows에서 .cmd 파일 실행 위해
|
|
1036
1144
|
}).unref();
|
|
1037
1145
|
}
|
|
1038
1146
|
async function launchLinux(ide, port, workspace, newWindow) {
|
|
@@ -1052,13 +1160,12 @@ program.name("adhdev").description("\u{1F309} ADHDev \u2014 Agent Dashboard Hub
|
|
|
1052
1160
|
program.command("setup", { isDefault: true }).description("Run the interactive setup wizard").option("-f, --force", "Force re-run setup even if already configured").action(async (options) => {
|
|
1053
1161
|
await runWizard({ force: options.force });
|
|
1054
1162
|
});
|
|
1055
|
-
program.command("launch [ide]").description("Launch IDE with
|
|
1163
|
+
program.command("launch [ide]").description("Launch or relaunch IDE with CDP debugging port (kills existing process first)").option("-w, --workspace <path>", "Workspace/folder to open").option("-n, --new-window", "Open in a new window").action(async (ideArg, options) => {
|
|
1056
1164
|
const ora2 = await import("ora");
|
|
1057
1165
|
const spinner = ora2.default("Detecting IDE...").start();
|
|
1058
1166
|
try {
|
|
1059
1167
|
const result = await launchWithCdp({
|
|
1060
1168
|
ideId: ideArg,
|
|
1061
|
-
port: options.port ? parseInt(options.port) : void 0,
|
|
1062
1169
|
workspace: options.workspace,
|
|
1063
1170
|
newWindow: options.newWindow
|
|
1064
1171
|
});
|
|
@@ -1075,7 +1182,7 @@ program.command("launch [ide]").description("Launch IDE with Chrome DevTools Pro
|
|
|
1075
1182
|
}
|
|
1076
1183
|
});
|
|
1077
1184
|
console.log(import_chalk2.default.gray(`
|
|
1078
|
-
Usage: adhdev launch <ide-id>
|
|
1185
|
+
Usage: adhdev launch <ide-id>
|
|
1079
1186
|
`));
|
|
1080
1187
|
process.exit(1);
|
|
1081
1188
|
}
|
|
@@ -1083,13 +1190,16 @@ program.command("launch [ide]").description("Launch IDE with Chrome DevTools Pro
|
|
|
1083
1190
|
console.log(import_chalk2.default.bold(" \u{1F680} IDE Launched with CDP\n"));
|
|
1084
1191
|
console.log(` ${import_chalk2.default.bold("IDE:")} ${result.ideName}`);
|
|
1085
1192
|
console.log(` ${import_chalk2.default.bold("CDP:")} ${import_chalk2.default.cyan(`ws://127.0.0.1:${result.port}`)}`);
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1193
|
+
switch (result.action) {
|
|
1194
|
+
case "reused":
|
|
1195
|
+
console.log(` ${import_chalk2.default.bold("Action:")} ${import_chalk2.default.yellow("CDP already active \u2014 reusing existing session")}`);
|
|
1196
|
+
break;
|
|
1197
|
+
case "restarted":
|
|
1198
|
+
console.log(` ${import_chalk2.default.bold("Action:")} ${import_chalk2.default.green("\u2713 Killed existing process \u2192 Restarted with CDP")}`);
|
|
1199
|
+
break;
|
|
1200
|
+
case "started":
|
|
1201
|
+
console.log(` ${import_chalk2.default.bold("Action:")} ${import_chalk2.default.green("\u2713 Started fresh with CDP")}`);
|
|
1202
|
+
break;
|
|
1093
1203
|
}
|
|
1094
1204
|
console.log();
|
|
1095
1205
|
console.log(import_chalk2.default.gray(" Bridge extension will auto-connect to CDP."));
|