dev3000 0.0.174 → 0.0.175
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/README.md +0 -4
- package/dist/cdp-monitor.d.ts +3 -0
- package/dist/cdp-monitor.d.ts.map +1 -1
- package/dist/cdp-monitor.js +225 -38
- package/dist/cdp-monitor.js.map +1 -1
- package/dist/cli.js +172 -217
- package/dist/cli.js.map +1 -1
- package/dist/commands/crawl.d.ts.map +1 -1
- package/dist/commands/crawl.js +4 -43
- package/dist/commands/crawl.js.map +1 -1
- package/dist/commands/errors.d.ts.map +1 -1
- package/dist/commands/errors.js +4 -53
- package/dist/commands/errors.js.map +1 -1
- package/dist/commands/fix.d.ts.map +1 -1
- package/dist/commands/fix.js +5 -74
- package/dist/commands/fix.js.map +1 -1
- package/dist/commands/logs.d.ts.map +1 -1
- package/dist/commands/logs.js +4 -53
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/skill-runner.d.ts +14 -0
- package/dist/commands/skill-runner.d.ts.map +1 -0
- package/dist/commands/skill-runner.js +494 -0
- package/dist/commands/skill-runner.js.map +1 -0
- package/dist/dev-environment.d.ts +4 -3
- package/dist/dev-environment.d.ts.map +1 -1
- package/dist/dev-environment.js +111 -95
- package/dist/dev-environment.js.map +1 -1
- package/dist/skills/d3k/internal-skill.md +145 -0
- package/dist/skills/index.test.ts +28 -1
- package/dist/skills/index.ts +58 -7
- package/dist/utils/agent-browser.d.ts.map +1 -1
- package/dist/utils/agent-browser.js +6 -3
- package/dist/utils/agent-browser.js.map +1 -1
- package/dist/utils/agent-detection.d.ts +1 -0
- package/dist/utils/agent-detection.d.ts.map +1 -1
- package/dist/utils/agent-detection.js +11 -0
- package/dist/utils/agent-detection.js.map +1 -1
- package/dist/utils/agent-selection.js +3 -3
- package/dist/utils/agent-selection.js.map +1 -1
- package/dist/utils/browser-command-argv.d.ts +1 -1
- package/dist/utils/browser-command-argv.d.ts.map +1 -1
- package/dist/utils/browser-command-argv.js +1 -1
- package/dist/utils/browser-command-argv.js.map +1 -1
- package/dist/utils/project-name.d.ts +2 -0
- package/dist/utils/project-name.d.ts.map +1 -1
- package/dist/utils/project-name.js +6 -0
- package/dist/utils/project-name.js.map +1 -1
- package/dist/utils/session.d.ts +14 -0
- package/dist/utils/session.d.ts.map +1 -0
- package/dist/utils/session.js +65 -0
- package/dist/utils/session.js.map +1 -0
- package/dist/utils/version-check.js +2 -2
- package/dist/utils/version-check.js.map +1 -1
- package/package.json +8 -18
- package/dist/commands/cloud-check-pr.d.ts +0 -9
- package/dist/commands/cloud-check-pr.d.ts.map +0 -1
- package/dist/commands/cloud-check-pr.js +0 -243
- package/dist/commands/cloud-check-pr.js.map +0 -1
- package/dist/commands/cloud-fix.d.ts +0 -13
- package/dist/commands/cloud-fix.d.ts.map +0 -1
- package/dist/commands/cloud-fix.js +0 -79
- package/dist/commands/cloud-fix.js.map +0 -1
- package/dist/commands/find-component.d.ts +0 -8
- package/dist/commands/find-component.d.ts.map +0 -1
- package/dist/commands/find-component.js +0 -182
- package/dist/commands/find-component.js.map +0 -1
- package/dist/skills/d3k/SKILL.md +0 -126
- package/dist/skills/index.d.ts +0 -46
- package/dist/skills/index.d.ts.map +0 -1
- package/dist/skills/index.js +0 -174
- package/dist/skills/index.js.map +0 -1
|
@@ -41,7 +41,7 @@ interface DevEnvironmentOptions {
|
|
|
41
41
|
startupTimeoutSeconds: number;
|
|
42
42
|
browserNavigationTimeoutSeconds: number;
|
|
43
43
|
profileDir: string;
|
|
44
|
-
browserTool: "agent-browser"
|
|
44
|
+
browserTool: "agent-browser";
|
|
45
45
|
logFile: string;
|
|
46
46
|
debug?: boolean;
|
|
47
47
|
serversOnly?: boolean;
|
|
@@ -62,6 +62,7 @@ interface DevEnvironmentOptions {
|
|
|
62
62
|
skillsAgentId?: string;
|
|
63
63
|
autoSkills?: boolean;
|
|
64
64
|
installSkills?: boolean;
|
|
65
|
+
screenshotsDir?: string;
|
|
65
66
|
}
|
|
66
67
|
/**
|
|
67
68
|
* Count active d3k instances by checking PID files in tmpdir.
|
|
@@ -104,7 +105,7 @@ export declare function isServerListening(port: string | number): Promise<Server
|
|
|
104
105
|
export declare function tryHttpConnection(port: string | number): Promise<boolean>;
|
|
105
106
|
export declare function tryHttpsConnection(port: string | number): Promise<boolean>;
|
|
106
107
|
export declare function findAvailablePort(startPort: number): Promise<string>;
|
|
107
|
-
export declare function createPersistentLogFile(): string;
|
|
108
|
+
export declare function createPersistentLogFile(override?: string): string;
|
|
108
109
|
/**
|
|
109
110
|
* Write session info for external tooling to discover.
|
|
110
111
|
*
|
|
@@ -116,7 +117,7 @@ export declare function createPersistentLogFile(): string;
|
|
|
116
117
|
* processes belong to THIS d3k instance so we don't accidentally kill
|
|
117
118
|
* Chrome instances from other d3k sessions.
|
|
118
119
|
*/
|
|
119
|
-
export declare function writeSessionInfo(projectName: string, logFilePath: string, appPort: string, publicUrl?: string | null, cdpUrl?: string | null, chromePids?: number[], serverCommand?: string, framework?: "nextjs" | "svelte" | "other", serverPid?: number, skillsInstalled?: string[], skillsAgentId?: string | null, preferredBrowserTool?: "agent-browser"
|
|
120
|
+
export declare function writeSessionInfo(projectName: string, logFilePath: string, appPort: string, publicUrl?: string | null, cdpUrl?: string | null, chromePids?: number[], serverCommand?: string, framework?: "nextjs" | "svelte" | "other", serverPid?: number, skillsInstalled?: string[], skillsAgentId?: string | null, preferredBrowserTool?: "agent-browser", agentName?: string | null): void;
|
|
120
121
|
export declare function getSessionChromePids(projectName: string): number[];
|
|
121
122
|
export declare class DevEnvironment {
|
|
122
123
|
private serverProcess;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dev-environment.d.ts","sourceRoot":"","sources":["../src/dev-environment.ts"],"names":[],"mappings":"AA2DA;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAA;IACX,+DAA+D;IAC/D,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,6CAA6C;IAC7C,MAAM,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,OAAO,GAAG,MAAM,KAAK,IAAI,CAAA;IAC/D,sCAAsC;IACtC,OAAO,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IACvC,4BAA4B;IAC5B,QAAQ,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;CACjC;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,yCAAyC;IACzC,UAAU,EAAE,OAAO,CAAA;IACnB,+DAA+D;IAC/D,QAAQ,EAAE,OAAO,CAAA;IACjB,8CAA8C;IAC9C,UAAU,EAAE,OAAO,CAAA;CACpB;AAED;;;;;;;;;GASG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,kBAAkB,CAAC,CA0DnG;AAED,UAAU,qBAAqB;IAC7B,IAAI,EAAE,MAAM,CAAA;IACZ,aAAa,EAAE,MAAM,CAAA;IACrB,qBAAqB,EAAE,MAAM,CAAA;IAC7B,+BAA+B,EAAE,MAAM,CAAA;IACvC,UAAU,EAAE,MAAM,CAAA;IAClB,WAAW,EAAE,eAAe,
|
|
1
|
+
{"version":3,"file":"dev-environment.d.ts","sourceRoot":"","sources":["../src/dev-environment.ts"],"names":[],"mappings":"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"}
|
package/dist/dev-environment.js
CHANGED
|
@@ -12,7 +12,7 @@ import { CDPMonitor } from "./cdp-monitor.js";
|
|
|
12
12
|
import { ensurePortlessAlias, getPortlessUrl, isPortlessInstalled, removePortlessAlias } from "./portless.js";
|
|
13
13
|
import { ScreencastManager } from "./screencast-manager.js";
|
|
14
14
|
import { NextJsErrorDetector, OutputProcessor, StandardLogParser } from "./services/parsers/index.js";
|
|
15
|
-
import {
|
|
15
|
+
import { getBundledD3kSkillPath, listAvailableSkills } from "./skills/index.js";
|
|
16
16
|
import { DevTUI } from "./tui-interface.js";
|
|
17
17
|
import { readProjectAgentName, rememberProjectAgentName } from "./utils/project-metadata.js";
|
|
18
18
|
import { getProjectDir, getProjectDisplayName, getProjectName } from "./utils/project-name.js";
|
|
@@ -103,8 +103,8 @@ class Logger {
|
|
|
103
103
|
if (!existsSync(logDir)) {
|
|
104
104
|
mkdirSync(logDir, { recursive: true });
|
|
105
105
|
}
|
|
106
|
-
//
|
|
107
|
-
|
|
106
|
+
// Touch the log file without truncating an explicit existing --log-file.
|
|
107
|
+
appendFileSync(this.logFile, "");
|
|
108
108
|
}
|
|
109
109
|
log(source, message) {
|
|
110
110
|
const timestamp = formatTimestamp(new Date(), this.dateTimeFormat);
|
|
@@ -126,6 +126,68 @@ function isInSandbox() {
|
|
|
126
126
|
existsSync("/.dockerenv") ||
|
|
127
127
|
existsSync("/run/.containerenv"));
|
|
128
128
|
}
|
|
129
|
+
function parsePortNumber(port) {
|
|
130
|
+
if (!/^\d+$/.test(port)) {
|
|
131
|
+
return null;
|
|
132
|
+
}
|
|
133
|
+
const parsed = Number.parseInt(port, 10);
|
|
134
|
+
if (!Number.isInteger(parsed) || parsed < 1 || parsed > 65535) {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
return parsed;
|
|
138
|
+
}
|
|
139
|
+
function escapeRegexForPkill(value) {
|
|
140
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
141
|
+
}
|
|
142
|
+
function killPortProcessesSync(port, debugLog) {
|
|
143
|
+
if (isInSandbox()) {
|
|
144
|
+
debugLog(`Skipping synchronous port kill in sandbox environment`);
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const parsedPort = parsePortNumber(port);
|
|
148
|
+
if (parsedPort === null) {
|
|
149
|
+
debugLog(`Skipping synchronous port kill for invalid port: ${port}`);
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
try {
|
|
153
|
+
const result = spawnSync("lsof", ["-ti", `:${parsedPort}`], {
|
|
154
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
155
|
+
encoding: "utf8",
|
|
156
|
+
timeout: 5000
|
|
157
|
+
});
|
|
158
|
+
const pidStrings = result.stdout
|
|
159
|
+
.split(/\s+/)
|
|
160
|
+
.map((value) => value.trim())
|
|
161
|
+
.filter((value) => /^\d+$/.test(value));
|
|
162
|
+
for (const pidString of pidStrings) {
|
|
163
|
+
try {
|
|
164
|
+
process.kill(Number.parseInt(pidString, 10), "SIGKILL");
|
|
165
|
+
}
|
|
166
|
+
catch (error) {
|
|
167
|
+
debugLog(`Failed to synchronously kill PID ${pidString} on port ${parsedPort}: ${error}`);
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
debugLog(`Synchronous kill for port ${parsedPort} found ${pidStrings.length} process(es)`);
|
|
171
|
+
}
|
|
172
|
+
catch (error) {
|
|
173
|
+
debugLog(`Synchronous kill error for port ${parsedPort}: ${error}`);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
function pkillByPattern(pattern, debugLog) {
|
|
177
|
+
if (isInSandbox()) {
|
|
178
|
+
debugLog(`Skipping pkill in sandbox environment`);
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
try {
|
|
182
|
+
spawnSync("pkill", ["-f", pattern], {
|
|
183
|
+
stdio: "ignore",
|
|
184
|
+
timeout: 5000
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
catch (error) {
|
|
188
|
+
debugLog(`pkill failed for pattern ${pattern}: ${error}`);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
129
191
|
/**
|
|
130
192
|
* Count active d3k instances by checking PID files in tmpdir.
|
|
131
193
|
* Returns the count of running d3k processes (excluding the current one if specified).
|
|
@@ -415,11 +477,8 @@ export async function findAvailablePort(startPort) {
|
|
|
415
477
|
*/
|
|
416
478
|
async function ensureD3kSkill(skillsAgentId) {
|
|
417
479
|
try {
|
|
418
|
-
const
|
|
419
|
-
if (!
|
|
420
|
-
return;
|
|
421
|
-
const bundledSkillPath = join(bundledSkillsDir, "d3k", "SKILL.md");
|
|
422
|
-
if (!existsSync(bundledSkillPath))
|
|
480
|
+
const bundledSkillPath = getBundledD3kSkillPath();
|
|
481
|
+
if (!bundledSkillPath)
|
|
423
482
|
return;
|
|
424
483
|
const targetSkillsDir = skillsAgentId ? getSkillsPathForLocation(skillsAgentId, "project")?.path : null;
|
|
425
484
|
const skillRoots = new Set();
|
|
@@ -471,7 +530,21 @@ async function autoInstallSkills(agentId, debugLog) {
|
|
|
471
530
|
}
|
|
472
531
|
// REMOVED: cleanup functions are no longer needed
|
|
473
532
|
// CLI integration config files are now kept persistent across dev3000 restarts
|
|
474
|
-
export function createPersistentLogFile() {
|
|
533
|
+
export function createPersistentLogFile(override) {
|
|
534
|
+
if (override && override.length > 0) {
|
|
535
|
+
const resolved = resolve(override);
|
|
536
|
+
const logDir = dirname(resolved);
|
|
537
|
+
try {
|
|
538
|
+
if (!existsSync(logDir)) {
|
|
539
|
+
mkdirSync(logDir, { recursive: true });
|
|
540
|
+
}
|
|
541
|
+
appendFileSync(resolved, "");
|
|
542
|
+
return resolved;
|
|
543
|
+
}
|
|
544
|
+
catch (error) {
|
|
545
|
+
throw new Error(`Failed to initialize --log-file at ${resolved}: ${error instanceof Error ? error.message : String(error)}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
475
548
|
// Get unique project name
|
|
476
549
|
const projectName = getProjectName();
|
|
477
550
|
// Use ~/.d3k/{projectName}/logs directory for persistent, accessible logs
|
|
@@ -660,7 +733,7 @@ export class DevEnvironment {
|
|
|
660
733
|
}
|
|
661
734
|
// Store screenshots in project-specific directory for local access
|
|
662
735
|
const projectName = getProjectName();
|
|
663
|
-
this.screenshotDir = join(getProjectDir(), "screenshots");
|
|
736
|
+
this.screenshotDir = options.screenshotsDir ? resolve(options.screenshotsDir) : join(getProjectDir(), "screenshots");
|
|
664
737
|
// Use project-specific PID and lock files to allow multiple projects to run simultaneously
|
|
665
738
|
this.pidFile = join(tmpdir(), `dev3000-${projectName}.pid`);
|
|
666
739
|
this.lockFile = join(tmpdir(), `dev3000-${projectName}.lock`);
|
|
@@ -829,10 +902,7 @@ export class DevEnvironment {
|
|
|
829
902
|
// Best-effort synchronous cleanup (mirrors SIGHUP handler).
|
|
830
903
|
const port = this.options.port;
|
|
831
904
|
this.debugLog(`Synchronous kill for port ${port}`);
|
|
832
|
-
|
|
833
|
-
stdio: "pipe",
|
|
834
|
-
timeout: 5000
|
|
835
|
-
});
|
|
905
|
+
killPortProcessesSync(port, this.debugLog.bind(this));
|
|
836
906
|
const projectName = getProjectName();
|
|
837
907
|
const sessionInfo = getSessionInfo(projectName);
|
|
838
908
|
const chromePids = sessionInfo?.chromePids ?? [];
|
|
@@ -904,25 +974,7 @@ export class DevEnvironment {
|
|
|
904
974
|
// This ensures cleanup happens even if the event loop gets interrupted
|
|
905
975
|
const port = this.options.port;
|
|
906
976
|
this.debugLog(`Synchronous kill for port ${port}`);
|
|
907
|
-
|
|
908
|
-
stdio: "pipe",
|
|
909
|
-
timeout: 5000
|
|
910
|
-
});
|
|
911
|
-
const projectName = getProjectName();
|
|
912
|
-
const chromePids = getSessionChromePids(projectName);
|
|
913
|
-
if (chromePids.length > 0) {
|
|
914
|
-
this.debugLog(`Synchronous kill for Chrome PIDs: [${chromePids.join(", ")}]`);
|
|
915
|
-
for (const pid of chromePids) {
|
|
916
|
-
try {
|
|
917
|
-
process.kill(pid, "SIGTERM");
|
|
918
|
-
process.kill(pid, 0);
|
|
919
|
-
process.kill(pid, "SIGKILL");
|
|
920
|
-
}
|
|
921
|
-
catch {
|
|
922
|
-
// Ignore - process may already be dead
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
}
|
|
977
|
+
killPortProcessesSync(port, this.debugLog.bind(this));
|
|
926
978
|
// Now do the rest of cleanup async
|
|
927
979
|
this.tui?.updateStatus("Shutting down...");
|
|
928
980
|
this.handleShutdown()
|
|
@@ -1091,7 +1143,7 @@ export class DevEnvironment {
|
|
|
1091
1143
|
console.log(chalk.cyan(`Logs: ${this.options.logFile}`));
|
|
1092
1144
|
console.log(chalk.cyan("☝️ Give this to an AI to auto debug and fix your app\n"));
|
|
1093
1145
|
console.log(chalk.cyan(`🌐 Your App: ${this.preferredAppUrl}`));
|
|
1094
|
-
console.log(chalk.cyan(`🔧 CLI Tools: d3k fix, d3k crawl
|
|
1146
|
+
console.log(chalk.cyan(`🔧 CLI Tools: d3k fix, d3k crawl`));
|
|
1095
1147
|
if (this.options.serversOnly) {
|
|
1096
1148
|
console.log(chalk.cyan("🖥️ Servers-only mode - browser monitoring disabled"));
|
|
1097
1149
|
}
|
|
@@ -1811,7 +1863,7 @@ export class DevEnvironment {
|
|
|
1811
1863
|
console.log(chalk.gray(`ℹ️ Skipping ${name} port kill in sandbox environment`));
|
|
1812
1864
|
return;
|
|
1813
1865
|
}
|
|
1814
|
-
if (
|
|
1866
|
+
if (parsePortNumber(port) === null) {
|
|
1815
1867
|
this.debugLog(`Skipping ${name} port kill for invalid port: ${port}`);
|
|
1816
1868
|
return;
|
|
1817
1869
|
}
|
|
@@ -1851,23 +1903,27 @@ export class DevEnvironment {
|
|
|
1851
1903
|
// Kill app server only
|
|
1852
1904
|
console.log(chalk.cyan("🔄 Killing app server..."));
|
|
1853
1905
|
await killPortProcess(this.options.port, "your app server");
|
|
1854
|
-
// Kill server process and its children using the saved PID (from before session file was deleted)
|
|
1855
|
-
if (sessionInfo?.serverPid) {
|
|
1856
|
-
this.killServerPidIfOwned(sessionInfo.serverPid, sessionInfo.cwd, "graceful shutdown");
|
|
1857
|
-
}
|
|
1858
|
-
// Always kill tracked Chrome processes, even if cdpMonitor is unavailable.
|
|
1859
|
-
this.killTrackedChromePids(sessionInfo?.chromePids ?? [], "graceful shutdown");
|
|
1860
1906
|
// Shutdown CDP monitor if it was started
|
|
1907
|
+
let chromeShutdownHandled = false;
|
|
1861
1908
|
if (this.cdpMonitor) {
|
|
1862
1909
|
try {
|
|
1863
1910
|
console.log(chalk.cyan("🔄 Closing CDP monitor..."));
|
|
1864
1911
|
await this.cdpMonitor.shutdown();
|
|
1912
|
+
chromeShutdownHandled = true;
|
|
1865
1913
|
console.log(chalk.green("✅ CDP monitor closed"));
|
|
1866
1914
|
}
|
|
1867
1915
|
catch (_error) {
|
|
1868
1916
|
console.log(chalk.gray("⚠️ CDP monitor shutdown failed"));
|
|
1869
1917
|
}
|
|
1870
1918
|
}
|
|
1919
|
+
if (!chromeShutdownHandled) {
|
|
1920
|
+
// Safety net when CDP was unavailable: terminate only Chrome processes from this d3k session.
|
|
1921
|
+
this.killTrackedChromePids(sessionInfo?.chromePids ?? [], "graceful shutdown");
|
|
1922
|
+
}
|
|
1923
|
+
// Kill server process and its children using the saved PID (from before session file was deleted)
|
|
1924
|
+
if (sessionInfo?.serverPid) {
|
|
1925
|
+
this.killServerPidIfOwned(sessionInfo.serverPid, sessionInfo.cwd, "graceful shutdown");
|
|
1926
|
+
}
|
|
1871
1927
|
console.log(chalk.red(`❌ ${this.options.commandName} exited due to server failure`));
|
|
1872
1928
|
// Show recent log entries to help diagnose the issue
|
|
1873
1929
|
this.showRecentLogs();
|
|
@@ -1908,26 +1964,9 @@ export class DevEnvironment {
|
|
|
1908
1964
|
// This ensures cleanup happens even if the event loop gets interrupted
|
|
1909
1965
|
const port = this.options.port;
|
|
1910
1966
|
this.debugLog(`Synchronous kill for port ${port}`);
|
|
1911
|
-
|
|
1912
|
-
stdio: "pipe",
|
|
1913
|
-
timeout: 5000
|
|
1914
|
-
});
|
|
1967
|
+
killPortProcessesSync(port, this.debugLog.bind(this));
|
|
1915
1968
|
const projectName = getProjectName();
|
|
1916
1969
|
const sessionInfo = getSessionInfo(projectName);
|
|
1917
|
-
const chromePids = sessionInfo?.chromePids ?? [];
|
|
1918
|
-
if (chromePids.length > 0) {
|
|
1919
|
-
this.debugLog(`Synchronous kill for Chrome PIDs: [${chromePids.join(", ")}]`);
|
|
1920
|
-
for (const pid of chromePids) {
|
|
1921
|
-
try {
|
|
1922
|
-
process.kill(pid, "SIGTERM");
|
|
1923
|
-
process.kill(pid, 0);
|
|
1924
|
-
process.kill(pid, "SIGKILL");
|
|
1925
|
-
}
|
|
1926
|
-
catch {
|
|
1927
|
-
// Ignore - process may already be dead
|
|
1928
|
-
}
|
|
1929
|
-
}
|
|
1930
|
-
}
|
|
1931
1970
|
if (sessionInfo?.serverPid) {
|
|
1932
1971
|
this.killServerPidIfOwned(sessionInfo.serverPid, sessionInfo.cwd, "SIGINT");
|
|
1933
1972
|
}
|
|
@@ -1940,7 +1979,7 @@ export class DevEnvironment {
|
|
|
1940
1979
|
const forceExitTimeout = setTimeout(() => {
|
|
1941
1980
|
this.debugLog("Shutdown timeout reached, forcing exit");
|
|
1942
1981
|
process.exit(1);
|
|
1943
|
-
},
|
|
1982
|
+
}, 10000); // Give Chrome enough time to record a clean profile exit.
|
|
1944
1983
|
// Call async cleanup in a non-blocking way
|
|
1945
1984
|
this.handleShutdown()
|
|
1946
1985
|
.then(() => {
|
|
@@ -1967,26 +2006,9 @@ export class DevEnvironment {
|
|
|
1967
2006
|
// CRITICAL: Kill port processes SYNCHRONOUSLY first, before anything else
|
|
1968
2007
|
const port = this.options.port;
|
|
1969
2008
|
this.debugLog(`Synchronous kill for port ${port}`);
|
|
1970
|
-
|
|
1971
|
-
stdio: "pipe",
|
|
1972
|
-
timeout: 5000
|
|
1973
|
-
});
|
|
2009
|
+
killPortProcessesSync(port, this.debugLog.bind(this));
|
|
1974
2010
|
const projectName = getProjectName();
|
|
1975
2011
|
const sessionInfo = getSessionInfo(projectName);
|
|
1976
|
-
const chromePids = sessionInfo?.chromePids ?? [];
|
|
1977
|
-
if (chromePids.length > 0) {
|
|
1978
|
-
this.debugLog(`Synchronous kill for Chrome PIDs: [${chromePids.join(", ")}]`);
|
|
1979
|
-
for (const pid of chromePids) {
|
|
1980
|
-
try {
|
|
1981
|
-
process.kill(pid, "SIGTERM");
|
|
1982
|
-
process.kill(pid, 0);
|
|
1983
|
-
process.kill(pid, "SIGKILL");
|
|
1984
|
-
}
|
|
1985
|
-
catch {
|
|
1986
|
-
// Ignore - process may already be dead
|
|
1987
|
-
}
|
|
1988
|
-
}
|
|
1989
|
-
}
|
|
1990
2012
|
if (sessionInfo?.serverPid) {
|
|
1991
2013
|
this.killServerPidIfOwned(sessionInfo.serverPid, sessionInfo.cwd, "SIGTERM");
|
|
1992
2014
|
}
|
|
@@ -2136,7 +2158,7 @@ export class DevEnvironment {
|
|
|
2136
2158
|
this.debugLog(`Skipping ${name} port kill in sandbox environment`);
|
|
2137
2159
|
return;
|
|
2138
2160
|
}
|
|
2139
|
-
if (
|
|
2161
|
+
if (parsePortNumber(port) === null) {
|
|
2140
2162
|
this.debugLog(`Skipping ${name} port kill for invalid port: ${port}`);
|
|
2141
2163
|
return;
|
|
2142
2164
|
}
|
|
@@ -2197,12 +2219,7 @@ export class DevEnvironment {
|
|
|
2197
2219
|
// Primary: Synchronous kill - most reliable, ensures completion
|
|
2198
2220
|
// NOTE: We always try this, even if lsof might not exist - errors are caught
|
|
2199
2221
|
try {
|
|
2200
|
-
|
|
2201
|
-
const result = spawnSync("sh", ["-c", `lsof -ti:${this.options.port} | xargs kill -9 2>/dev/null`], {
|
|
2202
|
-
stdio: "pipe",
|
|
2203
|
-
timeout: 5000
|
|
2204
|
-
});
|
|
2205
|
-
this.debugLog(`Synchronous kill for port ${this.options.port} exit code: ${result.status}`);
|
|
2222
|
+
killPortProcessesSync(this.options.port, this.debugLog.bind(this));
|
|
2206
2223
|
}
|
|
2207
2224
|
catch (error) {
|
|
2208
2225
|
this.debugLog(`Synchronous kill error: ${error}`);
|
|
@@ -2231,25 +2248,24 @@ export class DevEnvironment {
|
|
|
2231
2248
|
await killPortProcess(this.options.port, "your app server");
|
|
2232
2249
|
// Double-check: try to kill any remaining processes on the app port
|
|
2233
2250
|
try {
|
|
2234
|
-
const
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2251
|
+
const parsedPort = parsePortNumber(this.options.port);
|
|
2252
|
+
if (parsedPort !== null) {
|
|
2253
|
+
pkillByPattern(`:${parsedPort}`, this.debugLog.bind(this));
|
|
2254
|
+
this.debugLog(`Sent pkill signal for port ${parsedPort}`);
|
|
2255
|
+
}
|
|
2238
2256
|
// Specifically kill any remaining next dev processes in the current directory
|
|
2239
2257
|
// This catches cases where the shell wrapper exited but next-server survived
|
|
2240
2258
|
const cwd = process.cwd();
|
|
2241
|
-
|
|
2242
|
-
|
|
2259
|
+
const escapedCwd = escapeRegexForPkill(cwd);
|
|
2260
|
+
pkillByPattern(`next dev.*${escapedCwd}`, this.debugLog.bind(this));
|
|
2261
|
+
pkillByPattern(`next-server.*${escapedCwd}`, this.debugLog.bind(this));
|
|
2243
2262
|
this.debugLog(`Sent pkill signal for next processes in ${cwd}`);
|
|
2244
2263
|
// Kill server process and its children using the saved PID (from before session file was deleted)
|
|
2245
2264
|
if (sessionInfo?.serverPid) {
|
|
2246
2265
|
this.killServerPidIfOwned(sessionInfo.serverPid, sessionInfo.cwd, "handleShutdown");
|
|
2247
2266
|
}
|
|
2248
2267
|
// Final synchronous lsof kill - most reliable method
|
|
2249
|
-
|
|
2250
|
-
stdio: "pipe"
|
|
2251
|
-
});
|
|
2252
|
-
this.debugLog(`Final lsof kill exit code: ${result.status}`);
|
|
2268
|
+
killPortProcessesSync(this.options.port, this.debugLog.bind(this));
|
|
2253
2269
|
}
|
|
2254
2270
|
catch {
|
|
2255
2271
|
// Ignore pkill errors
|