@seqyuan/annodex 0.1.40 → 0.1.41

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.
Files changed (60) hide show
  1. package/.next/BUILD_ID +1 -1
  2. package/.next/app-path-routes-manifest.json +4 -4
  3. package/.next/build-manifest.json +2 -2
  4. package/.next/prerender-manifest.json +3 -3
  5. package/.next/required-server-files.js +1 -1
  6. package/.next/required-server-files.json +1 -1
  7. package/.next/server/app/_global-error.html +1 -1
  8. package/.next/server/app/_global-error.rsc +1 -1
  9. package/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  10. package/.next/server/app/_global-error.segments/_global-error/__PAGE__.segment.rsc +1 -1
  11. package/.next/server/app/_global-error.segments/_global-error.segment.rsc +1 -1
  12. package/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  13. package/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  14. package/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  15. package/.next/server/app/_not-found.html +1 -1
  16. package/.next/server/app/_not-found.rsc +1 -1
  17. package/.next/server/app/_not-found.segments/_full.segment.rsc +1 -1
  18. package/.next/server/app/_not-found.segments/_head.segment.rsc +1 -1
  19. package/.next/server/app/_not-found.segments/_index.segment.rsc +1 -1
  20. package/.next/server/app/_not-found.segments/_not-found/__PAGE__.segment.rsc +1 -1
  21. package/.next/server/app/_not-found.segments/_not-found.segment.rsc +1 -1
  22. package/.next/server/app/_not-found.segments/_tree.segment.rsc +1 -1
  23. package/.next/server/app/api/internal/runtime/route.js +1 -1
  24. package/.next/server/app/api/version/route.js +1 -1
  25. package/.next/server/app/index.html +1 -1
  26. package/.next/server/app/index.rsc +1 -1
  27. package/.next/server/app/index.segments/__PAGE__.segment.rsc +1 -1
  28. package/.next/server/app/index.segments/_full.segment.rsc +1 -1
  29. package/.next/server/app/index.segments/_head.segment.rsc +1 -1
  30. package/.next/server/app/index.segments/_index.segment.rsc +1 -1
  31. package/.next/server/app/index.segments/_tree.segment.rsc +1 -1
  32. package/.next/server/app/login.html +1 -1
  33. package/.next/server/app/login.rsc +1 -1
  34. package/.next/server/app/login.segments/_full.segment.rsc +1 -1
  35. package/.next/server/app/login.segments/_head.segment.rsc +1 -1
  36. package/.next/server/app/login.segments/_index.segment.rsc +1 -1
  37. package/.next/server/app/login.segments/_tree.segment.rsc +1 -1
  38. package/.next/server/app/login.segments/login/__PAGE__.segment.rsc +1 -1
  39. package/.next/server/app/login.segments/login.segment.rsc +1 -1
  40. package/.next/server/app/workspace/page.js +2 -2
  41. package/.next/server/app/workspace/page_client-reference-manifest.js +1 -1
  42. package/.next/server/app/workspace.html +1 -1
  43. package/.next/server/app/workspace.rsc +2 -2
  44. package/.next/server/app/workspace.segments/_full.segment.rsc +2 -2
  45. package/.next/server/app/workspace.segments/_head.segment.rsc +1 -1
  46. package/.next/server/app/workspace.segments/_index.segment.rsc +1 -1
  47. package/.next/server/app/workspace.segments/_tree.segment.rsc +1 -1
  48. package/.next/server/app/workspace.segments/workspace/__PAGE__.segment.rsc +2 -2
  49. package/.next/server/app/workspace.segments/workspace.segment.rsc +1 -1
  50. package/.next/server/app-paths-manifest.json +4 -4
  51. package/.next/server/chunks/402.js +2 -2
  52. package/.next/server/middleware-build-manifest.js +1 -1
  53. package/.next/server/pages/404.html +1 -1
  54. package/.next/server/pages/500.html +1 -1
  55. package/.next/server/server-reference-manifest.json +1 -1
  56. package/.next/static/chunks/app/workspace/{page-8fac7ee42deeb8ca.js → page-e2d1ab62df4e4976.js} +2 -2
  57. package/bin/annodex.js +81 -44
  58. package/package.json +1 -1
  59. /package/.next/static/{wR2GoNpY1oWDdt11voI1Y → 93wajK0FYL6xkqktm1mwa}/_buildManifest.js +0 -0
  60. /package/.next/static/{wR2GoNpY1oWDdt11voI1Y → 93wajK0FYL6xkqktm1mwa}/_ssgManifest.js +0 -0
package/bin/annodex.js CHANGED
@@ -281,27 +281,72 @@ function autoRestartEnabled() {
281
281
  return true;
282
282
  }
283
283
 
284
+ function addPidIfValid(target, pidValue) {
285
+ const pid = Number(pidValue);
286
+ if (Number.isInteger(pid) && pid > 0 && pid !== process.pid) target.add(pid);
287
+ }
288
+
289
+ function localAddressMatchesPort(localAddress, listenPort) {
290
+ const match = String(localAddress || "").trim().match(/:(\d+)$/);
291
+ return !!match && Number(match[1]) === listenPort;
292
+ }
293
+
284
294
  function findListeningPids(listenPort) {
285
- if (process.platform === "win32") return [];
295
+ const targetPort = Number(listenPort);
296
+ if (!Number.isInteger(targetPort) || targetPort <= 0 || targetPort > 65535) return [];
286
297
  const pids = new Set();
298
+
299
+ if (process.platform === "win32") {
300
+ try {
301
+ const psCommand = [
302
+ `$port = ${targetPort}`,
303
+ "Get-NetTCPConnection -State Listen -LocalPort $port -ErrorAction Stop | Select-Object -ExpandProperty OwningProcess",
304
+ ].join("; ");
305
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-Command", psCommand], { encoding: "utf8", windowsHide: true });
306
+ if (result.status === 0) {
307
+ result.stdout
308
+ .split(/\r?\n/)
309
+ .map((value) => value.trim())
310
+ .filter(Boolean)
311
+ .forEach((value) => addPidIfValid(pids, value));
312
+ }
313
+ } catch {
314
+ // Fall through to netstat.
315
+ }
316
+ if (pids.size === 0) {
317
+ try {
318
+ const result = spawnSync("netstat", ["-ano", "-p", "tcp"], { encoding: "utf8", windowsHide: true });
319
+ for (const line of result.stdout.split(/\r?\n/)) {
320
+ const fields = line.trim().split(/\s+/);
321
+ if (fields.length < 5) continue;
322
+ const proto = fields[0].toUpperCase();
323
+ const localAddress = fields[1];
324
+ const state = fields[3] ? fields[3].toUpperCase() : "";
325
+ const pidValue = fields[fields.length - 1];
326
+ if (proto !== "TCP" || state !== "LISTENING" || !localAddressMatchesPort(localAddress, targetPort)) continue;
327
+ addPidIfValid(pids, pidValue);
328
+ }
329
+ } catch {
330
+ // Ignore lookup failures.
331
+ }
332
+ }
333
+ return [...pids];
334
+ }
335
+
287
336
  try {
288
- const result = spawnSync("lsof", [`-tiTCP:${listenPort}`, "-sTCP:LISTEN"], { encoding: "utf8" });
337
+ const result = spawnSync("lsof", [`-tiTCP:${targetPort}`, "-sTCP:LISTEN"], { encoding: "utf8" });
289
338
  result.stdout
290
339
  .split(/\s+/)
291
- .map((value) => Number(value))
292
- .filter((pid) => Number.isInteger(pid) && pid > 0 && pid !== process.pid)
293
- .forEach((pid) => pids.add(pid));
340
+ .filter(Boolean)
341
+ .forEach((value) => addPidIfValid(pids, value));
294
342
  } catch {
295
343
  // Fall through to ss.
296
344
  }
297
345
  if (pids.size === 0 && process.platform === "linux") {
298
346
  try {
299
- const result = spawnSync("ss", ["-H", "-ltnp", `sport = :${listenPort}`], { encoding: "utf8" });
347
+ const result = spawnSync("ss", ["-H", "-ltnp", `sport = :${targetPort}`], { encoding: "utf8" });
300
348
  const matches = result.stdout.matchAll(/pid=(\d+)/g);
301
- for (const match of matches) {
302
- const pid = Number(match[1]);
303
- if (Number.isInteger(pid) && pid > 0 && pid !== process.pid) pids.add(pid);
304
- }
349
+ for (const match of matches) addPidIfValid(pids, match[1]);
305
350
  } catch {
306
351
  // Ignore lookup failures.
307
352
  }
@@ -324,6 +369,22 @@ function isPathInside(childPath, parentPath) {
324
369
 
325
370
  function readProcessCmdline(pid) {
326
371
  if (!Number.isInteger(pid) || pid <= 0) return "";
372
+ if (process.platform === "win32") {
373
+ try {
374
+ const psCommand = `Get-CimInstance Win32_Process -Filter \"ProcessId = ${pid}\" -ErrorAction Stop | Select-Object -ExpandProperty CommandLine`;
375
+ const result = spawnSync("powershell.exe", ["-NoProfile", "-Command", psCommand], { encoding: "utf8", windowsHide: true });
376
+ if (result.status === 0 && result.stdout.trim()) return result.stdout.trim();
377
+ } catch {
378
+ // Fall through to wmic.
379
+ }
380
+ try {
381
+ const result = spawnSync("wmic", ["process", "where", `ProcessId=${pid}`, "get", "CommandLine", "/value"], { encoding: "utf8", windowsHide: true });
382
+ const line = result.stdout.split(/\r?\n/).find((value) => value.startsWith("CommandLine="));
383
+ return line ? line.slice("CommandLine=".length).trim() : "";
384
+ } catch {
385
+ return "";
386
+ }
387
+ }
327
388
  if (process.platform === "linux") {
328
389
  try {
329
390
  return fs.readFileSync(`/proc/${pid}/cmdline`, "utf8").replace(/\0/g, " ").trim();
@@ -673,8 +734,7 @@ Usage:
673
734
  annodex stop Stop background annodex
674
735
  annodex status [--json] Show background server status
675
736
  annodex logs [-f] Show background server logs
676
- annodex passwd Change password (or set if none)
677
- annodex passwd --reset Remove password (disable auth)
737
+ annodex passwd Set or change password (empty = disable auth)
678
738
  annodex update Update to the latest version
679
739
 
680
740
  Options:
@@ -754,7 +814,6 @@ if (firstPos === "update") {
754
814
 
755
815
  if (firstPos === "passwd") {
756
816
  const reset = positionals[1] === "--reset";
757
-
758
817
  if (reset) {
759
818
  if (fs.existsSync(authFile)) {
760
819
  fs.unlinkSync(authFile);
@@ -764,41 +823,26 @@ if (firstPos === "passwd") {
764
823
  }
765
824
  process.exit(0);
766
825
  }
767
-
768
826
  const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
769
827
  const ask = (prompt) => new Promise((res) => rl.question(prompt, res));
770
828
  (async () => {
771
829
  const exists = fs.existsSync(authFile);
772
830
  if (exists) {
773
- console.log("\n Changing password...\n");
774
- const oldPw = await ask("Current password: ");
775
- try {
776
- const cfg = JSON.parse(fs.readFileSync(authFile, "utf8"));
777
- if (!bcrypt.compareSync(oldPw, cfg.passwordHash)) {
778
- console.log(" ❌ Incorrect password.\n");
779
- rl.close();
780
- process.exit(1);
781
- }
782
- } catch { console.log(" ❌ Could not read auth file.\n"); rl.close(); process.exit(1); }
831
+ console.log("\n Changing password...");
832
+ console.log(" (Terminal access grants reset permission — no old password needed)\n");
783
833
  }
784
- const pw1 = await ask("New password (empty to disable): ");
785
- if (!pw1.trim()) {
834
+ const pw = await ask("New password (empty to disable): ");
835
+ if (!pw.trim()) {
786
836
  if (fs.existsSync(authFile)) fs.unlinkSync(authFile);
787
837
  console.log(" 🔓 Auth disabled.\n");
788
838
  rl.close();
789
839
  process.exit(0);
790
840
  }
791
- const pw2 = await ask("Confirm new password: ");
792
- if (pw1 !== pw2) {
793
- console.log(" ❌ Passwords don't match.\n");
794
- rl.close();
795
- process.exit(1);
796
- }
797
- const hash = bcrypt.hashSync(pw1, 10);
841
+ const hash = bcrypt.hashSync(pw, 10);
798
842
  const dir = path.dirname(authFile);
799
843
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
800
844
  fs.writeFileSync(authFile, JSON.stringify({ passwordHash: hash, enabled: true }, null, 2));
801
- console.log(exists ? " ✅ Password changed.\n" : " ✅ Password set.\n");
845
+ console.log(exists ? " ✅ Password changed.\n" : " ✅ Password set. Restart won't prompt.\n");
802
846
  rl.close();
803
847
  process.exit(0);
804
848
  })();
@@ -835,21 +879,14 @@ function promptPassword() {
835
879
  (async () => {
836
880
  console.log("\n🔐 No password set. You can protect annodex with a password.");
837
881
  console.log(" Leave empty and press Enter to skip.\n");
838
- const pw1 = await ask("Enter password: ");
839
- if (!pw1.trim()) {
882
+ const pw = await ask("Enter password: ");
883
+ if (!pw.trim()) {
840
884
  console.log(" Skipped — no password required.\n");
841
885
  rl.close();
842
886
  resolve(false);
843
887
  return;
844
888
  }
845
- const pw2 = await ask("Confirm password: ");
846
- if (pw1 !== pw2) {
847
- console.log(" Passwords don't match. Skipping.\n");
848
- rl.close();
849
- resolve(false);
850
- return;
851
- }
852
- const hash = bcrypt.hashSync(pw1, 10);
889
+ const hash = bcrypt.hashSync(pw, 10);
853
890
  const dir = path.dirname(authFile);
854
891
  if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
855
892
  fs.writeFileSync(authFile, JSON.stringify({ passwordHash: hash, enabled: true }, null, 2));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@seqyuan/annodex",
3
- "version": "0.1.40",
3
+ "version": "0.1.41",
4
4
  "description": "AI-native bioinformatics workspace by Annoroad",
5
5
  "license": "MIT",
6
6
  "bin": {