@novastorm-ai/cli 0.0.9 → 0.1.1

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/nova.js CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  run
4
- } from "../chunk-FPLZAHAV.js";
5
- import "../chunk-4AQQAQBM.js";
4
+ } from "../chunk-4EPZMOY6.js";
5
+ import "../chunk-KE7XWO5N.js";
6
6
  import "../chunk-QKD6A4EK.js";
7
7
  import "../chunk-KKTDQOQX.js";
8
8
  import "../chunk-3RG5ZIWI.js";
@@ -2,7 +2,7 @@ import {
2
2
  DevServerRunner,
3
3
  ProxyServer,
4
4
  WebSocketServer
5
- } from "./chunk-4AQQAQBM.js";
5
+ } from "./chunk-KE7XWO5N.js";
6
6
  import {
7
7
  ConfigReader,
8
8
  runSetup
@@ -916,6 +916,15 @@ async function startCommand() {
916
916
  const devServer = new DevServerRunner();
917
917
  const proxyServer = new ProxyServer();
918
918
  const wsServer = new WebSocketServer();
919
+ let earlyExit = true;
920
+ process.on("SIGINT", () => {
921
+ if (earlyExit) {
922
+ console.log(chalk6.dim("\nShutting down..."));
923
+ devServer.kill().catch(() => {
924
+ });
925
+ process.exit(0);
926
+ }
927
+ });
919
928
  const licenseChecker = new LicenseChecker();
920
929
  const indexer = new ProjectIndexer();
921
930
  const logger = new NovaLogger();
@@ -955,7 +964,7 @@ async function startCommand() {
955
964
  projectHash = createHash2("sha256").update(cwd).digest("hex");
956
965
  }
957
966
  const telemetry = new Telemetry();
958
- const cliPkg = await import("./package-RIMA2PN2.js").catch(
967
+ const cliPkg = await import("./package-XCCIIMWT.js").catch(
959
968
  () => ({ default: { version: "0.0.1" } })
960
969
  );
961
970
  telemetry.send({
@@ -1032,7 +1041,7 @@ ${nudgeMessage}
1032
1041
  }
1033
1042
  spinner.succeed("Project indexed.");
1034
1043
  const { ProjectAnalyzer, RagIndexer, createEmbeddingService } = await import("./dist-EMATXD3M.js");
1035
- const { ProjectMapApi } = await import("./dist-6FOBVQ63.js");
1044
+ const { ProjectMapApi } = await import("./dist-5FLNK6MH.js");
1036
1045
  const projectAnalyzer = new ProjectAnalyzer();
1037
1046
  spinner.start("Analyzing project structure...");
1038
1047
  const analysis = await projectAnalyzer.analyze(cwd, projectMap);
@@ -1075,7 +1084,7 @@ ${nudgeMessage}
1075
1084
  ragIndexer = null;
1076
1085
  }
1077
1086
  const projectMapApi = new ProjectMapApi();
1078
- const proxyPort = devPort + PROXY_PORT_OFFSET;
1087
+ let proxyPort = devPort + PROXY_PORT_OFFSET;
1079
1088
  spinner.start("Checking ports...");
1080
1089
  const devPortBusy = await isPortInUse(devPort);
1081
1090
  const proxyPortBusy = await isPortInUse(proxyPort);
@@ -1100,9 +1109,23 @@ ${nudgeMessage}
1100
1109
  await devServer.spawn(devCommand, cwd, devPort);
1101
1110
  } catch (err) {
1102
1111
  spinner.fail("Dev server failed to start.");
1103
- throw err;
1112
+ const msg = err instanceof Error ? err.message : String(err);
1113
+ console.log(chalk6.red(`
1114
+ ${msg}`));
1115
+ console.log(chalk6.gray(`
1116
+ Tips:`));
1117
+ console.log(chalk6.gray(` \u2022 Kill existing process: ${chalk6.cyan(`lsof -ti :${devPort} | xargs kill`)}`));
1118
+ console.log(chalk6.gray(` \u2022 Change port in nova.toml: ${chalk6.cyan(`port = ${devPort + 10}`)}`));
1119
+ process.exit(1);
1120
+ }
1121
+ const actualPort = devServer.getActualPort();
1122
+ if (actualPort && actualPort !== devPort) {
1123
+ spinner.succeed(`Dev server started on port ${chalk6.yellow(actualPort)} (requested ${devPort})`);
1124
+ devPort = actualPort;
1125
+ proxyPort = devPort + PROXY_PORT_OFFSET;
1126
+ } else {
1127
+ spinner.succeed("Dev server started");
1104
1128
  }
1105
- spinner.succeed("Starting dev server... done");
1106
1129
  spinner.start("Starting proxy server...");
1107
1130
  try {
1108
1131
  await proxyServer.start(devPort, proxyPort, OVERLAY_SCRIPT_PATH);
@@ -1537,6 +1560,7 @@ Dev server error: ${error}`));
1537
1560
  }
1538
1561
  });
1539
1562
  chat.start();
1563
+ earlyExit = false;
1540
1564
  process.on("SIGINT", () => {
1541
1565
  shutdown().catch(() => process.exit(1));
1542
1566
  });
@@ -288,6 +288,15 @@ var WebSocketServer = class {
288
288
  };
289
289
  var POLL_INTERVAL_MS = 500;
290
290
  var MAX_WAIT_MS = 3e4;
291
+ var ERROR_PATTERNS = [
292
+ /port \d+ is in use/i,
293
+ /EADDRINUSE/i,
294
+ /already running/i,
295
+ /address already in use/i,
296
+ /failed to start/i,
297
+ /error:/i
298
+ ];
299
+ var PORT_REDIRECT_PATTERN = /(?:using (?:available )?port|listening on|Local:\s+http:\/\/\S+:)(\d+)/i;
291
300
  var DevServerRunner = class {
292
301
  process = null;
293
302
  logs = [];
@@ -295,30 +304,39 @@ var DevServerRunner = class {
295
304
  readyHandler = null;
296
305
  errorHandler = null;
297
306
  outputHandlers = [];
307
+ detectedPort = null;
308
+ startupError = null;
298
309
  async spawn(command, cwd, port) {
299
310
  const [cmd, ...args] = command.split(" ");
300
311
  this.process = spawn(cmd, args, {
301
312
  cwd,
302
313
  shell: true,
303
314
  stdio: ["ignore", "pipe", "pipe"],
304
- env: { ...process.env }
315
+ env: { ...process.env, PORT: String(port) }
305
316
  });
306
317
  this.running = true;
307
318
  this.logs = [];
308
- this.process.stdout?.on("data", (data) => {
319
+ this.detectedPort = null;
320
+ this.startupError = null;
321
+ const handleOutput = (data) => {
309
322
  const text = data.toString();
310
323
  this.logs.push(text);
311
- for (const handler of this.outputHandlers) {
312
- handler(text);
324
+ const portMatch = PORT_REDIRECT_PATTERN.exec(text);
325
+ if (portMatch) {
326
+ this.detectedPort = parseInt(portMatch[1], 10);
327
+ }
328
+ for (const pattern of ERROR_PATTERNS) {
329
+ if (pattern.test(text)) {
330
+ this.startupError = text.trim();
331
+ break;
332
+ }
313
333
  }
314
- });
315
- this.process.stderr?.on("data", (data) => {
316
- const text = data.toString();
317
- this.logs.push(text);
318
334
  for (const handler of this.outputHandlers) {
319
335
  handler(text);
320
336
  }
321
- });
337
+ };
338
+ this.process.stdout?.on("data", handleOutput);
339
+ this.process.stderr?.on("data", handleOutput);
322
340
  this.process.on("exit", (code, signal) => {
323
341
  this.running = false;
324
342
  if (code !== 0 && code !== null) {
@@ -335,6 +353,12 @@ var DevServerRunner = class {
335
353
  });
336
354
  await this.pollUntilReady(port);
337
355
  }
356
+ getActualPort() {
357
+ return this.detectedPort;
358
+ }
359
+ getStartupError() {
360
+ return this.startupError;
361
+ }
338
362
  onReady(handler) {
339
363
  this.readyHandler = handler;
340
364
  }
@@ -375,40 +399,72 @@ var DevServerRunner = class {
375
399
  if (!this.running) {
376
400
  reject(
377
401
  new Error(
378
- `Dev server process exited before becoming ready. Logs:
402
+ `Dev server process exited before becoming ready.
403
+
379
404
  ${this.getLogs()}`
380
405
  )
381
406
  );
382
407
  return;
383
408
  }
384
- const tryConnect = (host, fallback) => {
385
- const req = http2.get(
386
- `http://${host}:${port}`,
387
- (res) => {
388
- res.resume();
389
- this.readyHandler?.();
390
- resolve();
391
- }
409
+ if (this.startupError) {
410
+ reject(
411
+ new Error(
412
+ `Dev server error:
413
+
414
+ ${this.startupError}`
415
+ )
392
416
  );
393
- req.on("error", () => {
394
- if (fallback) {
395
- tryConnect(fallback);
396
- return;
397
- }
398
- if (Date.now() - startTime >= MAX_WAIT_MS) {
399
- reject(
400
- new Error(
401
- `Dev server did not become ready within ${MAX_WAIT_MS / 1e3}s. Logs:
417
+ return;
418
+ }
419
+ const portsToTry = [port];
420
+ if (this.detectedPort && this.detectedPort !== port) {
421
+ portsToTry.push(this.detectedPort);
422
+ }
423
+ let remaining = portsToTry.length;
424
+ let resolved = false;
425
+ for (const tryPort of portsToTry) {
426
+ const tryConnect = (host, fallback) => {
427
+ if (resolved) return;
428
+ const req = http2.get(
429
+ `http://${host}:${tryPort}`,
430
+ (res) => {
431
+ res.resume();
432
+ if (!resolved) {
433
+ resolved = true;
434
+ if (tryPort !== port) {
435
+ this.detectedPort = tryPort;
436
+ }
437
+ this.readyHandler?.();
438
+ resolve();
439
+ }
440
+ }
441
+ );
442
+ req.on("error", () => {
443
+ if (resolved) return;
444
+ if (fallback) {
445
+ tryConnect(fallback);
446
+ return;
447
+ }
448
+ remaining--;
449
+ if (remaining <= 0) {
450
+ if (Date.now() - startTime >= MAX_WAIT_MS) {
451
+ reject(
452
+ new Error(
453
+ `Dev server did not become ready within ${MAX_WAIT_MS / 1e3}s.
454
+
455
+ Server output:
402
456
  ${this.getLogs()}`
403
- )
404
- );
405
- return;
406
- }
407
- setTimeout(check, POLL_INTERVAL_MS);
408
- });
409
- req.end();
410
- };
411
- tryConnect("127.0.0.1", "[::1]");
457
+ )
458
+ );
459
+ return;
460
+ }
461
+ setTimeout(check, POLL_INTERVAL_MS);
462
+ }
463
+ });
464
+ req.end();
465
+ };
466
+ tryConnect("127.0.0.1", "[::1]");
467
+ }
412
468
  };
413
469
  check();
414
470
  });
@@ -3,7 +3,7 @@ import {
3
3
  ProjectMapApi,
4
4
  ProxyServer,
5
5
  WebSocketServer
6
- } from "./chunk-4AQQAQBM.js";
6
+ } from "./chunk-KE7XWO5N.js";
7
7
  import "./chunk-3RG5ZIWI.js";
8
8
  export {
9
9
  DevServerRunner,
package/dist/index.js CHANGED
@@ -4,8 +4,8 @@ import {
4
4
  createCli,
5
5
  promptAndScaffold,
6
6
  run
7
- } from "./chunk-FPLZAHAV.js";
8
- import "./chunk-4AQQAQBM.js";
7
+ } from "./chunk-4EPZMOY6.js";
8
+ import "./chunk-KE7XWO5N.js";
9
9
  import {
10
10
  ConfigReader,
11
11
  runSetup
@@ -4,7 +4,7 @@ import "./chunk-3RG5ZIWI.js";
4
4
  var package_default = {
5
5
  name: "@novastorm-ai/cli",
6
6
  publishConfig: { access: "public" },
7
- version: "0.0.9",
7
+ version: "0.1.1",
8
8
  license: "SEE LICENSE IN LICENSE.md",
9
9
  type: "module",
10
10
  main: "dist/index.js",
package/package.json CHANGED
@@ -3,7 +3,7 @@
3
3
  "publishConfig": {
4
4
  "access": "public"
5
5
  },
6
- "version": "0.0.9",
6
+ "version": "0.1.1",
7
7
  "license": "SEE LICENSE IN LICENSE.md",
8
8
  "type": "module",
9
9
  "main": "dist/index.js",
@@ -35,9 +35,9 @@
35
35
  "devDependencies": {
36
36
  "tsup": "^8.4.0",
37
37
  "typescript": "^5.7.0",
38
- "@novastorm-ai/core": "0.0.1",
38
+ "@novastorm-ai/licensing": "0.0.1",
39
39
  "@novastorm-ai/proxy": "0.0.1",
40
- "@novastorm-ai/licensing": "0.0.1"
40
+ "@novastorm-ai/core": "0.0.1"
41
41
  },
42
42
  "scripts": {
43
43
  "build": "tsup",