buildwithnexus 0.2.3 → 0.2.4

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.4 \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,29 @@ 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 isPortFree(port) {
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, "127.0.0.1");
511
+ });
512
+ }
513
+ async function findFreePort(preferred, max = 20) {
514
+ for (let offset = 0; offset < max; offset++) {
515
+ const port = preferred + offset;
516
+ if (await isPortFree(port)) return port;
517
+ }
518
+ throw new Error(`No free port found near ${preferred}`);
519
+ }
502
520
  async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
521
+ const resolved = {
522
+ ssh: await findFreePort(ports.ssh),
523
+ http: await findFreePort(ports.http),
524
+ https: await findFreePort(ports.https)
525
+ };
503
526
  const machineArg = platform.os === "mac" ? "-machine virt,gic-version=3" : "-machine pc";
504
527
  const biosArgs = fs3.existsSync(platform.biosPath) ? ["-bios", platform.biosPath] : [];
505
528
  const args = [
@@ -512,7 +535,7 @@ async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
512
535
  "-drive",
513
536
  `file=${diskPath},if=virtio,cache=writethrough`,
514
537
  "-drive",
515
- `file=${initIsoPath},if=virtio,cache=writethrough`,
538
+ `file=${initIsoPath},if=virtio,format=raw,cache=writethrough`,
516
539
  "-display",
517
540
  "none",
518
541
  "-serial",
@@ -520,13 +543,14 @@ async function launchVm(platform, diskPath, initIsoPath, ram, cpus, ports) {
520
543
  "-net",
521
544
  "nic,model=virtio",
522
545
  "-net",
523
- `user,hostfwd=tcp::${ports.ssh}-:22,hostfwd=tcp::${ports.http}-:4200,hostfwd=tcp::${ports.https}-:443`,
546
+ `user,hostfwd=tcp::${resolved.ssh}-:22,hostfwd=tcp::${resolved.http}-:4200,hostfwd=tcp::${resolved.https}-:443`,
524
547
  ...biosArgs,
525
548
  "-pidfile",
526
549
  PID_FILE,
527
550
  "-daemonize"
528
551
  ];
529
552
  await execa(platform.qemuBinary, args, { env: scrubEnv() });
553
+ return resolved;
530
554
  }
531
555
  function readValidPid() {
532
556
  if (!fs3.existsSync(PID_FILE)) return null;
@@ -980,12 +1004,17 @@ var initCommand = new Command("init").description("Scaffold and launch a new NEX
980
1004
  spinner = createSpinner("Creating disk and launching VM...");
981
1005
  spinner.start();
982
1006
  const diskPath = await createDisk(imagePath, config.vmDisk);
983
- await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
1007
+ const resolvedPorts = await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
984
1008
  ssh: config.sshPort,
985
1009
  http: config.httpPort,
986
1010
  https: config.httpsPort
987
1011
  });
988
- succeed(spinner, "VM launched (daemonized)");
1012
+ config.sshPort = resolvedPorts.ssh;
1013
+ config.httpPort = resolvedPorts.http;
1014
+ config.httpsPort = resolvedPorts.https;
1015
+ saveConfig(config);
1016
+ const portNote = resolvedPorts.ssh !== 2222 || resolvedPorts.http !== 4200 || resolvedPorts.https !== 8443 ? ` (ports: SSH=${resolvedPorts.ssh}, HTTP=${resolvedPorts.http}, HTTPS=${resolvedPorts.https})` : "";
1017
+ succeed(spinner, `VM launched (daemonized)${portNote}`);
989
1018
  showPhase(7, TOTAL_PHASES, "VM Provisioning");
990
1019
  spinner = createSpinner("Waiting for SSH...");
991
1020
  spinner.start();
@@ -1227,9 +1256,9 @@ var doctorCommand = new Command5("doctor").description("Diagnose NEXUS runtime e
1227
1256
  if (config) {
1228
1257
  for (const [name, port] of [["SSH", config.sshPort], ["HTTP", config.httpPort], ["HTTPS", config.httpsPort]]) {
1229
1258
  try {
1230
- const net = await import("net");
1259
+ const net2 = await import("net");
1231
1260
  const available = await new Promise((resolve) => {
1232
- const server = net.createServer();
1261
+ const server = net2.createServer();
1233
1262
  server.once("error", () => resolve(false));
1234
1263
  server.once("listening", () => {
1235
1264
  server.close();
@@ -1594,7 +1623,7 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1594
1623
  });
1595
1624
 
1596
1625
  // src/cli.ts
1597
- var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.3");
1626
+ var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.4");
1598
1627
  cli.addCommand(initCommand);
1599
1628
  cli.addCommand(startCommand);
1600
1629
  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.4",
4
4
  "description": "Launch an autonomous AI runtime with triple-nested VM isolation in one command",
5
5
  "type": "module",
6
6
  "bin": {