@lunaroute/cli 0.2.2 → 0.2.3

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.
Files changed (2) hide show
  1. package/dist/index.js +65 -58
  2. package/package.json +3 -1
package/dist/index.js CHANGED
@@ -4,7 +4,7 @@
4
4
  import { Command, InvalidArgumentError, Option } from "commander";
5
5
 
6
6
  // package.json
7
- var version = "0.2.2";
7
+ var version = "0.2.3";
8
8
 
9
9
  // src/login.ts
10
10
  import { createServer } from "http";
@@ -536,8 +536,31 @@ async function promptInput(question, opts = {}) {
536
536
  return value === "" && opts.default !== void 0 ? opts.default : value;
537
537
  }
538
538
 
539
- // src/commands/setup.ts
540
- import { spawn } from "child_process";
539
+ // src/spawn.ts
540
+ import { spawn as nodeSpawn } from "child_process";
541
+ import { spawn as crossSpawn } from "cross-spawn";
542
+ function makeRealSpawn(platform = process.platform) {
543
+ if (platform === "win32") {
544
+ return (command, args, env) => crossSpawn(command, args, { stdio: "inherit", env });
545
+ }
546
+ return (command, args, env) => nodeSpawn(command, args, { stdio: "inherit", env });
547
+ }
548
+ function describeSpawnError(command, installHint, err) {
549
+ const code = err?.code;
550
+ if (code === "ENOENT") {
551
+ return {
552
+ message: `Error: "${command}" not found on PATH. ${installHint} (exit 127)`,
553
+ exitCode: 127
554
+ };
555
+ }
556
+ if (code === "EINVAL") {
557
+ return {
558
+ message: `Error: "${command}" could not be launched \u2014 Node on Windows refuses to execute npm .cmd shims directly (EINVAL). The tool is likely installed; try running it manually. (exit 126)`,
559
+ exitCode: 126
560
+ };
561
+ }
562
+ return { message: err instanceof Error ? err.message : String(err), exitCode: 1 };
563
+ }
541
564
 
542
565
  // src/setup/paths.ts
543
566
  import { execSync } from "child_process";
@@ -885,7 +908,7 @@ var ADAPTERS = {
885
908
  var PI_INSTALL_PACKAGES = ["npm:@lunaroute/pi-extension", "npm:pi-mcp-adapter"];
886
909
  async function runSetup(harness, opts, deps = {
887
910
  confirm,
888
- spawn: (command, args) => spawn(command, args, { stdio: "inherit" }),
911
+ spawn: makeRealSpawn(),
889
912
  runLogin
890
913
  }) {
891
914
  if (harness === "pi" && opts.extension && opts.models) {
@@ -1075,23 +1098,20 @@ function hermesConfigSetArgs(routingUrl, key) {
1075
1098
  ["config", "set", "LUNAROUTE_API_KEY", key]
1076
1099
  ];
1077
1100
  }
1078
- async function runHermesConfigSets(spawn3, routingUrl, key) {
1101
+ async function runHermesConfigSets(spawn, routingUrl, key) {
1079
1102
  const commands = hermesConfigSetArgs(routingUrl, key);
1080
1103
  const setKeys = commands.map((c) => c[2]);
1081
1104
  for (let i = 0; i < commands.length; i++) {
1082
1105
  const code = await new Promise((resolve) => {
1083
- const child = spawn3("hermes", commands[i]);
1106
+ const child = spawn("hermes", commands[i]);
1084
1107
  child.on("error", (err) => {
1085
- const e = err;
1086
- if (e?.code === "ENOENT") {
1087
- console.error(
1088
- `Error: "hermes" not found on PATH. Install Hermes Agent first: https://hermes-agent.nousresearch.com (exit 127)`
1089
- );
1090
- resolve(127);
1091
- return;
1092
- }
1093
- console.error(err instanceof Error ? err.message : String(err));
1094
- resolve(1);
1108
+ const { message, exitCode } = describeSpawnError(
1109
+ "hermes",
1110
+ "Install Hermes Agent first: https://hermes-agent.nousresearch.com",
1111
+ err
1112
+ );
1113
+ console.error(message);
1114
+ resolve(exitCode);
1095
1115
  });
1096
1116
  child.on("exit", (code2) => {
1097
1117
  resolve(typeof code2 === "number" ? code2 : 1);
@@ -1185,18 +1205,17 @@ Wrote: ${summary.written.join(", ")}`);
1185
1205
  return 1;
1186
1206
  }
1187
1207
  }
1188
- async function launchOpencode(spawn3) {
1208
+ async function launchOpencode(spawn) {
1189
1209
  return new Promise((resolve) => {
1190
- const child = spawn3("opencode", []);
1210
+ const child = spawn("opencode", []);
1191
1211
  child.on("error", (err) => {
1192
- const e = err;
1193
- if (e?.code === "ENOENT") {
1194
- console.error(`Error: "opencode" not found on PATH. Install OpenCode first: https://opencode.ai (exit 127)`);
1195
- resolve(127);
1196
- return;
1197
- }
1198
- console.error(err instanceof Error ? err.message : String(err));
1199
- resolve(1);
1212
+ const { message, exitCode } = describeSpawnError(
1213
+ "opencode",
1214
+ "Install OpenCode first: https://opencode.ai",
1215
+ err
1216
+ );
1217
+ console.error(message);
1218
+ resolve(exitCode);
1200
1219
  });
1201
1220
  child.on("exit", (code) => {
1202
1221
  resolve(typeof code === "number" ? code : 1);
@@ -1208,14 +1227,13 @@ async function installPiExtension(deps, opts) {
1208
1227
  const code = await new Promise((resolve) => {
1209
1228
  const child = deps.spawn("pi", ["install", pkg]);
1210
1229
  child.on("error", (err) => {
1211
- const e = err;
1212
- if (e?.code === "ENOENT") {
1213
- console.error(`Error: "pi" not found on PATH. Install pi first: https://pi.dev (exit 127)`);
1214
- resolve(127);
1215
- return;
1216
- }
1217
- console.error(err instanceof Error ? err.message : String(err));
1218
- resolve(1);
1230
+ const { message, exitCode } = describeSpawnError(
1231
+ "pi",
1232
+ "Install pi first: https://pi.dev",
1233
+ err
1234
+ );
1235
+ console.error(message);
1236
+ resolve(exitCode);
1219
1237
  });
1220
1238
  child.on("exit", (code2) => {
1221
1239
  resolve(typeof code2 === "number" ? code2 : 1);
@@ -1237,18 +1255,17 @@ async function installPiExtension(deps, opts) {
1237
1255
  console.log(" 2. /model \u2014 pick a lunaroute/* model (models auto-sync from /v1/models).");
1238
1256
  return 0;
1239
1257
  }
1240
- async function launchPi(spawn3) {
1258
+ async function launchPi(spawn) {
1241
1259
  return new Promise((resolve) => {
1242
- const child = spawn3("pi", []);
1260
+ const child = spawn("pi", []);
1243
1261
  child.on("error", (err) => {
1244
- const e = err;
1245
- if (e?.code === "ENOENT") {
1246
- console.error(`Error: "pi" not found on PATH. Install pi first: https://pi.dev (exit 127)`);
1247
- resolve(127);
1248
- return;
1249
- }
1250
- console.error(err instanceof Error ? err.message : String(err));
1251
- resolve(1);
1262
+ const { message, exitCode } = describeSpawnError(
1263
+ "pi",
1264
+ "Install pi first: https://pi.dev",
1265
+ err
1266
+ );
1267
+ console.error(message);
1268
+ resolve(exitCode);
1252
1269
  });
1253
1270
  child.on("exit", (code) => {
1254
1271
  resolve(typeof code === "number" ? code : 1);
@@ -1791,9 +1808,6 @@ async function runSkillInstall(profile, opts) {
1791
1808
  return 0;
1792
1809
  }
1793
1810
 
1794
- // src/commands/run.ts
1795
- import { spawn as spawn2 } from "child_process";
1796
-
1797
1811
  // src/run/adapters/claudeCode.ts
1798
1812
  function buildRunSpec(ctx) {
1799
1813
  return {
@@ -1840,7 +1854,7 @@ var INSTALL_HINT = {
1840
1854
  codex: "Install Codex: https://github.com/openai/codex#install"
1841
1855
  };
1842
1856
  var realDeps = {
1843
- spawn: (command, args, env) => spawn2(command, args, { env, stdio: "inherit" }),
1857
+ spawn: makeRealSpawn(),
1844
1858
  fetchModels
1845
1859
  };
1846
1860
  async function runRun(harness, opts, deps = realDeps) {
@@ -1880,16 +1894,9 @@ async function runRun(harness, opts, deps = realDeps) {
1880
1894
  const child = deps.spawn(spec.command, args, env);
1881
1895
  return new Promise((resolve) => {
1882
1896
  child.on("error", (err) => {
1883
- const e = err;
1884
- if (e?.code === "ENOENT") {
1885
- console.error(
1886
- `Error: "${spec.command}" not found on PATH. ${INSTALL_HINT[harness]} (exit 127)`
1887
- );
1888
- resolve(127);
1889
- return;
1890
- }
1891
- console.error(err instanceof Error ? err.message : String(err));
1892
- resolve(1);
1897
+ const { message, exitCode } = describeSpawnError(spec.command, INSTALL_HINT[harness], err);
1898
+ console.error(message);
1899
+ resolve(exitCode);
1893
1900
  });
1894
1901
  child.on("exit", (code) => {
1895
1902
  resolve(typeof code === "number" ? code : 1);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lunaroute/cli",
3
- "version": "0.2.2",
3
+ "version": "0.2.3",
4
4
  "description": "LunaRoute CLI — configure coding harnesses and manage your LunaRoute account.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -30,10 +30,12 @@
30
30
  "dependencies": {
31
31
  "@modelcontextprotocol/sdk": "^1.30.0",
32
32
  "commander": "^15.0.0",
33
+ "cross-spawn": "^7.0.6",
33
34
  "open": "^11.0.1",
34
35
  "zod": "^4.4.3"
35
36
  },
36
37
  "devDependencies": {
38
+ "@types/cross-spawn": "^6.0.6",
37
39
  "@types/node": "^26.2.0",
38
40
  "tsup": "^8.3.0",
39
41
  "tsx": "^4.23.12",