buildwithnexus 0.2.3 → 0.2.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
@@ -16,7 +16,7 @@ var BANNER = `
16
16
  `;
17
17
  function showBanner() {
18
18
  console.log(BANNER);
19
- console.log(chalk.dim(" v0.2.3 \xB7 buildwithnexus.dev\n"));
19
+ console.log(chalk.dim(" v0.2.5 \xB7 buildwithnexus.dev\n"));
20
20
  }
21
21
  function showPhase(phase, total, description) {
22
22
  const progress = chalk.cyan(`[${phase}/${total}]`);
@@ -458,6 +458,7 @@ function maskKey(key) {
458
458
 
459
459
  // src/core/qemu.ts
460
460
  import fs3 from "fs";
461
+ import net from "net";
461
462
  import path3 from "path";
462
463
  import { execa } from "execa";
463
464
  var VM_DIR = path3.join(NEXUS_HOME2, "vm");
@@ -499,7 +500,35 @@ async function createDisk(basePath, sizeGb) {
499
500
  await execa("qemu-img", ["create", "-f", "qcow2", "-b", basePath, "-F", "qcow2", diskPath, `${sizeGb}G`], { env: scrubEnv() });
500
501
  return diskPath;
501
502
  }
503
+ function tryBind(port, host) {
504
+ return new Promise((resolve) => {
505
+ const server = net.createServer();
506
+ server.once("error", () => resolve(false));
507
+ server.once("listening", () => {
508
+ server.close(() => resolve(true));
509
+ });
510
+ server.listen(port, host);
511
+ });
512
+ }
513
+ async function isPortFree(port) {
514
+ const free0 = await tryBind(port, "0.0.0.0");
515
+ if (!free0) return false;
516
+ const free1 = await tryBind(port, "127.0.0.1");
517
+ return free1;
518
+ }
519
+ async function findFreePort(preferred, max = 20) {
520
+ for (let offset = 0; offset < max; offset++) {
521
+ const port = preferred + offset;
522
+ if (await isPortFree(port)) return port;
523
+ }
524
+ throw new Error(`No free port found near ${preferred}`);
525
+ }
502
526
  async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
527
+ const resolved = {
528
+ ssh: await findFreePort(ports.ssh),
529
+ http: await findFreePort(ports.http),
530
+ https: await findFreePort(ports.https)
531
+ };
503
532
  const machineArg = platform.os === "mac" ? "-machine virt,gic-version=3" : "-machine pc";
504
533
  const biosArgs = fs3.existsSync(platform.biosPath) ? ["-bios", platform.biosPath] : [];
505
534
  const args = [
@@ -512,7 +541,7 @@ async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
512
541
  "-drive",
513
542
  `file=${diskPath},if=virtio,cache=writethrough`,
514
543
  "-drive",
515
- `file=${initIsoPath},if=virtio,cache=writethrough`,
544
+ `file=${initIsoPath},if=virtio,format=raw,cache=writethrough`,
516
545
  "-display",
517
546
  "none",
518
547
  "-serial",
@@ -520,13 +549,14 @@ async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
520
549
  "-net",
521
550
  "nic,model=virtio",
522
551
  "-net",
523
- `user,hostfwd=tcp::${ports.ssh}-:22,hostfwd=tcp::${ports.http}-:4200,hostfwd=tcp::${ports.https}-:443`,
552
+ `user,hostfwd=tcp::${resolved.ssh}-:22,hostfwd=tcp::${resolved.http}-:4200,hostfwd=tcp::${resolved.https}-:443`,
524
553
  ...biosArgs,
525
554
  "-pidfile",
526
555
  PID_FILE,
527
556
  "-daemonize"
528
557
  ];
529
558
  await execa(platform.qemuBinary, args, { env: scrubEnv() });
559
+ return resolved;
530
560
  }
531
561
  function readValidPid() {
532
562
  if (!fs3.existsSync(PID_FILE)) return null;
@@ -980,12 +1010,17 @@ var initCommand = new Command("init").description("Scaffold and launch a new NEX
980
1010
  spinner = createSpinner("Creating disk and launching VM...");
981
1011
  spinner.start();
982
1012
  const diskPath = await createDisk(imagePath, config.vmDisk);
983
- await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
1013
+ const resolvedPorts = await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
984
1014
  ssh: config.sshPort,
985
1015
  http: config.httpPort,
986
1016
  https: config.httpsPort
987
1017
  });
988
- succeed(spinner, "VM launched (daemonized)");
1018
+ config.sshPort = resolvedPorts.ssh;
1019
+ config.httpPort = resolvedPorts.http;
1020
+ config.httpsPort = resolvedPorts.https;
1021
+ saveConfig(config);
1022
+ const portNote = resolvedPorts.ssh !== 2222 || resolvedPorts.http !== 4200 || resolvedPorts.https !== 8443 ? ` (ports: SSH=${resolvedPorts.ssh}, HTTP=${resolvedPorts.http}, HTTPS=${resolvedPorts.https})` : "";
1023
+ succeed(spinner, `VM launched (daemonized)${portNote}`);
989
1024
  showPhase(7, TOTAL_PHASES, "VM Provisioning");
990
1025
  spinner = createSpinner("Waiting for SSH...");
991
1026
  spinner.start();
@@ -1227,9 +1262,9 @@ var doctorCommand = new Command5("doctor").description("Diagnose NEXUS runtime e
1227
1262
  if (config) {
1228
1263
  for (const [name, port] of [["SSH", config.sshPort], ["HTTP", config.httpPort], ["HTTPS", config.httpsPort]]) {
1229
1264
  try {
1230
- const net = await import("net");
1265
+ const net2 = await import("net");
1231
1266
  const available = await new Promise((resolve) => {
1232
- const server = net.createServer();
1267
+ const server = net2.createServer();
1233
1268
  server.once("error", () => resolve(false));
1234
1269
  server.once("listening", () => {
1235
1270
  server.close();
@@ -1594,7 +1629,7 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1594
1629
  });
1595
1630
 
1596
1631
  // src/cli.ts
1597
- var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.3");
1632
+ var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.5");
1598
1633
  cli.addCommand(initCommand);
1599
1634
  cli.addCommand(startCommand);
1600
1635
  cli.addCommand(stopCommand);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buildwithnexus",
3
- "version": "0.2.3",
3
+ "version": "0.2.5",
4
4
  "description": "Launch an autonomous AI runtime with triple-nested VM isolation in one command",
5
5
  "type": "module",
6
6
  "bin": {