@sruim/mentat-code-mini 0.1.2

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/checksums.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "mentat-macos-arm64": "",
3
+ "mentat-macos-x64": "",
4
+ "mentat-linux-x64": "",
5
+ "mentat-win-x64.exe": ""
6
+ }
package/install.js ADDED
@@ -0,0 +1,214 @@
1
+ const { Binary } = require("binary-install");
2
+ const os = require("os");
3
+ const fs = require("fs");
4
+ const path = require("path");
5
+ const crypto = require("crypto");
6
+ const https = require("https");
7
+ const http = require("http");
8
+
9
+ const REPO = "Sruimeng/mentat-code-mini";
10
+ const NAME = "mentat-code-mini";
11
+
12
+ const { version } = require("./package.json");
13
+
14
+ // 尝试加载校验和文件(如果存在)
15
+ let checksums = {};
16
+ try {
17
+ const checksumsPath = path.join(__dirname, "checksums.json");
18
+ if (fs.existsSync(checksumsPath)) {
19
+ checksums = require("./checksums.json");
20
+ }
21
+ } catch (e) {
22
+ // 校验和文件不存在或无法解析,继续但不验证
23
+ console.warn("⚠️ checksums.json not found, skipping integrity verification");
24
+ }
25
+
26
+ const getPlatform = () => {
27
+ const type = os.type();
28
+ const arch = os.arch();
29
+
30
+ if (type === "Windows_NT") return "win-x64.exe";
31
+ if (type === "Linux") return "linux-x64";
32
+ if (type === "Darwin") {
33
+ return arch === "arm64" ? "macos-arm64" : "macos-x64";
34
+ }
35
+ throw new Error(`Unsupported platform: ${type} ${arch}`);
36
+ };
37
+
38
+ const getBinaryUrl = () => {
39
+ const platform = getPlatform();
40
+ return `https://github.com/${REPO}/releases/download/v${version}/${NAME}-${platform}`;
41
+ };
42
+
43
+ /**
44
+ * 计算文件的 SHA256 哈希值
45
+ * @param {string} filePath - 文件路径
46
+ * @returns {Promise<string>} - 十六进制格式的哈希值
47
+ */
48
+ const calculateFileHash = (filePath) => {
49
+ return new Promise((resolve, reject) => {
50
+ const hash = crypto.createHash("sha256");
51
+ const stream = fs.createReadStream(filePath);
52
+
53
+ stream.on("data", (data) => hash.update(data));
54
+ stream.on("end", () => resolve(hash.digest("hex")));
55
+ stream.on("error", reject);
56
+ });
57
+ };
58
+
59
+ /**
60
+ * 验证文件完整性
61
+ * @param {string} filePath - 文件路径
62
+ * @param {string} expectedHash - 预期的哈希值
63
+ * @returns {Promise<boolean>} - 验证是否通过
64
+ */
65
+ const verifyIntegrity = async (filePath, expectedHash) => {
66
+ if (!expectedHash) {
67
+ console.warn("⚠️ No checksum available for verification");
68
+ return true; // 没有校验和时跳过验证
69
+ }
70
+
71
+ const actualHash = await calculateFileHash(filePath);
72
+
73
+ if (actualHash !== expectedHash) {
74
+ console.error("❌ Checksum verification failed!");
75
+ console.error(` Expected: ${expectedHash}`);
76
+ console.error(` Actual: ${actualHash}`);
77
+ return false;
78
+ }
79
+
80
+ console.log("✅ Checksum verification passed");
81
+ return true;
82
+ };
83
+
84
+ /**
85
+ * 获取二进制文件的安装路径
86
+ * @returns {string} - 二进制文件路径
87
+ */
88
+ const getBinaryPath = () => {
89
+ const platform = getPlatform();
90
+ const binaryName = platform.endsWith(".exe") ? `${NAME}.exe` : NAME;
91
+
92
+ // binary-install 默认安装到 node_modules/.bin 或包目录下
93
+ const possiblePaths = [
94
+ path.join(__dirname, "node_modules", ".bin", binaryName),
95
+ path.join(__dirname, binaryName),
96
+ path.join(__dirname, "bin", binaryName),
97
+ ];
98
+
99
+ for (const p of possiblePaths) {
100
+ if (fs.existsSync(p)) {
101
+ return p;
102
+ }
103
+ }
104
+
105
+ // 返回默认路径
106
+ return path.join(__dirname, binaryName);
107
+ };
108
+
109
+ /**
110
+ * 等待文件存在(用于等待 binary-install 完成)
111
+ * @param {string} filePath - 文件路径
112
+ * @param {number} timeout - 超时时间(毫秒)
113
+ * @param {number} interval - 检查间隔(毫秒)
114
+ * @returns {Promise<boolean>} - 文件是否存在
115
+ */
116
+ const waitForFile = (filePath, timeout = 30000, interval = 500) => {
117
+ return new Promise((resolve) => {
118
+ const startTime = Date.now();
119
+
120
+ const check = () => {
121
+ if (fs.existsSync(filePath)) {
122
+ resolve(true);
123
+ return;
124
+ }
125
+
126
+ if (Date.now() - startTime >= timeout) {
127
+ resolve(false);
128
+ return;
129
+ }
130
+
131
+ setTimeout(check, interval);
132
+ };
133
+
134
+ check();
135
+ });
136
+ };
137
+
138
+ const install = async () => {
139
+ try {
140
+ const platform = getPlatform();
141
+ const url = getBinaryUrl();
142
+
143
+ console.log(`📦 Installing ${NAME} v${version} for ${platform}...`);
144
+ console.log(` URL: ${url}`);
145
+
146
+ // 使用 binary-install 下载
147
+ // 注意:binary-install 的 install() 是同步操作,但内部可能有异步行为
148
+ const binary = new Binary(NAME, url);
149
+
150
+ // 包装为 Promise 以确保正确的异步处理
151
+ await new Promise((resolve, reject) => {
152
+ try {
153
+ binary.install();
154
+ resolve();
155
+ } catch (error) {
156
+ reject(error);
157
+ }
158
+ });
159
+
160
+ // 获取预期的校验和
161
+ const checksumKey = `${NAME}-${platform}`;
162
+ const expectedChecksum = checksums[checksumKey];
163
+
164
+ // 验证完整性(如果有校验和且非空)
165
+ if (expectedChecksum && expectedChecksum.length > 0) {
166
+ const binaryPath = getBinaryPath();
167
+
168
+ // 等待文件存在(最多 30 秒)
169
+ const fileExists = await waitForFile(binaryPath, 30000);
170
+
171
+ if (fileExists) {
172
+ const isValid = await verifyIntegrity(binaryPath, expectedChecksum);
173
+
174
+ if (!isValid) {
175
+ // 验证失败,删除文件并退出
176
+ try {
177
+ fs.unlinkSync(binaryPath);
178
+ } catch (e) {
179
+ console.warn(`⚠️ Failed to delete invalid binary: ${e.message}`);
180
+ }
181
+ console.error("❌ Installation aborted due to checksum mismatch");
182
+ console.error(
183
+ " This could indicate a corrupted download or a security issue."
184
+ );
185
+ console.error(" Please try again or report this issue.");
186
+ process.exit(1);
187
+ }
188
+ } else {
189
+ console.warn(
190
+ `⚠️ Binary not found at expected path after timeout: ${binaryPath}`
191
+ );
192
+ console.warn(" Skipping integrity verification");
193
+ }
194
+ } else {
195
+ console.log(
196
+ "ℹ️ No checksum configured, skipping integrity verification"
197
+ );
198
+ }
199
+
200
+ console.log(`✅ ${NAME} has been installed successfully!`);
201
+ } catch (error) {
202
+ console.error(`❌ Installation failed: ${error.message}`);
203
+ if (error.stack) {
204
+ console.error(` Stack: ${error.stack}`);
205
+ }
206
+ process.exit(1);
207
+ }
208
+ };
209
+
210
+ // 执行安装
211
+ install().catch((error) => {
212
+ console.error(`❌ Unexpected error: ${error.message}`);
213
+ process.exit(1);
214
+ });
package/package.json ADDED
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "@sruim/mentat-code-mini",
3
+ "version": "0.1.2",
4
+ "description": "Your AI Coding Agent - Rust-powered CLI distributed via npm",
5
+ "repository": {
6
+ "type": "git",
7
+ "url": "https://github.com/Sruimeng/mentat-code-mini.git"
8
+ },
9
+ "bin": {
10
+ "mentat": "run.js"
11
+ },
12
+ "scripts": {
13
+ "postinstall": "node install.js"
14
+ },
15
+ "keywords": [
16
+ "ai",
17
+ "coding",
18
+ "agent",
19
+ "cli",
20
+ "mentat"
21
+ ],
22
+ "author": "Sruimeng",
23
+ "license": "MIT",
24
+ "dependencies": {
25
+ "binary-install": "^1.1.0"
26
+ }
27
+ }
package/run.js ADDED
@@ -0,0 +1,58 @@
1
+ #!/usr/bin/env node
2
+
3
+ const { Binary } = require("binary-install");
4
+ const os = require("os");
5
+ const { version } = require("./package.json");
6
+
7
+ const REPO = "Sruimeng/mentat-code-mini";
8
+ const NAME = "mentat-code-mini";
9
+
10
+ /**
11
+ * 获取当前平台的二进制文件后缀
12
+ * @returns {string} 平台标识符
13
+ * @throws {Error} 如果平台不支持
14
+ */
15
+ const getPlatform = () => {
16
+ const type = os.type();
17
+ const arch = os.arch();
18
+
19
+ if (type === "Windows_NT") {
20
+ if (arch === "x64") return "win-x64.exe";
21
+ throw new Error(
22
+ `Unsupported Windows architecture: ${arch}. Only x64 is supported.`
23
+ );
24
+ }
25
+
26
+ if (type === "Linux") {
27
+ if (arch === "x64") return "linux-x64";
28
+ throw new Error(
29
+ `Unsupported Linux architecture: ${arch}. Only x64 is supported.`
30
+ );
31
+ }
32
+
33
+ if (type === "Darwin") {
34
+ if (arch === "arm64") return "macos-arm64";
35
+ if (arch === "x64") return "macos-x64";
36
+ throw new Error(
37
+ `Unsupported macOS architecture: ${arch}. Only arm64 and x64 are supported.`
38
+ );
39
+ }
40
+
41
+ throw new Error(`Unsupported platform: ${type} ${arch}`);
42
+ };
43
+
44
+ try {
45
+ const platform = getPlatform();
46
+ const url = `https://github.com/${REPO}/releases/download/v${version}/${NAME}-${platform}`;
47
+
48
+ const binary = new Binary(NAME, url);
49
+ binary.run();
50
+ } catch (error) {
51
+ console.error(`❌ ${error.message}`);
52
+ console.error("\nSupported platforms:");
53
+ console.error(" - Windows x64");
54
+ console.error(" - Linux x64");
55
+ console.error(" - macOS x64");
56
+ console.error(" - macOS arm64 (Apple Silicon)");
57
+ process.exit(1);
58
+ }