@jelou/cli 1.17.1 → 1.18.0

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/bin/jelou CHANGED
@@ -1,44 +1,37 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  const { execFileSync } = require("child_process");
4
- const { join } = require("path");
4
+ const {
5
+ PLATFORMS,
6
+ platformKey,
7
+ platformPackage,
8
+ platformBinaryPath,
9
+ } = require("../lib/platform");
5
10
 
6
- const PLATFORMS = {
7
- "darwin-arm64": "@jelou/cli-darwin-arm64",
8
- "darwin-x64": "@jelou/cli-darwin-x64",
9
- "linux-x64": "@jelou/cli-linux-x64",
10
- "linux-arm64": "@jelou/cli-linux-arm64",
11
- "win32-x64": "@jelou/cli-win32-x64",
12
- };
13
-
14
- const key = `${process.platform}-${process.arch}`;
15
- const pkg = PLATFORMS[key];
11
+ const key = platformKey();
12
+ const pkg = platformPackage();
16
13
 
17
14
  if (!pkg) {
18
15
  console.error(
19
16
  `@jelou/cli: unsupported platform ${key}\n` +
20
- `Supported: ${Object.keys(PLATFORMS).join(", ")}\n` +
21
- `Download manually from https://github.com/JelouLatam/jelou-cli/releases`
17
+ `Supported: ${Object.keys(PLATFORMS).join(", ")}\n` +
18
+ `Download manually from https://github.com/JelouLatam/jelou-cli/releases`,
22
19
  );
23
20
  process.exit(1);
24
21
  }
25
22
 
26
- let binPath;
27
- try {
28
- const pkgJson = require.resolve(`${pkg}/package.json`);
29
- const ext = process.platform === "win32" ? ".exe" : "";
30
- binPath = join(pkgJson, "..", "bin", `jelou${ext}`);
31
- } catch {
23
+ const binPath = platformBinaryPath();
24
+ if (!binPath) {
32
25
  console.error(
33
26
  `@jelou/cli: platform package ${pkg} is not installed.\n\n` +
34
- `An in-place \`npm install -g @jelou/cli\` upgrade can leave the wrapper\n` +
35
- `without its platform dependency (npm sees the wrapper as up-to-date and\n` +
36
- `skips re-resolving optional deps). The cleanest fix is to uninstall first:\n\n` +
37
- ` npm uninstall -g @jelou/cli\n` +
38
- ` npm install -g @jelou/cli\n\n` +
39
- `If that still fails, check that npm isn't configured to skip optional\n` +
40
- `dependencies (look for \`omit=optional\` in ~/.npmrc, or a global\n` +
41
- `\`--no-optional\` flag).\n`
27
+ `An in-place \`npm install -g @jelou/cli\` upgrade can leave the wrapper\n` +
28
+ `without its platform dependency (npm sees the wrapper as up-to-date and\n` +
29
+ `skips re-resolving optional deps). The cleanest fix is to uninstall first:\n\n` +
30
+ ` npm uninstall -g @jelou/cli\n` +
31
+ ` npm install -g @jelou/cli\n\n` +
32
+ `If that still fails, check that npm isn't configured to skip optional\n` +
33
+ `dependencies (look for \`omit=optional\` in ~/.npmrc, or a global\n` +
34
+ `\`--no-optional\` flag).\n`,
42
35
  );
43
36
  process.exit(1);
44
37
  }
@@ -1,38 +1,98 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // Runs after npm has resolved optionalDependencies. If we're on a supported
4
- // platform but the matching platform package didn't land on disk (npm's known
5
- // silent-skip on in-place upgrades), fail the install loudly instead of leaving
6
- // a broken wrapper that only surfaces the problem at runtime.
7
-
8
- const PLATFORMS = {
9
- "darwin-arm64": "@jelou/cli-darwin-arm64",
10
- "darwin-x64": "@jelou/cli-darwin-x64",
11
- "linux-x64": "@jelou/cli-linux-x64",
12
- "linux-arm64": "@jelou/cli-linux-arm64",
13
- "win32-x64": "@jelou/cli-win32-x64",
14
- };
15
-
16
- const key = `${process.platform}-${process.arch}`;
17
- const pkg = PLATFORMS[key];
3
+ // Two responsibilities, in order:
4
+ // 1. Verify the matching `@jelou/cli-<platform>` optional dep actually
5
+ // landed on disk (npm silent-skips optional deps on some in-place
6
+ // upgrades). Fail loudly here so users see the install break instead
7
+ // of a runtime "platform package not installed" later.
8
+ // 2. Replace the wrapper's `bin/jelou` (a node shim that adds ~20ms of
9
+ // cold-start) with a relative symlink to the platform binary itself.
10
+ // When npm wires `<global>/bin/jelou` -> `<wrapper>/bin/jelou`, the
11
+ // chain now resolves straight to the native binary, no node hop.
12
+
13
+ const fs = require("fs");
14
+ const path = require("path");
15
+ const {
16
+ PLATFORMS,
17
+ platformKey,
18
+ platformPackage,
19
+ platformBinaryPath,
20
+ } = require("../lib/platform");
21
+
22
+ const key = platformKey();
23
+ const pkg = platformPackage();
18
24
 
19
25
  if (!pkg) {
20
- // Unsupported platform — wrapper's bin script handles its own error path.
26
+ // Unsupported platform. Wrapper's bin script handles its own error path.
21
27
  process.exit(0);
22
28
  }
23
29
 
24
- try {
25
- require.resolve(`${pkg}/package.json`);
26
- process.exit(0);
27
- } catch {
30
+ const binPath = platformBinaryPath();
31
+ if (!binPath) {
28
32
  console.error(
29
33
  `\n@jelou/cli: optional dependency ${pkg} did not install.\n\n` +
30
- `npm sometimes silently skips optional deps on in-place upgrades. Fix\n` +
31
- `with a clean reinstall:\n\n` +
32
- ` npm uninstall -g @jelou/cli\n` +
33
- ` npm install -g @jelou/cli\n\n` +
34
- `If that still fails, check for \`omit=optional\` in ~/.npmrc or a\n` +
35
- `\`--no-optional\` flag.\n`
34
+ `npm sometimes silently skips optional deps on in-place upgrades. Fix\n` +
35
+ `with a clean reinstall:\n\n` +
36
+ ` npm uninstall -g @jelou/cli\n` +
37
+ ` npm install -g @jelou/cli\n\n` +
38
+ `If that still fails, check for \`omit=optional\` in ~/.npmrc or a\n` +
39
+ `\`--no-optional\` flag.\n`,
40
+ );
41
+ process.exit(1);
42
+ }
43
+
44
+ if (!fs.existsSync(binPath)) {
45
+ // Resolved the package, but the binary file isn't on disk. Same recovery.
46
+ console.error(
47
+ `\n@jelou/cli: ${pkg} resolved but its binary is missing at ${binPath}.\n` +
48
+ `Try: npm uninstall -g @jelou/cli && npm install -g @jelou/cli\n`,
36
49
  );
37
50
  process.exit(1);
38
51
  }
52
+
53
+ // --- fast-shim rewrite (Unix only for now) ---
54
+ // On Windows npm generates `.cmd` and `.ps1` shims that hardcode
55
+ // `node "<wrapper>/bin/jelou"`; replacing the wrapper script doesn't
56
+ // remove the node hop because the .cmd file in the global bin still
57
+ // invokes node first. A Windows fast path would need a separate native
58
+ // launcher (tracked separately as Tier 3). On Unix npm creates symlinks,
59
+ // so a symlink chain skips the node boot entirely.
60
+ if (process.platform === "win32") {
61
+ process.exit(0);
62
+ }
63
+
64
+ const wrapperBin = path.dirname(__filename); // <wrapper>/bin/
65
+ const shimPath = path.join(wrapperBin, "jelou");
66
+ const relativeTarget = path.relative(wrapperBin, binPath);
67
+
68
+ // Idempotence: if the shim already points at the right binary, no-op.
69
+ // Postinstall fires on every install / upgrade; re-creating the symlink
70
+ // each time would churn the inode and break editor watchers.
71
+ try {
72
+ const stat = fs.lstatSync(shimPath);
73
+ if (stat.isSymbolicLink() && fs.readlinkSync(shimPath) === relativeTarget) {
74
+ process.exit(0);
75
+ }
76
+ } catch (_) {
77
+ // shim not present yet — fine, we'll create it.
78
+ }
79
+
80
+ try {
81
+ fs.rmSync(shimPath, { force: true });
82
+ } catch (_) {
83
+ // nothing to remove
84
+ }
85
+
86
+ try {
87
+ fs.symlinkSync(relativeTarget, shimPath);
88
+ process.exit(0);
89
+ } catch (err) {
90
+ // EPERM (Windows w/o developer mode), EXDEV (cross-device install),
91
+ // EROFS (read-only FS in some sandboxes). Fall back to a tiny shell
92
+ // wrapper. Adds ~1-3ms vs ~0ms for symlink, but still much better than
93
+ // the 20ms node-boot hop the wrapper script costs.
94
+ const safeTarget = relativeTarget.replace(/(["\\$`])/g, "\\$1");
95
+ const shell = `#!/bin/sh\nexec "$(dirname "$0")/${safeTarget}" "$@"\n`;
96
+ fs.writeFileSync(shimPath, shell, { mode: 0o755 });
97
+ process.exit(0);
98
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+
3
+ // Shared platform detection used by `bin/jelou` (the runtime shim) and
4
+ // `bin/postinstall.js` (the install-time verifier + fast-shim writer).
5
+ // Keeping this in one place prevents the two from drifting out of sync.
6
+
7
+ const path = require("path");
8
+
9
+ const PLATFORMS = {
10
+ "darwin-arm64": "@jelou/cli-darwin-arm64",
11
+ "darwin-x64": "@jelou/cli-darwin-x64",
12
+ "linux-x64": "@jelou/cli-linux-x64",
13
+ "linux-arm64": "@jelou/cli-linux-arm64",
14
+ "win32-x64": "@jelou/cli-win32-x64",
15
+ };
16
+
17
+ function platformKey() {
18
+ return `${process.platform}-${process.arch}`;
19
+ }
20
+
21
+ function platformPackage() {
22
+ return PLATFORMS[platformKey()] || null;
23
+ }
24
+
25
+ // Resolves the platform binary path through Node's normal module resolution.
26
+ // Returns null when the platform is unsupported OR the optional dep didn't
27
+ // install (npm's silent-skip on in-place upgrades). Callers handle each case
28
+ // with their own error message.
29
+ function platformBinaryPath() {
30
+ const pkg = platformPackage();
31
+ if (!pkg) return null;
32
+ let pkgJson;
33
+ try {
34
+ pkgJson = require.resolve(`${pkg}/package.json`);
35
+ } catch {
36
+ return null;
37
+ }
38
+ const ext = process.platform === "win32" ? ".exe" : "";
39
+ return path.join(pkgJson, "..", "bin", `jelou${ext}`);
40
+ }
41
+
42
+ module.exports = {
43
+ PLATFORMS,
44
+ platformKey,
45
+ platformPackage,
46
+ platformBinaryPath,
47
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jelou/cli",
3
- "version": "1.17.1",
3
+ "version": "1.18.0",
4
4
  "description": "Build AI agents on the Jelou platform — from your terminal or your AI editor.",
5
5
  "author": "Jelou Inc. (https://jelou.ai)",
6
6
  "license": "SEE LICENSE IN LICENSE",
@@ -17,16 +17,17 @@
17
17
  },
18
18
  "files": [
19
19
  "bin/",
20
+ "lib/",
20
21
  "README.md",
21
22
  "LICENSE",
22
23
  "THIRD_PARTY_NOTICES.md"
23
24
  ],
24
25
  "optionalDependencies": {
25
- "@jelou/cli-darwin-arm64": "1.17.1",
26
- "@jelou/cli-darwin-x64": "1.17.1",
27
- "@jelou/cli-linux-x64": "1.17.1",
28
- "@jelou/cli-linux-arm64": "1.17.1",
29
- "@jelou/cli-win32-x64": "1.17.1"
26
+ "@jelou/cli-darwin-arm64": "1.18.0",
27
+ "@jelou/cli-darwin-x64": "1.18.0",
28
+ "@jelou/cli-linux-x64": "1.18.0",
29
+ "@jelou/cli-linux-arm64": "1.18.0",
30
+ "@jelou/cli-win32-x64": "1.18.0"
30
31
  },
31
32
  "keywords": [
32
33
  "jelou",