@jentrix/cli 0.5.6 → 0.5.7

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/main.js +118 -57
  2. package/package.json +1 -1
package/dist/main.js CHANGED
@@ -6418,7 +6418,7 @@ var require_compile = __commonJS({
6418
6418
  const schOrFunc = root.refs[ref];
6419
6419
  if (schOrFunc)
6420
6420
  return schOrFunc;
6421
- let _sch = resolve4.call(this, root, ref);
6421
+ let _sch = resolve5.call(this, root, ref);
6422
6422
  if (_sch === void 0) {
6423
6423
  const schema = (_a3 = root.localRefs) === null || _a3 === void 0 ? void 0 : _a3[ref];
6424
6424
  const { schemaId } = this.opts;
@@ -6445,7 +6445,7 @@ var require_compile = __commonJS({
6445
6445
  function sameSchemaEnv(s1, s2) {
6446
6446
  return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
6447
6447
  }
6448
- function resolve4(root, ref) {
6448
+ function resolve5(root, ref) {
6449
6449
  let sch;
6450
6450
  while (typeof (sch = this.refs[ref]) == "string")
6451
6451
  ref = sch;
@@ -7076,7 +7076,7 @@ var require_fast_uri = __commonJS({
7076
7076
  }
7077
7077
  return uri;
7078
7078
  }
7079
- function resolve4(baseURI, relativeURI, options) {
7079
+ function resolve5(baseURI, relativeURI, options) {
7080
7080
  const schemelessOptions = options ? Object.assign({ scheme: "null" }, options) : { scheme: "null" };
7081
7081
  const resolved = resolveComponent(parse3(baseURI, schemelessOptions), parse3(relativeURI, schemelessOptions), schemelessOptions, true);
7082
7082
  schemelessOptions.skipEscape = true;
@@ -7334,7 +7334,7 @@ var require_fast_uri = __commonJS({
7334
7334
  var fastUri = {
7335
7335
  SCHEMES,
7336
7336
  normalize,
7337
- resolve: resolve4,
7337
+ resolve: resolve5,
7338
7338
  resolveComponent,
7339
7339
  equal,
7340
7340
  serialize,
@@ -10337,7 +10337,7 @@ import {
10337
10337
  statSync as statSync3
10338
10338
  } from "node:fs";
10339
10339
  import { homedir } from "node:os";
10340
- import { basename as basename2, dirname as dirname4, join as join6 } from "node:path";
10340
+ import { basename as basename2, delimiter as delimiter2, dirname as dirname4, join as join6, resolve as resolve4 } from "node:path";
10341
10341
  import { fileURLToPath } from "node:url";
10342
10342
 
10343
10343
  // node_modules/.pnpm/commander@14.0.3/node_modules/commander/esm.mjs
@@ -17873,7 +17873,7 @@ var Protocol = class {
17873
17873
  return;
17874
17874
  }
17875
17875
  const pollInterval = task2.pollInterval ?? this._options?.defaultTaskPollInterval ?? 1e3;
17876
- await new Promise((resolve4) => setTimeout(resolve4, pollInterval));
17876
+ await new Promise((resolve5) => setTimeout(resolve5, pollInterval));
17877
17877
  options?.signal?.throwIfAborted();
17878
17878
  }
17879
17879
  } catch (error2) {
@@ -17890,7 +17890,7 @@ var Protocol = class {
17890
17890
  */
17891
17891
  request(request, resultSchema, options) {
17892
17892
  const { relatedRequestId, resumptionToken, onresumptiontoken, task, relatedTask } = options ?? {};
17893
- return new Promise((resolve4, reject) => {
17893
+ return new Promise((resolve5, reject) => {
17894
17894
  const earlyReject = (error2) => {
17895
17895
  reject(error2);
17896
17896
  };
@@ -17968,7 +17968,7 @@ var Protocol = class {
17968
17968
  if (!parseResult.success) {
17969
17969
  reject(parseResult.error);
17970
17970
  } else {
17971
- resolve4(parseResult.data);
17971
+ resolve5(parseResult.data);
17972
17972
  }
17973
17973
  } catch (error2) {
17974
17974
  reject(error2);
@@ -18229,12 +18229,12 @@ var Protocol = class {
18229
18229
  }
18230
18230
  } catch {
18231
18231
  }
18232
- return new Promise((resolve4, reject) => {
18232
+ return new Promise((resolve5, reject) => {
18233
18233
  if (signal.aborted) {
18234
18234
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
18235
18235
  return;
18236
18236
  }
18237
- const timeoutId = setTimeout(resolve4, interval);
18237
+ const timeoutId = setTimeout(resolve5, interval);
18238
18238
  signal.addEventListener("abort", () => {
18239
18239
  clearTimeout(timeoutId);
18240
18240
  reject(new McpError(ErrorCode.InvalidRequest, "Request cancelled"));
@@ -20962,7 +20962,7 @@ function refreshAccessToken(input) {
20962
20962
 
20963
20963
  // src/client.ts
20964
20964
  var CLI_NAME = "stacks-cli";
20965
- var CLI_VERSION = "0.5.6";
20965
+ var CLI_VERSION = "0.5.7";
20966
20966
  var DEAD_TOKEN_MESSAGE = "authentication failed (HTTP 401): the token is dead or expired \u2014 mint a new PAT at /account/tokens on your Jentrix server and update STACKS_TOKEN (or --token / the config file).";
20967
20967
  var RELOGIN_MESSAGE = "OAuth session expired and could not be refreshed \u2014 run `jentrix login` to sign in again.";
20968
20968
  function originOf2(url2) {
@@ -21130,7 +21130,7 @@ function escapeHtml(s) {
21130
21130
  );
21131
21131
  }
21132
21132
  function tryBindPort(port, timeoutMs = CALLBACK_TIMEOUT_MS) {
21133
- return new Promise((resolve4) => {
21133
+ return new Promise((resolve5) => {
21134
21134
  let settleCode = null;
21135
21135
  let rejectCode = null;
21136
21136
  let timer = null;
@@ -21155,9 +21155,9 @@ function tryBindPort(port, timeoutMs = CALLBACK_TIMEOUT_MS) {
21155
21155
  rejectCode?.(new Error("callback had no authorization code"));
21156
21156
  else settleCode?.({ code, state: url2.searchParams.get("state") });
21157
21157
  });
21158
- server.once("error", () => resolve4(null));
21158
+ server.once("error", () => resolve5(null));
21159
21159
  server.listen(port, LOOPBACK_HOST, () => {
21160
- resolve4({
21160
+ resolve5({
21161
21161
  port,
21162
21162
  waitForCode: () => new Promise((res, rej) => {
21163
21163
  settleCode = res;
@@ -21184,17 +21184,17 @@ async function bindLoopback(ports, timeoutMs = CALLBACK_TIMEOUT_MS) {
21184
21184
  return null;
21185
21185
  }
21186
21186
  function openBrowser(url2) {
21187
- return new Promise((resolve4) => {
21187
+ return new Promise((resolve5) => {
21188
21188
  const os = platform();
21189
21189
  const cmd = os === "darwin" ? "open" : os === "win32" ? "cmd" : "xdg-open";
21190
21190
  const args = os === "win32" ? ["/c", "start", "", url2] : [url2];
21191
21191
  try {
21192
21192
  const child = spawn(cmd, args, { stdio: "ignore", detached: true });
21193
- child.on("error", () => resolve4());
21193
+ child.on("error", () => resolve5());
21194
21194
  child.unref();
21195
21195
  } catch {
21196
21196
  }
21197
- resolve4();
21197
+ resolve5();
21198
21198
  });
21199
21199
  }
21200
21200
 
@@ -21747,13 +21747,13 @@ function normalizeRemoteRepo(url2) {
21747
21747
  if (trimmed.length < 2) return null;
21748
21748
  return `${trimmed[0]}/${trimmed[1]}`.toLowerCase();
21749
21749
  }
21750
- var defaultGitRunner = (args, cwd) => new Promise((resolve4) => {
21750
+ var defaultGitRunner = (args, cwd) => new Promise((resolve5) => {
21751
21751
  execFile(
21752
21752
  "git",
21753
21753
  args,
21754
21754
  { cwd, timeout: 1e4, maxBuffer: 4 * 1024 * 1024, windowsHide: true },
21755
21755
  (error2, stdout) => {
21756
- resolve4({
21756
+ resolve5({
21757
21757
  code: error2 === null ? 0 : typeof error2.code === "number" ? Number(error2.code) : 1,
21758
21758
  stdout: String(stdout)
21759
21759
  });
@@ -27905,9 +27905,12 @@ function say(deps2, text = "") {
27905
27905
  }
27906
27906
  async function installToolchain(deps2) {
27907
27907
  const npm = await deps2.resolveNpm();
27908
- const existing = await deps2.resolveJentrix();
27909
- if (existing) {
27910
- say(deps2, `jentrix ${CLI_VERSION} is already installed (${existing}).`);
27908
+ let global = await deps2.globalInstall();
27909
+ if (global.cliDir) {
27910
+ say(
27911
+ deps2,
27912
+ `jentrix ${CLI_VERSION} is already installed (${global.cliDir}).`
27913
+ );
27911
27914
  say(deps2, " Upgrade it any time with: npm update -g @jentrix/cli");
27912
27915
  } else {
27913
27916
  if (!npm) {
@@ -27934,15 +27937,16 @@ async function installToolchain(deps2) {
27934
27937
  );
27935
27938
  return EXIT_CODES.INTERNAL;
27936
27939
  }
27937
- if (!await deps2.resolveJentrix()) {
27940
+ global = await deps2.globalInstall();
27941
+ if (!global.cliDir) {
27938
27942
  deps2.writeErr(
27939
- "TOOLCHAIN_NOT_ON_PATH: the packages installed but `jentrix` is not resolvable \u2014 add npm's global bin directory (`npm prefix -g`) to PATH, then retry."
27943
+ "TOOLCHAIN_INSTALL_FAILED: npm reported success but @jentrix/cli is not under `npm root -g` \u2014 check npm's global prefix, then retry."
27940
27944
  );
27941
27945
  return EXIT_CODES.INTERNAL;
27942
27946
  }
27943
27947
  say(deps2, "Installed the CLI and the session runner.");
27944
27948
  }
27945
- if (!await deps2.resolveRunner()) {
27949
+ if (!global.runnerDir) {
27946
27950
  if (!npm) {
27947
27951
  deps2.writeErr(
27948
27952
  `RUNNER_NOT_INSTALLED: connected sessions need the runner and npm was not found to install it \u2014 npm install -g ${RUNNER_SPEC2}, then retry.`
@@ -27956,41 +27960,56 @@ async function installToolchain(deps2) {
27956
27960
  void 0,
27957
27961
  NPM_INSTALL_TIMEOUT_MS2
27958
27962
  );
27959
- if (runner.code !== 0 || !await deps2.resolveRunner()) {
27963
+ global = await deps2.globalInstall();
27964
+ if (runner.code !== 0 || !global.runnerDir) {
27960
27965
  deps2.writeErr(
27961
- `RUNNER_NOT_INSTALLED: \`npm install -g ${RUNNER_SPEC2}\` did not leave a resolvable runner \u2014 install it by hand, then retry.`
27966
+ `RUNNER_NOT_INSTALLED: \`npm install -g ${RUNNER_SPEC2}\` did not leave the runner under \`npm root -g\` \u2014 install it by hand, then retry.`
27962
27967
  );
27963
27968
  return EXIT_CODES.INTERNAL;
27964
27969
  }
27965
27970
  }
27966
- return EXIT_CODES.OK;
27967
- }
27968
- async function installRuntimes(deps2) {
27969
- if (await deps2.resolveClaude()) {
27970
- await deps2.installPlugin("claude");
27971
- } else {
27972
- say(deps2, "note: the `claude` CLI is not installed \u2014 skipped its plugin.");
27971
+ if (global.binDir && !global.binDirOnPath) {
27972
+ say(deps2, "");
27973
+ say(deps2, "note: npm's global bin directory is NOT on your PATH \u2014");
27974
+ say(deps2, ` ${global.binDir}`);
27973
27975
  say(
27974
27976
  deps2,
27975
- " Install Claude Code (https://claude.com/claude-code), then run: jentrix plugin install"
27977
+ " The toolchain is installed, but `jentrix` will not be found in a new"
27976
27978
  );
27977
- }
27978
- if (await deps2.resolveCodex()) {
27979
- if (await deps2.installPlugin("codex") !== EXIT_CODES.OK) {
27980
- say(
27981
- deps2,
27982
- "note: `jentrix plugin install codex` did not complete \u2014 retry it after `jentrix login`."
27983
- );
27984
- }
27985
- } else {
27986
27979
  say(
27987
27980
  deps2,
27988
- "note: the `codex` CLI is not installed \u2014 skipped its plugin and MCP server."
27981
+ " terminal until you add that directory to PATH and reopen your shell."
27989
27982
  );
27990
- say(
27991
- deps2,
27983
+ }
27984
+ return EXIT_CODES.OK;
27985
+ }
27986
+ var RUNTIMES = [
27987
+ {
27988
+ provider: "claude",
27989
+ resolve: (deps2) => deps2.resolveClaude(),
27990
+ absent: [
27991
+ "note: the `claude` CLI is not installed \u2014 skipped its plugin.",
27992
+ " Install Claude Code (https://claude.com/claude-code), then run: jentrix plugin install"
27993
+ ]
27994
+ },
27995
+ {
27996
+ provider: "codex",
27997
+ resolve: (deps2) => deps2.resolveCodex(),
27998
+ absent: [
27999
+ "note: the `codex` CLI is not installed \u2014 skipped its plugin and MCP server.",
27992
28000
  " Install Codex (https://developers.openai.com/codex/cli), then re-run this command."
27993
- );
28001
+ ]
28002
+ }
28003
+ ];
28004
+ async function installRuntimes(deps2, pending) {
28005
+ for (const runtime of RUNTIMES) {
28006
+ if (!await runtime.resolve(deps2)) {
28007
+ for (const line of runtime.absent) say(deps2, line);
28008
+ continue;
28009
+ }
28010
+ if (await deps2.installPlugin(runtime.provider) !== EXIT_CODES.OK) {
28011
+ pending.failedPlugins.push(runtime.provider);
28012
+ }
27994
28013
  }
27995
28014
  }
27996
28015
  async function registerCodexMcp(deps2, codex, pending) {
@@ -28118,7 +28137,8 @@ async function runSetupCommand(flags, deps2) {
28118
28137
  }
28119
28138
  const toolchain = await installToolchain(deps2);
28120
28139
  if (toolchain !== EXIT_CODES.OK) return toolchain;
28121
- await installRuntimes(deps2);
28140
+ const pending = { failedPlugins: [] };
28141
+ await installRuntimes(deps2, pending);
28122
28142
  if (!deps2.hasCredential()) {
28123
28143
  if (deps2.isInteractive) {
28124
28144
  say(deps2, "");
@@ -28136,13 +28156,25 @@ async function runSetupCommand(flags, deps2) {
28136
28156
  );
28137
28157
  }
28138
28158
  }
28139
- const pending = {};
28140
28159
  const codex = await deps2.resolveCodex();
28141
28160
  if (codex) await registerCodexMcp(deps2, codex, pending);
28142
28161
  if (flags.git !== false && deps2.isInteractive && deps2.cwd() !== deps2.homeDir()) {
28143
28162
  await bootstrapRepository(deps2);
28144
28163
  }
28145
28164
  say(deps2, "");
28165
+ if (pending.failedPlugins.length) {
28166
+ for (const provider of pending.failedPlugins) {
28167
+ say(
28168
+ deps2,
28169
+ `note: the ${provider} plugin did NOT install \u2014 its commands will be missing.`
28170
+ );
28171
+ say(
28172
+ deps2,
28173
+ ` Run \`jentrix plugin install ${provider}\` on its own to see why.`
28174
+ );
28175
+ }
28176
+ say(deps2, "");
28177
+ }
28146
28178
  say(deps2, "Done. Verify with: jentrix whoami");
28147
28179
  if (pending.codexLoginUrl) {
28148
28180
  say(deps2, "");
@@ -28185,7 +28217,7 @@ async function runSetupCommand(flags, deps2) {
28185
28217
  deps2,
28186
28218
  "(Bind a folder to a different server any time with: jentrix login --local)"
28187
28219
  );
28188
- return EXIT_CODES.OK;
28220
+ return pending.failedPlugins.length ? EXIT_CODES.INTERNAL : EXIT_CODES.OK;
28189
28221
  }
28190
28222
  function registerSetupCommand(program3, deps2, onExit2) {
28191
28223
  return program3.command("setup").description(
@@ -28539,12 +28571,12 @@ function surfaceFileMtime() {
28539
28571
  }
28540
28572
  }
28541
28573
  function readStdin() {
28542
- return new Promise((resolve4, reject) => {
28574
+ return new Promise((resolve5, reject) => {
28543
28575
  const chunks = [];
28544
28576
  process.stdin.on("data", (chunk) => chunks.push(chunk));
28545
28577
  process.stdin.on(
28546
28578
  "end",
28547
- () => resolve4(Buffer.concat(chunks).toString("utf8"))
28579
+ () => resolve5(Buffer.concat(chunks).toString("utf8"))
28548
28580
  );
28549
28581
  process.stdin.on("error", reject);
28550
28582
  });
@@ -28555,14 +28587,14 @@ function configFile() {
28555
28587
  return readConfigFile(CONFIG_PATH);
28556
28588
  }
28557
28589
  function readLine(prompt) {
28558
- return new Promise((resolve4) => {
28590
+ return new Promise((resolve5) => {
28559
28591
  const rl = createInterface({
28560
28592
  input: process.stdin,
28561
28593
  output: process.stdout
28562
28594
  });
28563
28595
  rl.question(prompt, (answer) => {
28564
28596
  rl.close();
28565
- resolve4(answer);
28597
+ resolve5(answer);
28566
28598
  });
28567
28599
  });
28568
28600
  }
@@ -28620,7 +28652,7 @@ var deps = {
28620
28652
  `),
28621
28653
  writeErr: (text) => process.stderr.write(`${text}
28622
28654
  `),
28623
- sleep: (ms) => new Promise((resolve4) => setTimeout(resolve4, ms)),
28655
+ sleep: (ms) => new Promise((resolve5) => setTimeout(resolve5, ms)),
28624
28656
  now: () => Date.now()
28625
28657
  };
28626
28658
  var loginDeps = {
@@ -28810,7 +28842,36 @@ registerSetupCommand(
28810
28842
  program2,
28811
28843
  {
28812
28844
  ...pluginDeps,
28813
- resolveJentrix: () => resolveExecutableOnPath(platformExecutableNames("jentrix"), process.env),
28845
+ // npm's global prefix, read from npm itself — never a PATH probe. Under
28846
+ // `npx @jentrix/cli setup` the _npx cache is prepended to PATH and holds a
28847
+ // `jentrix` shim, so a PATH answer is always yes and always meaningless.
28848
+ globalInstall: async () => {
28849
+ const npm = await resolveExecutableOnPath(
28850
+ platformExecutableNames("npm"),
28851
+ process.env
28852
+ );
28853
+ const ask = async (args) => {
28854
+ if (!npm) return null;
28855
+ const out = (await invokeRunnerProcess(npm, args)).stdout.trim();
28856
+ return out || null;
28857
+ };
28858
+ const root = await ask(["root", "-g"]);
28859
+ const prefix = await ask(["prefix", "-g"]);
28860
+ const binDir = prefix ? process.platform === "win32" ? prefix : join6(prefix, "bin") : null;
28861
+ const dir = (name) => {
28862
+ if (!root) return null;
28863
+ const candidate = join6(root, "@jentrix", name);
28864
+ return existsSync6(join6(candidate, "package.json")) ? candidate : null;
28865
+ };
28866
+ return {
28867
+ cliDir: dir("cli"),
28868
+ runnerDir: dir("runner"),
28869
+ binDir,
28870
+ binDirOnPath: Boolean(
28871
+ binDir && (process.env.PATH ?? "").split(delimiter2).some((entry) => entry && resolve4(entry) === resolve4(binDir))
28872
+ )
28873
+ };
28874
+ },
28814
28875
  resolveGit: () => resolveExecutableOnPath(platformExecutableNames("git"), process.env),
28815
28876
  // Register the plugin from whichever copy of the package PERSISTS. Under
28816
28877
  // `npx @jentrix/cli setup` the running module lives in npm's _npx cache,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jentrix/cli",
3
- "version": "0.5.6",
3
+ "version": "0.5.7",
4
4
  "description": "Command-line client for the Jentrix MCP surface (jentrix tool <name>, generated noun-verb commands).",
5
5
  "keywords": [
6
6
  "jentrix",