engine7 7.1.118 → 7.1.119

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.
@@ -23776,17 +23776,81 @@ import * as path16 from "node:path";
23776
23776
  import fs11 from "node:fs";
23777
23777
  import path11 from "node:path";
23778
23778
  import { execSync as execSync2 } from "node:child_process";
23779
- function acquireEngineLock(stateDir) {
23780
- const lockFile = path11.join(stateDir, ".engine.pid");
23781
- const myPid = process.pid;
23779
+ function enginePidFile(stateDir) {
23780
+ return path11.join(stateDir, ".engine.pid");
23781
+ }
23782
+ function isEngineImage(text) {
23783
+ return /node|engine7|electron/i.test(text);
23784
+ }
23785
+ function isPidAlive(pid) {
23786
+ try {
23787
+ process.kill(pid, 0);
23788
+ return true;
23789
+ } catch {
23790
+ return false;
23791
+ }
23792
+ }
23793
+ function probeImage(pid) {
23782
23794
  try {
23783
- const oldPid = parseInt(fs11.readFileSync(lockFile, "utf-8").trim(), 10);
23784
- if (oldPid && oldPid !== myPid && isNodeEngineAlive(oldPid)) {
23785
- console.log(`[pid-lock] Stale engine PID ${oldPid} still alive (node), killing tree...`);
23786
- killTree(oldPid);
23795
+ if (process.platform === "win32") {
23796
+ return execSync2(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
23797
+ encoding: "utf-8",
23798
+ timeout: 3e3,
23799
+ stdio: ["ignore", "pipe", "ignore"]
23800
+ });
23787
23801
  }
23802
+ if (process.platform === "darwin") {
23803
+ return execSync2(`ps -p ${pid} -o comm=`, {
23804
+ encoding: "utf-8",
23805
+ timeout: 3e3,
23806
+ stdio: ["ignore", "pipe", "ignore"]
23807
+ });
23808
+ }
23809
+ return fs11.readFileSync(`/proc/${pid}/comm`, "utf-8");
23810
+ } catch {
23811
+ return null;
23812
+ }
23813
+ }
23814
+ function probeEngineImage(pid) {
23815
+ return isEngineImage(probeImage(pid) ?? "");
23816
+ }
23817
+ function isCliWrapperImage(text) {
23818
+ return /node/i.test(text);
23819
+ }
23820
+ function probeIsCliWrapper(pid) {
23821
+ return isCliWrapperImage(probeImage(pid) ?? "");
23822
+ }
23823
+ function readOwnEnginePidText(stateDir) {
23824
+ try {
23825
+ return fs11.readFileSync(enginePidFile(stateDir), "utf-8");
23788
23826
  } catch (err) {
23789
23827
  if (err?.code !== "ENOENT") console.warn(`[pid-lock] read lock failed: ${err.message}`);
23828
+ return null;
23829
+ }
23830
+ }
23831
+ function pickOwnEnginePid(probe) {
23832
+ const pid = parseInt((probe.pidFileContent ?? "").trim(), 10);
23833
+ if (!Number.isInteger(pid) || pid <= 0) return null;
23834
+ if (pid === probe.myPid) return null;
23835
+ if (!probe.isAlive(pid)) return null;
23836
+ if (!probe.isEngineImage(pid)) return null;
23837
+ return pid;
23838
+ }
23839
+ function ownEnginePid(stateDir, myPid = process.pid) {
23840
+ return pickOwnEnginePid({
23841
+ pidFileContent: readOwnEnginePidText(stateDir),
23842
+ myPid,
23843
+ isAlive: isPidAlive,
23844
+ isEngineImage: probeEngineImage
23845
+ });
23846
+ }
23847
+ function acquireEngineLock(stateDir) {
23848
+ const lockFile = enginePidFile(stateDir);
23849
+ const myPid = process.pid;
23850
+ const stale = ownEnginePid(stateDir, myPid);
23851
+ if (stale !== null) {
23852
+ console.log(`[pid-lock] Stale engine PID ${stale} still alive (engine), killing tree...`);
23853
+ killTree(stale);
23790
23854
  }
23791
23855
  try {
23792
23856
  fs11.mkdirSync(stateDir, { recursive: true });
@@ -23812,54 +23876,42 @@ function acquireEngineLock(stateDir) {
23812
23876
  process.exit(0);
23813
23877
  });
23814
23878
  }
23815
- function isNodeEngineAlive(pid) {
23816
- try {
23817
- process.kill(pid, 0);
23818
- } catch {
23819
- return false;
23820
- }
23821
- try {
23822
- if (process.platform === "win32") {
23823
- const out = execSync2(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
23824
- encoding: "utf-8",
23825
- timeout: 3e3,
23826
- stdio: ["ignore", "pipe", "ignore"]
23827
- });
23828
- return /node\.exe/i.test(out);
23829
- } else if (process.platform === "darwin") {
23830
- const out = execSync2(`ps -p ${pid} -o comm=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] });
23831
- return /node/.test(out);
23832
- }
23833
- return /node/.test(fs11.readFileSync(`/proc/${pid}/cmdline`, "utf-8"));
23834
- } catch {
23835
- return false;
23836
- }
23879
+ function pickParentPid(procStatus, psOutput) {
23880
+ const fromProc = Number(/PPid:\s*(\d+)/.exec(procStatus ?? "")?.[1] ?? NaN);
23881
+ if (Number.isInteger(fromProc) && fromProc > 0) return fromProc;
23882
+ const fromPs = Number((psOutput ?? "").trim());
23883
+ return Number.isInteger(fromPs) && fromPs > 0 ? fromPs : 0;
23837
23884
  }
23838
23885
  function killTree(pid) {
23839
23886
  try {
23840
23887
  if (process.platform === "win32") {
23841
23888
  execSync2(`taskkill /PID ${pid} /T /F`, { stdio: "ignore", timeout: 8e3 });
23842
23889
  try {
23843
- const parentPid = execSync2(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1];
23844
- if (parentPid && parseInt(parentPid) !== process.ppid) {
23890
+ const parentPid = parseInt(execSync2(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1] ?? "0", 10);
23891
+ if (parentPid && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
23845
23892
  execSync2(`taskkill /PID ${parentPid} /F`, { stdio: "ignore", timeout: 3e3 });
23846
23893
  }
23847
23894
  } catch {
23848
23895
  }
23849
23896
  } else {
23850
23897
  process.kill(pid, "SIGKILL");
23898
+ let parentPid = 0;
23851
23899
  try {
23852
- const ppid = parseInt(fs11.readFileSync(`/proc/${pid}/status`, "utf-8").match(/PPid:\s+(\d+)/)?.[1] || "0", 10);
23853
- const macPpid = parseInt(execSync2(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).trim(), 10);
23854
- const parentPid = ppid || macPpid;
23855
- if (parentPid && parentPid > 1) {
23856
- try {
23857
- process.kill(parentPid, "SIGKILL");
23858
- } catch {
23859
- }
23860
- }
23900
+ parentPid = pickParentPid(fs11.readFileSync(`/proc/${pid}/status`, "utf-8"), null);
23861
23901
  } catch {
23862
23902
  }
23903
+ if (!parentPid) {
23904
+ try {
23905
+ parentPid = pickParentPid(null, execSync2(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }));
23906
+ } catch {
23907
+ }
23908
+ }
23909
+ if (parentPid > 1 && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
23910
+ try {
23911
+ process.kill(parentPid, "SIGKILL");
23912
+ } catch {
23913
+ }
23914
+ }
23863
23915
  }
23864
23916
  } catch (err) {
23865
23917
  console.warn(`[pid-lock] kill ${pid} failed: ${err.message}`);
package/dist/main.mjs CHANGED
@@ -24156,17 +24156,81 @@ import * as path16 from "node:path";
24156
24156
  import fs11 from "node:fs";
24157
24157
  import path11 from "node:path";
24158
24158
  import { execSync as execSync2 } from "node:child_process";
24159
- function acquireEngineLock(stateDir) {
24160
- const lockFile = path11.join(stateDir, ".engine.pid");
24161
- const myPid = process.pid;
24159
+ function enginePidFile(stateDir) {
24160
+ return path11.join(stateDir, ".engine.pid");
24161
+ }
24162
+ function isEngineImage(text) {
24163
+ return /node|engine7|electron/i.test(text);
24164
+ }
24165
+ function isPidAlive(pid) {
24166
+ try {
24167
+ process.kill(pid, 0);
24168
+ return true;
24169
+ } catch {
24170
+ return false;
24171
+ }
24172
+ }
24173
+ function probeImage(pid) {
24162
24174
  try {
24163
- const oldPid = parseInt(fs11.readFileSync(lockFile, "utf-8").trim(), 10);
24164
- if (oldPid && oldPid !== myPid && isNodeEngineAlive(oldPid)) {
24165
- console.log(`[pid-lock] Stale engine PID ${oldPid} still alive (node), killing tree...`);
24166
- killTree(oldPid);
24175
+ if (process.platform === "win32") {
24176
+ return execSync2(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
24177
+ encoding: "utf-8",
24178
+ timeout: 3e3,
24179
+ stdio: ["ignore", "pipe", "ignore"]
24180
+ });
24167
24181
  }
24182
+ if (process.platform === "darwin") {
24183
+ return execSync2(`ps -p ${pid} -o comm=`, {
24184
+ encoding: "utf-8",
24185
+ timeout: 3e3,
24186
+ stdio: ["ignore", "pipe", "ignore"]
24187
+ });
24188
+ }
24189
+ return fs11.readFileSync(`/proc/${pid}/comm`, "utf-8");
24190
+ } catch {
24191
+ return null;
24192
+ }
24193
+ }
24194
+ function probeEngineImage(pid) {
24195
+ return isEngineImage(probeImage(pid) ?? "");
24196
+ }
24197
+ function isCliWrapperImage(text) {
24198
+ return /node/i.test(text);
24199
+ }
24200
+ function probeIsCliWrapper(pid) {
24201
+ return isCliWrapperImage(probeImage(pid) ?? "");
24202
+ }
24203
+ function readOwnEnginePidText(stateDir) {
24204
+ try {
24205
+ return fs11.readFileSync(enginePidFile(stateDir), "utf-8");
24168
24206
  } catch (err) {
24169
24207
  if (err?.code !== "ENOENT") console.warn(`[pid-lock] read lock failed: ${err.message}`);
24208
+ return null;
24209
+ }
24210
+ }
24211
+ function pickOwnEnginePid(probe) {
24212
+ const pid = parseInt((probe.pidFileContent ?? "").trim(), 10);
24213
+ if (!Number.isInteger(pid) || pid <= 0) return null;
24214
+ if (pid === probe.myPid) return null;
24215
+ if (!probe.isAlive(pid)) return null;
24216
+ if (!probe.isEngineImage(pid)) return null;
24217
+ return pid;
24218
+ }
24219
+ function ownEnginePid(stateDir, myPid = process.pid) {
24220
+ return pickOwnEnginePid({
24221
+ pidFileContent: readOwnEnginePidText(stateDir),
24222
+ myPid,
24223
+ isAlive: isPidAlive,
24224
+ isEngineImage: probeEngineImage
24225
+ });
24226
+ }
24227
+ function acquireEngineLock(stateDir) {
24228
+ const lockFile = enginePidFile(stateDir);
24229
+ const myPid = process.pid;
24230
+ const stale = ownEnginePid(stateDir, myPid);
24231
+ if (stale !== null) {
24232
+ console.log(`[pid-lock] Stale engine PID ${stale} still alive (engine), killing tree...`);
24233
+ killTree(stale);
24170
24234
  }
24171
24235
  try {
24172
24236
  fs11.mkdirSync(stateDir, { recursive: true });
@@ -24192,54 +24256,42 @@ function acquireEngineLock(stateDir) {
24192
24256
  process.exit(0);
24193
24257
  });
24194
24258
  }
24195
- function isNodeEngineAlive(pid) {
24196
- try {
24197
- process.kill(pid, 0);
24198
- } catch {
24199
- return false;
24200
- }
24201
- try {
24202
- if (process.platform === "win32") {
24203
- const out = execSync2(`tasklist /FI "PID eq ${pid}" /NH /FO CSV`, {
24204
- encoding: "utf-8",
24205
- timeout: 3e3,
24206
- stdio: ["ignore", "pipe", "ignore"]
24207
- });
24208
- return /node\.exe/i.test(out);
24209
- } else if (process.platform === "darwin") {
24210
- const out = execSync2(`ps -p ${pid} -o comm=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] });
24211
- return /node/.test(out);
24212
- }
24213
- return /node/.test(fs11.readFileSync(`/proc/${pid}/cmdline`, "utf-8"));
24214
- } catch {
24215
- return false;
24216
- }
24259
+ function pickParentPid(procStatus, psOutput) {
24260
+ const fromProc = Number(/PPid:\s*(\d+)/.exec(procStatus ?? "")?.[1] ?? NaN);
24261
+ if (Number.isInteger(fromProc) && fromProc > 0) return fromProc;
24262
+ const fromPs = Number((psOutput ?? "").trim());
24263
+ return Number.isInteger(fromPs) && fromPs > 0 ? fromPs : 0;
24217
24264
  }
24218
24265
  function killTree(pid) {
24219
24266
  try {
24220
24267
  if (process.platform === "win32") {
24221
24268
  execSync2(`taskkill /PID ${pid} /T /F`, { stdio: "ignore", timeout: 8e3 });
24222
24269
  try {
24223
- const parentPid = execSync2(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1];
24224
- if (parentPid && parseInt(parentPid) !== process.ppid) {
24270
+ const parentPid = parseInt(execSync2(`wmic process where ProcessId=${pid} get ParentProcessId /value`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).match(/ParentProcessId=(\d+)/)?.[1] ?? "0", 10);
24271
+ if (parentPid && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
24225
24272
  execSync2(`taskkill /PID ${parentPid} /F`, { stdio: "ignore", timeout: 3e3 });
24226
24273
  }
24227
24274
  } catch {
24228
24275
  }
24229
24276
  } else {
24230
24277
  process.kill(pid, "SIGKILL");
24278
+ let parentPid = 0;
24231
24279
  try {
24232
- const ppid = parseInt(fs11.readFileSync(`/proc/${pid}/status`, "utf-8").match(/PPid:\s+(\d+)/)?.[1] || "0", 10);
24233
- const macPpid = parseInt(execSync2(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }).trim(), 10);
24234
- const parentPid = ppid || macPpid;
24235
- if (parentPid && parentPid > 1) {
24236
- try {
24237
- process.kill(parentPid, "SIGKILL");
24238
- } catch {
24239
- }
24240
- }
24280
+ parentPid = pickParentPid(fs11.readFileSync(`/proc/${pid}/status`, "utf-8"), null);
24241
24281
  } catch {
24242
24282
  }
24283
+ if (!parentPid) {
24284
+ try {
24285
+ parentPid = pickParentPid(null, execSync2(`ps -p ${pid} -o ppid=`, { encoding: "utf-8", timeout: 3e3, stdio: ["ignore", "pipe", "ignore"] }));
24286
+ } catch {
24287
+ }
24288
+ }
24289
+ if (parentPid > 1 && parentPid !== process.ppid && probeIsCliWrapper(parentPid)) {
24290
+ try {
24291
+ process.kill(parentPid, "SIGKILL");
24292
+ } catch {
24293
+ }
24294
+ }
24243
24295
  }
24244
24296
  } catch (err) {
24245
24297
  console.warn(`[pid-lock] kill ${pid} failed: ${err.message}`);
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "engine7",
3
3
  "license": "Apache-2.0",
4
- "version": "7.1.118",
4
+ "version": "7.1.119",
5
5
  "type": "module",
6
6
  "description": "Engine 7 — 给助手一个家 / A home for your AI assistant",
7
7
  "main": "dist/main.mjs",