agenteval-cli 0.8.2 → 0.8.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.
@@ -0,0 +1,124 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { execFileSync } = require("child_process");
4
+ const { createHash } = require("crypto");
5
+ const { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync, readFileSync, writeFileSync } = require("fs");
6
+ const { join } = require("path");
7
+ const https = require("https");
8
+
9
+ const REPO = "lukasmetzler/agenteval";
10
+ const CACHE_DIR = join(require("os").homedir(), ".agenteval", "bin");
11
+ const BIN_PATH = join(CACHE_DIR, "agenteval");
12
+ const VERSION_PATH = join(CACHE_DIR, ".version");
13
+
14
+ // SHA256 checksums injected by the release workflow.
15
+ // If all zeros, integrity check is skipped (dev/unreleased builds).
16
+ const CHECKSUMS = {
17
+ "agenteval-linux-x64": "a6dd2cd218972abe6de3b0ab8392160fbc2d1c3fc4cdcac3a97babd9b2cafb53",
18
+ "agenteval-darwin-arm64": "cfb44ac1227a16c70dd2d4fb0fa525ebccdfbbb93952595a5b5dc943c58d8c06",
19
+ "agenteval-darwin-x64": "3b23625fce940f5a97d358ec1e925bbc8e7395413157d9d5c79437374e1a2ab9",
20
+ };
21
+
22
+ function getPlatformKey() {
23
+ if (process.platform === "darwin" && process.arch === "arm64") return "agenteval-darwin-arm64";
24
+ if (process.platform === "darwin" && process.arch === "x64") return "agenteval-darwin-x64";
25
+ if (process.platform === "linux" && process.arch === "x64") return "agenteval-linux-x64";
26
+ return null;
27
+ }
28
+
29
+ function getPackageVersion() {
30
+ try { return require("../package.json").version; } catch { return null; }
31
+ }
32
+
33
+ function getCachedVersion() {
34
+ try { return readFileSync(VERSION_PATH, "utf8").trim(); } catch { return null; }
35
+ }
36
+
37
+ function verifySHA256(data, expected) {
38
+ // Skip verification if checksums are placeholder zeros
39
+ if (expected.startsWith("0000000000")) return true;
40
+ const actual = createHash("sha256").update(data).digest("hex");
41
+ return actual === expected;
42
+ }
43
+
44
+ function download(url, maxRedirects) {
45
+ if (maxRedirects === undefined) maxRedirects = 5;
46
+ if (maxRedirects <= 0) return Promise.reject(new Error("Too many redirects"));
47
+ return new Promise((resolve, reject) => {
48
+ const parsedUrl = new URL(url);
49
+ const options = { hostname: parsedUrl.hostname, path: parsedUrl.pathname + parsedUrl.search, headers: { "User-Agent": "agenteval-cli" } };
50
+ https.get(options, (res) => {
51
+ if (res.statusCode === 301 || res.statusCode === 302) {
52
+ const location = res.headers.location;
53
+ if (!location || (!location.startsWith("https://") && !location.startsWith("https://github.com"))) {
54
+ reject(new Error(`Unsafe redirect to ${location}`));
55
+ return;
56
+ }
57
+ return download(location, maxRedirects - 1).then(resolve, reject);
58
+ }
59
+ if (res.statusCode !== 200) { reject(new Error(`HTTP ${res.statusCode}`)); return; }
60
+ const chunks = [];
61
+ res.on("data", (chunk) => chunks.push(chunk));
62
+ res.on("end", () => resolve(Buffer.concat(chunks)));
63
+ res.on("error", reject);
64
+ }).on("error", reject);
65
+ });
66
+ }
67
+
68
+ async function ensureBinary() {
69
+ const pkgVersion = getPackageVersion();
70
+ const cachedVersion = getCachedVersion();
71
+
72
+ if (existsSync(BIN_PATH) && cachedVersion === pkgVersion) {
73
+ return BIN_PATH;
74
+ }
75
+
76
+ const binary = getPlatformKey();
77
+ if (!binary) {
78
+ console.error(`agenteval: unsupported platform ${process.platform}-${process.arch}`);
79
+ console.error("Supported: linux-x64, darwin-arm64, darwin-x64");
80
+ process.exit(1);
81
+ }
82
+
83
+ const version = pkgVersion ? `v${pkgVersion}` : "latest";
84
+ const url = `https://github.com/${REPO}/releases/download/${version}/${binary}`;
85
+
86
+ console.error(`Downloading agenteval ${version} (${binary})...`);
87
+ mkdirSync(CACHE_DIR, { recursive: true });
88
+
89
+ const tmpPath = `${BIN_PATH}.tmp.${Date.now()}`;
90
+ try {
91
+ const data = await download(url);
92
+
93
+ // Verify integrity
94
+ const expectedHash = CHECKSUMS[binary];
95
+ if (!verifySHA256(data, expectedHash)) {
96
+ throw new Error("SHA256 checksum mismatch — download may be corrupted or tampered with");
97
+ }
98
+
99
+ writeFileSync(tmpPath, data);
100
+ chmodSync(tmpPath, 0o755);
101
+ if (existsSync(BIN_PATH)) { try { unlinkSync(BIN_PATH); } catch {} }
102
+ renameSync(tmpPath, BIN_PATH);
103
+ writeFileSync(VERSION_PATH, pkgVersion || version);
104
+ console.error("Done.");
105
+ } catch (err) {
106
+ try { unlinkSync(tmpPath); } catch {}
107
+ console.error(`agenteval: download failed (${err.message})`);
108
+ console.error(`Install manually: https://github.com/${REPO}/releases`);
109
+ process.exit(1);
110
+ }
111
+
112
+ return BIN_PATH;
113
+ }
114
+
115
+ ensureBinary().then((binPath) => {
116
+ try {
117
+ execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" });
118
+ } catch (err) {
119
+ process.exit(err && typeof err === "object" && "status" in err ? err.status : 1);
120
+ }
121
+ }).catch((err) => {
122
+ console.error(`agenteval: ${err.message}`);
123
+ process.exit(1);
124
+ });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agenteval-cli",
3
- "version": "0.8.2",
3
+ "version": "0.8.4",
4
4
  "description": "Lint, benchmark, and CI gate for AI coding instructions",
5
5
  "keywords": [
6
6
  "cli",
@@ -30,7 +30,7 @@
30
30
  "node": ">=18"
31
31
  },
32
32
  "bin": {
33
- "agenteval": "bin/agenteval"
33
+ "agenteval": "bin/agenteval.js"
34
34
  },
35
35
  "files": [
36
36
  "bin/",
package/bin/agenteval DELETED
@@ -1,113 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- const { execFileSync, execSync } = require("child_process");
4
- const { existsSync, mkdirSync, chmodSync, renameSync, unlinkSync } = require("fs");
5
- const { join } = require("path");
6
- const https = require("https");
7
-
8
- const REPO = "lukasmetzler/agenteval";
9
- const CACHE_DIR = join(require("os").homedir(), ".agenteval", "bin");
10
- const BIN_PATH = join(CACHE_DIR, "agenteval");
11
- const VERSION_PATH = join(CACHE_DIR, ".version");
12
-
13
- function getPlatformKey() {
14
- const platform = process.platform;
15
- const arch = process.arch;
16
- if (platform === "darwin" && arch === "arm64") return "agenteval-darwin-arm64";
17
- if (platform === "darwin" && arch === "x64") return "agenteval-darwin-x64";
18
- if (platform === "linux" && arch === "x64") return "agenteval-linux-x64";
19
- return null;
20
- }
21
-
22
- function getPackageVersion() {
23
- try {
24
- return require("../package.json").version;
25
- } catch {
26
- return null;
27
- }
28
- }
29
-
30
- function getCachedVersion() {
31
- try {
32
- return require("fs").readFileSync(VERSION_PATH, "utf8").trim();
33
- } catch {
34
- return null;
35
- }
36
- }
37
-
38
- function download(url) {
39
- return new Promise((resolve, reject) => {
40
- https.get(url, (res) => {
41
- if (res.statusCode === 301 || res.statusCode === 302) {
42
- return download(res.headers.location).then(resolve, reject);
43
- }
44
- if (res.statusCode !== 200) {
45
- reject(new Error(`HTTP ${res.statusCode}`));
46
- return;
47
- }
48
- const chunks = [];
49
- res.on("data", (chunk) => chunks.push(chunk));
50
- res.on("end", () => resolve(Buffer.concat(chunks)));
51
- res.on("error", reject);
52
- }).on("error", reject);
53
- });
54
- }
55
-
56
- async function ensureBinary() {
57
- const pkgVersion = getPackageVersion();
58
- const cachedVersion = getCachedVersion();
59
-
60
- // Binary exists and matches current package version
61
- if (existsSync(BIN_PATH) && cachedVersion === pkgVersion) {
62
- return BIN_PATH;
63
- }
64
-
65
- const binary = getPlatformKey();
66
- if (!binary) {
67
- console.error(`agenteval: unsupported platform ${process.platform}-${process.arch}`);
68
- console.error("Supported: linux-x64, darwin-arm64, darwin-x64");
69
- console.error("Install manually: https://github.com/lukasmetzler/agenteval/releases");
70
- process.exit(1);
71
- }
72
-
73
- const version = pkgVersion ? `v${pkgVersion}` : "latest";
74
- const url = `https://github.com/${REPO}/releases/download/${version}/${binary}`;
75
-
76
- console.error(`Downloading agenteval ${version} (${binary})...`);
77
-
78
- mkdirSync(CACHE_DIR, { recursive: true });
79
-
80
- const tmpPath = `${BIN_PATH}.tmp.${Date.now()}`;
81
- try {
82
- const data = await download(url);
83
- require("fs").writeFileSync(tmpPath, data);
84
- chmodSync(tmpPath, 0o755);
85
-
86
- // Atomic replace
87
- if (existsSync(BIN_PATH)) {
88
- try { unlinkSync(BIN_PATH); } catch {}
89
- }
90
- renameSync(tmpPath, BIN_PATH);
91
- require("fs").writeFileSync(VERSION_PATH, pkgVersion || version);
92
-
93
- console.error("Done.");
94
- } catch (err) {
95
- try { unlinkSync(tmpPath); } catch {}
96
- console.error(`agenteval: download failed (${err.message})`);
97
- console.error(`Install manually: https://github.com/${REPO}/releases`);
98
- process.exit(1);
99
- }
100
-
101
- return BIN_PATH;
102
- }
103
-
104
- ensureBinary().then((binPath) => {
105
- try {
106
- const result = execFileSync(binPath, process.argv.slice(2), { stdio: "inherit" });
107
- } catch (err) {
108
- process.exit(err && typeof err === "object" && "status" in err ? err.status : 1);
109
- }
110
- }).catch((err) => {
111
- console.error(`agenteval: ${err.message}`);
112
- process.exit(1);
113
- });