buildwithnexus 0.3.3 → 0.3.5

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/bin.js CHANGED
@@ -438,59 +438,59 @@ async function getPortBlocker(port) {
438
438
  return null;
439
439
  }
440
440
  }
441
- async function findFreePort(preferred, max = 20) {
442
- for (let offset = 0; offset < max; offset++) {
443
- if (await isPortFree(preferred + offset)) return preferred + offset;
444
- }
445
- throw new Error(`No free port found near ${preferred}`);
446
- }
447
441
  async function resolvePortConflicts(ports) {
448
442
  const labels = { ssh: "SSH", http: "HTTP", https: "HTTPS" };
449
443
  const resolved = { ...ports };
444
+ const claimed = /* @__PURE__ */ new Set();
450
445
  for (const [key, port] of Object.entries(ports)) {
451
- if (await isPortFree(port)) continue;
452
- const blocker = await getPortBlocker(port);
453
- const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "unknown process";
454
- const altPort = await findFreePort(port + 1).catch(() => null);
455
- const choices = [];
456
- if (blocker) {
457
- choices.push({
458
- name: `Kill ${desc} and use port ${port}`,
459
- value: "kill"
460
- });
446
+ if (await isPortFree(port) && !claimed.has(port)) {
447
+ claimed.add(port);
448
+ continue;
449
+ }
450
+ let altPort = null;
451
+ for (let offset = 1; offset <= 50; offset++) {
452
+ const candidate = port + offset;
453
+ if (!claimed.has(candidate) && await isPortFree(candidate)) {
454
+ altPort = candidate;
455
+ break;
456
+ }
461
457
  }
462
458
  if (altPort) {
463
- choices.push({
464
- name: `Use alternate port ${altPort} instead`,
465
- value: "alt"
459
+ resolved[key] = altPort;
460
+ claimed.add(altPort);
461
+ const blocker = await getPortBlocker(port);
462
+ const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "another process";
463
+ console.log(chalk5.yellow(` \u26A0 Port ${port} (${labels[key]}) in use by ${desc} \u2192 using ${altPort}`));
464
+ } else {
465
+ const blocker = await getPortBlocker(port);
466
+ const desc = blocker ? `${blocker.process} (PID ${blocker.pid})` : "unknown process";
467
+ console.log("");
468
+ console.log(chalk5.red(` \u2717 Port ${port} (${labels[key]}) is in use by ${desc} and no free port found nearby`));
469
+ const action = await select({
470
+ message: `No free ${labels[key]} port found. Kill ${desc} to free port ${port}?`,
471
+ choices: [
472
+ ...blocker ? [{ name: `Kill ${desc} and use port ${port}`, value: "kill" }] : [],
473
+ { name: "Abort init", value: "abort" }
474
+ ]
466
475
  });
467
- }
468
- choices.push({ name: "Abort init", value: "abort" });
469
- console.log("");
470
- console.log(chalk5.yellow(` \u26A0 Port ${port} (${labels[key]}) is in use by ${desc}`));
471
- const action = await select({
472
- message: `How would you like to resolve the ${labels[key]} port conflict?`,
473
- choices
474
- });
475
- if (action === "kill" && blocker) {
476
- try {
477
- process.kill(blocker.pid, "SIGTERM");
478
- await new Promise((r) => setTimeout(r, 1e3));
479
- if (!await isPortFree(port)) {
480
- process.kill(blocker.pid, "SIGKILL");
481
- await new Promise((r) => setTimeout(r, 500));
476
+ if (action === "kill" && blocker) {
477
+ try {
478
+ process.kill(blocker.pid, "SIGTERM");
479
+ await new Promise((r) => setTimeout(r, 1e3));
480
+ if (!await isPortFree(port)) {
481
+ process.kill(blocker.pid, "SIGKILL");
482
+ await new Promise((r) => setTimeout(r, 500));
483
+ }
484
+ claimed.add(port);
485
+ console.log(chalk5.green(` \u2713 Killed ${desc}, port ${port} is now free`));
486
+ } catch {
487
+ console.log(chalk5.red(` \u2717 Failed to kill PID ${blocker.pid}. Try: sudo kill ${blocker.pid}`));
488
+ process.exit(1);
482
489
  }
483
- console.log(chalk5.green(` \u2713 Killed ${desc}, port ${port} is now free`));
484
- } catch {
485
- console.log(chalk5.red(` \u2717 Failed to kill PID ${blocker.pid}. Try: sudo kill ${blocker.pid}`));
486
- process.exit(1);
490
+ } else {
491
+ console.log(chalk5.dim(" Init aborted."));
492
+ process.exit(0);
487
493
  }
488
- } else if (action === "alt" && altPort) {
489
- resolved[key] = altPort;
490
- console.log(chalk5.green(` \u2713 Using port ${altPort} for ${labels[key]}`));
491
- } else {
492
- console.log(chalk5.dim(" Init aborted."));
493
- process.exit(0);
494
494
  }
495
495
  }
496
496
  return resolved;
@@ -671,7 +671,7 @@ function addSshConfig(port) {
671
671
  fs4.writeFileSync(sshConfigPath, block, { mode: 384 });
672
672
  }
673
673
  }
674
- async function waitForSsh(port, timeoutMs = 3e5) {
674
+ async function waitForSsh(port, timeoutMs = 6e5) {
675
675
  const start = Date.now();
676
676
  while (Date.now() - start < timeoutMs) {
677
677
  try {
@@ -1045,7 +1045,7 @@ async function checkHealth(port, vmRunning) {
1045
1045
  }
1046
1046
  return status;
1047
1047
  }
1048
- async function waitForServer(port, timeoutMs = 9e5) {
1048
+ async function waitForServer(port, timeoutMs = 36e5) {
1049
1049
  const start = Date.now();
1050
1050
  let lastLog = 0;
1051
1051
  while (Date.now() - start < timeoutMs) {
@@ -1069,7 +1069,7 @@ async function waitForServer(port, timeoutMs = 9e5) {
1069
1069
  }
1070
1070
  return false;
1071
1071
  }
1072
- async function waitForCloudInit(port, timeoutMs = 18e5) {
1072
+ async function waitForCloudInit(port, timeoutMs = 72e5) {
1073
1073
  const start = Date.now();
1074
1074
  let lastLog = 0;
1075
1075
  while (Date.now() - start < timeoutMs) {
@@ -1339,7 +1339,7 @@ var phases = [
1339
1339
  spinner.start();
1340
1340
  const cloudInitDone = await waitForCloudInit(config.sshPort);
1341
1341
  if (!cloudInitDone) {
1342
- fail(spinner, "Cloud-init timed out after 30 minutes");
1342
+ fail(spinner, "Cloud-init timed out after 2 hours");
1343
1343
  log.warn("Check progress: buildwithnexus ssh \u2192 tail -f /var/log/cloud-init-output.log");
1344
1344
  throw new Error("Cloud-init timed out");
1345
1345
  }
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buildwithnexus",
3
- "version": "0.3.3",
3
+ "version": "0.3.5",
4
4
  "description": "Launch an autonomous AI runtime with triple-nested VM isolation in one command",
5
5
  "type": "module",
6
6
  "bin": {