buildwithnexus 0.2.2 → 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.2 \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,18 +535,22 @@ 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`,
516
- "-nographic",
538
+ `file=${initIsoPath},if=virtio,format=raw,cache=writethrough`,
539
+ "-display",
540
+ "none",
541
+ "-serial",
542
+ "none",
517
543
  "-net",
518
544
  "nic,model=virtio",
519
545
  "-net",
520
- `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`,
521
547
  ...biosArgs,
522
548
  "-pidfile",
523
549
  PID_FILE,
524
550
  "-daemonize"
525
551
  ];
526
552
  await execa(platform.qemuBinary, args, { env: scrubEnv() });
553
+ return resolved;
527
554
  }
528
555
  function readValidPid() {
529
556
  if (!fs3.existsSync(PID_FILE)) return null;
@@ -977,12 +1004,17 @@ var initCommand = new Command("init").description("Scaffold and launch a new NEX
977
1004
  spinner = createSpinner("Creating disk and launching VM...");
978
1005
  spinner.start();
979
1006
  const diskPath = await createDisk(imagePath, config.vmDisk);
980
- await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
1007
+ const resolvedPorts = await launchVm(platform, diskPath, isoPath, config.vmRam, config.vmCpus, {
981
1008
  ssh: config.sshPort,
982
1009
  http: config.httpPort,
983
1010
  https: config.httpsPort
984
1011
  });
985
- 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}`);
986
1018
  showPhase(7, TOTAL_PHASES, "VM Provisioning");
987
1019
  spinner = createSpinner("Waiting for SSH...");
988
1020
  spinner.start();
@@ -1224,9 +1256,9 @@ var doctorCommand = new Command5("doctor").description("Diagnose NEXUS runtime e
1224
1256
  if (config) {
1225
1257
  for (const [name, port] of [["SSH", config.sshPort], ["HTTP", config.httpPort], ["HTTPS", config.httpsPort]]) {
1226
1258
  try {
1227
- const net = await import("net");
1259
+ const net2 = await import("net");
1228
1260
  const available = await new Promise((resolve) => {
1229
- const server = net.createServer();
1261
+ const server = net2.createServer();
1230
1262
  server.once("error", () => resolve(false));
1231
1263
  server.once("listening", () => {
1232
1264
  server.close();
@@ -1591,7 +1623,7 @@ var brainstormCommand = new Command11("brainstorm").description("Brainstorm an i
1591
1623
  });
1592
1624
 
1593
1625
  // src/cli.ts
1594
- var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.2");
1626
+ var cli = new Command12().name("buildwithnexus").description("Auto-scaffold and launch a fully autonomous NEXUS runtime").version("0.2.4");
1595
1627
  cli.addCommand(initCommand);
1596
1628
  cli.addCommand(startCommand);
1597
1629
  cli.addCommand(stopCommand);
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "buildwithnexus",
3
- "version": "0.2.2",
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": {